由于需要对Adnroid手游游合规检测,即需要识别游戏是否展示“游戏协议声明”,因此需要提取游戏组件内相关原生组件文本。 由于目前Android手游主要以Unity引擎为主,因此首先尝试切入Unity引擎,获取原生组件通杀方案。
首先Unity开发语言是C#, 但是由于起初C#生态并没有跨平台支持(真的瓜这决策...),然而Unity又需要跨平台,因此早年间,为了兼容C#和跨平台需求,Unity自己重写了一套C#解释引擎,并且完全支持原生C#语法。 C#作为虚拟机语言,原生是提供了“反射”功能,所以Unity引擎作为C#解释器,也必然支持反射功能,无论是使用mono编译还是il2cpp编译,他都会支持“反射”。
因此我们的突破点,便是这个“反射”。 使用反射,即可获取C#中任何类、字段、属性、方法等所有信息,因此也可以获取Unity组件信息,获取到组件实例信息 ,就可以对其做任何读写操作 。
同时反射机制,相对于使用其他的hook机制,反射可以为我们带来更强的通用性和版本兼容性。
由于目前很多游戏考虑到安全性问题,一般都使用相对安全点的“il2cpp”编译模式,因此接下来的案例,也是在il2cpp基础上做分析。
il2cpp是将C# IL(.net平台一种中间语言)转为C++并编译为native,因此这种模式下,反射接口和直接使用C#的反射接口使用方式不太一样,但是大致流程还是差不多。
所以接下来,主要是要找到和整理native模式下,函数的定位以及组合规则。
注意 :以下有些备注可能不准确,可以作为意会和参考,因为确实有点词穷(理解不够深........), 另外以是伪代码,着重描述核心的底层接口脉络,详细代码,会放在最后。
以上就是读取一个组件,所涉及的核心接口,以及组合方式。 当然不同组件,还会有一些其他接口涉及,但是也是依葫芦画瓢,根据函数名字大概就能推断出什么含义。
既然能获取所有实例对象和信息,并且具备读写能力,那么理论上,可以基于这套思路完成无源码修改游戏,以及基于组件级的脚本点击............... 另外需要提取游戏内资源,此方案也可以绕过大部分加固......
这个方案是完全依赖多个关键函数的symbol,目前听说(没实际了解)一些加固厂商,会将这些symbol抹除,如果抹除就通过函数特诊码搜索函数位置,但是这样兼容性有个问题,准确性也是个问题.......
更多il2cpp反射api定义,在il2cpp-api-functions.h
。
il2cpp的结构体定义在il2cpp-class.h
。
完整源码项目文件是_agent.js
_agent.js中的UnityApi
类,封装了一部分反射api。
_agent.js中的Example类是案例:
Zygisk-Il2CppDumper
通过Zygisk-Il2CppDumper源码,偶然间看到相关代码,才获得灵感进一步深挖“反射”这条思路
百度网盘:
/
/
假定一个TextMeshProGUI实例对象
let text_mesh_pro_gui_instance;
/
/
获取进程域
/
/
*
*
核心函数:il2cpp_domain_get
*
*
let domain
=
il2cpp_domain_get()
/
/
获取所有程序集。类似C
/
/
*
*
核心函数:il2cpp_domain_get_assemblies
*
*
let assmblies
=
il2cpp_domain_get_assemblies(domain)
let assembly_images
=
[];
for
(let i
=
0
;i<assmblies.size;i
+
+
){
assm
=
assmblies[i];
/
/
*
*
核心函数:il2cpp_assembly_get_image
*
*
images.add(il2cpp_assembly_get_image(assm))
}
/
/
获取指定程序集反射image对象
/
/
*
*
核心函数:il2cpp_image_get_name
*
*
let target_assembly_image
=
assembly_images
.
filter
(assembly_img
=
>il2cpp_image_get_name(assembly_img)
=
=
"Unity.TextMeshPro.dll"
)
.pop()
/
/
通过C
/
/
TextMeshProGUI类型组件限定名是
"TMPro.TextMeshProGUI"
,并属于
"Unity.TextMeshPro.dll"
程序集
/
/
*
*
核心函数:il2cpp_class_from_name
*
*
let TextMeshPro_class
=
il2cpp_class_from_name(target_assembly_image,
"TMPro"
,
"TextMeshProGUI"
)
/
/
获取文本字段反射信息
/
/
TextMeshProGUI存储文本的字段是“m_text”
/
/
*
*
核心函数:il2cpp_class_get_field_from_name
*
*
m_text_field
=
il2cpp_class_get_field_from_name(TextMeshPro_class,
"m_text"
)
/
/
读取字段内容实例,实例是个结构体
/
/
*
*
核心函数:il2cpp_field_get_value_object
*
*
let str_content_struct
=
il2cpp_field_get_value_object(m_text_field,text_mesh_pro_gui_instance);
/
/
读取结构体内字符串内容,这里就是获取最终C版本的字符串
/
/
*
*
核心函数:func_il2cpp_string_chars
*
*
content_chars
=
func_il2cpp_string_chars(str_content_struct)
/
/
假定一个TextMeshProGUI实例对象
let text_mesh_pro_gui_instance;
/
/
获取进程域
/
/
*
*
核心函数:il2cpp_domain_get
*
*
let domain
=
il2cpp_domain_get()
/
/
获取所有程序集。类似C
/
/
*
*
核心函数:il2cpp_domain_get_assemblies
*
*
let assmblies
=
il2cpp_domain_get_assemblies(domain)
let assembly_images
=
[];
for
(let i
=
0
;i<assmblies.size;i
+
+
){
assm
=
assmblies[i];
/
/
*
*
核心函数:il2cpp_assembly_get_image
*
*
images.add(il2cpp_assembly_get_image(assm))
}
/
/
获取指定程序集反射image对象
/
/
*
*
核心函数:il2cpp_image_get_name
*
*
let target_assembly_image
=
assembly_images
.
filter
(assembly_img
=
>il2cpp_image_get_name(assembly_img)
=
=
"Unity.TextMeshPro.dll"
)
.pop()
/
/
通过C
/
/
TextMeshProGUI类型组件限定名是
"TMPro.TextMeshProGUI"
,并属于
"Unity.TextMeshPro.dll"
程序集
/
/
*
*
核心函数:il2cpp_class_from_name
*
*
let TextMeshPro_class
=
il2cpp_class_from_name(target_assembly_image,
"TMPro"
,
"TextMeshProGUI"
)
/
/
获取文本字段反射信息
/
/
TextMeshProGUI存储文本的字段是“m_text”
/
/
*
*
核心函数:il2cpp_class_get_field_from_name
*
*
m_text_field
=
il2cpp_class_get_field_from_name(TextMeshPro_class,
"m_text"
)
/
/
读取字段内容实例,实例是个结构体
/
/
*
*
核心函数:il2cpp_field_get_value_object
*
*
let str_content_struct
=
il2cpp_field_get_value_object(m_text_field,text_mesh_pro_gui_instance);
/
/
读取结构体内字符串内容,这里就是获取最终C版本的字符串
/
/
*
*
核心函数:func_il2cpp_string_chars
*
*
content_chars
=
func_il2cpp_string_chars(str_content_struct)
/
*
*
*
android框架的so接口
*
/
class
AndroidApi {
static
/
*
*
*
@returns {AndroidApi}
*
/
static get Api() {
if
(!this.
this.
}
return
this.
}
/
*
*
*
@param {InvocationListenerCallbacks} callback
*
@constructor
*
/
AttachDlopen(callback) {
let android_dlopen_ext
=
Module.findExportByName(null,
"android_dlopen_ext"
);
if
(android_dlopen_ext !
=
null) {
Interceptor.attach(android_dlopen_ext, callback);
console.log(
"找到了 android_dlopen_ext"
);
}
else
{
console.error(
"未找到 android_dlopen_ext"
);
}
let dlopen
=
Module.findExportByName(null,
"dlopen"
);
if
(dlopen !
=
null) {
Interceptor.attach(dlopen, callback);
console.log(
"找到了 dlopen"
);
}
else
{
console.error(
"未找到 dlopen"
);
}
}
}
class
UCommonUtil {
static
/
*
*
*
@
return
{UCommonUtil}
*
/
static get Api() {
if
(this.
this.
}
return
this.
}
/
*
*
*
获取il2cpp里的迭代器
*
@
return
{NativePointer}
*
/
GetEmptyIter() {
let
iter
=
Memory.alloc(Process.pointerSize);
iter
.writePointer(NULL);
return
iter
;
}
}
class
CommonUtil {
static
/
*
*
*
@
return
{CommonUtil}
*
/
static get Api() {
if
(this.
this.
}
return
this.
}
/
*
*
*
创建NativeFunction封装,用于少写两行代码,方便使用
*
@returns {NativeFunction}
*
/
NewNativeFunction(module, exportName, retType, argTypes) {
let ptr
=
module.findExportByName(exportName);
if
(ptr
=
=
null) {
console.error(`没有找到【${exportName}】`);
return
null;
}
console.log(`成功找到【${exportName}】`);
return
new NativeFunction(ptr, retType, argTypes);
}
}
/
*
*
*
unity il2cpp中的so接口
*
/
class
UnityApi {
static
static
/
*
*
*
@
type
{Module}
*
/
/
/
class
/
/
domain
/
/
assembly
/
/
image
/
/
runtime
/
/
type
/
/
field
/
/
property
/
/
object
/
/
string
constructor() {
this.
}
/
*
*
*
由于Unity Il2cpp相关接口,需要在il2cpp处加载后,
*
才能正常发现,所以需要先在合适的地方初始化,再后续使用
*
@constructor
*
/
static Init() {
if
(!this.
this.
}
}
/
*
*
*
静态暴露接口
*
@returns {UnityApi}
*
/
static get Api() {
if
(!this.
throw
"UnityApi还未初始化"
}
return
this.
}
/
/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
【API】
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
/
*
*
*
@
return
{NativePointer}
*
/
il2cpp_get_corlib() {
return
this.
}
/
*
*
*
根据类的限定名,获取
Type
信息
*
@param image_p .dll基址
*
@param namespace 命名空间
*
@param name 类名
*
@returns {NativePointer}
*
/
il2cpp_class_from_name(image_p, namespace, name) {
let ns
=
Memory.allocUtf8String(namespace);
let className
=
Memory.allocUtf8String(name);
return
this.
}
/
*
*
*
通过
class
获取
type
*
@param {NativePointer} klass
*
@
return
{NativePointer}
*
/
il2cpp_class_get_type(klass) {
return
this.
}
/
*
*
*
反射获取指定方法
*
@param {NativePointer} klass
class
句柄
*
@param {string} methodName 指定方法名
*
@param {number} argCount 参数个数
*
@
return
{NativePointer}
*
/
il2cpp_class_get_method_from_name(klass, methodName, argCount) {
let methodNameP
=
Memory.allocUtf8String(methodName);
return
this.
}
/
*
*
*
获取
class
下所有字段
*
@param {NativePointer} klass
*
@
return
{Generator<
*
, void,
*
>}
*
/
*
il2cpp_class_get_fields(klass) {
let
iter
=
UCommonUtil.Api.GetEmptyIter();
while
(true) {
let result
=
this.
if
(result.valueOf()
=
=
0
) {
break
;
}
yield
result;
}
}
/
*
*
*
获取进程域
*
@returns {NativePointer}
*
/
il2cpp_domain_get() {
return
this.
}
/
*
*
*
获取所有程序集的基址
*
@param domain
*
@
return
{{size:number,assemblies:
any
}} .dll数组(const Il2CppAssembly
*
*
)
*
/
il2cpp_domain_get_assemblies(domain) {
let size
=
Memory.alloc(
4
);
size.writeInt(
0
);
let assemblies
=
this.
return
{
size: size.readInt(),
assemblies: assemblies
}
}
/
*
*
*
获取.dll的句柄
*
@param assembly .dll信息指针
*
@
return
{NativePointer} .dll句柄
*
/
il2cpp_assembly_get_image(assembly) {
return
this.
}
/
*
*
*
获取image的name
*
@param {NativePointer} image
*
@
return
{string} image的名字
*
/
il2cpp_image_get_name(image) {
let result
=
this.
return
result.readPointer().readCString();
}
/
*
*
*
获取.dll下有多少个
class
*
@param {NativePointer} image .dll句柄
*
@
return
{number}
class
个数
*
/
il2cpp_image_get_class_count(image) {
let result
=
this.
return
result;
}
/
*
*
*
获取
class
*
@param {NativePointer} image
*
@param {number} index
*
@
return
{NativePointer}
*
/
il2cpp_image_get_class(image, index) {
return
this.
}
/
*
*
*
通过
class
获取作用域名
*
@param {NativePointer} klass
*
@
return
{string};
*
/
il2cpp_class_get_namespace(klass) {
let result
=
this.
let ns
=
ptr(result).readCString();
return
ns;
}
/
*
*
*
通过
class
获取名字
*
@param {NativePointer} klass
*
@
return
{string}
*
/
il2cpp_class_get_name(klass) {
let result
=
this.
return
ptr(result).readCString();
}
/
*
*
*
@param {NativePointer} klass
*
@
return
{NativePointer}
*
/
il2cpp_class_get_image(klass) {
return
this.
}
/
*
*
*
反射调用方法
*
@param {NativePointer} methodInfo 反射方法对象
*
@param {NativePointer} obj 方法所属实例,static为NULL
*
@param {NativePointer} params 参数数组
*
@param {NativePointer} exception 报错
*
@
return
{NativePointer}
*
/
il2cpp_runtime_invoke(methodInfo, obj, params, exception) {
return
this.
}
/
*
*
*
获取
class
的TypeInfo信息
*
@param {NativePointer}
type
*
@
return
{NativePointer}
*
/
il2cpp_class_from_type(
type
) {
return
this.
}
/
*
*
*
@param {NativePointer} klass
*
@param {string} name
*
@
return
{NativePointer}
*
/
il2cpp_class_get_field_from_name(klass, name) {
let nameP
=
Memory.allocUtf8String(name);
return
this.
}
/
*
*
*
读取字段的名字
*
@param {NativePointer} field
*
@
return
{string}
*
/
il2cpp_field_get_name(field) {
let result
=
this.
return
ptr(result).readCString();
}
/
*
*
*
@param {NativePointer} field
*
@
return
{NativePointer}
*
/
il2cpp_field_get_type(field) {
return
this.
}
/
*
*
*
获取
class
所有属性
*
@param {NativePointer} klass
*
@
return
{
*
}
*
/
*
il2cpp_class_get_properties(klass) {
let
iter
=
UCommonUtil.Api.GetEmptyIter();
while
(true) {
let result
=
this.
if
(result.valueOf()
=
=
0
) {
break
;
}
yield
result;
}
}
/
*
*
*
通过名字,获取
class
指定属性
*
@param {NativePointer} klass
*
@param {string} name
*
@
return
{NativePointer}
*
/
il2cpp_class_get_property_from_name(klass, name) {
let nameP
=
Memory.allocUtf8String(name);
return
this.
}
/
*
*
*
@param {NativePointer}
type
*
@
return
{number}
*
/
il2cpp_type_get_type(
type
) {
return
this.
}
/
*
*
*
根据反射信息,创建
Type
对象(即C
*
@param {NativePointer}
type
*
@
return
{NativePointer}
*
/
il2cpp_type_get_object(
type
) {
return
this.
}
/
*
*
*
@param {NativePointer}
type
*
@
return
{NativePointer}
*
/
il2cpp_type_get_class_or_element_class(
type
) {
return
this.
}
/
*
*
*
反射读取字段值
*
@param {NativePointer} field
*
@param {NativePointer} obj
*
@
return
{NativePointer}
*
/
il2cpp_field_get_value_object(field, obj) {
return
this.
}
/
*
*
*
获取属性的get方法(及读取属性值行为)
*
@param {NativePointer} prop
*
@
return
{NativePointer}
*
/
il2cpp_property_get_get_method(prop) {
return
this.
}
/
*
*
*
获取属性名字
*
@param {NativePointer} prop
*
@
return
{NativePointer}
*
/
il2cpp_property_get_name(prop) {
let result
=
this.
return
ptr(result).readCString();
}
/
*
*
*
获取对象大小
*
@param {NativePointer} obj
*
@
return
{number}
*
/
il2cpp_object_get_size(obj) {
return
this.
}
/
*
*
*
@param {NativePointer} obj
*
@
return
{NativePointer}
*
/
il2cpp_object_get_class(obj) {
return
this.
}
/
*
*
*
@param {NativePointer}
str
*
@
return
{string}
*
/
func_il2cpp_string_chars(
str
) {
let result
=
this.
return
ptr(result).readUtf16String();
}
/
/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
【Attach】
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
/
*
*
*
@param {InvocationListenerCallbacks} callback
*
/
Attach_il2cpp_get_corlib(callback) {
let func
=
this.
Interceptor.attach(func, callback);
}
/
*
*
*
@param {InvocationListenerCallbacks} callback
*
/
Attach_il2cpp_class_from_name(callback) {
let func
=
this.
Interceptor.attach(func, callback);
}
/
*
*
*
初始化so函数
*
/
this.
if
(!this.
console.error(
"未发现il2cppModule"
);
return
;
}
/
/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
this.
"pointer"
,
[]);
/
/
class
this.
"pointer"
,
[
"pointer"
,
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
,
"int"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
/
/
domain
this.
"pointer"
,
[]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
/
/
assembly
this.
"pointer"
,
[
"pointer"
]);
/
/
image
this.
"pointer"
,
[
"pointer"
]);
this.
"uint32"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"uint32"
]);
/
/
runtime
this.
"pointer"
,
[
"pointer"
,
"pointer"
,
"pointer"
,
"pointer"
]);
/
/
type
this.
"int"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
/
/
field
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
/
/
property
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
/
/
object
this.
"uint32"
,
[
"pointer"
]);
/
/
string
this.
"pointer"
,
[
"pointer"
]);
/
/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
}
}
/
*
*
*
懒加载包装类
*
/
class
Lazy {
/
*
*
*
@
type
{function ():
*
} value
*
/
/
*
*
*
@param {
*
} this上下文
*
@param {function ():
*
} value 实例化对象的方法回调
*
@
return
{Lazy}
*
/
static New(context,value) {
let lazy
=
new Lazy();
lazy.Value
=
value.bind(context);
return
lazy;
}
/
*
*
*
@param {function ():
*
} value
*
/
set
Value(value) {
this.
}
/
*
*
*
@
return
{
*
}
*
/
get Value() {
if
(this.
this.
}
return
this.
}
}
class
UMethodInfo {
/
*
*
*
@
type
{Lazy}
*
/
/
*
*
*
@
type
{UnityApi}
*
/
/
*
*
*
@param {
*
{
*
kalss:NativePointer,
*
methodName:string
*
argCount:number
*
}
*
}
input
*
/
constructor(
input
) {
this.
return
this.
input
.methodName,
input
.argCount);
});
}
/
*
*
*
*
@param {NativePointer} args 参数数组
*
@param {NativePointer} obj 实例对象
*
@
return
{(NativePointer |
*
)}
*
@constructor
*
/
Invoke(obj, args) {
let result
=
this.
obj, args, NULL);
return
result;
}
}
class
UDomain {
static
/
*
*
*
@
type
{NativePointer}
*
/
/
*
*
*
@
type
{{size:number,assemblies:
any
}}
*
/
/
*
*
*
@
type
{NativePointer[]}
*
/
/
*
*
*
@
type
{UnityApi}
*
/
constructor() {
this.
this.
this.
this.
}
/
*
*
*
@
return
{UDomain}
*
/
static get Api() {
if
(UDomain.
UDomain.
}
return
UDomain.
}
/
*
*
*
@
return
{NativePointer[]}
*
/
get AllAssemblyImages() {
return
this.
}
/
*
*
*
@param {string} name
*
@
return
{NativePointer}
*
/
GetAssemblyImageByName(name) {
return
this.
.
filter
(image
=
> this.
.pop()
.readPointer();
}
this.
}
this.
}
let images
=
[...Array(this.
.
map
(value
=
> ptr(this.
.
map
(assm
=
> this.
this.
}
}
/
*
*
*
@readonly
*
@enum {string}
*
/
const AssemblyName
=
{
UnityEngine:
"UnityEngine.dll"
,
UnityEngineUI:
"UnityEngine.UI.dll"
,
UnityTextMeshPro:
"Unity.TextMeshPro.dll"
,
UnityEngineCoreModule:
"UnityEngine.CoreModule.dll"
};
class
UnityUtil {
static
/
*
*
*
@
return
{UnityUtil}
*
/
static get Api() {
if
(UnityUtil.
UnityUtil.
}
return
UnityUtil.
}
/
*
*
*
获取Class
*
@param {
*
{
*
domain:UDomain,
*
assemblyName:string,
*
namespace:string,
*
klassName:string,
*
}
*
}
input
*
@
return
{NativePointer}
*
/
GetClass(
input
) {
let assemblyImage
=
input
.domain.GetAssemblyImageByName(
input
.assemblyName);
let klass
=
UnityApi.Api.il2cpp_class_from_name(assemblyImage,
input
.namespace,
input
.klassName);
return
klass;
}
/
*
*
*
获取指定类的
Type
实例
*
@param {
*
{
*
klass:NativePointer
*
}
*
}
input
*
@
return
{NativePointer}
*
/
GetTypeObj(
input
) {
let
type
=
UnityApi.Api.il2cpp_class_get_type(
input
.klass);
let typeObj
=
UnityApi.Api.il2cpp_type_get_object(
type
);
return
typeObj;
}
/
*
*
*
反射读取字符串类型字段的值
*
@param {NativePointer} field
*
@param {NativePointer} obj
*
@
return
{string}
*
/
ReadFieldWithString(field, obj) {
let valueObj
=
UnityApi.Api.il2cpp_field_get_value_object(field, obj);
let valueReal
=
UnityApi.Api.func_il2cpp_string_chars(valueObj);
return
valueReal;
}
/
*
*
*
反射读取字符串类型属性值
*
@param {NativePointer}
property
*
@param {NativePointer} obj
*
/
ReadPropertyWithString(
property
, obj) {
let getFunc
=
UnityApi.Api.il2cpp_property_get_get_method(
property
);
let valueObj
=
UnityApi.Api.il2cpp_runtime_invoke(getFunc, obj, NULL, NULL);
let valueReal
=
UnityApi.Api.func_il2cpp_string_chars(valueObj);
return
valueReal;
}
}
class
ReflectionInfoInput {
dllName;
namespace;
className;
constructor(dllName,namespace,className) {
this.dllName
=
dllName;
this.namespace
=
namespace;
this.className
=
className;
}
}
class
ReflectionBase {
get UApi(){
return
UnityApi.Api;
}
/
*
*
*
*
@
return
{function(): UDomain}
*
@constructor
*
/
get Domain(){
return
UDomain.Api;
}
}
class
UReflectionInfo extends ReflectionBase {
/
*
*
*
@
type
{ReflectionInfoInput}
*
/
/
*
*
*
实例对象
*
@
type
{NativePointer}
*
/
/
*
*
*
@
type
{Lazy}
*
/
/
*
*
*
@
type
{Lazy}
*
/
/
*
*
*
@
type
{Lazy}
*
/
/
*
*
*
@
type
{Lazy}
*
/
/
*
*
*
@
type
{Lazy}
*
/
/
*
*
*
@param {ReflectionInfoInput | NativePointer}
input
*
/
constructor(
input
) {
super
();
if
(
input
instanceof ReflectionInfoInput) {
this.
}
if
(
input
instanceof NativePointer) {
this.
}
this.
}
/
*
*
*
@
return
{NativePointer}
*
/
get Class() {
return
this.
}
get
Type
() {
return
this.
}
get Fields() {
return
this.
}
get Properties() {
return
this.
}
PropertyByName(name) {
return
this.UApi.il2cpp_class_get_property_from_name(this.Class, name);
}
/
*
*
*
@param {string} name
*
@
return
{NativePointer}
*
/
FieldByName(name) {
return
this.UApi.il2cpp_class_get_field_from_name(this.Class, name);
}
/
*
*
*
@param name 方法名字
*
@param argCount 方法个数
*
@
return
{UMethodInfo}
*
/
MethodByName(name, argCount) {
return
new UMethodInfo({
kalss: this.
methodName: name,
argCount: argCount
})
}
this.
objNotNull: this.
inputNotNull: this.
});
this.
this.
this.
this.
}
/
*
*
*
@param {
*
{
*
objNotNull:function ():
*
,
*
inputNotNull:function ():
*
*
}
*
}
input
*
@
return
{
*
}
*
/
if
(this.
return
input
.objNotNull.call(this);
}
if
(this.
return
input
.inputNotNull.call(this);
}
}
this.
objNotNull: ()
=
> Lazy.New(this, ()
=
> this.UApi.il2cpp_class_get_image(this.Class)),
inputNotNull: ()
=
> Lazy.New(this, ()
=
> this.Domain.GetAssemblyImageByName(this.
});
}
this.
}
this.
this.
this.
);
}
this.
let
type
=
this.UApi.il2cpp_class_get_type(this.Class);
return
this.UApi.il2cpp_type_get_object(
type
);
});
}
this.
}
this.
}
}
/
*
类型反射信息定义
(在此处定义好类型的反射信息,需要某类型反射信息可方便使用)
*
/
class
UTypeDefinition {
static
AssemblyName.UnityEngine,
"UnityEngine"
,
"Object"
));
AssemblyName.UnityEngine,
"UnityEngine"
,
"Behaviour"
));
AssemblyName.UnityEngineUI,
"UnityEngine.UI"
,
"Text"
));
AssemblyName.UnityTextMeshPro,
"TMPro"
,
"TextMeshProUGUI"
));
AssemblyName.UnityEngineCoreModule,
"UnityEngine"
,
"Resources"
));
/
*
*
*
@
return
{UTypeDefinition}
*
/
static get Api() {
if
(UTypeDefinition.
UTypeDefinition.
}
return
UTypeDefinition.
}
/
*
*
*
@
return
{UReflectionInfo}
*
/
get U_Object() {
return
this.
}
/
*
*
*
@
return
{UReflectionInfo}
*
/
get U_Behaviour() {
return
this.
}
/
*
*
*
@
return
{UReflectionInfo}
*
/
get U_UI_Text() {
return
this.
}
/
*
*
*
@
return
{UReflectionInfo}
*
/
get U_TextMeshProUGUI() {
return
this.
}
/
*
*
*
@
return
{UReflectionInfo}
*
/
get U_Resources() {
return
this.
}
}
class
UObject {
/
*
*
*
@
type
{Domain}
*
/
/
*
*
*
@
type
{UnityApi}
*
/
/
*
*
*
@
type
{NativePointer}
*
/
/
*
*
*
实例对象的
class
*
@
type
{UReflectionInfo}
*
/
/
*
*
*
@param {
*
{
*
obj:NativePointer,
*
}
*
}
input
*
/
constructor(
input
) {
this.
this.
}
/
*
*
*
获取组件自定义
ID
名字
*
@
return
{string}
*
/
get IDName() {
let
property
=
this.
let name
=
UnityUtil.Api.ReadPropertyWithString(
property
, this.
return
name;
}
/
*
*
*
获取类型限定名字
*
@
return
{string}
*
/
get TypeName() {
let namespace
=
this.
let className
=
this.
return
`${namespace}.${className}`;
}
/
*
*
*
@
return
{UReflectionInfo}
*
/
get InstanceReflection() {
return
this.
}
/
*
*
*
@
return
{UnityApi}
*
/
get UApi() {
return
this.
}
/
*
*
*
@
return
{Domain}
*
/
get Domain() {
return
this.
}
/
*
*
*
@
return
{NativePointer}
*
/
get ObjInstance() {
return
this.
}
this.
}
}
class
UBehavior extends UObject {
/
*
*
*
*
@param {
*
{
*
obj:NativePointer
*
}
*
}
input
*
/
constructor(
input
) {
super
(
input
);
}
}
class
UTextMeshProUGUI extends UObject {
/
*
*
*
@param {
*
{
*
obj:NativePointer
*
}
*
}
input
*
/
constructor(
input
) {
super
(
input
);
}
/
*
*
*
@
return
{string}
*
/
get TextContent() {
let field
=
UTypeDefinition.Api.U_TextMeshProUGUI.FieldByName(
"m_text"
);
let content
=
UnityUtil.Api.ReadFieldWithString(field, this.ObjInstance);
return
content;
}
}
class
UServiceBase {
/
*
*
*
@
type
{UDomain}
*
/
/
*
*
*
@
type
{UnityApi}
*
/
get UApi() {
return
this.
}
get Domain() {
return
this.
}
}
class
UIText extends UObject {
/
*
*
*
@param {
*
{
*
obj:NativePointer,
*
}
*
}
input
*
/
constructor(
input
) {
super
(
input
);
}
/
*
*
*
@
return
{string}
*
/
get TextContent(){
let
property
=
UTypeDefinition.Api.U_UI_Text.PropertyByName(
"text"
);
let content
=
UnityUtil.Api.ReadPropertyWithString(
property
, this.ObjInstance);
return
content;
}
}
/
*
*
*
搜索功能封装
*
/
class
UFind extends UServiceBase {
/
*
*
*
@
type
{UMethodInfo}
*
/
constructor() {
super
();
this.
}
/
*
*
*
获取当前界面的所有控件元素
*
@
return
{UBehavior[]}
*
/
GetCurrentAllComponent() {
let components
=
this.
let behaviors
=
components
.
map
(obj
=
> new UBehavior({
obj: obj
}));
/
/
for
(const behavior of behaviors) {
/
/
console.log(`behavior.TypeName:${behavior.TypeName}`);
/
/
}
/
/
/
/
console.log(
"----------------------"
)
/
/
/
/
for
(let behavior of behaviors) {
/
/
console.log(`
ID
Name:${behavior.IDName}
-
-
`);
/
/
}
return
behaviors;
}
/
*
*
*
@
return
{UTextMeshProUGUI[]}
*
/
GetCurrentComponentByTextMeshProUGUI() {
let objs
=
this.
let tmps
=
objs.
map
(value
=
> new UTextMeshProUGUI({
obj: value
}));
/
/
console.log(`tmps个数:${tmps.length}`)
/
/
/
/
for
(let elem of tmps) {
/
/
console.log(`tmp text:${elem.TextContent}`);
/
/
}
return
tmps;
}
/
*
*
*
@
return
{UIText[]}
*
/
GetCurrentComponentByText() {
let objs
=
this.
let texts
=
objs.
map
(value
=
> new UIText({
obj: value
}));
/
/
console.log(`UI_Text个数:${texts.length}`)
/
/
/
/
for
(let elem of texts) {
/
/
console.log(`ui text:${elem.TextContent}`);
/
/
}
return
texts;
}
/
*
*
*
获取指定类型的所有子类元素
*
@param {NativePointer} obj 实例对象
*
@param {NativePointer}
type
类型
Type
信息
*
@
return
{NativePointer[]}
*
/
/
/
构建装参数指针的数组
let argArr
=
Memory.alloc(Process.pointerSize);
argArr.writePointer(
type
);
let result
=
this.
/
/
读取数组长度
let length
=
result.add(Process.pointerSize
*
3
).readInt();
/
/
读取元素数组头
let elemArr
=
result.add(Process.pointerSize
*
4
);
let objArr
=
[...Array(length).keys()]
/
/
读取数组元素
.
map
(value
=
> ptr(elemArr).add(Process.pointerSize
*
value).readPointer());
return
objArr;
}
this.
1
);
}
}
class
AndroidApplicationContext {
static
constructor() {
this.
}
/
*
*
*
@
return
{AndroidApplicationContext}
*
/
static get Api() {
if
(AndroidApplicationContext.
AndroidApplicationContext.
}
return
AndroidApplicationContext.
}
/
*
*
*
获取路径结果:
/
data
/
app
/
包名
+
随机数
/
xx.apk
*
@
return
{string}
*
/
get getPackageCodePath() {
return
this.
}
/
*
*
*
@
return
{string}
*
/
get nativeLibraryDir() {
return
this.
}
let activityThread
=
Java.use(
"android.app.ActivityThread"
);
let currentApplication
=
activityThread.currentApplication();
this.
}
}
class
AndroidFile {
constructor(absPath) {
this.
let fileClass
=
Java.use(
"java.io.File"
);
this.
}
/
*
*
*
@
return
{boolean}
*
/
exists() {
return
this.
}
}
class
UnityEngine {
/
*
*
*
@
type
{Find}
*
/
/
*
*
*
判断是否是Unity引擎的游戏
*
@param {function (boolean)} callback
*
/
IsUnity(callback) {
/
/
此处如果不使用延迟加载,会很大概率出现无法找到context
setTimeout(()
=
> {
/
/
直接读取apk文件夹是否有libil2cpp.so判断是否unity游戏
let nativeLibraryDir
=
AndroidApplicationContext.Api.nativeLibraryDir;
let
file
=
new AndroidFile(`${nativeLibraryDir}
/
libil2cpp.so`);
callback(
file
.exists());
},
1000
);
}
/
*
*
*
Unity引擎初始化
*
@param {function (UnityEngine)} onComplete 初始化完成后回调
*
/
Init(onComplete) {
let that
=
this;
let modules
=
Process.enumerateModules();
let haveIl2Cpp
=
modules.find(value
=
> value.name
=
=
"libil2cpp.so"
);
/
/
先遍历内存,是否有il2cpp.so,没有就hook dlopen
if
(haveIl2Cpp) {
this.
}
else
{
/
/
hook so加载节点
AndroidApi.Api.AttachDlopen({
onEnter(args) {
let soPath
=
args[
0
].readCString();
/
/
判断加载文件是否存在libil2cpp.so,如果存在,接下来hook该so相关东西
this.haveIl2cpp
=
soPath.endsWith(
"libil2cpp.so"
);
},
onLeave(rv) {
if
(!this.haveIl2cpp)
return
;
/
/
发现il2cpp.so加载,延迟一小会再加载,避免so无法找到
setTimeout(()
=
> {
that.
},
2000
);
}
});
}
}
/
*
*
*
@
return
{UFind}
*
/
get Find() {
return
this.
}
UnityApi.Init();
this.
onComplete(this);
}
}
class
EngineManager {
/
*
*
*
@
return
{UnityEngine}
*
/
static GetUnityEngine(){
return
new UnityEngine();
}
}
/
/
初始化成功后,在frida cli中调用样例
/
/
Example.Print_CurrentAllComponent()
/
/
Example.Print_CurrentComponentByTextMeshProUGUI()
/
/
Example.Print_CurrentComponentByText()
class
Example {
static
/
*
*
*
方便明亮行调用,所以此处设置一个静态属性
*
@
return
{UnityEngine}
*
/
static get UnityEngine() {
return
Example.
}
/
*
*
*
初始化成功后,在frida cli中调用样例
*
Example.Print_CurrentAllComponent()
*
/
static Print_CurrentAllComponent(){
let uBehaviors
=
Example.UnityEngine.Find.GetCurrentAllComponent();
for
(let item of uBehaviors) {
console.log(`组件类型名字:${item.TypeName}
-
-
-
组件
ID
名:${item.IDName}`);
}
console.log(`Behavior子类个数:${uBehaviors.length}`);
}
/
*
*
*
初始化成功后,在frida cli中调用样例
*
Example.Print_CurrentComponentByTextMeshProUGUI()
*
/
static Print_CurrentComponentByTextMeshProUGUI(){
let uTextMeshProUGUIS
=
Example.UnityEngine.Find.GetCurrentComponentByTextMeshProUGUI();
for
(let item of uTextMeshProUGUIS) {
console.log(`TextMeshProUGUI文本内容:【${item.TextContent}】`);
}
console.log(`TextMeshProUGUI子类个数:${uTextMeshProUGUIS.length}`);
}
/
*
*
*
初始化成功后,在frida cli中调用样例
*
Example.Print_CurrentComponentByText()
*
/
static Print_CurrentComponentByText(){
let uiTexts
=
Example.UnityEngine.Find.GetCurrentComponentByText();
for
(let item of uiTexts) {
console.log(`Text组件内容:【${item.TextContent}】`);
}
console.log(`UIText子类个数:${uiTexts.length}`);
}
Entry() {
/
/
使用样例
let unityEngine
=
EngineManager.GetUnityEngine();
unityEngine.IsUnity(isUnity
=
>{
if
(!isUnity)
{
console.error(
"此游戏非Unity引擎游戏"
);
return
;
}
console.log(
"此游戏是Unity引擎游戏"
);
unityEngine.Init(engine
=
> {
console.log(
"初始化成功!!"
);
Example.
});
});
}
}
/
*
*
*
编译脚本入口。
*
所有js脚本,全部自动编译整合进入
"_agent.js"
。
*
/
function main(){
console.log(
"frida main代码快进入执行了"
);
Java.perform(()
=
> {
console.log(
"frida perform代码快进入执行了"
);
if
(!Java.available) {
console.log(
"Frida服务没有启动,取消执行"
);
}
let example
=
new Example();
example.Entry();
});
}
main();
/
*
*
*
android框架的so接口
*
/
class
AndroidApi {
static
/
*
*
*
@returns {AndroidApi}
*
/
static get Api() {
if
(!this.
this.
}
return
this.
}
/
*
*
*
@param {InvocationListenerCallbacks} callback
*
@constructor
*
/
AttachDlopen(callback) {
let android_dlopen_ext
=
Module.findExportByName(null,
"android_dlopen_ext"
);
if
(android_dlopen_ext !
=
null) {
Interceptor.attach(android_dlopen_ext, callback);
console.log(
"找到了 android_dlopen_ext"
);
}
else
{
console.error(
"未找到 android_dlopen_ext"
);
}
let dlopen
=
Module.findExportByName(null,
"dlopen"
);
if
(dlopen !
=
null) {
Interceptor.attach(dlopen, callback);
console.log(
"找到了 dlopen"
);
}
else
{
console.error(
"未找到 dlopen"
);
}
}
}
class
UCommonUtil {
static
/
*
*
*
@
return
{UCommonUtil}
*
/
static get Api() {
if
(this.
this.
}
return
this.
}
/
*
*
*
获取il2cpp里的迭代器
*
@
return
{NativePointer}
*
/
GetEmptyIter() {
let
iter
=
Memory.alloc(Process.pointerSize);
iter
.writePointer(NULL);
return
iter
;
}
}
class
CommonUtil {
static
/
*
*
*
@
return
{CommonUtil}
*
/
static get Api() {
if
(this.
this.
}
return
this.
}
/
*
*
*
创建NativeFunction封装,用于少写两行代码,方便使用
*
@returns {NativeFunction}
*
/
NewNativeFunction(module, exportName, retType, argTypes) {
let ptr
=
module.findExportByName(exportName);
if
(ptr
=
=
null) {
console.error(`没有找到【${exportName}】`);
return
null;
}
console.log(`成功找到【${exportName}】`);
return
new NativeFunction(ptr, retType, argTypes);
}
}
/
*
*
*
unity il2cpp中的so接口
*
/
class
UnityApi {
static
static
/
*
*
*
@
type
{Module}
*
/
/
/
class
/
/
domain
/
/
assembly
/
/
image
/
/
runtime
/
/
type
/
/
field
/
/
property
/
/
object
/
/
string
constructor() {
this.
}
/
*
*
*
由于Unity Il2cpp相关接口,需要在il2cpp处加载后,
*
才能正常发现,所以需要先在合适的地方初始化,再后续使用
*
@constructor
*
/
static Init() {
if
(!this.
this.
}
}
/
*
*
*
静态暴露接口
*
@returns {UnityApi}
*
/
static get Api() {
if
(!this.
throw
"UnityApi还未初始化"
}
return
this.
}
/
/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
【API】
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
/
*
*
*
@
return
{NativePointer}
*
/
il2cpp_get_corlib() {
return
this.
}
/
*
*
*
根据类的限定名,获取
Type
信息
*
@param image_p .dll基址
*
@param namespace 命名空间
*
@param name 类名
*
@returns {NativePointer}
*
/
il2cpp_class_from_name(image_p, namespace, name) {
let ns
=
Memory.allocUtf8String(namespace);
let className
=
Memory.allocUtf8String(name);
return
this.
}
/
*
*
*
通过
class
获取
type
*
@param {NativePointer} klass
*
@
return
{NativePointer}
*
/
il2cpp_class_get_type(klass) {
return
this.
}
/
*
*
*
反射获取指定方法
*
@param {NativePointer} klass
class
句柄
*
@param {string} methodName 指定方法名
*
@param {number} argCount 参数个数
*
@
return
{NativePointer}
*
/
il2cpp_class_get_method_from_name(klass, methodName, argCount) {
let methodNameP
=
Memory.allocUtf8String(methodName);
return
this.
}
/
*
*
*
获取
class
下所有字段
*
@param {NativePointer} klass
*
@
return
{Generator<
*
, void,
*
>}
*
/
*
il2cpp_class_get_fields(klass) {
let
iter
=
UCommonUtil.Api.GetEmptyIter();
while
(true) {
let result
=
this.
if
(result.valueOf()
=
=
0
) {
break
;
}
yield
result;
}
}
/
*
*
*
获取进程域
*
@returns {NativePointer}
*
/
il2cpp_domain_get() {
return
this.
}
/
*
*
*
获取所有程序集的基址
*
@param domain
*
@
return
{{size:number,assemblies:
any
}} .dll数组(const Il2CppAssembly
*
*
)
*
/
il2cpp_domain_get_assemblies(domain) {
let size
=
Memory.alloc(
4
);
size.writeInt(
0
);
let assemblies
=
this.
return
{
size: size.readInt(),
assemblies: assemblies
}
}
/
*
*
*
获取.dll的句柄
*
@param assembly .dll信息指针
*
@
return
{NativePointer} .dll句柄
*
/
il2cpp_assembly_get_image(assembly) {
return
this.
}
/
*
*
*
获取image的name
*
@param {NativePointer} image
*
@
return
{string} image的名字
*
/
il2cpp_image_get_name(image) {
let result
=
this.
return
result.readPointer().readCString();
}
/
*
*
*
获取.dll下有多少个
class
*
@param {NativePointer} image .dll句柄
*
@
return
{number}
class
个数
*
/
il2cpp_image_get_class_count(image) {
let result
=
this.
return
result;
}
/
*
*
*
获取
class
*
@param {NativePointer} image
*
@param {number} index
*
@
return
{NativePointer}
*
/
il2cpp_image_get_class(image, index) {
return
this.
}
/
*
*
*
通过
class
获取作用域名
*
@param {NativePointer} klass
*
@
return
{string};
*
/
il2cpp_class_get_namespace(klass) {
let result
=
this.
let ns
=
ptr(result).readCString();
return
ns;
}
/
*
*
*
通过
class
获取名字
*
@param {NativePointer} klass
*
@
return
{string}
*
/
il2cpp_class_get_name(klass) {
let result
=
this.
return
ptr(result).readCString();
}
/
*
*
*
@param {NativePointer} klass
*
@
return
{NativePointer}
*
/
il2cpp_class_get_image(klass) {
return
this.
}
/
*
*
*
反射调用方法
*
@param {NativePointer} methodInfo 反射方法对象
*
@param {NativePointer} obj 方法所属实例,static为NULL
*
@param {NativePointer} params 参数数组
*
@param {NativePointer} exception 报错
*
@
return
{NativePointer}
*
/
il2cpp_runtime_invoke(methodInfo, obj, params, exception) {
return
this.
}
/
*
*
*
获取
class
的TypeInfo信息
*
@param {NativePointer}
type
*
@
return
{NativePointer}
*
/
il2cpp_class_from_type(
type
) {
return
this.
}
/
*
*
*
@param {NativePointer} klass
*
@param {string} name
*
@
return
{NativePointer}
*
/
il2cpp_class_get_field_from_name(klass, name) {
let nameP
=
Memory.allocUtf8String(name);
return
this.
}
/
*
*
*
读取字段的名字
*
@param {NativePointer} field
*
@
return
{string}
*
/
il2cpp_field_get_name(field) {
let result
=
this.
return
ptr(result).readCString();
}
/
*
*
*
@param {NativePointer} field
*
@
return
{NativePointer}
*
/
il2cpp_field_get_type(field) {
return
this.
}
/
*
*
*
获取
class
所有属性
*
@param {NativePointer} klass
*
@
return
{
*
}
*
/
*
il2cpp_class_get_properties(klass) {
let
iter
=
UCommonUtil.Api.GetEmptyIter();
while
(true) {
let result
=
this.
if
(result.valueOf()
=
=
0
) {
break
;
}
yield
result;
}
}
/
*
*
*
通过名字,获取
class
指定属性
*
@param {NativePointer} klass
*
@param {string} name
*
@
return
{NativePointer}
*
/
il2cpp_class_get_property_from_name(klass, name) {
let nameP
=
Memory.allocUtf8String(name);
return
this.
}
/
*
*
*
@param {NativePointer}
type
*
@
return
{number}
*
/
il2cpp_type_get_type(
type
) {
return
this.
}
/
*
*
*
根据反射信息,创建
Type
对象(即C
*
@param {NativePointer}
type
*
@
return
{NativePointer}
*
/
il2cpp_type_get_object(
type
) {
return
this.
}
/
*
*
*
@param {NativePointer}
type
*
@
return
{NativePointer}
*
/
il2cpp_type_get_class_or_element_class(
type
) {
return
this.
}
/
*
*
*
反射读取字段值
*
@param {NativePointer} field
*
@param {NativePointer} obj
*
@
return
{NativePointer}
*
/
il2cpp_field_get_value_object(field, obj) {
return
this.
}
/
*
*
*
获取属性的get方法(及读取属性值行为)
*
@param {NativePointer} prop
*
@
return
{NativePointer}
*
/
il2cpp_property_get_get_method(prop) {
return
this.
}
/
*
*
*
获取属性名字
*
@param {NativePointer} prop
*
@
return
{NativePointer}
*
/
il2cpp_property_get_name(prop) {
let result
=
this.
return
ptr(result).readCString();
}
/
*
*
*
获取对象大小
*
@param {NativePointer} obj
*
@
return
{number}
*
/
il2cpp_object_get_size(obj) {
return
this.
}
/
*
*
*
@param {NativePointer} obj
*
@
return
{NativePointer}
*
/
il2cpp_object_get_class(obj) {
return
this.
}
/
*
*
*
@param {NativePointer}
str
*
@
return
{string}
*
/
func_il2cpp_string_chars(
str
) {
let result
=
this.
return
ptr(result).readUtf16String();
}
/
/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
【Attach】
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
/
*
*
*
@param {InvocationListenerCallbacks} callback
*
/
Attach_il2cpp_get_corlib(callback) {
let func
=
this.
Interceptor.attach(func, callback);
}
/
*
*
*
@param {InvocationListenerCallbacks} callback
*
/
Attach_il2cpp_class_from_name(callback) {
let func
=
this.
Interceptor.attach(func, callback);
}
/
*
*
*
初始化so函数
*
/
this.
if
(!this.
console.error(
"未发现il2cppModule"
);
return
;
}
/
/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
this.
"pointer"
,
[]);
/
/
class
this.
"pointer"
,
[
"pointer"
,
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
,
"int"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
/
/
domain
this.
"pointer"
,
[]);
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
/
/
assembly
this.
"pointer"
,
[
"pointer"
]);
/
/
image
this.
"pointer"
,
[
"pointer"
]);
this.
"uint32"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
,
"uint32"
]);
/
/
runtime
this.
"pointer"
,
[
"pointer"
,
"pointer"
,
"pointer"
,
"pointer"
]);
/
/
type
this.
"int"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
/
/
field
this.
"pointer"
,
[
"pointer"
,
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
/
/
property
this.
"pointer"
,
[
"pointer"
]);
this.
"pointer"
,
[
"pointer"
]);
/
/
object
this.
"uint32"
,
[
"pointer"
]);
/
/
string
this.
"pointer"
,
[
"pointer"
]);
/
/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
}
}
/
*
*
*
懒加载包装类
*
/
class
Lazy {
/
*
*
*
@
type
{function ():
*
} value
*
/
/
*
*
*
@param {
*
} this上下文
*
@param {function ():
*
} value 实例化对象的方法回调
*
@
return
{Lazy}
*
/
static New(context,value) {
let lazy
=
new Lazy();
lazy.Value
=
value.bind(context);
return
lazy;
}
/
*
*
*
@param {function ():
*
} value
*
/
set
Value(value) {
this.
}
/
*
*
*
@
return
{
*
}
*
/
get Value() {
if
(this.
this.
}
return
this.
}
}
class
UMethodInfo {
/
*
*
*
@
type
{Lazy}
*
/
/
*
*
*
@
type
{UnityApi}
*
/
/
*
*
*
@param {
*
{
*
kalss:NativePointer,
*
methodName:string
*
argCount:number
*
}
*
}
input
*
/
constructor(
input
) {
this.
return
this.
input
.methodName,
input
.argCount);
});
}
/
*
*
*
*
@param {NativePointer} args 参数数组
*
@param {NativePointer} obj 实例对象
*
@
return
{(NativePointer |
*
)}
*
@constructor
*
/
Invoke(obj, args) {
let result
=
this.
obj, args, NULL);
return
result;
}
}
class
UDomain {
static
/
*
*
*
@
type
{NativePointer}
*
/
/
*
*
*
@
type
{{size:number,assemblies:
any
}}
*
/
/
*
*
*
@
type
{NativePointer[]}
*
/
/
*
*
*
@
type
{UnityApi}
*
/
constructor() {
this.
this.
this.
this.
}
/
*
*
*
@
return
{UDomain}
*
/
static get Api() {
if
(UDomain.
UDomain.
}
return
UDomain.
}
/
*
*
*
@
return
{NativePointer[]}
*
/
get AllAssemblyImages() {
return
this.
}
/
*
*
*
@param {string} name
*
@
return
{NativePointer}
*
/
GetAssemblyImageByName(name) {
return
this.
.
filter
(image
=
> this.
.pop()
.readPointer();
}
this.
}
this.
}
let images
=
[...Array(this.
.
map
(value
=
> ptr(this.
.
map
(assm
=
> this.
this.
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2022-7-14 19:03
被憨豆爆发编辑
,原因: 调整标题