启动时候HookDlopen,并在加载libmono.so的时候对导出函数 mono_image_open_from_data_with_name 进行Hook 拿到加载进来的dll的image对象,返回值就是一个_MonoImage结构体指针
关注上图中的
*raw_data dll在内存中的起始地址
raw_data_len dll的长度
即可写出,记录下arr_imgs_addr 和 arr_imgs_name
以上为启动的时候就进行Hook可以拿到Image结构体,不在启动的时候Hook同样也可以拿到
使用导出函数中的 mono_image_loaded 即可
对于如何拿到method对象的话,我们还是冲导出函数入手,使用IDA查看一下导出函数,看看关键字method,可以看到这些函数,选几个长得像那么回事的函数去源码搜搜
搜了一下源码得到一下声明
第一个token我们不好找,放弃
第二个flags也不好找,放弃
第四个显然就是一个通过class来遍历method的方法,可用但是没必要
所以看参数我们要去找 MonoClass,那继续去找导出函数
于是找到了 mono_class_from_nam() 函数
由此我们需要的参数也都筹齐了,写出一下hook代码
运行见效果:
简单的看了一下导出函数,发现有一个 mono_runtime_invoke 传参就是 MonoMethod
于是可以尝试主动调用
这里选了一个get_identifier 来主动调用,可以发现没问题
(但是这里仅限于不带参数的Static方法)
看着这个mono_runtime_invoke(MonoMethod method, void obj, void **params,MonoObject **exc)的声明参数就不想看它了,有更简单的方法,这里就简述一下这个简单的方法
我们换一个思路,总所周知,dll是被加载进去内存在动态编译的,这里我们手动调用mono_compile_method来编译这个MonoMethod即可得到类似于il2cpp中的MethodInfo的函数指针,详见下图
/
*
*
*
启动时候Hook mono_image_open_from_data_with_name 记录dll的起始位置,名称
*
/
function HookMono() {
/
/
MonoImage
*
mono_image_open_from_data_with_name (char
*
data, uint32_t data_len, mono_bool need_copy,MonoImageOpenStatus
*
status, mono_bool refonly, const char
*
name);
Interceptor.attach(Module.findExportByName(soName,
"mono_image_open_from_data_with_name"
), {
onEnter: function (args) {
this.name
=
args[
5
].readCString()
this.size
=
args[
1
].toInt32()
},
onLeave: function (ret) {
var t_ret
=
ret
LOG(
"[*] "
+
t_ret
+
"\t"
+
this.name,LogColor.C36)
var t_arr
=
this.name.split(
"/"
)
var t_name
=
t_arr[(t_arr.length)
-
1
].split(
".dll"
)[
0
]
arr_imgs_addr.push(String(t_ret))
arr_imgs_name.push(t_name)
}
});
}
/
*
*
*
启动时候Hook mono_image_open_from_data_with_name 记录dll的起始位置,名称
*
/
function HookMono() {
/
/
MonoImage
*
mono_image_open_from_data_with_name (char
*
data, uint32_t data_len, mono_bool need_copy,MonoImageOpenStatus
*
status, mono_bool refonly, const char
*
name);
Interceptor.attach(Module.findExportByName(soName,
"mono_image_open_from_data_with_name"
), {
onEnter: function (args) {
this.name
=
args[
5
].readCString()
this.size
=
args[
1
].toInt32()
},
onLeave: function (ret) {
var t_ret
=
ret
LOG(
"[*] "
+
t_ret
+
"\t"
+
this.name,LogColor.C36)
var t_arr
=
this.name.split(
"/"
)
var t_name
=
t_arr[(t_arr.length)
-
1
].split(
".dll"
)[
0
]
arr_imgs_addr.push(String(t_ret))
arr_imgs_name.push(t_name)
}
});
}
MonoImage
*
mono_image_loaded (const char
*
name);
MonoImage
*
mono_image_loaded (const char
*
name);
MonoMethod
*
mono_get_method (MonoImage
*
image, uint32_t token, MonoClass
*
klass);
MonoMethod
*
mono_class_get_method_from_name (MonoClass
*
klass, const char
*
name,
int
param_count);
MonoMethod
*
mono_class_get_method_from_name_flags (MonoClass
*
klass, const char
*
name,
int
param_count,
int
flags);
MonoMethod
*
mono_class_get_methods (MonoClass
*
klass, void
*
*
iter
);
MonoMethod
*
mono_get_method (MonoImage
*
image, uint32_t token, MonoClass
*
klass);
MonoMethod
*
mono_class_get_method_from_name (MonoClass
*
klass, const char
*
name,
int
param_count);
MonoMethod
*
mono_class_get_method_from_name_flags (MonoClass
*
klass, const char
*
name,
int
param_count,
int
flags);
MonoMethod
*
mono_class_get_methods (MonoClass
*
klass, void
*
*
iter
);
/
/
函数声明
MonoClass
*
mono_class_from_name (MonoImage
*
image, const char
*
name_space, const char
*
name);
struct _MonoMethod {
guint16 flags;
/
*
method flags
*
/
guint16 iflags;
/
*
method implementation flags
*
/
guint32 token;
MonoClass
*
klass;
/
*
To what
class
does this method belong
*
/
MonoMethodSignature
*
signature;
/
*
name
is
useful mostly
for
debugging
*
/
const char
*
name;
.....
}
struct _MonoClass {
MonoClass
*
element_class;
MonoClass
*
cast_class;
MonoClass
*
*
supertypes;
guint16 idepth;
guint8 rank;
int
instance_size;
......
MonoImage
*
image;
const char
*
name;
const char
*
name_space;
......
}
struct _MonoMethodSignature {
MonoType
*
ret;
guint8 param_count;
gint8 sentinelpos;
unsigned
int
generic_param_count :
5
;
guint16 param_count;
gint16 sentinelpos;
unsigned
int
generic_param_count :
16
;
unsigned
int
call_convention :
6
;
unsigned
int
hasthis :
1
;
unsigned
int
explicit_this :
1
;
unsigned
int
pinvoke :
1
;
unsigned
int
is_inflated :
1
;
unsigned
int
has_type_parameters :
1
;
MonoType
*
params [MONO_ZERO_LEN_ARRAY];
};
/
/
函数声明
MonoClass
*
mono_class_from_name (MonoImage
*
image, const char
*
name_space, const char
*
name);
struct _MonoMethod {
guint16 flags;
/
*
method flags
*
/
guint16 iflags;
/
*
method implementation flags
*
/
guint32 token;
MonoClass
*
klass;
/
*
To what
class
does this method belong
*
/
MonoMethodSignature
*
signature;
/
*
name
is
useful mostly
for
debugging
*
/
const char
*
name;
.....
}
struct _MonoClass {
MonoClass
*
element_class;
MonoClass
*
cast_class;
MonoClass
*
*
supertypes;
guint16 idepth;
guint8 rank;
int
instance_size;
......
MonoImage
*
image;
const char
*
name;
const char
*
name_space;
......
}
struct _MonoMethodSignature {
MonoType
*
ret;
guint8 param_count;
gint8 sentinelpos;
unsigned
int
generic_param_count :
5
;
guint16 param_count;
gint16 sentinelpos;
unsigned
int
generic_param_count :
16
;
unsigned
int
call_convention :
6
;
unsigned
int
hasthis :
1
;
unsigned
int
explicit_this :
1
;
unsigned
int
pinvoke :
1
;
unsigned
int
is_inflated :
1
;
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-5-31 17:24
被唱过阡陌编辑
,原因: