所在的位置: mysql >> mysql资源 >> Android原创Android1

Android原创Android1

北京最好皮肤科医院 http://baidianfeng.39.net/a_yqyy/160214/4770025.html

作者论坛账号:CIBao

前言[toc]

对于自动化hookIl2cpp的模块来说,dlopen的hook相当于一个大门,没有该大门口,一切都是纸上谈兵

在armabi-v7a上hookdlopen,轻松的不要不要的,甚至借用一下virtual系列app的va++核心提供的hook_dlopen函数的接口都行

可是到了aarch64这里,找了一圈,能用的hook构件也就一枚And64InlineHook,而且源项目好像还得自己手动修一下才能使用....(可惜whale不支持安卓10,原hookzz的Dobby也木大)

好了有hook构件了,但是我看了一圈主流的VirtualApp商业授权做出来的虚拟多开系列软件,基本上都没实现aarch64的hook_dlopen,有的实现了却没有给调用,自己去调用的话就会卡死(还想借鉴一下方案,逃个课先)

环境预习

测试平台机型:红米K30-4G,已Root系统:miui11,android-10

看雪上看到的一篇文章:Android9.0hookdlopen问题虽然半年前就看到这篇文章,但是基本上在看天书,现在拿出来看了一圈,关键实现就是这里虽然我看不懂什么LR寄存器什么的,但是唯独看懂这第三个参数强制赋值为dlerror函数的函数地址,以达到越过系统的限制

而关于那所谓的系统限制,就是在安卓7开始,系统就禁止用户APP打开/读取部分系统库文件,所以直接dlopenlinker会直接失败,具体可以使用dlerror()函数查看原因(懒不贴图了)

初步尝试Hook反汇编libdl.so

貌似安卓9开始,dlopen就由libdl.so库进行导入,反汇编看看

看了一下导出函数,也就只有两个函数涉及到dlopen

让我康康这个dlopen长什么样!

中间的.__loader_dlopen是个跳板

最终指向的是got表的导出变量__loader_dlopen

康康__loader_dlopen

步骤很简单

加载libdl.so

使用dlsym()获取__loader_dlopen

打印该值,顺便看看该内存所在maps的何处

LOGE("pid:%d",getpid());void*libdl_handle=dlopen("libdl.so",RTLD_NOW);LOGE("libdl_handle:%p",libdl_handle);void*__loader_dlopen_addr=dlsym(libdl_handle,"__loader_dlopen");LOGE("__loader_dlopenat:%p",__loader_dlopen_addr);

先查看logcat输出__loader_dlopen的值为0xf11c

使用adbshell去查看对应的内存区段

adbshellsu#升级为root用户cat/proc/目标pid/maps

跑到linker64里去了,把文件提取出来反汇编,顺便先把这__loader_dlopen的偏移值算出来0xf11c-0x=0xC

反汇编linker64

利用刚刚算出来的偏移,转跳后发现指向的是linker64里的__loader_dlopen函数

淦ta

直接一套组合拳打在__loader_dlopen函数上!

//定义原型void*(*orig___loader_dlopen)(constchar*,int,constvoid*)=nullptr;void*new___loader_dlopen(constchar*filename,intflags,constvoid*caller_addr){void*handle=orig___loader_dlopen(filename,flags,caller_addr);LOGE("LoadedLib:{%s}:%p",filename,handle);returnhandle;}//执行hookLOGE("pid:%d",getpid());void*libdl_handle=dlopen("libdl.so",RTLD_NOW);LOGE("libdl_handle:%p",libdl_handle);void*__loader_dlopen_addr=dlsym(libdl_handle,"__loader_dlopen");LOGE("__loader_dlopenat:%p",__loader_dlopen_addr);A64HookFunction(__loader_dlopen_addr,(void*)new___loader_dlopen,(void**)orig___loader_dlopen);

然后TM就蹦了!

骚操作Hook各种骚操作(木大)

一开始以为是hook构件出问题,各种log查看后来试试whale,但这玩意不支持安卓10(淦)然后试试直接dlopen直接加载libil2cpp.so,也木大尝试直接加载linker64再去hook,但这玩意直接被限制,读取都做不到一天下来,都要放弃了,突然想到一个骚主意,再试试吧

解析转跳指令

__loader_dlopen函数中实际上进行dlopen的是该函数

不过由于没法进行加载linker64文件,正常手段根本获取不到这玩意(virtualApp的解析用上了open函数,但是linker64文件无法被加载...木大)

不过好在我有解析过Bxx指令的经验相关文章:B与BL跳转指令目标地址计算方法(aarch64无需再+8)

关键逻辑就是(手动计算时,注意大小端转换!人话就是,字节倒序才是内存中实际的样子!)

指令进行左移8位(2字节)去掉转跳指令

右移8位,高位空缺填补回去

左移2位,获得实际的转跳偏移

合并到一起就变成了

//提取B指令的偏移!!指令为4字节,一定要用对应的数据类型#defineExtract(symbol)(*(int32_t*)(symbol)86)测试看看

计算目标指令的偏移(目标指令地址-函数头地址=偏移)0x-0xC=0x44

上代码!

//提取B指令的偏移#defineExtract(symbol)(ulong)(*(int32_t*)(symbol)86)//内存偏移templateclassTinlineTMemoryOff(void*addr,ulongoff){return(T)((char*)addr+off);}//修正B指令转跳templatetypenameTinlineTAmend_Bxx(Tsymbol){returnMemoryOffT((void*)symbol,Extract(symbol));}//打印autob_do_dlopen=MemoryOffvoid*(__loader_dlopen_addr,0x44);LOGE("hex:%x",*(int32_t*)b_do_dlopen);autodo_dlopen=Amend_Bxx(b_do_dlopen);LOGE("do_dlopen:%p",do_dlopen);

让我康康!

指令是没错了,解析也正常,看看打印出来的地址是否正确0xc4-0x=0x3C2C4

完美!!

进行Hook

直接提着地址进行hook!

//源函数声明void*(*_DlopenV26)(constchar*,int,int,int)=nullptr;void*DlopenV26(constchar*name,intflag1,intflag2,intflag3){void*handle=_DlopenV26(name,flag1,flag2,flag3);if(handle!=nullptr)LOGE("LoadedLib:{%s}:%p",name,handle);returnhandle;}//hookA64HookFunction(do_dlopen,(void*)DlopenV26,(void**)_DlopenV26);

终于成功!!

关于Bxx指令偏移

目前只反编译过红米K30-4G,红米K20Pro的linker64文件偏移均为0x44,其他机型的linker64文件建议自行反编译看看因为用的是骚操作,能用就已经算不错了T_T

总结

本方法算是笨方法,不过总算有个门能让我踏进aarch64的世界了有点诡异的是,不知为何hook__loader_dlopen函数会奔溃理论上Bxx指令的偏移都是0x44,源码的实现都应该一样的至于其他安卓版本....手头上就只有安卓10啊,有心无力...

--官方论坛




转载请注明:http://www.aierlanlan.com/rzgz/123.html