30.安卓逆向2-frida hook技术-hook So文件(获取app加载的所有模块、导入函数、导出函数、hook SO函数)
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
内容参考于:图灵Python学院
工具下载:
链接:https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwd=zy89
提取码:zy89
复制这段内容后打开百度网盘手机App,操作更方便哦
上一个内容:29.安卓逆向2-frida hook技术-逆向os文件(二)IDA工具下载和使用
如下图现在有一个nativeSum的c代码
然后使用ida反编译它的so文件,然后搜索nativeMessage方法
然后开始Frida hook So代码
Module.findExportByName(moduleName, exportName) 通过模块名称和导出函数名查找在内存中加载的模块,并返回导出函数的地址。
Module.getExportByName(moduleName, exportName) 通过模块名称和导出函数名获取导出函数的地址但是如果找不到指定的导出函数则会返回null。
Module.findBaseAddress(moduleName) 通过模块名称查找在内存中加载的模块,并返回模块的基址
Interceptor.attach(target, callbacks) 对目标函数进行拦截,并在函数执行前后调用相应回调函数
Interceptor.replace(target, replacement)替换目标函数的实现,将重定向到自定义的替代函数。
Memory.readPointer(address) 读取指定内存地址处的指针值。
Memory.writePointer(address, value) 向指定内存地址写入指针值。
Memory.readByteArray(address, length) 读取指定内存地址处的字节数组。
Memory.writeByteArray(address, data) 向指定内存地址写入字节数组。
Memory.protect(address, size, prot) 修改指定内存范围的保护属性,如可读、可写、可执行等
导出所有模块
function 导出模块(){var module = Process.enumerateModules();for(var i = 0; i < module.length; i++){console.log(module[i].name);// 模块名}
}
导出模块();
查找某个搜文件,打印地址和名字
function 导出模块(){var module = Process.enumerateModules();for(var i = 0; i < module.length; i++){if(module[i].name == "libnative-lib.so"){console.log(module[i].base);// 模块地址console.log(module[i].name);// 模块名}}
}
导出模块();
可以看到一个app的运行会加载很多模块,
可以看到我们自己写的 libnative-lib 模块,还可以看到 frida 的模块
列出所有导入函数(导入函数是So文件所依赖的其它So文件(库文件)中的函数)
function 导入函数(){var imports = Module.enumerateImports("libnative-lib.so");for(var i = 0; i < imports.length; i++){console.log(JSON.stringify(imports[i]));console.log(imports[i].address);}
}
导入函数()
列出所有导出函数(导出之后可以给别的模块使用)
下方是导出所有
function 导出函数(){var exports = Module.enumerateExports("libnative-lib.so");for(var i = 0; i < exports.length; i++){console.log(JSON.stringify(exports[i]));console.log(exports[i].address);}
}
导出函数()
导出java的jni函数(不管谁写的,只要用了jni它就会以java开头,这是写jni的规定,也就是说自己写的so文件里的函数就会以java开头)
function 导出函数(){var Exports = Module.enumerateExports("libnative-lib.so");for(var i = 0; i < Exports.length; i++){// 只要以java开头的就是jni的函数if(Exports[i].name.includes("Java")){console.log(JSON.stringify(Exports[i]));}}
}
导出函数()
hook so方法,需要先得到方法的地址上图中可以得到,下面用另一种方式得到
function hookSo函数(){/*** findExportByName函数用来在指定so文件中查找一个函数的地址* libnative-lib.so 文件名* Java_com_luoge_com_MainActivity_nativeMessage so文件中的函数名*/var addr = Module.findExportByName("libnative-lib.so","Java_com_luoge_com_MainActivity_nativeMessage");console.log(addr);Interceptor.attach(addr,{// 函数执行前onEnter: function(args){console.log("函数调用");},// 函数执行后onLeave: function(retval){console.log("函数返回:", retval);}})}
hookSo函数();
可以看到它返回的不是中文,它是一个地址
我们的so返回的是,是一个String类型,需要处理一下
如下图代码,强制转成 java.lang.String
function hookSo函数(){/*** findExportByName函数用来在指定so文件中查找一个函数的地址* libnative-lib.so 文件名* Java_com_luoge_com_MainActivity_nativeMessage so文件中的函数名*/var addr = Module.findExportByName("libnative-lib.so","Java_com_luoge_com_MainActivity_nativeMessage");console.log(addr);Interceptor.attach(addr,{// 函数执行前onEnter: function(args){console.log("函数调用");},// 函数执行后onLeave: function(retval){console.log("函数返回:", retval);// 强制转成 Stringvar strres = Java.cast(retval, Java.use("java.lang.String"))console.log(strres);}})}
hookSo函数();
然后就可以了