首先参考阅读这篇文章
ART 在 Android 安全攻防中的应用
code_item指令会执行到Execute函数
来自于EnterInterpreterFromInvoke的调用
对应于我的libart.so的地址分别是0x002D8F40 和 0x002D85C0
在0x002D8F40处下断点,第二个参数即为DexFile::CodeItem*的值
地址指针为esp+0x4处
根据CodeItem的定义可以得知
指令的长度为CodeItem+0xC的值*2+0x10
有了这两个参数就可以实时的导出所运行的指令
处于测试的目的我手动调用JAVA函数,并在每一条JAVA指令下打印LOG
最终结果如下
日志信息为
修复时首先在class_def_item 中找到指定的类
然后在encoded_method_list中找到需要修复的函数,就可以跳转到对应的code_item
原始的code_item的值如下
日志中的值为
直接二进制替换
我一共修复了3个函数,分别为getEncString、getEncCode和parseByte2HexStr
对比一下原始的反编译效果如下
以下是修复后的效果
267
static inline JValue Execute(
268
Thread
*
self
,
269
const DexFile::CodeItem
*
code_item,
270
ShadowFrame& shadow_frame,
271
JValue result_register,
272
bool
stay_in_interpreter
=
false) SHARED_REQUIRES(Locks::mutator_lock_)
267
static inline JValue Execute(
268
Thread
*
self
,
269
const DexFile::CodeItem
*
code_item,
270
ShadowFrame& shadow_frame,
271
JValue result_register,
272
bool
stay_in_interpreter
=
false) SHARED_REQUIRES(Locks::mutator_lock_)
391
void EnterInterpreterFromInvoke(Thread
*
self
, ArtMethod
*
method,
Object
*
receiver,
392
uint32_t
*
args, JValue
*
result,
393
bool
stay_in_interpreter)
391
void EnterInterpreterFromInvoke(Thread
*
self
, ArtMethod
*
method,
Object
*
receiver,
392
uint32_t
*
args, JValue
*
result,
393
bool
stay_in_interpreter)
280
/
/
Raw code_item.
281
struct CodeItem {
282
uint16_t registers_size_;
/
/
the number of registers used by this code
283
/
/
(
locals
+
parameters)
284
uint16_t ins_size_;
/
/
the number of words of incoming arguments to the method
285
/
/
that this code
is
for
286
uint16_t outs_size_;
/
/
the number of words of outgoing argument space required
287
/
/
by this code
for
method invocation
288
uint16_t tries_size_;
/
/
the number of try_items
for
this instance. If non
-
zero,
289
/
/
then these appear as the tries array just after the
290
/
/
insns
in
this instance.
291
uint32_t debug_info_off_;
/
/
file
offset to debug info stream
292
uint32_t insns_size_in_code_units_;
/
/
size of the insns array,
in
2
byte code units
293
uint16_t insns_[
1
];
/
/
actual array of bytecode.
294
295
private:
296
DISALLOW_COPY_AND_ASSIGN(CodeItem);
297
};
280
/
/
Raw code_item.
281
struct CodeItem {
282
uint16_t registers_size_;
/
/
the number of registers used by this code
283
/
/
(
locals
+
parameters)
284
uint16_t ins_size_;
/
/
the number of words of incoming arguments to the method
285
/
/
that this code
is
for
286
uint16_t outs_size_;
/
/
the number of words of outgoing argument space required
287
/
/
by this code
for
method invocation
288
uint16_t tries_size_;
/
/
the number of try_items
for
this instance. If non
-
zero,
289
/
/
then these appear as the tries array just after the
290
/
/
insns
in
this instance.
291
uint32_t debug_info_off_;
/
/
file
offset to debug info stream
292
uint32_t insns_size_in_code_units_;
/
/
size of the insns array,
in
2
byte code units
293
uint16_t insns_[
1
];
/
/
actual array of bytecode.
294
295
private:
296
DISALLOW_COPY_AND_ASSIGN(CodeItem);
297
};
function hook_art_module(){
var art_module
=
Module.findBaseAddress(
"libart.so"
);
var Execute
=
art_module.add(
0x002D8F40
);
Interceptor.attach(Execute, {
onEnter: function(args)
{
var vm_addr
=
Memory.readPointer((this.context.esp).add(
0x4
));
var vm_size
=
Memory.readUInt(vm_addr.add(
0xC
));
var code_size
=
vm_size
*
2
+
0x10
;
console.log(hexdump(vm_addr, {
offset:
0
,
length: code_size,
header: true,
ansi: true
}));
},
onLeave: function (retval) {
}
});
}
function hook_art_module(){
var art_module
=
Module.findBaseAddress(
"libart.so"
);
var Execute
=
art_module.add(
0x002D8F40
);
Interceptor.attach(Execute, {
onEnter: function(args)
{
var vm_addr
=
Memory.readPointer((this.context.esp).add(
0x4
));
var vm_size
=
Memory.readUInt(vm_addr.add(
0xC
));
var code_size
=
vm_size
*
2
+
0x10
;
console.log(hexdump(vm_addr, {
offset:
0
,
length: code_size,
header: true,
ansi: true
}));
},
onLeave: function (retval) {
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2023-1-16 16:19
被易之生生编辑
,原因: 标点符号