-
-
[原创]IL2cpp 无导出 il2cpp_image_get_class 和 il2cpp_image_get_class _count函数的解决方法
-
发表于:
2021-9-28 18:22
9027
-
[原创]IL2cpp 无导出 il2cpp_image_get_class 和 il2cpp_image_get_class _count函数的解决方法
前言:
第一次发帖,请多多指教。
问题背景:
在分析il2cpp游戏过程中,通过用frida脚本去hook游戏中的所有函数来观察程序的调用过程,进而快速确定目标调用的位置所在。由于一些游戏的il2cpp中的il2cpp_image_get_class 和 il2cpp_image_get_class _count函数未导出,使得通过获取导出函数来实现上述功能就不能实现,因为无法获取类信息,就得不到方法信息,也就谈不上对所有方法进行hook了。
问题分析和解决
没有导出函数,但是可以通过获取偏移去得到这个函数的指针,
如何获取函数偏移,废话不多说直接上结论。
先获取源码,源码就在unity引擎安装目录下的il2cpp文件夹中,可以自己到引擎目录中搜索。
1--分析 il2cpp_image_get_class _count
1--查看源码,通过查看源码发现 il2cpp_image_get_class _count的实现其实就是这个样子的,
1 2 3 4 | size_t Image::GetNumTypes(const Il2CppImage * image)
{
return image - >typeCount;
}
|
很容易发现,这个仅仅是读取了Il2CppImage结构体中的typeCount这个字段,
因此通过查看Il2CppImage的结构体获取typeCount在结构体中的偏移,就可以直接写出代码
1 2 3 4 5 | function temp(imageAddr)
{
return imageAddr.add(p_size * 4 ).readPointer();
}
il2cpp_image_get_class_count = temp;
|
2--分析 il2cpp_image_get_class
根据源码发现这个函数并不是仅仅是偏移就可以模仿的,源码中函数大概如下
1 2 3 4 5 6 7 | / / 通过分析发现, GetTypeInfoFromTypeDefinitionIndex
const Il2CppClass * Image::GetType(const Il2CppImage * image, size_t index)
{
size_t typeDefinitionIndex = image - >typeStart + index;
IL2CPP_ASSERT(typeDefinitionIndex < = static_cast<size_t>(std::numeric_limits<TypeDefinitionIndex>:: max ()));
return MetadataCache::GetTypeInfoFromTypeDefinitionIndex(static_cast<TypeDefinitionIndex>(typeDefinitionIndex));
}
|
分析可知最关键的是GetTypeInfoFromTypeDefinitionIndex 函数,只需要定位到这个函数是在ida中被调用的位置,即可得到函数偏移,进而模拟出il2cpp_image_get_class 这个函数,(因为是自己用所以没去判断类的数量范围)
接着我们只需要查找下GetTypeInfoFromTypeDefinitionIndex在源码中还被哪些函数调用。
查找发现,最可能的函数是ClassFromName
1 2 3 4 5 6 7 8 9 10 | Il2CppClass * Image::ClassFromName(const Il2CppImage * image, const char * namespaze, const char * name)
{
/ /
Il2CppNameToTypeDefinitionIndexHashTable::const_iterator iter = image - >nameToClassHashTable - >find(std::make_pair(namespaze, name));
if ( iter ! = image - >nameToClassHashTable - >end())
return MetadataCache::GetTypeInfoFromTypeDefinitionIndex( iter - >second);
return NULL;
}
|
这时候就要根据经验了,自然就想到了这个il2cpp函数 il2cpp_class_from_name
很幸运的是确定这个函数在ida中确实有导出,这样就直接到ida中定位到函数位置,观察函数的流程,就可以轻松确定出GetTypeInfoFromTypeDefinitionIndex函数在ida中的位置
1 2 3 4 5 6 7 | / / 这个是截取ida中ClassFromName的部分代码,可以发现
sub_D6EC58(&v16);
if ( v12 = = v17 )
result = 0 ;
else
result = sub_D35254( * (_DWORD * )(v12 + 12 ));
return result;
|
最终确定 sub_D35254 函数便是我们要找的GetTypeInfoFromTypeDefinitionIndex函数,到此就全部确定完成了。
最终的代码如下,注意这里没判断类的数量范围,自己用要判断不判断都可以
1 2 3 4 5 6 7 8 9 10 11 12 | var func_offset = 0xD35254 ;
var func = n_addr_so.add(func_offset);
var getclass = new NativeFunction(func, 'pointer' , [ 'int' ]);
LOG(`getclass :${getclass} `,LogColor.C93);
function tempgetclass(image, id )
{
/ / 源码中是有判断 id 的范围的,这里不判断,目前没影响
var idtype = image.add(p_size * 3 ).readPointer().toInt32() + id ;
return getclass(idtype);
}
/ / 最后把函数 赋值给il2cpp_image_get_class , 后面就是正常调用这个函数就行了
il2cpp_image_get_class = tempgetclass;
|
目前这个就ok了,要是有的游戏的目标函数偏移不同就根据这个文章教程自己修改下,很简单的。
要是有帮助到各位,那就可以了。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)