Unity Refection

问题

unity 版本不同导出函数也有些不同,所以有时候借助导出函数去遍历class或者method就会出问题,但是mscorlib总是有的,也就是说使用反射总是可行的

测试背景

  1. 这里使用2021.3版本的unity头文件作为示例,具体更多更完整的可以参考 这个git项目
  2. 环境使用 frida动态调用测试 和 c++静态实现

实现

按照 Perfare大佬的项目 Zygisk-Il2CppDumper 逻辑

  1. 拿到domain和assemblies
Il2CppDomain* domain = il2cpp_domain_get();
size_t size = 0;
const Il2CppAssembly** assemblies = il2cpp_domain_get_assemblies(domain, &size);
  1. 我们需要依旧是常规获取 core lib
const Il2CppImage* corlib = il2cpp_get_corlib(); // 拿到 mscorlib
  1. 然后是常规方式使用导出函数去拿到我们要用到的类方法
    // System.Reflection.Assembly → public static Assembly Load(string assemblyString)
    // System.Type → public virtual Type[] GetTypes()
Il2CppClass* assemblyClass = il2cpp_class_from_name(corlib, "System.Reflection", "Assembly");
const MethodInfo* assemblyLoad = il2cpp_class_get_method_from_name(assemblyClass, "Load", 1);
const MethodInfo* assemblyGetTypes = il2cpp_class_get_method_from_name(assemblyClass, "GetTypes", 0);
  1. 两次遍历拿到classtype
foreach assemblies
  const Il2CppImage* image = il2cpp_assembly_get_image(assemblies[i]);
  const char* image_name = il2cpp_image_get_name(image); // === image->name
  Il2CppArray* reflectionTypes = ((Assembly_GetTypes_ftn) assemblyGetTypes->methodPointer)(reflectionAssembly, nullptr)
  foreach reflectionTypes 
     Il2CppClass* klass = il2cpp_class_from_system_type((Il2CppReflectionType *) items[j]);
     const Il2CppType* type = il2cpp_class_get_type(klass);
  endforeach
endforeach

写了小段代码来验证

  • public static Assembly Load(string assemblyString) 返回值为C#中的System.Reflection.Assembly,在内存中实际上为 Il2CppReflectionAssembly*
  • public virtual Type[] GetTypes() 返回值为C#中的 System.Type, 实际上为 Il2CppReflectionRuntimeType*
[MI 8::XXX ]-> i()
 --------------------------------------------------------------
| List Images { assembly -> image -> classCount -> imageName } |
 --------------------------------------------------------------
[*] 0xb637a300 -> 0xc1bdaf10    3       __Generated
[*] 0xb6379080 -> 0xc1bda258    922     Assembly-CSharp
[*] 0xb6379a40 -> 0xc1bda90c    6       Coffee.UIParticle
[*] 0xb6379fc0 -> 0xc1bdacd4    5       DelaunayER
[*] 0xb6379140 -> 0xc1bda2dc    107     EasyRoads3Dv3
[*] 0xb637a000 -> 0xc1bdad00    8       Google.Play.Review
[*] 0xb6379f80 -> 0xc1bdaca8    15      Google.Play.Core
[*] 0xb6379b00 -> 0xc1bda990    12      Google.Play.Common
[*] 0xb6379380 -> 0xc1bda468    85      Mono.Security
[*] 0xb6379000 -> 0xc1bda200    1627    mscorlib
[*] 0xb6379200 -> 0xc1bda360    305     Newtonsoft.Json
...

[MI 8::XXX ]-> callFunction(find_method("mscorlib", "Assembly", "Load", 1), allocUStr("mscorlib"))
"0xc2c9daf0"
[MI 8::XXX ]-> seeHexA(0xc2c9daf0)
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
c2c9daf0  80 2e b9 c1 00 00 00 00 00 90 37 b6 00 00 00 00  ..........7.....
c2c9db00  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
c2c9db10  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
c2c9db20  00 00 00 00 00 00 00 00 00 5f 81 bf 00 00 00 00  ........._......

