Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
S
SandHook
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
SandHook
Commits
d577c5a6
Commit
d577c5a6
authored
Feb 15, 2019
by
swift_gan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix crash when hook replacement
parent
a7924ae8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
132 additions
and
9 deletions
+132
-9
art_method.cpp
hooklib/src/main/cpp/art/art_method.cpp
+16
-0
cast_art_method.cpp
hooklib/src/main/cpp/casts/cast_art_method.cpp
+11
-0
art_method.h
hooklib/src/main/cpp/includes/art_method.h
+3
-0
cast_art_method.h
hooklib/src/main/cpp/includes/cast_art_method.h
+1
-0
log.h
hooklib/src/main/cpp/includes/log.h
+16
-0
sandhook.cpp
hooklib/src/main/cpp/sandhook.cpp
+48
-6
trampoline_manager.cpp
hooklib/src/main/cpp/trampoline/trampoline_manager.cpp
+11
-3
SandHook.java
hooklib/src/main/java/com/swift/sandhook/SandHook.java
+26
-0
No files found.
hooklib/src/main/cpp/art/art_method.cpp
View file @
d577c5a6
...
...
@@ -51,6 +51,14 @@ bool ArtMethod::isCompiled() {
return
getQuickCodeEntry
()
!=
SandHook
::
CastArtMethod
::
quickToInterpreterBridge
;
}
bool
ArtMethod
::
isThumbCode
()
{
#if defined(__arm__)
return
(
reinterpret_cast
<
Size
>
(
getQuickCodeEntry
())
&
0x1
)
==
0x1
;
#else
return
false
;
#endif
}
void
ArtMethod
::
setAccessFlags
(
uint32_t
flags
)
{
CastArtMethod
::
accessFlag
->
set
(
this
,
flags
);
}
...
...
@@ -84,6 +92,10 @@ void* ArtMethod::getInterpreterCodeEntry() {
return
CastArtMethod
::
entryPointFormInterpreter
->
get
(
this
);
}
void
*
ArtMethod
::
getDeclaringClassPtr
()
{
return
CastArtMethod
::
declaringClass
->
get
(
this
);
}
void
ArtMethod
::
setQuickCodeEntry
(
void
*
entry
)
{
CastArtMethod
::
entryPointQuickCompiled
->
set
(
this
,
entry
);
}
...
...
@@ -103,6 +115,10 @@ void ArtMethod::setDexCacheResolveItem(uint32_t index, void* item) {
CastArtMethod
::
dexCacheResolvedMethods
->
setElement
(
this
,
index
,
item
);
}
void
ArtMethod
::
setDeclaringClassPtr
(
void
*
classPtr
)
{
CastArtMethod
::
declaringClass
->
set
(
this
,
classPtr
);
}
bool
ArtMethod
::
compile
(
JNIEnv
*
env
)
{
if
(
isCompiled
())
return
true
;
...
...
hooklib/src/main/cpp/casts/cast_art_method.cpp
View file @
d577c5a6
...
...
@@ -101,6 +101,13 @@ namespace SandHook {
}
};
class
CastShadowClass
:
public
IMember
<
art
::
mirror
::
ArtMethod
,
void
*>
{
protected
:
Size
calOffset
(
JNIEnv
*
jniEnv
,
mirror
::
ArtMethod
*
p
)
override
{
return
0
;
}
};
class
CastDexMethodIndex
:
public
IMember
<
art
::
mirror
::
ArtMethod
,
uint32_t
>
{
protected
:
...
...
@@ -148,6 +155,9 @@ namespace SandHook {
dexMethodIndex
=
new
CastDexMethodIndex
();
dexMethodIndex
->
init
(
env
,
m1
,
size
);
declaringClass
=
new
CastShadowClass
();
declaringClass
->
init
(
env
,
m1
,
size
);
jclass
neverCallTestClass
=
env
->
FindClass
(
"com/swift/sandhook/ClassNeverCall"
);
art
::
mirror
::
ArtMethod
*
neverCall
=
reinterpret_cast
<
art
::
mirror
::
ArtMethod
*>
(
env
->
GetMethodID
(
neverCallTestClass
,
"neverCall"
,
"()V"
));
...
...
@@ -173,6 +183,7 @@ namespace SandHook {
ArrayMember
<
art
::
mirror
::
ArtMethod
,
void
*>
*
CastArtMethod
::
dexCacheResolvedMethods
=
nullptr
;
IMember
<
art
::
mirror
::
ArtMethod
,
uint32_t
>
*
CastArtMethod
::
dexMethodIndex
=
nullptr
;
IMember
<
art
::
mirror
::
ArtMethod
,
uint32_t
>
*
CastArtMethod
::
accessFlag
=
nullptr
;
IMember
<
art
::
mirror
::
ArtMethod
,
void
*>
*
CastArtMethod
::
declaringClass
=
nullptr
;
void
*
CastArtMethod
::
quickToInterpreterBridge
=
nullptr
;
void
*
CastArtMethod
::
genericJniStub
=
nullptr
;
void
*
CastArtMethod
::
staticResolveStub
=
nullptr
;
...
...
hooklib/src/main/cpp/includes/art_method.h
View file @
d577c5a6
...
...
@@ -48,6 +48,7 @@ public:
bool
isAbstract
();
bool
isNative
();
bool
isCompiled
();
bool
isThumbCode
();
void
setAccessFlags
(
uint32_t
flags
);
void
disableCompilable
();
...
...
@@ -61,11 +62,13 @@ public:
void
setInterpreterCodeEntry
(
void
*
entry
);
void
setDexCacheResolveList
(
void
*
list
);
void
setDexCacheResolveItem
(
uint32_t
index
,
void
*
item
);
void
setDeclaringClassPtr
(
void
*
classPtr
);
void
*
getQuickCodeEntry
();
void
*
getInterpreterCodeEntry
();
uint32_t
getAccessFlags
();
uint32_t
getDexMethodIndex
();
void
*
getDeclaringClassPtr
();
bool
compile
(
JNIEnv
*
env
);
void
flushCache
();
...
...
hooklib/src/main/cpp/includes/cast_art_method.h
View file @
d577c5a6
...
...
@@ -18,6 +18,7 @@ namespace SandHook {
static
ArrayMember
<
art
::
mirror
::
ArtMethod
,
void
*>*
dexCacheResolvedMethods
;
static
IMember
<
art
::
mirror
::
ArtMethod
,
uint32_t
>*
dexMethodIndex
;
static
IMember
<
art
::
mirror
::
ArtMethod
,
uint32_t
>*
accessFlag
;
static
IMember
<
art
::
mirror
::
ArtMethod
,
void
*>*
declaringClass
;
static
void
*
quickToInterpreterBridge
;
static
void
*
genericJniStub
;
static
void
*
staticResolveStub
;
...
...
hooklib/src/main/cpp/includes/log.h
0 → 100644
View file @
d577c5a6
//
// Created by SwiftGan on 2019/2/15.
//
#ifndef SANDHOOK_LOG_H
#define SANDHOOK_LOG_H
#include "android/log.h"
#define TAG "SandHook-Native"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#endif //SANDHOOK_LOG_H
hooklib/src/main/cpp/sandhook.cpp
View file @
d577c5a6
...
...
@@ -2,6 +2,7 @@
#include "includes/cast_art_method.h"
#include "includes/trampoline_manager.h"
#include "includes/hide_api.h"
#include "includes/log.h"
SandHook
::
TrampolineManager
trampolineManager
;
...
...
@@ -13,6 +14,8 @@ enum HookMode {
REPLACE
=
2
};
HookMode
gHookMode
=
AUTO
;
extern
"C"
JNIEXPORT
jboolean
JNICALL
Java_com_swift_sandhook_SandHook_initNative
(
JNIEnv
*
env
,
jclass
type
,
jint
sdk
)
{
...
...
@@ -50,18 +53,29 @@ void ensureMethodCached(art::mirror::ArtMethod *hookMethod, art::mirror::ArtMeth
}
}
void
ensureMethodDeclaringClass
(
art
::
mirror
::
ArtMethod
*
origin
,
art
::
mirror
::
ArtMethod
*
backup
)
{
if
(
origin
->
getDeclaringClassPtr
()
!=
backup
->
getDeclaringClassPtr
())
{
LOGW
(
"backup method declaringClass is out to date due to Moving GC!"
);
backup
->
setDeclaringClassPtr
(
origin
->
getDeclaringClassPtr
());
backup
->
flushCache
();
}
}
bool
doHookWithReplacement
(
JNIEnv
*
env
,
art
::
mirror
::
ArtMethod
*
originMethod
,
art
::
mirror
::
ArtMethod
*
hookMethod
,
art
::
mirror
::
ArtMethod
*
backupMethod
)
{
if
(
!
hookMethod
->
isCompiled
())
{
hookMethod
->
compile
(
env
);
if
(
!
backupMethod
->
isCompiled
())
{
backupMethod
->
compile
(
env
);
}
if
(
SDK_INT
>=
ANDROID_N
)
{
originMethod
->
disableCompilable
();
hookMethod
->
disableCompilable
();
}
originMethod
->
tryDisableInline
();
if
(
backupMethod
!=
nullptr
)
{
originMethod
->
backup
(
backupMethod
);
if
(
SDK_INT
>=
ANDROID_N
)
{
...
...
@@ -71,13 +85,13 @@ bool doHookWithReplacement(JNIEnv* env,
backupMethod
->
disableInterpreterForO
();
}
backupMethod
->
tryDisableInline
();
backupMethod
->
setPrivate
();
backupMethod
->
flushCache
();
}
if
(
SDK_INT
>=
ANDROID_O
)
{
if
(
SDK_INT
>=
ANDROID_O
&&
SDK_INT
<
ANDROID_P
)
{
originMethod
->
disableInterpreterForO
();
}
SandHook
::
HookTrampoline
*
hookTrampoline
=
trampolineManager
.
installReplacementTrampoline
(
originMethod
,
hookMethod
,
backupMethod
);
if
(
hookTrampoline
!=
nullptr
)
{
originMethod
->
setQuickCodeEntry
(
hookTrampoline
->
replacement
->
getCode
());
...
...
@@ -130,7 +144,6 @@ bool doHookWithInline(JNIEnv* env,
backupMethod
->
disableInterpreterForO
();
}
backupMethod
->
tryDisableInline
();
backupMethod
->
setPrivate
();
backupMethod
->
flushCache
();
}
return
true
;
...
...
@@ -164,9 +177,14 @@ Java_com_swift_sandhook_SandHook_hookMethod(JNIEnv *env, jclass type, jobject or
goto
label_hook
;
}
if
(
origin
->
isAbstract
())
{
isInlineHook
=
false
;
}
else
if
(
gHookMode
!=
AUTO
)
{
if
(
gHookMode
==
INLINE
)
{
isInlineHook
=
origin
->
compile
(
env
);
}
else
{
isInlineHook
=
false
;
}
}
else
if
(
!
origin
->
isCompiled
())
{
if
(
SDK_INT
>=
ANDROID_N
)
{
isInlineHook
=
origin
->
compile
(
env
);
...
...
@@ -180,8 +198,10 @@ Java_com_swift_sandhook_SandHook_hookMethod(JNIEnv *env, jclass type, jobject or
label_hook
:
if
(
isInlineHook
&&
trampolineManager
.
canSafeInline
(
origin
))
{
LOGD
(
"method hook by inline!"
);
return
static_cast
<
jboolean
>
(
doHookWithInline
(
env
,
origin
,
hook
,
backup
));
}
else
{
LOGW
(
"method hook by replacement!"
);
return
static_cast
<
jboolean
>
(
doHookWithReplacement
(
env
,
origin
,
hook
,
backup
));
}
...
...
@@ -196,6 +216,28 @@ Java_com_swift_sandhook_SandHook_ensureMethodCached(JNIEnv *env, jclass type, jo
ensureMethodCached
(
hookeMethod
,
backupMethod
);
}
extern
"C"
JNIEXPORT
void
JNICALL
Java_com_swift_sandhook_SandHook_ensureMethodDeclaringClass
(
JNIEnv
*
env
,
jclass
type
,
jobject
originMethod
,
jobject
backupMethod
)
{
if
(
backupMethod
==
NULL
||
originMethod
==
NULL
)
return
;
art
::
mirror
::
ArtMethod
*
origin
=
reinterpret_cast
<
art
::
mirror
::
ArtMethod
*>
(
env
->
FromReflectedMethod
(
originMethod
));
art
::
mirror
::
ArtMethod
*
backup
=
reinterpret_cast
<
art
::
mirror
::
ArtMethod
*>
(
env
->
FromReflectedMethod
(
backupMethod
));
ensureMethodDeclaringClass
(
origin
,
backup
);
}
extern
"C"
JNIEXPORT
void
JNICALL
Java_com_swift_sandhook_SandHook_setHookMode
(
JNIEnv
*
env
,
jclass
type
,
jint
mode
)
{
// TODO
gHookMode
=
static_cast
<
HookMode
>
(
mode
);
}
extern
"C"
JNIEXPORT
void
JNICALL
Java_com_swift_sandhook_test_TestClass_jni_1test
(
JNIEnv
*
env
,
jobject
instance
)
{
...
...
hooklib/src/main/cpp/trampoline/trampoline_manager.cpp
View file @
d577c5a6
...
...
@@ -4,6 +4,7 @@
#include "../includes/trampoline_manager.h"
#include "../includes/trampoline.h"
#include "../includes/inst.h"
#include "../includes/log.h"
extern
int
SDK_INT
;
#define SWITCH_SETX0 false
...
...
@@ -108,8 +109,10 @@ namespace SandHook {
replacementHookTrampoline
=
new
ReplacementHookTrampoline
();
replacementHookTrampoline
->
init
();
replacementHookTrampolineSpace
=
allocExecuteSpace
(
replacementHookTrampoline
->
getCodeLen
());
if
(
replacementHookTrampolineSpace
==
0
)
if
(
replacementHookTrampolineSpace
==
0
)
{
LOGE
(
"hook error due to can not alloc execute space!"
);
goto
label_error
;
}
replacementHookTrampoline
->
setExecuteSpace
(
replacementHookTrampolineSpace
);
replacementHookTrampoline
->
setEntryCodeOffset
(
quickCompileOffset
);
replacementHookTrampoline
->
setHookMethod
(
reinterpret_cast
<
Code
>
(
hookMethod
));
...
...
@@ -164,8 +167,10 @@ namespace SandHook {
checkThumbCode
(
inlineHookTrampoline
,
getEntryCode
(
originMethod
));
inlineHookTrampoline
->
init
();
inlineHookTrampolineSpace
=
allocExecuteSpace
(
inlineHookTrampoline
->
getCodeLen
());
if
(
inlineHookTrampolineSpace
==
0
)
if
(
inlineHookTrampolineSpace
==
0
)
{
LOGE
(
"hook error due to can not alloc execute space!"
);
goto
label_error
;
}
inlineHookTrampoline
->
setExecuteSpace
(
inlineHookTrampolineSpace
);
inlineHookTrampoline
->
setEntryCodeOffset
(
quickCompileOffset
);
inlineHookTrampoline
->
setOriginMethod
(
reinterpret_cast
<
Code
>
(
originMethod
));
...
...
@@ -183,6 +188,7 @@ namespace SandHook {
directJumpTrampoline
->
init
();
originEntry
=
getEntryCode
(
originMethod
);
if
(
!
memUnprotect
(
reinterpret_cast
<
Size
>
(
originEntry
),
directJumpTrampoline
->
getCodeLen
()))
{
LOGE
(
"hook error due to can not write origin code!"
);
goto
label_error
;
}
...
...
@@ -200,8 +206,10 @@ namespace SandHook {
checkThumbCode
(
callOriginTrampoline
,
getEntryCode
(
originMethod
));
callOriginTrampoline
->
init
();
callOriginTrampolineSpace
=
allocExecuteSpace
(
callOriginTrampoline
->
getCodeLen
());
if
(
callOriginTrampolineSpace
==
0
)
if
(
callOriginTrampolineSpace
==
0
)
{
goto
label_error
;
}
callOriginTrampoline
->
setExecuteSpace
(
callOriginTrampolineSpace
);
callOriginTrampoline
->
setOriginMethod
(
reinterpret_cast
<
Code
>
(
originMethod
));
Code
originCode
=
nullptr
;
...
...
hooklib/src/main/java/com/swift/sandhook/SandHook.java
View file @
d577c5a6
...
...
@@ -17,6 +17,7 @@ import java.util.concurrent.ConcurrentHashMap;
public
class
SandHook
{
static
Map
<
Member
,
HookWrapper
.
HookEntity
>
globalHookEntityMap
=
new
ConcurrentHashMap
<>();
static
Map
<
Method
,
HookWrapper
.
HookEntity
>
globalBackupMap
=
new
ConcurrentHashMap
<>();
public
static
Class
artMethodClass
;
...
...
@@ -69,6 +70,9 @@ public class SandHook {
}
Log
.
d
(
"SandHook"
,
"method <"
+
entity
.
target
.
getName
()
+
"> hook success!"
);
globalHookEntityMap
.
put
(
entity
.
target
,
entity
);
if
(
entity
.
backup
!=
null
)
{
globalBackupMap
.
put
(
entity
.
backup
,
entity
);
}
}
}
...
...
@@ -91,6 +95,24 @@ public class SandHook {
return
res
;
}
public
static
void
ensureBackupDelaringClass
(
Method
backupMethod
)
{
if
(
backupMethod
==
null
)
return
;
HookWrapper
.
HookEntity
hookEntity
=
globalBackupMap
.
get
(
backupMethod
);
if
(
hookEntity
==
null
)
return
;
ensureMethodDeclaringClass
(
hookEntity
.
target
,
backupMethod
);
}
public
static
void
ensureBackupDelaringClassByOrigin
(
Member
originMethod
)
{
if
(
originMethod
==
null
)
return
;
HookWrapper
.
HookEntity
hookEntity
=
globalHookEntityMap
.
get
(
originMethod
);
if
(
hookEntity
==
null
||
hookEntity
.
backup
==
null
)
return
;
ensureMethodDeclaringClass
(
originMethod
,
hookEntity
.
backup
);
}
private
static
void
resolveStaticMethod
(
Member
method
)
{
//ignore result, just call to trigger resolve
try
{
...
...
@@ -182,8 +204,12 @@ public class SandHook {
private
static
native
boolean
initNative
(
int
sdk
);
public
static
native
void
setHookMode
(
int
hookMode
);
private
static
native
boolean
hookMethod
(
Member
originMethod
,
Method
hookMethod
,
Method
backupMethod
,
int
hookMode
);
public
static
native
void
ensureMethodCached
(
Method
hook
,
Method
backup
);
public
static
native
void
ensureMethodDeclaringClass
(
Member
originMethod
,
Method
backupMethod
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment