/
*
*
*
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();