typedef struct Il2CppReflectionAssembly
{
    Il2CppObject object;
    const Il2CppAssembly *assembly;
    Il2CppObject *resolve_event_holder;
    Il2CppObject *evidence;
    Il2CppObject *minimum;
    Il2CppObject *optional;
    Il2CppObject *refuse;
    Il2CppObject *granted;
    Il2CppObject *denied;
    bool from_byte_array;
    Il2CppString *name;
} Il2CppReflectionAssembly;

参考上述内容 并结合结构体即可看出Load调用后返回的
*(对比const Il2CppAssembly *assembly的值)*
System.Reflection.Assembly === Il2CppReflectionAssembly*

代码中这个类型 mscorlib.System.Type 是C++中的这个结构体(被强转为这个) Il2CppReflectionType* , 但是实际上它是这个类型 Il2CppReflectionRuntimeType, 是属于 Il2CppReflectionType 的子类,所以这样向上转型也没问题,我这里简单的实现了一个 showTypeParent 来验证这个说法

↓ showTypeParent 的结果 ↓

Object(0xbf2daf60) <--- MemberInfo(0xbf2da920) <--- Type(0xbf2da960) <--- TypeInfo(0xa9a37960) <--- RuntimeType(0xc4224680)

// 参考这两个结构体
// Il2CppReflectionRuntimeType 持有 Il2CppReflectionType 而不是 Il2CppReflectionType*
// 同时补充了一些成员变量,所以这明显就是一个继承关系 ↓

typedef struct Il2CppReflectionType
{
    Il2CppObject object;
    const Il2CppType *type;
} Il2CppReflectionType;
typedef struct Il2CppReflectionRuntimeType
{
    Il2CppReflectionType type;
    Il2CppObject* type_info;
    Il2CppObject* genericCache;
    Il2CppObject* serializationCtor;
} Il2CppReflectionRuntimeType;
typedef struct Il2CppObject
{
    union
    {
        Il2CppClass *klass;
        Il2CppVTable *vtable;
    };
    MonitorData *monitor;
} Il2CppObject;
  1. 根据目前的信息已经拿到了

这两个类下的方法很多相似的基本就类似于没有复写的虚函数


il2cpp:0115D224                               System.Type$$.ctor                      ; CODE XREF: il2cpp:01058D80↑p
il2cpp:0115D224                               ; __unwind {
il2cpp:0115D224 00 10 A0 E3                   MOV             R1, #0
il2cpp:0115D228 D6 DB FB EA                   B               System.Reflection.MemberInfo$$.ctor

il2cpp:0115D234                               System.Type$$GetType
il2cpp:0115D234 00 10 A0 E3                   MOV             R1, #0
il2cpp:0115D238 10 E8 00 EA                   B               System.Object$$GetType

il2cpp:0115D234                               System.Type$$GetType                    ; CODE XREF: il2cpp:01021D24↑p
il2cpp:0115D234                                                                       ; il2cpp:0116F408↓p
il2cpp:0115D234 00 10 A0 E3                   MOV             R1, #0
il2cpp:0115D238 10 E8 00 EA                   B               System.Object$$GetType

再看看一个比较常使用的方法
public virtual bool get_IsEnum() @ 0x115D9A0

标题

参考文章

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、目标 很多时候App加密本身并不难,难得是他用了一套新玩意,天生自带加密光环。例如PC时代的VB,直接ida的...
    奋飞安全阅读 2,513评论 0 1
  • 一:什么是协同程序?答:在主线程运行时同时开启另一段逻辑处理,来协助当前程序的执行。换句话说,开启协程就是开启一个...
    CrixalisAs阅读 2,101评论 1 7
  • Using .NET 4.x in Unity 设置的方法: 原贴地址【Unity - Manual: .NET ...
    昵称违法阅读 8,491评论 0 0
  • 一:什么是协同程序? 答:在主线程运行时同时开启另一段逻辑处理,来协助当前程序的执行。换句话说,开启协程就是开启一...
    好怕怕阅读 3,937评论 2 23
  • 代码总览 在Unity打包过程中IL2CPP会生成il2cpp代码。生成的目录是Temp/StagingArea/...
    塘朗山小钻风阅读 5,650评论 0 1