-
-
[原创]分享Unity游戏逆向的小工具
-
发表于:
2020-9-9 08:32
19496
-
使用 frida 的第n天
"真香 ~~~ "
今天的主题是用结合使用frida和Il2CppDumper对Unity游戏的批量断点
方便大家动态分析方法调用(指的libil2cpp.so)
欢迎Unity逆向玩家食用
Il2CppHookScripts
简单的介绍一下,主要是两个文件
这里举例的libmain.so,其他也一样,一般是断libil2cpp.so
以上为静态使用Il2CppDumperTool生成的数据来进行筛选搜索,来排查我们需要hook的函数位置,那又有小伙伴要说了,“你这玩意用起来太麻烦了,步骤好多,我们可以用贼香贼香的frida来实现动态hook吗?“
”答案当然是肯定可以的“
以下就简要的分析以下libil2cpp.so相关的东西,以目的为主,需要深入的玩家请看参考文章(参考:https://floe-ice.cn/archives/502)
调用链:
il2cpp_class_get_methods_0 -->SetupMethods--> SetupMethodsLocked
先在导出函数看看il2cpp_class_get_methods_0
参见函数原型,三个参数(IDA识别错误的两个参数)
这个函数的返回值就是一个MethodInfo结构体
1 2 3 4 5 6 7 8 9 10 | typedef struct MethodInfo
{
int32_t methodPointer;
int32_t invoker_method;
const char * name;
Il2CppClass * klass;
const void * return_type;
const void * parameters;
...
} MethodInfo;
|
这里会用到一个结构体Il2CppClass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | struct Il2CppClass
{
const Il2CppImage * image;
void * gc_desc;
const char * name;
const char * namespaze;
const Il2CppType * byval_arg;
const Il2CppType * this_arg;
Il2CppClass * element_class;
Il2CppClass * castClass;
Il2CppClass * declaringType;
Il2CppClass * parent;
Il2CppGenericClass * generic_class;
const Il2CppTypeDefinition * typeDefinition;
const Il2CppInteropData * interopData;
...
};
|
这两个结构体里面就包含了我们Hook需要的基本信息了
所以我们直接Hook
这张图是il2cpp_class_get_methods_0的返回值,结合上面的结构体去看
下面咋们就直接给出稍微整理后的Hook的结果
第一列是真实运行时候的地址,第二列是so里面的地址,还有就是函数名,这就相当于有了函数符号表了鸭,回到主题,hook位置我们可以在这个时候去筛选名称进行hook,这还是蛮方便的 ~
附上frida代码,可以自行尝试:
(ps:记得在hook dlopen判断so加载哦,第一时间hook)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | function hook(){
var p_size = Process.pointerSize
var soAddr = Module.findBaseAddress( "libil2cpp.so" )
Interceptor.attach(Module.findExportByName( "libil2cpp.so" , "il2cpp_class_get_methods" ),{
onEnter:function(args){
},
onLeave:function(ret){
console.error( "--------------------------------------------------------" )
console.log(hexdump(ret,{length: 16 }))
console.log( "methodPointer => \t" + ret.readPointer() + "\t ===> \t" + ret.readPointer().sub(soAddr))
console.log( "invoker_method => \t" + ret.add(p_size * 1 ).readPointer() + "\t ===> \t" + ret.add(p_size * 1 ).readPointer().sub(soAddr))
console.log( "MethodName => \t\t" + ret.add(p_size * 2 ).readPointer().readCString())
var klass = ret.add(p_size * 3 ).readPointer()
console.log( "namespaze => \t\t" + klass.add(p_size * 3 ).readPointer().readCString() + "."
+ klass.add(p_size * 2 ).readPointer().readCString())
}
})
}
|
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-5-31 17:28
被唱过阡陌编辑
,原因: