首页
关于
案例站
tools
记录
推荐
我的B站
Search
1
安卓逆向-unidbg辅助算法还原
34 阅读
2
安卓逆向-Bilibili播放量接口
29 阅读
3
JS逆向-知网滑块
21 阅读
4
安卓逆向-五菱白盒AES
16 阅读
5
安卓逆向-瑞幸咖啡白盒AES
14 阅读
JS逆向
安卓逆向
小程序逆向
登录
Search
标签搜索
安卓逆向
JS逆向
密码学
unidbg
sana
累计撰写
12
篇文章
累计收到
6
条评论
首页
栏目
JS逆向
安卓逆向
小程序逆向
页面
关于
案例站
tools
记录
推荐
我的B站
搜索到
12
篇与
的结果
2024-07-07
安卓逆向-Native层相关HOOK
一、Native层相关hook1. hook_so层hook_so层只需要得到它的函数地址,有函数地址就能hook与主动调用,而得到函数地址的方式有两种;1.1 方式一通过frida提供的api来得到,该函数必须有符号的才可以;有符号是指此函数是否出现在导出、导入、符号表里;1.2 方式二通过计算得到地址:so基址+函数在so中的偏移[+1](32位+1)2. 各种枚举2.1 枚举导入表通过枚举导入表,可以得到出现在导入表中的函数地址;(enumerateImports)var imports = Module.enumerateImports("libifeng_secure.so"); // console.log(JSON.stringify(imports[0])) for (var i = 0; i < imports.length; i++) { // if (imports[i].name == "atoi") { // console.log(JSON.stringify(imports[i])); console.log('导入函数名--->>>',imports[i].name); console.log('导入函数地址--->>>',imports[i].address); console.log('-----------------------------------------------------------------') // break; // } } 以某so为例,得到的结果如下:2.2 枚举导出表通过枚举导出表,可以得到出现在导出表中的函数地址,与导入表同理,api不同;(enumerateExports)var imports = Module.enumerateExports("libifeng_secure.so"); // console.log(JSON.stringify(imports[0])) for (var i = 0; i < imports.length; i++) { // if (imports[i].name == "atoi") { // console.log(JSON.stringify(imports[i])); console.log('导出函数名--->>>',imports[i].name); console.log('导出函数地址--->>>',imports[i].address); console.log('-----------------------------------------------------------------') // break; // } }以某so为例结果如下:2.3 枚举符号表通过枚举符号表,可以得到出现在符号表中的函数地址;var symbols = Module.enumerateSymbols("libifeng_secure.so"); // console.log(JSON.stringify(symbols[0])) for (var i = 0; i < symbols.length; i++) { console.log('符号表函数名--->>>',symbols[i].name); console.log('符号表函数地址--->>>',symbols[i].address); console.log('-----------------------------------------------------------------') }2.4 枚举模块通过枚举模块,再枚举模块里面的导出表,可以快速找到某个导入函数出自哪个so;// 枚举进程中已加载的模块 var modules = Process.enumerateModules(); var module = modules[0].enumerateExports() for(let i = 0; i < module.length; i++){ console.log('枚举进程函数名--->>>',module[i].name); console.log('枚举进程函数地址--->>>',module[i].address); console.log('-----------------------------------------------------------------') } // console.log(JSON.stringify(modules[0].enumerateExports()));通过枚举模块得到的是一个数组,取第一个后就可以调用上述三个方法;3. hook导出函数在so导出表里的函数,可以通过frida提供的api来获取函数地址,Module.findExportByName("xxxx.so", "add"),函数名以汇编中出现的为准;// 导出函数的hook var funcAddr = Module.findExportByName("libencryptlib.so", "_ZN7MD5_CTX11MakePassMD5EPhjS0_"); console.log('函数地址--->>>',funcAddr); Interceptor.attach(funcAddr, { onEnter: function (args) { console.log("funcAddr onEnter args[1]: ", hexdump(args[1])); console.log("funcAddr onEnter args[2]: ", args[2].toInt32()); this.args3 = args[3]; }, onLeave: function (retval) { console.log("funcAddr onLeave args[3]: ", hexdump(this.args3)); } });在这里以口袋48为例:在这里我们的前置条件是,传了三个参数,这里初始打印第三个参数时,发现结果全是0,这里大概就是一个缓冲区,这里是因为C语言里,非常喜欢将参数当作返回值使用,那么这里我们就需要在离开的时候再读取内存;this.args3 = args[3]; console.log("funcAddr onLeave args[3]: ", hexdump(this.args3));在这里我们知道它是MD5,我们对比一下结果;可以发现与hook到的结果是一致的;4. 获取模块基址在此的前提是,我们需要的函数不在三个表里,我们就没办法直接使用frida提供的api来获取函数地址,在此需要计算它的函数地址;计算公式如下:so基址+函数在so中的偏移[+1] 32位则 +1因此,我们需要先得到so基址,也就是模块基址;4.1 findModuleByName使用findModuleByName时,指明so文件即可,得到的是一个module对象,可以进行转换,也可以直接.base取地址;var module1 = Process.findModuleByName("libencryptlib.so"); console.log("module1对象--->>>",JSON.stringify(module1)); console.log("module1基址--->>>", module1.base);直接.base取的就是基址;4.2 getModuleByName与findModuleByName类似,得到的也是一个对象;var module2 = Process.getModuleByName("libencryptlib.so"); console.log("module2对象--->>>",JSON.stringify(module2)); console.log("module2基址--->>>", module2.base);结果如下:4.3 findBaseAddress(推荐)与前两个有所不同,这里得到的直接就是函数地址,也就是基址;var soAddr = Module.findBaseAddress("libencryptlib.so"); console.log("soAddr基址--->>>", soAddr);这里就无需再去操作,返回值就是地址;4.4 enumerateModules通过枚举所有模块,再判断是否与我们需要的模块一样,如果一致则输出地址等;var modules = Process.enumerateModules(); for(let i = 0; i < modules.length; i++){ if(modules[i].name == "libencryptlib.so"){ console.log(modules[i].name + " " + modules[i].base); } }不过此方式用的较少;也可以通过地址找模块,这也就可以调用一些方法;var module = Process.findModuleByAddress(Module.findBaseAddress("libencryptlib.so")); console.log("module " + module.name + " " + module.base);5. 函数地址计算5.1 偏移上述描述可知,函数地址计算如下:so基址+函数在so中的偏移[+1] [ 32位则 +1]基址我们已经能够获取到了,那就剩下偏移;以口袋48app为例,这里我们需要找某函数的偏移;在其定义位置按下tab,则可转到汇编,界面如下:实际上这就是它的偏移,它是相对so基址的偏移;得到这个偏移就可以计算出函数地址了;在这里是否+1呢,在目前来说,大部分是64位的so,此时则不需要加,若为32位则需要加;5.2 地址计算依据公式,首先得到基址,再加上偏移;var soAddr = Module.findBaseAddress("libencryptlib.so"); console.log(ptr(soAddr).add(0xxx));soAddr得到是基址,其实也就是指针,在这里通过add (sub方法为减) 加上偏移,ptr实际上就是指针,也可以不加ptr;而add里面是一个数值,不是字符串,这里是十六进制,则需要加上0x;何时加ptr呢,若你的soAddr为具体的数值,则需要加,如:var soAddr = Module.findBaseAddress("libencryptlib.so"); var so = 0x72777a6000; console.log("soAddr基址--->>>" + soAddr); console.log(ptr(so).add(0x1FA38)); // new NativePointer() == ptr()在一个具体的数值add时,由于不是指针,则无法调用add方法,加上ptr即可,也是同样可以得到地址的;6. hook任意函数根据上述条件,我们已经可以hook任意的函数了,得到一个地址即可;var soAddr = Module.findBaseAddress("libencryptlib.so"); // var so = 0x72777a6000; console.log("soAddr基址--->>>" + soAddr); // console.log(ptr(so).add(0x1FA38)); // new NativePointer() var funcAddr = soAddr.add(0x1FA38); console.log("funcAddr函数地址--->>>" + funcAddr); Interceptor.attach(funcAddr, { onEnter: function (args) { console.log("funcAddr onEnter args[1]: ", hexdump(args[1])); console.log("funcAddr onEnter args[2]: ", args[2].toInt32()); this.args3 = args[3]; }, onLeave: function (retval) { console.log("funcAddr onLeave args[3]: ", hexdump(this.args3)); } });其余就与hook导出函数是类似的;
2024年07月07日
8 阅读
0 评论
0 点赞
2024-07-07
安卓逆向-java层加密算法
加密算法
2024年07月07日
12 阅读
0 评论
2 点赞
1
2
3