首页
社区
课程
招聘
[原创]IL2cpp 无导出 il2cpp_image_get_class 和 il2cpp_image_get_class _count函数的解决方法
2021-9-28 18:22 8159

[原创]IL2cpp 无导出 il2cpp_image_get_class 和 il2cpp_image_get_class _count函数的解决方法

2021-9-28 18:22
8159

前言:

第一次发帖,请多多指教。

问题背景:

在分析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了,要是有的游戏的目标函数偏移不同就根据这个文章教程自己修改下,很简单的。

 

要是有帮助到各位,那就可以了。


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞2
打赏
分享
最新回复 (3)
雪    币: 13
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
onlythis 2021-9-29 09:18
2
0
大佬如何用frida脚本去hook游戏中的所有函数?
雪    币: 240
活跃值: (47)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
黑洞yyh 2021-9-29 10:39
3
0
扫描所有类,之后通过类扫描得到类中的所有函数,之后再用frida的attach,进行hook,就跟你hook一个函数一样,
雪    币: 13
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
onlythis 2021-9-29 19:51
4
0
大佬 能否留个联系方式?第一次用frida不太会写这种脚本
游客
登录 | 注册 方可回帖
返回