forked from asLody/VirtualApp
-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
48 changed files
with
627 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,3 +38,6 @@ captures/ | |
|
||
# Keystore files | ||
*.jks | ||
|
||
*.swp | ||
.externalNativeBuild |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/build | ||
.externalNativeBuild |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
apply plugin: 'com.android.library' | ||
|
||
android { | ||
compileSdkVersion 25 | ||
buildToolsVersion "25.0.2" | ||
|
||
defaultConfig { | ||
minSdkVersion 14 | ||
targetSdkVersion 23 | ||
versionCode 1 | ||
versionName "1.0" | ||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | ||
ndk { | ||
// Specifies the ABI configurations of your native | ||
// libraries Gradle should build and package with your APK. | ||
abiFilters 'armeabi', 'armeabi-v7a', 'x86' | ||
} | ||
} | ||
buildTypes { | ||
release { | ||
minifyEnabled false | ||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | ||
} | ||
} | ||
externalNativeBuild { | ||
ndkBuild { | ||
path 'src/main/jni/Android.mk' | ||
} | ||
} | ||
} | ||
|
||
dependencies { | ||
compile fileTree(include: ['*.jar'], dir: 'libs') | ||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { | ||
exclude group: 'com.android.support', module: 'support-annotations' | ||
}) | ||
testCompile 'junit:junit:4.12' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Add project specific ProGuard rules here. | ||
# By default, the flags in this file are appended to flags specified | ||
# in /usr/local/opt/android-sdk-macosx/tools/proguard/proguard-android.txt | ||
# You can edit the include path and order by changing the proguardFiles | ||
# directive in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# Add any project specific keep options here: | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
26 changes: 26 additions & 0 deletions
26
VirtualApp/YAHFA/src/androidTest/java/lab/galaxy/yahfa/ExampleInstrumentedTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package lab.galaxy.yahfa; | ||
|
||
import android.content.Context; | ||
import android.support.test.InstrumentationRegistry; | ||
import android.support.test.runner.AndroidJUnit4; | ||
|
||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
/** | ||
* Instrumentation test, which will execute on an Android device. | ||
* | ||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a> | ||
*/ | ||
@RunWith(AndroidJUnit4.class) | ||
public class ExampleInstrumentedTest { | ||
@Test | ||
public void useAppContext() throws Exception { | ||
// Context of the app under test. | ||
Context appContext = InstrumentationRegistry.getTargetContext(); | ||
|
||
assertEquals("lab.galaxy.yahfa.test", appContext.getPackageName()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
|
||
package="lab.galaxy.yahfa"> | ||
|
||
<application android:allowBackup="true" android:label="@string/app_name" | ||
android:supportsRtl="true"> | ||
|
||
</application> | ||
|
||
</manifest> |
77 changes: 77 additions & 0 deletions
77
VirtualApp/YAHFA/src/main/java/lab/galaxy/yahfa/HookMain.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package lab.galaxy.yahfa; | ||
|
||
import android.app.Application; | ||
import android.util.Log; | ||
|
||
import java.lang.reflect.Method; | ||
|
||
import dalvik.system.DexClassLoader; | ||
|
||
/** | ||
* Created by liuruikai756 on 28/03/2017. | ||
*/ | ||
|
||
public class HookMain { | ||
private static final String TAG = "YAHFA"; | ||
|
||
static { | ||
System.loadLibrary("yahfa"); | ||
} | ||
|
||
public HookMain() { | ||
init(android.os.Build.VERSION.SDK_INT); | ||
} | ||
|
||
public void doHookDefault(ClassLoader patchClassLoader, ClassLoader originClassLoader) { | ||
try { | ||
Class<?> hookInfoClass = Class.forName("lab.galaxy.yahfa.HookInfo", true, patchClassLoader); | ||
String[] hookItemNames = (String[])hookInfoClass.getField("hookItemNames").get(null); | ||
for(String hookItemName : hookItemNames) { | ||
doHookItemDefault(patchClassLoader, hookItemName, originClassLoader); | ||
} | ||
} | ||
catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
|
||
public void doHookItemDefault(ClassLoader patchClassLoader, String hookItemName, ClassLoader originClassLoader) { | ||
try { | ||
Log.i(TAG, "Start hooking with item "+hookItemName); | ||
Class<?> hookItem = Class.forName(hookItemName, true, patchClassLoader); | ||
String className = (String)hookItem.getField("className").get(null); | ||
String methodName = (String)hookItem.getField("methodName").get(null); | ||
String methodSig = (String)hookItem.getField("methodSig").get(null); | ||
|
||
if(className == null || className.equals("")) { | ||
Log.w(TAG, "No target class. Skipping..."); | ||
return; | ||
} | ||
Class<?> clazz = Class.forName(className, true, originClassLoader); | ||
|
||
Method hook = null; | ||
Method backup = null; | ||
for (Method method : hookItem.getDeclaredMethods()) { | ||
if (method.getName().equals("hook")) { | ||
hook = method; | ||
} else if (method.getName().equals("origin")) { | ||
backup = method; | ||
} | ||
} | ||
if (hook == null) { | ||
Log.e(TAG, "Cannot find hook for "+methodName); | ||
return; | ||
} | ||
findAndBackupAndHook(clazz, methodName, methodSig, hook, backup); | ||
} | ||
catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
|
||
|
||
public native void findAndBackupAndHook(Class targetClass, String methodName, String methodSig, | ||
Method hook, Method backup); | ||
|
||
private native void init(int SDK_version); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
LOCAL_PATH:= $(call my-dir) | ||
include $(CLEAR_VARS) | ||
|
||
ifeq "$(TARGET_ARCH_ABI)" "x86" | ||
LOCAL_SRC_FILES:= HookMain.c entrypoints_x86.S | ||
else | ||
LOCAL_SRC_FILES:= HookMain.c entrypoints_arm.S | ||
endif | ||
|
||
LOCAL_LDLIBS := -llog | ||
|
||
LOCAL_MODULE:= yahfa | ||
|
||
include $(BUILD_SHARED_LIBRARY) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
APP_ABI := armeabi armeabi-v7a x86 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
#include "jni.h" | ||
#include <android/log.h> | ||
#include <string.h> | ||
|
||
#define LOG_TAG "YAHFA-Native" | ||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) | ||
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) | ||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) | ||
|
||
void hook_new_entry_23(); | ||
void hook_new_entry_22(); | ||
|
||
static int OFFSET_dex_cache_resolved_methods_in_ArtMethod; | ||
static int OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod; | ||
static int OFFSET_entry_point_from_jni_in_ArtMethod; | ||
static int OFFSET_dex_method_index_in_ArtMethod; | ||
static int OFFSET_array_in_PointerArray; | ||
static int OFFSET_ArtMehod_in_Object; | ||
static size_t pointer_size; | ||
static size_t ArtMethodSize; | ||
static void *hook_new_entry; | ||
|
||
static unsigned int read32(void *addr) { | ||
return *((unsigned int*)addr); | ||
} | ||
|
||
static unsigned long read64(void *addr) { | ||
return *((unsigned long*)addr); | ||
} | ||
|
||
static unsigned long readAddr(void *addr) { | ||
if(pointer_size == 4) { | ||
return read32(addr); | ||
} | ||
else if(pointer_size == 8) { | ||
return read64(addr); | ||
} | ||
else { | ||
LOGE("unknown pointer size %d", pointer_size); | ||
return 0; | ||
} | ||
} | ||
|
||
void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVersion) { | ||
switch(sdkVersion) { | ||
case 23: | ||
LOGI("init to SDK %d", sdkVersion); | ||
OFFSET_dex_cache_resolved_methods_in_ArtMethod = 4; | ||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod = 36; | ||
OFFSET_entry_point_from_jni_in_ArtMethod = 32; | ||
OFFSET_dex_method_index_in_ArtMethod = 20; | ||
OFFSET_array_in_PointerArray = 12; | ||
OFFSET_ArtMehod_in_Object = 0; | ||
pointer_size = sizeof(void *); | ||
ArtMethodSize = 40; | ||
hook_new_entry = (void *)hook_new_entry_23; | ||
break; | ||
case 22: | ||
LOGI("init to SDK %d", sdkVersion); | ||
OFFSET_dex_cache_resolved_methods_in_ArtMethod = 12; | ||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod = 44; | ||
OFFSET_entry_point_from_jni_in_ArtMethod = 40; | ||
OFFSET_dex_method_index_in_ArtMethod = 28; | ||
OFFSET_array_in_PointerArray = 12; | ||
OFFSET_ArtMehod_in_Object = 8; | ||
pointer_size = sizeof(void *); | ||
ArtMethodSize = 48; | ||
hook_new_entry = (void *)hook_new_entry_22; | ||
break; | ||
default: | ||
LOGE("not compatible with SDK %d", sdkVersion); | ||
break; | ||
} | ||
} | ||
|
||
static void doBackupAndHook(void *originMethod, void *hookMethod, void *backupMethod) { | ||
if(!backupMethod) { | ||
LOGW("backup method is null"); | ||
} | ||
else { //do method backup | ||
void *dexCacheResolvedMethods = (void *)readAddr((void *)((char *)backupMethod+OFFSET_dex_cache_resolved_methods_in_ArtMethod)); | ||
int methodIndex = read32((void *)((char *)backupMethod+OFFSET_dex_method_index_in_ArtMethod)); | ||
//first update the cached method manually | ||
memcpy((void *)((char *)dexCacheResolvedMethods+OFFSET_array_in_PointerArray+pointer_size*methodIndex), (void *)(&backupMethod), pointer_size); | ||
//then replace the placeholder with original method | ||
memcpy((void *)((char *)backupMethod+OFFSET_ArtMehod_in_Object), | ||
(void *)((char *)originMethod+OFFSET_ArtMehod_in_Object), | ||
ArtMethodSize-OFFSET_ArtMehod_in_Object); | ||
} | ||
//do method replacement | ||
//save the hook method at entry_point_from_jni_ | ||
memcpy((void *)((char *)originMethod+OFFSET_entry_point_from_jni_in_ArtMethod), (void *)(&hookMethod), pointer_size); | ||
//update the entrypoint | ||
memcpy((void *)((char *)originMethod+OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod), (void *)(&hook_new_entry), pointer_size); | ||
LOGI("hook and backup done"); | ||
} | ||
|
||
void Java_lab_galaxy_yahfa_HookMain_findAndBackupAndHook(JNIEnv *env, jclass clazz, | ||
jclass targetClass, jstring methodName, jstring methodSig, jobject hook, jobject backup) { | ||
if(!methodName || !methodSig) { | ||
LOGE("empty method name or signature"); | ||
return; | ||
} | ||
const char *c_methodName = (*env)->GetStringUTFChars(env, methodName, NULL); | ||
const char *c_methodSig = (*env)->GetStringUTFChars(env, methodSig, NULL); | ||
if(c_methodName == NULL || c_methodSig == NULL) { | ||
LOGE("failed to get c string"); | ||
return; | ||
} | ||
void *targetMethod = NULL; | ||
LOGI("Start findAndBackupAndHook for method %s%s", c_methodName, c_methodSig); | ||
if(pointer_size == 0) { | ||
LOGE("Not initialized"); | ||
goto end; | ||
} | ||
targetMethod = (void *)(*env)->GetMethodID(env, targetClass, c_methodName, c_methodSig); | ||
if((*env)->ExceptionCheck(env)) { | ||
(*env)->ExceptionClear(env); //cannot find non-static method | ||
targetMethod = (void *)(*env)->GetStaticMethodID(env, targetClass, c_methodName, c_methodSig); | ||
if((*env)->ExceptionCheck(env)) { | ||
(*env)->ExceptionClear(env); //cannot find static method | ||
LOGE("Cannot find target method %s%s", c_methodName, c_methodSig); | ||
goto end; | ||
} | ||
} | ||
doBackupAndHook(targetMethod, (void *)(*env)->FromReflectedMethod(env, hook), | ||
backup==NULL ? NULL : (void *)(*env)->FromReflectedMethod(env, backup)); | ||
|
||
end: | ||
(*env)->ReleaseStringUTFChars(env, methodName, c_methodName); | ||
(*env)->ReleaseStringUTFChars(env, methodSig, c_methodSig); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
.macro BEGIN_ENTRY eName | ||
.globl \eName | ||
.type \eName, %function | ||
.balign 16 | ||
\eName: | ||
.endm | ||
|
||
.macro END_ENTRY eName | ||
.size \eName, .-\eName | ||
.endm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#include "common.S" | ||
|
||
.text | ||
BEGIN_ENTRY hook_new_entry_23 | ||
ldr r0, [r0, #32] | ||
ldr pc, [r0, #36] | ||
END_ENTRY hook_new_entry_23 | ||
|
||
BEGIN_ENTRY hook_new_entry_22 | ||
ldr r0, [r0, #40] | ||
ldr pc, [r0, #44] | ||
END_ENTRY hook_new_entry_22 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include "common.S" | ||
|
||
.text | ||
BEGIN_ENTRY hook_new_entry_23 | ||
mov 32(%eax), %eax | ||
push 36(%eax) | ||
ret | ||
END_ENTRY hook_new_entry_23 | ||
|
||
|
||
BEGIN_ENTRY hook_new_entry_22 | ||
mov 40(%eax), %eax | ||
push 44(%eax) | ||
ret | ||
END_ENTRY hook_new_entry_22 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<resources> | ||
<string name="app_name">YAHFA</string> | ||
</resources> |
Oops, something went wrong.