├── .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 |
7 |
8 |
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 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
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 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app-art/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/app-art/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-art/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-art/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-art/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-art/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-art/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-art/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-art/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-art/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app-art/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app-art/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | android_hook_demo_art
3 |
4 | Hello world!
5 | Settings
6 |
7 |
--------------------------------------------------------------------------------
/app-art/src/test/java/com/zhaoxiaodan/hookdemo/art/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.zhaoxiaodan.hookdemo.art;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest
11 | {
12 | @Test
13 | public void addition_isCorrect() throws Exception
14 | {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app-dalvik/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app-dalvik/app-dalvik.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
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-dalvik/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.model.application'
2 |
3 |
4 |
5 | model {
6 | android {
7 | compileSdkVersion = 19
8 | buildToolsVersion = "22.0.1"
9 |
10 | defaultConfig.with {
11 | applicationId = "com.zhaoxiaodan.android_hook_demo_dalvik"
12 | minSdkVersion.apiLevel = 19
13 | targetSdkVersion.apiLevel = 19
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-dalvik"
29 | cppFlags += ["-std=c++11", "-DHAVE_LITTLE_ENDIAN","-DANDROID_SMP=0"]
30 | ldLibs += ["log", "z", "android", "atomic", "dvm", "android_runtime"]
31 | stl = "gnustl_static"
32 |
33 | abiFilters += ["x86"]
34 | abiFilters += ["armeabi-v7a"]
35 |
36 | def android_branch = "android-2.3.3_r1.1";
37 |
38 | ldFlags += "-L${getRootDir()}/dexposed-patch/${android_branch}/jniLibs/x86".toString()
39 | ldFlags += "-L${getRootDir()}/dexposed-patch/${android_branch}/jniLibs/armeabi-v7a".toString()
40 |
41 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/dalvik".toString()
42 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/dalvik/vm".toString()
43 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/system/core/include".toString()
44 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/frameworks/native/include".toString()
45 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/frameworks/base/include".toString()
46 | cppFlags += "-I${getRootDir()}/dexposed-patch/${android_branch}/include/libnativehelper/include".toString()
47 |
48 | }
49 | }
50 |
51 |
52 | dependencies {
53 | compile fileTree(dir: 'libs', include: ['*.jar'])
54 | }
55 |
--------------------------------------------------------------------------------
/app-dalvik/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-dalvik/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app-dalvik/src/main/java/com/zhaoxiaodan/hookdemo/dalvik/Demo1.java:
--------------------------------------------------------------------------------
1 | package com.zhaoxiaodan.hookdemo.dalvik;
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-dalvik/src/main/java/com/zhaoxiaodan/hookdemo/dalvik/Demo2.java:
--------------------------------------------------------------------------------
1 | package com.zhaoxiaodan.hookdemo.dalvik;
2 |
3 | import android.util.Log;
4 |
5 |
6 | public class Demo2
7 | {
8 | String TAG = "===[hookdemo]===";
9 |
10 | public interface Handler
11 | {
12 | /**
13 | * 在原方法执行之前执行
14 | * @param params 原方法参数
15 | */
16 | public void before(Object instance, Object[] params);
17 | }
18 |
19 | public String test(String param1, long param2, int[] param3)
20 | {
21 | return param1;
22 | }
23 |
24 | public static String staticTest(String param1, Long param2, int[] param3)
25 | {
26 | return param1;
27 | }
28 | public void demo()
29 | {
30 | String param1 = "param1";
31 |
32 | /**
33 | * 设置hook
34 | * hook 住Demo2 这个类的 test 方法
35 | * 实现一个Handler类来实现 回调函数 before
36 | */
37 | hook(Demo2.class, "test", "(Ljava/lang/String;J[I)Ljava/lang/String;", new Handler()
38 | {
39 | @Override
40 | public void before(Object instance, Object[] params)
41 | {
42 | Log.d(TAG, "===========Handler before,param len: "+params.length+",instance:"+instance);
43 | for (int i = 0; i < params.length; i++)
44 | {
45 | Log.d(TAG, "p" + i + "=" + params[i]);
46 | }
47 | }
48 | });
49 | Log.d(TAG, "===========call test" + this.test(param1,999L,new int[]{1,2,3}));
50 |
51 |
52 | /**
53 | * 测试静态函数的hook, 则回调函数参数中 instance 为 null
54 | */
55 | hook(Demo2.class, "staticTest", "(Ljava/lang/String;Ljava/lang/Long;[I)Ljava/lang/String;", new Handler()
56 | {
57 | @Override
58 | public void before(Object instance, Object[] params)
59 | {
60 | Log.d(TAG, "===========Handler before,param len: "+params.length+",instance:"+instance);
61 | for (int i = 0; i < params.length; i++)
62 | {
63 | Log.d(TAG, "p" + i + "=" + params[i]);
64 | }
65 | }
66 | });
67 | Log.d(TAG, "===========call test" + this.staticTest(param1, 999L, new int[]{1, 2, 3}));
68 | }
69 |
70 | /**
71 | * hook 函数, 是个jni 函数
72 | * @param clazzToHook
73 | * @param methodName
74 | * @param methodSig
75 | * @param handler
76 | */
77 | private native void hook(Class> clazzToHook, String methodName, String methodSig, Handler handler);
78 | }
79 |
--------------------------------------------------------------------------------
/app-dalvik/src/main/java/com/zhaoxiaodan/hookdemo/dalvik/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhaoxiaodan.hookdemo.dalvik;
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-dalvik");
12 | }
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState)
16 | {
17 | super.onCreate(savedInstanceState);
18 | setContentView(R.layout.activity_main);
19 |
20 | ((Button)findViewById(R.id.button)).setOnClickListener(new View.OnClickListener()
21 | {
22 | @Override
23 | public void onClick(View v)
24 | {
25 | new Demo2().demo();
26 | }
27 | });
28 | }
29 |
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/app-dalvik/src/main/jni/hookdemo1.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "log.h"
3 | #include "Dalvik.h"
4 |
5 | static void showMethodInfo(const Method* method)
6 | {
7 | //看看method的各个属性都是啥:
8 | LOGD("accessFlags:%d",method->accessFlags);
9 | LOGD("clazz->descriptor:%s",method->clazz->descriptor);
10 | LOGD("clazz->sourceFile:%s",method->clazz->sourceFile);
11 | LOGD("methodIndex:%d",method->methodIndex);
12 | LOGD("name:%s",method->name);
13 | LOGD("shorty:%s",method->shorty);
14 | }
15 |
16 | /**
17 | * 使用jni GetMethodID 方法获取jmethodID 强制转为 Method 的hook 方法 示例
18 | */
19 | static void newTestMethod(const u4* args, JValue* pResult,
20 | const Method* method, struct Thread* self) {
21 |
22 | // args 是原来函数的参数数组, 原来test函数只有一个String型参数
23 | // 并且要注意, 如果是不是static函数, 下标0 是函数所在类的实例obj
24 | // 在dvm中Object, jni 中的jobject 和 java 中的 Object类 都不是同一个东西
25 | // String类对应StringObject
26 | // 取出参数打印出来看看
27 | StringObject* param1 = NULL;
28 |
29 | if(dvmIsStaticMethod(method))
30 | param1 = (StringObject*)args[0];
31 | else
32 | param1 = (StringObject*)args[1];
33 | LOGD("param1:%s",dvmCreateCstrFromString(param1));
34 |
35 | //JValue 是个union ,要返回int 就 pResult->i=1; 返回Object对象就 pResult->l = ojb;
36 | // 但是, 在dvm中的Object, jni 中的jobject 和 java 中的 Object类 都不是同一个东西
37 | // 所以, 我们这里使用dvm的函数来创建一个StringObject*
38 | pResult->l = dvmCreateStringFromCstr("newTestMethod");
39 |
40 | // 一般情况应该使用宏 : RETURN_XXX(result);
41 | return;
42 | }
43 |
44 | extern "C" JNIEXPORT void JNICALL
45 | Java_com_zhaoxiaodan_hookdemo_Demo1_hook(JNIEnv *env, jobject instance, jobject clazzToHook,
46 | jstring methodName_, jstring methodSig_) {
47 |
48 | const char *methodName = env->GetStringUTFChars(methodName_, 0);
49 | const char *methodSig = env->GetStringUTFChars(methodSig_, 0);
50 |
51 | jmethodID methodIDToHook = env->GetMethodID((jclass) clazzToHook,methodName,methodSig);
52 |
53 | // 找不到有可能是个static
54 | if(nullptr == methodIDToHook){
55 | env->ExceptionClear();
56 | methodIDToHook = env->GetStaticMethodID((jclass) clazzToHook,methodName,methodSig);
57 | }
58 |
59 |
60 | if(methodIDToHook != nullptr)
61 | {
62 | //主要在这里替换
63 | //jmethodID 在dvm里实际上就是个Method 结构体
64 | Method* method = (Method*) methodIDToHook;
65 |
66 | //看看method的各个属性都是啥:
67 | showMethodInfo(method);
68 |
69 | //设置Method 的 accessFlags 为 枚举型
70 | // ACC_NATIVE 表示 这个method 切换成了一个native 方法
71 | // 这个枚举 在 dalvik/libdex/DexFile.h
72 | // 类似:
73 | // ACC_PUBLIC = 0x00000001, // class, field, method, ic
74 | // ACC_PRIVATE = 0x00000002, // field, method, ic
75 | // ACC_PROTECTED = 0x00000004, // field, method, ic
76 | SET_METHOD_FLAG(method, ACC_NATIVE);
77 |
78 | //既然是一个native方法, 那就把 nativeFunc 指针指向我们的hook, 用来替换test的新方法
79 | method->nativeFunc = &newTestMethod;
80 |
81 | // registersSize是函数栈大小, insSize是参数占用大小
82 | // 如果是native方法, 就没有额外开销了
83 | // 所有开销就是参数占用, 所以把它设置成跟参数占用空间
84 | method->registersSize=method->insSize;
85 |
86 | //未知
87 | method->outsSize=0;
88 | }
89 |
90 | env->ReleaseStringUTFChars(methodName_, methodName);
91 | env->ReleaseStringUTFChars(methodSig_, methodSig);
92 | }
93 |
94 |
--------------------------------------------------------------------------------
/app-dalvik/src/main/jni/hookdemo2.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "log.h"
3 | #include "Dalvik.h"
4 |
5 | /**
6 | * dvmCallMethod 需要的是 ArrayObject*, 而 nativeFunction 传入的参数是 const u4*
7 | * 做个转换
8 | */
9 | ArrayObject* argsToArrayObject(const char* argsTypeDesc, const u4* args)
10 | {
11 | //全部参数都转成Object型
12 | ClassObject* objectArrayClass = dvmFindArrayClass("[Ljava/lang/Object;", NULL);
13 |
14 | // 参数个数, 类型描述符都是一个字符, 所以 argsTypeDesc 字符串长度就是参数个数
15 | int argsSize = strlen(argsTypeDesc);
16 |
17 | // 分配空间
18 | ArrayObject* argArray = dvmAllocArrayByClass(objectArrayClass,argsSize ,ALLOC_DEFAULT);
19 |
20 | // 挨个赋值
21 | // 因为 args 并不是一个真正意义上的"数组", 当long 或者 double 形, 会占用 args[i]和args[i+1]
22 | // 所以需要多一个下标来指向args内存
23 | int pArgs = 0;
24 | for(int i=0;i(reinterpret_cast(method->insns));
80 |
81 | // 在原方法执行之前, 我们是要调用 Handler 的 before 这个hook
82 | Method* handlerBeforeMethod = dvmFindInterfaceMethodHierByDescriptor(handlerObject->clazz,"before","(Ljava/lang/Object;[Ljava/lang/Object;)V");
83 |
84 | if(nullptr != handlerBeforeMethod)
85 | {
86 | LOGD("handlerBeforeMethod name:%s,desc:%s",handlerBeforeMethod->name,handlerBeforeMethod->shorty);
87 | JValue* result = new JValue();
88 |
89 | // method->shorty[0] 表示返回值类型, 比如"ILJ" 说明原函数有一个Object型参数和一个long型参数, 返回值为 整形
90 | // 注意自动装配类型, int long double, 如果是Integer, Long, Double, 则描述符为Ljava/lang/Integer,Ljava/lang/Long和Ljava/lang/Double
91 | const char returnTypeDesc = method->shorty[0];
92 | const char* argsTypeDesc = &(method->shorty[1]);
93 |
94 | // 转一下参数格式
95 | ArrayObject* argsArray ;
96 | Object* originalInstance;
97 |
98 | // 同样的, 如果原函数不是static 的, args[0] 函数是所在类的实例
99 | if(dvmIsStaticMethod(method))
100 | {
101 | argsArray = argsToArrayObject(argsTypeDesc,&(args[0]));
102 | originalInstance = nullptr;
103 | }else{
104 | argsArray = argsToArrayObject(argsTypeDesc,&(args[1]));
105 | originalInstance = (Object*)(args[0]);
106 | }
107 |
108 |
109 | dvmCallMethod(self,handlerBeforeMethod, handlerObject, result, originalInstance ,argsArray);
110 | }else{
111 | LOGE("method no found....");
112 | }
113 |
114 | // before 前置调用先不修改原返回值了
115 | pResult->l = nullptr;
116 |
117 |
118 | }
119 |
120 |
121 | /**
122 | * 设置hook, 将原函数调用转发给nativeFunc forwardToHander 进行处理
123 | */
124 | extern "C" JNIEXPORT void JNICALL
125 | Java_com_zhaoxiaodan_hookdemo_Demo2_hook(JNIEnv *env, jobject instance, jobject clazzToHook,
126 | jstring methodName_, jstring methodSig_,
127 | jobject handler) {
128 | const char *methodName = env->GetStringUTFChars(methodName_, 0);
129 | const char *methodSig = env->GetStringUTFChars(methodSig_, 0);
130 |
131 | jmethodID methodIDToHook = env->GetMethodID((jclass) clazzToHook,methodName,methodSig);
132 |
133 | // 找不到有可能是个static
134 | if(nullptr == methodIDToHook){
135 | env->ExceptionClear();
136 | methodIDToHook = env->GetStaticMethodID((jclass) clazzToHook,methodName,methodSig);
137 | }
138 |
139 |
140 | if(methodIDToHook != nullptr)
141 | {
142 | Method* method = reinterpret_cast(methodIDToHook);
143 |
144 | LOGD("hook function %s, args desc:%s",method->name,method->shorty);
145 |
146 | SET_METHOD_FLAG(method, ACC_NATIVE);
147 | //转发
148 | method->nativeFunc = &forwardToHander;
149 | method->registersSize=method->insSize;
150 | method->outsSize=0;
151 |
152 | // "附加参数" 功能
153 | // 在hook 的时候传进来的 handler 实现实例, 我们放到Method 结构体的insns 属性中
154 | // 到时候dvm 调用 nativeFunc 的时候会带回到 nativeFunc 中, 我们就能取到了
155 | method->insns = reinterpret_cast(dvmDecodeIndirectRef(dvmThreadSelf(),handler));
156 | }
157 |
158 | env->ReleaseStringUTFChars(methodName_, methodName);
159 | env->ReleaseStringUTFChars(methodSig_, methodSig);
160 | }
--------------------------------------------------------------------------------
/app-dalvik/src/main/jni/init.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
4 | {
5 |
6 | JNIEnv *env = nullptr;
7 | if (vm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) {
8 | return -1;
9 | }
10 |
11 | return JNI_VERSION_1_6;
12 | }
13 |
--------------------------------------------------------------------------------
/app-dalvik/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 | #include "Dalvik.h"
10 |
11 | #define LOG_TAG "[---hookdemo---]"
12 |
13 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
14 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
15 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
16 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
17 |
18 | #endif //ANDROID_HOOK_DEMO_LOG_H
19 |
--------------------------------------------------------------------------------
/app-dalvik/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
15 |
16 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app-dalvik/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-dalvik/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-dalvik/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-dalvik/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-dalvik/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-dalvik/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-dalvik/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-dalvik/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-dalvik/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app-dalvik/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app-dalvik/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | android-hook-demo
3 |
4 | Hello world!
5 | Settings
6 |
7 |
--------------------------------------------------------------------------------
/app-elf/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app-elf/app-elf.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
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-elf/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.model.application'
2 |
3 |
4 |
5 | model {
6 | android {
7 | compileSdkVersion = 21
8 | buildToolsVersion = "22.0.1"
9 |
10 | defaultConfig.with {
11 | applicationId = "com.zhaoxiaodan.android_hook_demo_elf"
12 | minSdkVersion.apiLevel = 10
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-elf"
29 | toolchain = "gcc"
30 | toolchainVersion = "4.9"
31 |
32 | cppFlags += ["-std=c++11"]
33 | ldLibs += ["log", "z", "android"]
34 | stl = "gnustl_static"
35 |
36 | abiFilters += ["x86"]
37 | abiFilters += ["armeabi-v7a"]
38 |
39 | }
40 | }
41 |
42 |
43 | dependencies {
44 | compile fileTree(dir: 'libs', include: ['*.jar'])
45 | }
46 |
--------------------------------------------------------------------------------
/app-elf/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-elf/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app-elf/src/main/java/com/zhaoxiaodan/hookdemo/elf/Demo1.java:
--------------------------------------------------------------------------------
1 | package com.zhaoxiaodan.hookdemo.elf;
2 |
3 | import android.util.Log;
4 |
5 | public class Demo1
6 | {
7 |
8 | static {
9 | // System.loadLibrary("call-test-function");
10 | }
11 |
12 | String TAG = "===[hookdemo]===";
13 |
14 | public void demo()
15 | {
16 | hook("libcall-test-function.so","_Z12testFunctionPKci");
17 | // callTestFunction("beforehook",1111);
18 | }
19 |
20 | private native void callTestFunction(String p1,int p2);
21 |
22 | private native void hook(String soname,String functionName);
23 | }
24 |
--------------------------------------------------------------------------------
/app-elf/src/main/java/com/zhaoxiaodan/hookdemo/elf/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhaoxiaodan.hookdemo.elf;
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-elf");
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-elf/src/main/jni/hookdemo1.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by liangwei on 15/8/24.
3 | //
4 |
5 | #include
6 | #include
7 |
8 |
9 | #include "log.h"
10 |
11 | #ifdef create_test_function
12 | void testFunction(const char* p1, int p2)
13 | {
14 | LOGD("==============in testFunction p1=%s, p2=%d",p1,p2);
15 | }
16 |
17 |
18 | extern "C" JNIEXPORT void JNICALL
19 | Java_com_zhaoxiaodan_hookdemo_elf_Demo1_callTestFunction(JNIEnv *env, jobject instance, jstring p1_,
20 | jint p2) {
21 | const char *p1 = env->GetStringUTFChars(p1_, 0);
22 |
23 | testFunction(p1,p2);
24 |
25 | env->ReleaseStringUTFChars(p1_, p1);
26 | }
27 | #else
28 |
29 | void replaceFunction()
30 | {
31 | LOGD("==============replaceFunction");
32 | }
33 |
34 |
35 | extern "C" JNIEXPORT void JNICALL
36 | Java_com_zhaoxiaodan_hookdemo_elf_Demo1_hook(JNIEnv *env, jobject instance, jstring soname_,
37 | jstring functionName_) {
38 | const char *soname = env->GetStringUTFChars(soname_, 0);
39 | const char *functionName = env->GetStringUTFChars(functionName_, 0);
40 |
41 | void (*hookFunction)(const char*,int);
42 | *(void **)(hookFunction) = dlsym(RTLD_DEFAULT,functionName);
43 |
44 | if(nullptr == hookFunction)
45 | {
46 | LOGE("can't find func %s, error:%s",functionName,dlerror());
47 | } else{
48 | LOGD("invokeOriginalMethod");
49 | hookFunction("hook",222);
50 | }
51 |
52 | // void* handle = dlopen(soname,RTLD_NOW);
53 | // if(nullptr == handle)
54 | // {
55 | // LOGE("open lib %s error:%s",soname,dlerror());
56 | // }else{
57 | // void (*hookFunction)(const char*,int);
58 | // *(void **)(hookFunction) = dlsym(handle,functionName);
59 | //
60 | // if(nullptr == hookFunction)
61 | // {
62 | // LOGE("can't find func %s, error:%s",functionName,dlerror());
63 | // } else{
64 | // LOGD("invokeOriginalMethod");
65 | // hookFunction("hook",222);
66 | // }
67 | //
68 | // }
69 |
70 | env->ReleaseStringUTFChars(soname_, soname);
71 | env->ReleaseStringUTFChars(functionName_, functionName);
72 | }
73 |
74 | #endif
--------------------------------------------------------------------------------
/app-elf/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-elf/src/main/jniLibs/armeabi-v7a/libcall-test-function.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-elf/src/main/jniLibs/armeabi-v7a/libcall-test-function.so
--------------------------------------------------------------------------------
/app-elf/src/main/jniLibs/x86/libcall-test-function.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-elf/src/main/jniLibs/x86/libcall-test-function.so
--------------------------------------------------------------------------------
/app-elf/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
15 |
16 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app-elf/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/app-elf/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-elf/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-elf/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-elf/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-elf/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-elf/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-elf/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/app-elf/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app-elf/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app-elf/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app-elf/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | android_hook_demo_elf
3 |
4 | Hello world!
5 | Settings
6 |
7 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle-experimental:0.2.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pangliang/android-hook-demo/fcd68a9cde3a73ec6e9b3298041e463cfb9ea75e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Aug 12 10:14:33 CST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app-dalvik', ':app-art', ':app-elf'
2 |
--------------------------------------------------------------------------------