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

歡迎訪問 生活随笔!

生活随笔

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

Android

hook java android_Android Hook Java的的一個改進版本

發布時間:2023/12/10 Android 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hook java android_Android Hook Java的的一個改進版本 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Hook Java的的一個改進版本

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

改進點一:更簡單地修改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("[*]?%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,不過這部分邏輯我沒有做上,有興趣的朋友可以加上。

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(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等等。

總結

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

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