首页
社区
课程
招聘
[原创]Hook Java的的一个改进版本
发表于: 2014-9-29 11:09 32831

[原创]Hook Java的的一个改进版本

2014-9-29 11:09
32831

<center> Hook Java的的一个改进版本
--------------------------

[《注入安卓进程,并Hook java世界的方法》](http://bbs.pediy.com/showthread.php?t=186054)这篇好文相信大家都看这,里面所提到的方法估计大家也都试过。不过里面的所用的方法,我发现有两个可以改进的地方。

##改进点一:更简单地修改java方法为本地方法##

```
        ...
        // hook method
        int argsSize = calcMethodArgsSize(method->shorty);
        if (!dvmIsStaticMethod(method))
                argsSize++;

        SET_METHOD_FLAG(method, ACC_NATIVE);
        method->registersSize = method->insSize = argsSize;
        method->outsSize = 0;
        method->jniArgInfo = dvmComputeJniArgInfo(method->shorty);

        // save info to insns
        method->insns = (u2*)info;

        // bind the bridge func,only one line
        method->nativeFunc = method_handler;
        LOGI("[+] %s->%s was hooked\n", classDesc, methodName);
        ...
```
直接把method->nativeFunc即可,无需重新调用JNIEnv的RegisterNatives方法,其中method_handler可以是下面两种形式之一:

```
typedef void (*DalvikBridgeFunc)(const u4* args, JValue* pResult, const Method* method, struct Thread* self);
typedef void (*DalvikNativeFunc)(const u4* args, JValue* pResult);
```

这样有一个好处,就是所有java方法都可以统一指向同一个native func,而不需要像为每一个java method方法指定一个native func。

##改进点二:方法回调避免线程安全问题##
原来的方法,是这样的

```
  //hook之前先拷贝
  uint mlen = sizeof(Method);
  Method *oldMeth = (Method*)malloc(mlen);
  memcpy(oldMeth,method,mlen);
  info->odlMethod = oldMeth;
  info->curMethod = method;
  
  //回调后再拷贝回来,再通过jni->callXXXXMethod调用,之后再重新hook
  memcpy(hi->curMethod,hi->odlMethod,mlen);
  jmethodID om = (jmethodID)hi->curMethod;
  jenv->CallVoidMethod(me,om,gDevice_Sensors);
  ClassMethodHook(jenv,&baiduhookInfos[0]);
```
这个方法,其实是有线程安全问题的,其中在dalvik中,有很多方法可以直接调用Method对象,比如dvmCallMethod, dvmCallMethodA, dvmCallMethodV,dvmInvokeMethod等等。针对DalvikBridgeFunc和DalvikNativeFunc的参数,我最后选择使用dvmInvokeMethod,这个函数的原型是这样的:

```
Object* dvmInvokeMethod(Object* obj, const Method* method, ArrayObject* argList, ArrayObject* params, ClassObject* returnType, bool noAccessCheck)

```

其中,obj是this或者null(如果是static方法),method可以直接使用hook之前copy的对象,比较麻烦是argList,params和returnType的获取。获取argList的方法,我在Proxy.cpp中到了现成的boxMethodArgs方法,而returnType通过Reflect.h中dvmGetBoxedReturnType的方法也可以获取,而剩下的params只能自己写代码了,下面是我的代码:

```
STATIC ArrayObject* dvmGetMethodParamTypes(const Method* method, const char* methodsig){
        /* count args */
        size_t argCount = dexProtoGetParameterCount(&method->prototype);
        STATIC ClassObject* java_lang_object_array = dvmFindSystemClass("[Ljava/lang/Object;");

        /* allocate storage */
        ArrayObject* argTypes = dvmAllocArrayByClass(java_lang_object_array, argCount, ALLOC_DEFAULT);
        if(argTypes == NULL){
                return NULL;
        }

        Object** argObjects = (Object**) argTypes->contents;
        const char *desc = (const char *)(strchr(methodsig, '(') + 1);

        /*
         * Fill in the array.
         */
        size_t desc_index = 0;
        size_t arg_index = 0;
        bool isArray = false;
        char descChar = desc[desc_index];

        while (descChar != ')') {

                switch (descChar) {
                case 'Z':
                case 'C':
                case 'F':
                case 'B':
                case 'S':
                case 'I':
                case 'D':
                case 'J':
                        if(!isArray){
                                argObjects[arg_index++] = dvmFindPrimitiveClass(descChar);
                                isArray = false;
                        }else{
                                char buf[3] = {0};
                                memcpy(buf, desc + desc_index - 1, 2);
                                argObjects[arg_index++] = dvmFindSystemClass(buf);
                        }

                        desc_index++;
                        break;

                case '[':
                        isArray = true;
                        desc_index++;
                        break;

                case 'L':
                        int s_pos = desc_index, e_pos = desc_index;
                        while(desc[++e_pos] != ';');
                        s_pos = isArray ? s_pos - 1 : s_pos;
                        isArray = false;

                        size_t len = e_pos - s_pos + 1;
                        char buf[128] = { 0 };
                        memcpy((void *)buf, (const void *)(desc + s_pos), len);
                        argObjects[arg_index++] = dvmFindClass(buf);
                        desc_index = e_pos + 1;
                        break;
                }

                descChar = desc[desc_index];
        }

        return argTypes;
}
```

通过上面几个类型的获取之后,最后再看一下整个method hook的实现,过程其实大同小异,不过直接把上述提及的向种类型信息预先获取并保存到method->insns里头了:

```
extern int __attribute__ ((visibility ("hidden"))) dalvik_java_method_hook(JNIEnv* env, HookInfo *info) {
        const char* classDesc = info->classDesc;
        const char* methodName = info->methodName;
        const char* methodSig = info->methodSig;
        const bool isStaticMethod = info->isStaticMethod;

        jclass classObj = dvmFindJNIClass(env, classDesc);
        if (classObj == NULL) {
                LOGE("[-] %s class not found", classDesc);
                return -1;
        }

        jmethodID methodId =
                        isStaticMethod ?
                                        env->GetStaticMethodID(classObj, methodName, methodSig) :
                                        env->GetMethodID(classObj, methodName, methodSig);

        if (methodId == NULL) {
                LOGE("[-] %s->%s method not found", classDesc, methodName);
                return -1;
        }

        // backup method
        Method* method = (Method*) methodId;
        if(method->nativeFunc == method_handler){
                LOGW("


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 3
支持
分享
最新回复 (33)
雪    币: 76
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
顶,期待inline hook, elf hook等。
不知道是不是兼容性的问题,目前这几个hook java的例子我都没有编译成功运行过。。。
用boyliang兄编译的可以运行。。。
最好源代码里面也有Android.mk文件:)
2014-9-29 11:18
0
雪    币: 233
活跃值: (148)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
3
这次我把所有的东西上传了,编译应该没有问题了
2014-9-29 11:20
0
雪    币: 76
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
thanks  
有空我再测试下,有问题再麻烦boyliang兄
2014-9-29 11:23
0
雪    币: 370
活跃值: (1180)
能力值: ( LV9,RANK:310 )
在线值:
发帖
回帖
粉丝
5
学习了!感谢分享!
2014-9-29 12:20
0
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
mark..
2014-9-29 12:37
0
雪    币: 14983
活跃值: (5285)
能力值: ( LV15,RANK:880 )
在线值:
发帖
回帖
粉丝
7
mark
2014-9-29 15:43
0
雪    币: 275
活跃值: (254)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
不管是在博客,还是在看雪,感觉boyliang前辈总是这么nice,过程详细清晰,代码完整可用,真的对于我们初学者很大的帮助,非常的感谢前辈。
2014-9-29 16:44
0
雪    币: 233
活跃值: (148)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
9
谢谢夸奖啊,如有不足,还请多多指正
2014-9-29 18:54
0
雪    币: 546
活跃值: (1672)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
10
mark
2014-9-29 21:58
0
雪    币: 216
活跃值: (55)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
是在Eclipse——import...——Existing Projects into Workspace导入后编译吗?为什么我import后,看不到任何project,Finish按钮也无法选择?
2014-9-30 10:31
0
雪    币: 29
活跃值: (499)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
12
终于有空了,马上学习学习!
2014-9-30 10:45
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
非常期待inline hook, elf hook
2014-10-5 11:13
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
请教一下,如果想要模拟gbd给某个代码地址加上断点,arm汇编应该怎么写比较好?
2014-10-15 09:23
0
雪    币: 233
活跃值: (148)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
15
你为什么不参考一下gdb的源码呢
2014-10-15 09:31
0
雪    币: 200
活跃值: (26)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
请问我编译SO的时候 include <android_runtime/AndroidRuntime.h> 这个库找不到是什么原因?
2014-10-22 15:32
0
雪    币: 230
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
mark
2014-10-23 09:52
0
雪    币: 49
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
换一种思路,这样也可以。是吧,影帝:)
void* handle = dlopen("/system/lib/libandroid_runtime.so", RTLD_NOW);
void* jvmAddr = dlsym(handle, "_ZN7android14AndroidRuntime7mJavaVME");
javaVM = *((JavaVM**) jvmAddr);
2014-10-23 16:46
0
雪    币: 34
活跃值: (50)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
19
好东西,群主,我关注了,加油!
2014-10-24 12:46
0
雪    币: 105
活跃值: (211)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
20
无法编译呀,boyliang大大什么时候可以把自己的NDK共享一下呀。
我这里找不到一大把头文件
2014-11-12 16:09
0
雪    币: 233
活跃值: (148)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
21
https://github.com/boyliang/ndk-patch
2014-11-12 21:32
0
雪    币: 133
活跃值: (587)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
22
hook 静态函数dvmInvokeMethod 貌似出错了
2014-11-22 22:52
0
雪    币: 233
活跃值: (148)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
23
可以把错误日志发一下不?另外,静态函数,你应该无法编译的吧?
2014-11-23 11:32
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
收藏了。感谢
2014-12-7 10:54
0
雪    币: 26
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
Android NDK: WARNING: APP_PLATFORM android-21 is larger than android:minSdkVersion 14 in /cygdrive/f/android/workspace/AllHookInOne/AndroidManifest.xml
Android NDK: WARNING:/cygdrive/f/android/workspace/AllHookInOne/jni/Android.mk:onehook: non-system libraries in linker flags: -landroid_runtime -lart -ldvm.2   
Android NDK:     This is likely to result in incorrect builds. Try using LOCAL_STATIC_LIBRARIES
Android NDK:     or LOCAL_SHARED_LIBRARIES instead to list the library dependencies of the
Android NDK:     current module
[armeabi] Compile++ thumb: onehook <= ArtMethodHook.cpp
In file included from F:/android/workspace/AllHookInOne/jni/JavaHook/ArtMethodHook.cpp0:
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:221:70: error: expected ')' before '::' token
     mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
                                                                      ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:74: note: in definition of macro 'SHARED_LOCKS_REQUIRED'
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                          ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:87: warning: 'shared_locks_required' attribute directive ignored [-Wattributes]
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                                       ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:221:43: note: in expansion of macro 'SHARED_LOCKS_REQUIRED'
     mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
                                           ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:223:86: error: expected ')' before '::' token
     mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
                                                                                      ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:74: note: in definition of macro 'SHARED_LOCKS_REQUIRED'
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                          ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:87: warning: 'shared_locks_required' attribute directive ignored [-Wattributes]
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                                       ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:223:59: note: in expansion of macro 'SHARED_LOCKS_REQUIRED'
     mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
                                                           ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:379:68: error: expected ')' before '::' token
  bool IsValidIndex(int32_t index) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
                                                                    ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:74: note: in definition of macro 'SHARED_LOCKS_REQUIRED'
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                          ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:87: warning: 'shared_locks_required' attribute directive ignored [-Wattributes]
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                                       ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:379:41: note: in expansion of macro 'SHARED_LOCKS_REQUIRED'
  bool IsValidIndex(int32_t index) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
                                         ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:395:53: error: expected ')' before '::' token
   T Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
                                                     ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:74: note: in definition of macro 'SHARED_LOCKS_REQUIRED'
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                          ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:87: warning: 'shared_locks_required' attribute directive ignored [-Wattributes]
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                                       ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:395:26: note: in expansion of macro 'SHARED_LOCKS_REQUIRED'
   T Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
                          ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:616:59: error: expected ')' before '::' token
  Class* GetSuperClass() const SHARED_LOCKS_REQUIRED (Locks::mutator_lock_){
                                                           ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:74: note: in definition of macro 'SHARED_LOCKS_REQUIRED'
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                          ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:87: warning: 'shared_locks_required' attribute directive ignored [-Wattributes]
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                                       ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:616:31: note: in expansion of macro 'SHARED_LOCKS_REQUIRED'
  Class* GetSuperClass() const SHARED_LOCKS_REQUIRED (Locks::mutator_lock_){
                               ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:624:60: error: expected ')' before '::' token
  DexCache* GetDexCache() const SHARED_LOCKS_REQUIRED (Locks::mutator_lock_){
                                                            ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:74: note: in definition of macro 'SHARED_LOCKS_REQUIRED'
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                          ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:42:87: warning: 'shared_locks_required' attribute directive ignored [-Wattributes]
#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__)))
                                                                                       ^
F:/android/workspace/AllHookInOne/jni/JavaHook/art_object_4_4.h:624:32: note: in expansion of macro 'SHARED_LOCKS_REQUIRED'
  DexCache* GetDexCache() const SHARED_LOCKS_REQUIRED (Locks::mutator_lock_){
                                ^
/cygdrive/d/Android/Sdk/ndk-bundle/build/core/build-binary.mk:466: recipe for target '/cygdrive/f/android/workspace/AllHookInOne/obj/local/armeabi/objs/onehook/JavaHook/ArtMethodHook.o' failed
make: *** [/cygdrive/f/android/workspace/AllHookInOne/obj/local/armeabi/objs/onehook/JavaHook/ArtMethodHook.o] Error 1
2016-3-9 13:41
0
游客
登录 | 注册 方可回帖
返回
//