日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Hook Java的的一个改进版本

發布時間:2025/3/15 Android 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Hook Java的的一个改进版本 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄(?)[-]

  • Hook Java的的一個改進版本
  • 改進點一更簡單地修改java方法為本地方法
  • 改進點二方法回調避免線程安全問題
  • 最后
  • Hook Java的的一個改進版本

    《注入安卓進程,并Hook java世界的方法》這篇好文相信大家都看這,里面所提到的方法估計大家也都試過。不過里面的所用的方法,我發現有兩個可以改進的地方。

    改進點一:更簡單地修改java方法為本地方法

    [cpp] view plain copy
  • ...??
  • ????//?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可以是下面兩種形式之一:

    [cpp] view plain copy
  • 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。

    改進點二:方法回調避免線程安全問題

    原來的方法,是這樣的

    [cpp] view plain copy
  • //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,這個函數的原型是這樣的:

    [cpp] view plain copy
  • 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只能自己寫代碼了,下面是我的代碼:

    [cpp] view plain copy
  • 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里頭了:

    [cpp] view plain copy
  • 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("[*]?%s->%s?method?had?been?hooked",?classDesc,?methodName);??
  • ????????return?-1;??
  • ????}??
  • ????Method*?bakMethod?=?(Method*)?malloc(sizeof(Method));??
  • ????memcpy(bakMethod,?method,?sizeof(Method));??
  • ??
  • ??
  • ????//?init?info??
  • ????info->originalMethod?=?(void?*)bakMethod;??
  • ????info->returnType?=?(void?*)dvmGetBoxedReturnType(bakMethod);??
  • ????info->paramTypes?=?dvmGetMethodParamTypes(bakMethod,?info->methodSig);??
  • ??
  • ??
  • ????//?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);??
  • ??
  • ??
  • ????return?0;??
  • }??

  • 然后是method_handler的實現,這個方法是所有java方法的跳轉函數,所以在這里可以注冊callback,不過這部分邏輯我沒有做上,有興趣的朋友可以加上。

    [cpp] view plain copy
  • STATIC?void?method_handler(const?u4*?args,?JValue*?pResult,?const?Method*?method,?struct?Thread*?self){??
  • ????HookInfo*?info?=?(HookInfo*)method->insns;?//get?hookinfo?pointer?from?method-insns??
  • ????LOGI("entry?%s->%s",?info->classDesc,?info->methodName);??
  • ??
  • ??
  • ????Method*?originalMethod?=?reinterpret_cast<Method*>(info->originalMethod);??
  • ????Object*?thisObject?=?(Object*)args[0];??
  • ??
  • ??
  • ????ArrayObject*?argTypes?=?dvmBoxMethodArgs(originalMethod,?args?+?1);???
  • ????pResult->l?=?(void?*)dvmInvokeMethod(thisObject,?originalMethod,?argTypes,?(ArrayObject?*)info->paramTypes,?(ClassObject?*)info->returnType,?true);??
  • ??
  • ??
  • ????dvmReleaseTrackedAlloc((Object?*)argTypes,?self);??
  • }??


  • 最后通過dvmInvokeMethod就可以直接調回原來的函數了。

    最后

    寫這個代碼,主要是因為我在工作中要注入到某個系統進程,然后要hook java中的某些方法,但用cydia和xposed感覺太笨重了,特別是xposed,里面的很多參數的boxed/unboxed都是通過jni模塊自動轉換的,整個框架已經離不開dex文件了。

    所以才想自己實現一套純本地的java hook代碼,而《注入安卓進程,并Hook java世界的方法》所介紹的方法,我感覺用起來不太方便,跟cydia和xposed兩個框架的主要區別就是缺少了一個“中轉函數”,所以而有了本碼。

    代碼我上傳到github,目前只有java hook,我打算把目前的hook技術都集成到這里,包括inline hook, elf hook等等。


    原文地址:?http://blog.csdn.net/l173864930/article/details/39667355

    總結

    以上是生活随笔為你收集整理的Android Hook Java的的一个改进版本的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。