├── .gitignore ├── .gitmodules ├── README.md ├── android-hook-demo.iml ├── app-art ├── .gitignore ├── app-art.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── zhaoxiaodan │ │ │ └── hookdemo │ │ │ └── art │ │ │ ├── Demo1.java │ │ │ └── MainActivity.java │ ├── jni │ │ ├── hookdemo1.cpp │ │ └── log.h │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── dimens.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── zhaoxiaodan │ └── hookdemo │ └── art │ └── ExampleUnitTest.java ├── app-dalvik ├── .gitignore ├── app-dalvik.iml ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zhaoxiaodan │ │ └── hookdemo │ │ └── dalvik │ │ ├── Demo1.java │ │ ├── Demo2.java │ │ └── MainActivity.java │ ├── jni │ ├── hookdemo1.cpp │ ├── hookdemo2.cpp │ ├── init.cpp │ └── log.h │ └── res │ ├── layout │ └── activity_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ └── strings.xml ├── app-elf ├── .gitignore ├── app-elf.iml ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zhaoxiaodan │ │ └── hookdemo │ │ └── elf │ │ ├── Demo1.java │ │ └── MainActivity.java │ ├── jni │ ├── hookdemo1.cpp │ └── log.h │ ├── jniLibs │ ├── armeabi-v7a │ │ └── libcall-test-function.so │ └── x86 │ │ └── libcall-test-function.so │ └── res │ ├── layout │ └── activity_main.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ └── strings.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | .idea 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dexposed-patch"] 2 | path = dexposed-patch 3 | url = https://pangliang@github.com/pangliang/dexposed-patch.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #android-hook-demo 2 | 3 | 这是个android 勾子机制 以及 [alibaba/dexposed](https://github.com/alibaba/dexposed) 项目的原理学习 4 | 5 | 学习笔记在: 6 | 7 | - [Android Hook(1) Dexposed原理](http://www.zhaoxiaodan.com/android/Android-Hook(1)-dexposed%E5%8E%9F%E7%90%86.html) 8 | - [Android Hook(2) Java2java](http://www.zhaoxiaodan.com/android/Android-Hook(2)-java2java.html) -------------------------------------------------------------------------------- /android-hook-demo.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app-art/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app-art/app-art.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /app-art/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.model.application' 2 | 3 | 4 | 5 | model { 6 | android { 7 | compileSdkVersion = 22 8 | buildToolsVersion = "22.0.1" 9 | 10 | defaultConfig.with { 11 | applicationId = "com.zhaoxiaodan.android_hook_demo_art" 12 | minSdkVersion.apiLevel = 22 13 | targetSdkVersion.apiLevel = 22 14 | versionCode = 1 15 | versionName = "1.0" 16 | } 17 | 18 | } 19 | 20 | android.buildTypes { 21 | release { 22 | minifyEnabled = false 23 | proguardFiles += file('proguard-rules.pro') 24 | } 25 | } 26 | 27 | android.ndk { 28 | moduleName = "hookdemo-art" 29 | toolchain = "gcc" 30 | toolchainVersion = "4.9" 31 | 32 | CFlags += ["-D_USING_LIBCXX", "-UNDEBUG","-O1", "-DDYNAMIC_ANNOTATIONS_ENABLED=1"] 33 | cppFlags += ["-std=c++0x", "-DPLATFORM_SDK_VERSION=21", "-DANDROID_SMP=0", "-UNDEBUG","-O0", "-DDYNAMIC_ANNOTATIONS_ENABLED=1","-DIMT_SIZE=64"] 34 | ldLibs += ["c++", "art", "cutils","utils", "log", "m", "c", "atomic", "z", "art_quick_dexposed_invoke_handler"] 35 | stl = "c++_static" // libart.so extern std::__1::stream so use libc++ 36 | 37 | abiFilters += ["x86"] 38 | abiFilters += ["armeabi-v7a"] 39 | 40 | def android_branch = "android-5.1.0_r5"; 41 | 42 | ldFlags += "-L${getRootDir()}/dexposed-patch/${android_branch}/jniLibs/x86".toString() 43 | ldFlags += "-L${getRootDir()}/dexposed-patch/${android_branch}/jniLibs/armeabi-v7a".toString() 44 | 45 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/art".toString() 46 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/art/runtime".toString() 47 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/art/runtime/arch/arm".toString() 48 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/art/runtime/entrypoints/quick".toString() 49 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/external/gtest/include".toString() 50 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/external/valgrind/main".toString() 51 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/external/valgrind/main/include".toString() 52 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/external/libcxx/include".toString() 53 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/system/core/include".toString() 54 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/frameworks/base/include".toString() 55 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/frameworks/native/include".toString() 56 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/libnativehelper/include".toString() 57 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/libnativehelper/include/nativehelper".toString() 58 | } 59 | } 60 | 61 | 62 | dependencies { 63 | compile fileTree(dir: 'libs', include: ['*.jar']) 64 | } 65 | -------------------------------------------------------------------------------- /app-art/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Volumes/f/server/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app-art/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app-art/src/main/java/com/zhaoxiaodan/hookdemo/art/Demo1.java: -------------------------------------------------------------------------------- 1 | package com.zhaoxiaodan.hookdemo.art; 2 | 3 | import android.util.Log; 4 | 5 | public class Demo1 6 | { 7 | String TAG = "===[hookdemo]==="; 8 | 9 | public static String staticTest(String param1) 10 | { 11 | return "staticTest"; 12 | } 13 | 14 | public String test(String param1) 15 | { 16 | return "11111"; 17 | } 18 | 19 | public void demo() 20 | { 21 | String param1 = "param1"; 22 | Log.d(TAG, "===========before hook test:" + this.test(param1)); 23 | hook(Demo1.class, "test", "(Ljava/lang/String;)Ljava/lang/String;"); 24 | Log.d(TAG, "===========after hook test:" + this.test(param1)); 25 | 26 | Log.d(TAG, "===========before hook staticTest:" + this.staticTest(param1)); 27 | hook(Demo1.class, "staticTest", "(Ljava/lang/String;)Ljava/lang/String;"); 28 | Log.d(TAG, "===========after hook staticTest:" + this.staticTest(param1)); 29 | } 30 | 31 | private native void hook(Class clazzToHook, String methodName, String methodSig); 32 | } 33 | -------------------------------------------------------------------------------- /app-art/src/main/java/com/zhaoxiaodan/hookdemo/art/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhaoxiaodan.hookdemo.art; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.Button; 7 | 8 | public class MainActivity extends Activity 9 | { 10 | static { 11 | System.loadLibrary("hookdemo-art"); 12 | } 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) 15 | { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_main); 18 | 19 | ((Button)findViewById(R.id.button)).setOnClickListener(new View.OnClickListener() 20 | { 21 | @Override 22 | public void onClick(View v) 23 | { 24 | new Demo1().demo(); 25 | } 26 | }); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app-art/src/main/jni/hookdemo1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by liangwei on 15/8/24. 3 | // 4 | 5 | #include 6 | #include "log.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using art::mirror::ArtMethod; 19 | using art::mirror::Array; 20 | using art::mirror::ObjectArray; 21 | using art::mirror::Class; 22 | using art::mirror::Object; 23 | using art::PrettyMethod; 24 | using art::Runtime; 25 | using art::Thread; 26 | 27 | using art::WellKnownClasses; 28 | using art::Primitive; 29 | using art::BoxPrimitive; 30 | using art::UnboxPrimitiveForResult; 31 | using art::UnboxPrimitiveForField; 32 | using art::JValue; 33 | using art::ScopedObjectAccess; 34 | using art::ScopedObjectAccessUnchecked; 35 | using art::ScopedObjectAccessAlreadyRunnable; 36 | using art::StackHandleScope; 37 | using art::Handle; 38 | using art::MethodHelper; 39 | using art::StackReference; 40 | using art::ClassLinker; 41 | using art::ScopedJniEnvLocalRefState; 42 | using art::ThrowLocation; 43 | 44 | extern "C" void art_quick_dexposed_invoke_handler(); 45 | 46 | extern "C" uint64_t artQuickDexposedInvokeHandler(ArtMethod *proxy_method, 47 | Object *receiver, Thread *self, 48 | StackReference *sp) 49 | SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 50 | 51 | LOG(INFO) << "dexposed >>> artQuickDexposedInvokeHandler " << PrettyMethod(proxy_method);; 52 | 53 | return 0; 54 | } 55 | 56 | 57 | extern "C" JNIEXPORT void JNICALL 58 | Java_com_zhaoxiaodan_hookdemo_art_Demo1_hook(JNIEnv *env, jobject instance, jobject clazzToHook, 59 | jstring methodName_, jstring methodSig_) { 60 | const char *methodName = env->GetStringUTFChars(methodName_, 0); 61 | const char *methodSig = env->GetStringUTFChars(methodSig_, 0); 62 | 63 | ScopedObjectAccess soa(env); 64 | art::Thread *self = art::Thread::Current(); 65 | 66 | jmethodID methodIDToHook = env->GetMethodID((jclass) clazzToHook,methodName,methodSig); 67 | 68 | // 找不到有可能是个static 69 | if(nullptr == methodIDToHook){ 70 | env->ExceptionClear(); 71 | methodIDToHook = env->GetStaticMethodID((jclass) clazzToHook,methodName,methodSig); 72 | } 73 | 74 | 75 | if(methodIDToHook != nullptr) 76 | { 77 | // 跟delvik 一样, art中的 jmethodID 实际上也是一个 art中的 ArtMethod 类 78 | // delvik 是结构体, art 中是类, art 使用得更多的是c++11的特性 79 | ArtMethod *artmeth = reinterpret_cast(methodIDToHook); 80 | artmeth->SetEntryPointFromQuickCompiledCode((const void *)art_quick_dexposed_invoke_handler); 81 | } 82 | 83 | 84 | env->ReleaseStringUTFChars(methodName_, methodName); 85 | env->ReleaseStringUTFChars(methodSig_, methodSig); 86 | } -------------------------------------------------------------------------------- /app-art/src/main/jni/log.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by liangwei on 15/8/14. 3 | // 4 | 5 | #ifndef ANDROID_HOOK_DEMO_LOG_H 6 | #define ANDROID_HOOK_DEMO_LOG_H 7 | 8 | #include "android/log.h" 9 | 10 | #define LOG_TAG "[---hookdemo---]" 11 | 12 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) 13 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) 14 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) 15 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) 16 | 17 | #endif //ANDROID_HOOK_DEMO_LOG_H 18 | -------------------------------------------------------------------------------- /app-art/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 |