


function dump_so() {
Java.perform(function() {
var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
var dir = currentApplication.getApplicationContext().getFilesDir().getPath();
var libso = Process.getModuleByName("libil2cpp.so");
var file_path = dir + "/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + ".so";
var file_handle = new File(file_path, "wb");
if (file_handle && file_handle != null) {
Memory.protect(ptr(libso.base), libso.size, 'rwx');
var libso_buffer = ptr(libso.base).readByteArray(libso.size);
file_handle.write(libso_buffer);
file_handle.flush();
file_handle.close();
console.log("[dump]:", file_path);
}
});
}
var isCalled = false;
function hookdlopen() {
var dlopen = Module.findExportByName(null, "dlopen");
Interceptor.attach(dlopen, {
onEnter: function (args) {
var path = args[0].readCString();
if (path && path.indexOf('libil2cpp.so') !== -1) {
this.path = path;
}
},
onLeave: function (retval) {
if (this.path && this.path.indexOf('libil2cpp.so') !== -1 && !isCalled) {
dump_so();
isCalled = true;
}
}
});
}
hookdlopen();














function print_arg(){
var libtprtaddr = Module.findBaseAddress("libtprt.so");
console.log("libtprt基址: ",libtprtaddr);
console.log("libil2cpp基址: ",Module.findBaseAddress("libil2cpp.so"));
var function_addr = libtprtaddr.add(0x1BCE3C);
Interceptor.attach(function_addr,{
onEnter:function (args) {
console.log("0x277DA0: ",Memory.readPointer(libtprtaddr.add(0x277DA0)));
},
onLeave:function (returnValue) {
}
})
}
var isCalled = false;
function hookdlopen() {
var dlopen = Module.findExportByName(null, "dlopen");
Interceptor.attach(dlopen, {
onEnter: function (args) {
var path = args[0].readCString();
if (path && path.indexOf('libil2cpp.so') !== -1) {
this.path = path;
}
},
onLeave: function (retval) {
if (this.path && this.path.indexOf('libil2cpp.so') !== -1 && !isCalled) {
print_arg();
isCalled = true;
}
}
});
}
hookdlopen();
运行后查看打印情况
function print_arg(){
var libtprtaddr = Module.findBaseAddress("libtprt.so");
var libil2cppaddr = Module.findBaseAddress("libil2cpp.so");
console.log("n");
console.log("libtprt基址:",libtprtaddr);
console.log("libil2cpp基址:",libil2cppaddr);
var function_addr = libtprtaddr.add(0x1BCA50);
var hooked = false;
Interceptor.attach(function_addr,{
onEnter:function (args) {
this.len = parseInt(this.context.x1);
},
onLeave:function (returnValue) {
if(!hooked){
hooked = true;
var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
var dir = currentApplication.getApplicationContext().getFilesDir().getPath();
var file_path = dir + "/global-metadata.dat";
var file_handle = new File(file_path, "wb");
if (file_handle && file_handle != null) {
var buffer = ptr(this.context.x0).readByteArray(this.len);
file_handle.write(buffer);
file_handle.flush();
file_handle.close();
console.log("[dump]:", file_path);
}
}
}
})
}
var isCalled = false;
function hookdlopen() {
var dlopen = Module.findExportByName(null, "dlopen");
Interceptor.attach(dlopen, {
onEnter: function (args) {
var path = args[0].readCString();
if (path && path.indexOf('libil2cpp.so') !== -1) {
this.path = path;
}
},
onLeave: function (retval) {
if (this.path && this.path.indexOf('libil2cpp.so') !== -1 && !isCalled) {
print_arg();
isCalled = true;
}
}
});
}
hookdlopen();
这里需要注意,我是测试过这个函数是第一个加载global-metadata的,所以添加了个hooked变量去控制,如果不清楚是什么时候加载global-metadata的话,可以打印this.len看看,一般来说和安装包内的大小差不多,可能会有些许差距
看看内存dump出来的global-metadta吧
function stop(){
var libtprtaddr = Module.findBaseAddress("libtprt.so");
var libil2cppaddr = Module.findBaseAddress("libil2cpp.so");
console.log("n");
console.log("libtprt基址:",libtprtaddr);
console.log("libil2cpp基址:",libil2cppaddr);
var function_addr = libil2cppaddr.add(0x1684F68);
Interceptor.attach(function_addr,{
onEnter:function (args) {
console.log(`./arm_64 -t -b ${Process.getCurrentThreadId()} rw8 ${this.context.x0.add(0x100)}`)
console.log("开始暂停");
// 暂停当前线程 10 秒
const startTime = Date.now();
while (Date.now() - startTime < 10000) {
}
console.log("恢复线程");
},
onLeave:function (returnValue) {
}
})
}
为什么hook 0x1684F68呢,因为这是在前面sub_1685100函数运行成功后的下一个地址,在刚加载完就进行hook,可以有效避免其他情况影响
frida打印为:后记这篇文章年前就准备写了,只是一直偷懒导致拖了许久。文章中写的都是我最开始尝试时用到的方法,其实还有很多地方可以进行优化,比如在定位解密函数时,是可以hook il2cpp_string_new_len这个导出函数通过打印堆栈来定位到的,当然,这个都是后话了,hook il2cpp_string_new_len并不如我原文中写的方法具体代表性,因为它完全可以自实现这个函数,只不过并没有罢了。文章写到这里其实是并没有完结的,此时使用il2cppdumper还是会报错,metadata里的数据并没有高熵了,那么有问题的地方应该就是il2cpp.so了,但是在写完这篇文章前,我已经没有在玩那个游戏了,耗费这个精力对我来说并不值得。如果评论区有知道的朋友,望不吝赐教
原文始发于微信公众号(吾爱破解论坛):某手游il2cpp逆向分析----libtprt保护
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论