Skip to content

Commit

Permalink
support for Android P
Browse files Browse the repository at this point in the history
  • Loading branch information
rk700 committed Aug 10, 2018
1 parent b57672d commit f7719da
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 22 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -12,6 +12,7 @@ YAHFA is a hook framework for Android ART. It provides an efficient way for Java
- Android 7.1(API 25)
- Android 8.0(API 26)
- Android 8.1(API 27)
- Android 9.0(API 28)

with ABI:

Expand Down
28 changes: 17 additions & 11 deletions demoApp/src/main/java/lab/galaxy/yahfa/demoApp/MainActivity.java
Expand Up @@ -22,18 +22,24 @@ protected void onCreate(Bundle savedInstanceState) {
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Log.e() should be hooked
Log.e("origin", "call Log.e()");
// String.startsWith() should be hooked
Log.w("origin", "foo startsWith f is "+"foo".startsWith("f"));
// ClassWithVirtualMethod.tac() should be hooked
Log.w("origin", "virtual tac a,b,c,d, got "+
new ClassWithVirtualMethod().tac("a","b","c","d"));
// ClassWithStaticMethod.tac() should be hooked
Log.w("origin", "static tac a,b,c,d, got "+
ClassWithStaticMethod.tac("a","b","c","d"));
Log.w("origin", "JNI method return string: "+ClassWithJNIMethod.fromJNI());
for(int i=0; i<200; i++) {
doWork();
}
}
});
}

void doWork() {
// Log.e() should be hooked
Log.e("origin", "call Log.e()");
// String.startsWith() should be hooked
Log.w("origin", "foo startsWith f is "+"foo".startsWith("f"));
// ClassWithVirtualMethod.tac() should be hooked
Log.w("origin", "virtual tac a,b,c,d, got "+
new ClassWithVirtualMethod().tac("a","b","c","d"));
// ClassWithStaticMethod.tac() should be hooked
Log.w("origin", "static tac a,b,c,d, got "+
ClassWithStaticMethod.tac("a","b","c","d"));
Log.w("origin", "JNI method return string: "+ClassWithJNIMethod.fromJNI());
}
}
37 changes: 26 additions & 11 deletions library/src/main/jni/HookMain.c
Expand Up @@ -36,7 +36,17 @@ void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVers
SDKVersion = sdkVersion;
LOGI("init to SDK %d", sdkVersion);
switch(sdkVersion) {
case ANDROID_P:
kAccCompileDontBother = 0x02000000;
OFFSET_ArtMehod_in_Object = 0;
OFFSET_access_flags_in_ArtMethod = 4;
//OFFSET_dex_method_index_in_ArtMethod = 4*3;
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
roundUpToPtrSize(4*4+2*2) + pointer_size;
ArtMethodSize = roundUpToPtrSize(4*4+2*2) + pointer_size*2;
break;
case ANDROID_O2:
kAccCompileDontBother = 0x02000000;
case ANDROID_O:
OFFSET_ArtMehod_in_Object = 0;
OFFSET_access_flags_in_ArtMethod = 4;
Expand Down Expand Up @@ -132,16 +142,21 @@ static int doBackupAndHook(void *targetMethod, void *hookMethod, void *backupMet
}

if(backupMethod) {// do method backup
// update the cached method manually
// first we find the array of cached methods
void *dexCacheResolvedMethods = (void *) readAddr(
(void *) ((char *) hookMethod + OFFSET_dex_cache_resolved_methods_in_ArtMethod));
// then we get the dex method index of the static backup method
int methodIndex = read32((void *) ((char *) backupMethod + OFFSET_dex_method_index_in_ArtMethod));
// finally the addr of backup method is put at the corresponding location in cached methods array
memcpy((char *) dexCacheResolvedMethods + OFFSET_array_in_PointerArray + pointer_size * methodIndex,
(&backupMethod),
pointer_size);
if(SDKVersion < ANDROID_P) {

This comment has been minimized.

Copy link
@aviraxp

aviraxp Feb 26, 2020

Contributor

P and up don't need this?

This comment has been minimized.

Copy link
@rk700

rk700 Feb 27, 2020

Author Member

I think so, since there's no such a field in ArtMethod: http://androidxref.com/9.0.0_r3/xref/art/runtime/art_method.h

// update the cached method manually
// first we find the array of cached methods
void *dexCacheResolvedMethods = (void *) readAddr(
(void *) ((char *) hookMethod +
OFFSET_dex_cache_resolved_methods_in_ArtMethod));
// then we get the dex method index of the static backup method
int methodIndex = read32(
(void *) ((char *) backupMethod + OFFSET_dex_method_index_in_ArtMethod));
// finally the addr of backup method is put at the corresponding location in cached methods array
memcpy((char *) dexCacheResolvedMethods + OFFSET_array_in_PointerArray +
pointer_size * methodIndex,
(&backupMethod),
pointer_size);
}

// have to copy the whole target ArtMethod here
// if the target method calls other methods which are to be resolved
Expand Down Expand Up @@ -177,13 +192,13 @@ static int doBackupAndHook(void *targetMethod, void *hookMethod, void *backupMet
// set the target method to native so that Android O wouldn't invoke it with interpreter
if(SDKVersion >= ANDROID_O) {
int access_flags = read32((char *) targetMethod + OFFSET_access_flags_in_ArtMethod);
LOGI("access flags is 0x%x", access_flags);
access_flags |= kAccNative;
memcpy(
(char *) targetMethod + OFFSET_access_flags_in_ArtMethod,
&access_flags,
4
);
LOGI("access flags is 0x%x", access_flags);
}

LOGI("hook and backup done");
Expand Down
1 change: 1 addition & 0 deletions library/src/main/jni/env.h
Expand Up @@ -12,6 +12,7 @@
#define ANDROID_N2 25
#define ANDROID_O 26
#define ANDROID_O2 27
#define ANDROID_P 28

#define roundUpTo4(v) ((v+4-1) - ((v+4-1)&3))
#define roundUpTo8(v) ((v+8-1) - ((v+8-1)&7))
Expand Down

0 comments on commit f7719da

Please sign in to comment.