首先参考阅读这篇文章
code_item指令会执行到Execute函数
1
2
3
4
5
6
|
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_)
|
来自于EnterInterpreterFromInvoke的调用
1
2
3
|
391
void EnterInterpreterFromInvoke(Thread
*
self
, ArtMethod
*
method,
Object
*
receiver,
392
uint32_t
*
args, JValue
*
result,
393
bool
stay_in_interpreter)
|
对应于我的libart.so的地址分别是0x002D8F40 和 0x002D85C0
在0x002D8F40处下断点,第二个参数即为DexFile::CodeItem*的值
地址指针为esp+0x4处
根据CodeItem的定义可以得知
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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
};
|
指令的长度为CodeItem+0xC的值*2+0x10
有了这两个参数就可以实时的导出所运行的指令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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) {
}
});
}
|
处于测试的目的我手动调用JAVA函数,并在每一条JAVA指令下打印LOG
1
2
3
4
5
6
7
8
9
10
|
function run_java_function(){
Java.perform(function(){
var DesHylEncodeUtilClass
=
Java.use(
"com.mc.sdk.utils.DesHylEncodeUtil"
);
console.log(
"DesHylEncodeUtilClass:"
, JSON.stringify(DesHylEncodeUtilClass));
var mDesHylEncodeUtil
=
DesHylEncodeUtilClass.getInstance(
'12345678'
);
console.log(
"mDesHylEncodeUtil:"
, JSON.stringify(mDesHylEncodeUtil));
var encryptstr
=
mDesHylEncodeUtil.getEncString(
'1234567890'
);
console.log(
"encryptstr:"
,encryptstr);
})
}
|
最终结果如下
日志信息为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
mDesHylEncodeUtil:
"<instance: com.mc.sdk.utils.DesHylEncodeUtil>"
libart.so|Execute code_size :
60
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
bf15c280
03
00
02
00
02
00
01
00
06
83
3f
00
16
00
00
00
..........?.....
bf15c290
1b
00
83
24
01
00
6e
20
5d
b2
02
00
0c
02
6e
20
...$..n ].....n
bf15c2a0 ac a4
21
00
0c
02
71
10
af a4
02
00
0c
02
11
02
..!...q.........
bf15c2b0
0d
02
6e
10
c3 b1
02
00
12
02
11
02
..n.........
libart.so|Execute code_size :
98
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
bf15c20c
06
00
02
00
04
00
01
00
fc
82
3f
00
29
00
00
00
..........?.)...
bf15c21c
22
00
7f
1c
62
01
0a
8b
70
20
ec b5
10
00
22
01
"...b...p ...."
.
bf15c22c
84
1c
62
02
0b
8b
6e
10
5c
b2
02
00
0c
02
1a
03
..b...n.\.......
bf15c23c b0
1b
70
30
ef b5
21
03
1a
02
b1
1b
71
10
d8 b5 ..p0..!.....q...
bf15c24c
02
00
0c
02
12
13
6e
40
db b5
32
01
6e
20
d5 b5 ......n@..
2.n
..
bf15c25c
52
00
0c
05
11
05
0d
05
6e
10
c3 b1
05
00
12
05
R.......n.......
bf15c26c
11
05
..
libart.so|Execute code_size :
128
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
bf15c040
06
00
01
00
02
00
00
00
d2
82
3f
00
38
00
00
00
..........?.
8.
..
bf15c050
22
00
a6
1b
70
10
85
b2
00
00
12
01
21
52
35
21
"...p.......!R5!
bf15c060
2c
00
48
02
05
01
d5
22
ff
00
71
10
e5 b1
02
00
,.H...."..q.....
bf15c070
0c
02
6e
10
69
b2
02
00
0a
03
12
14
33
43
13
00
..n.i.......
3C
..
bf15c080
22
03
a7
1b
70
10
9a
b2
03
00
13
04
30
00
6e
20
"...p.......
0.n
bf15c090
9d
b2
43
00
6e
20
a3 b2
23
00
6e
10
b2 b2
03
00
..C.n ..
#.n.....
bf15c0a0
0c
02
6e
10
7a
b2
02
00
0c
02
6e
20
8c
b2
20
00
..n.z.....n .. .
bf15c0b0 d8
01
01
01
28
d4
6e
10
99
b2
00
00
0c
05
11
05
....(.n.........
encryptstr:
5F6A7D528E394F397F5FB2DA0643A620
|
修复时首先在class_def_item 中找到指定的类
然后在encoded_method_list中找到需要修复的函数,就可以跳转到对应的code_item
原始的code_item的值如下
1
2
3
4
|
03
00
02
00
02
00
01
00
F0 BE FE
03
16
00
00
00
12
00
11
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
|
日志中的值为
1
2
3
4
|
03
00
02
00
02
00
01
00
06
83
3f
00
16
00
00
00
1b
00
83
24
01
00
6e
20
5d
b2
02
00
0c
02
6e
20
ac a4
21
00
0c
02
71
10
af a4
02
00
0c
02
11
02
0d
02
6e
10
c3 b1
02
00
12
02
11
02
|
直接二进制替换
我一共修复了3个函数,分别为getEncString、getEncCode和parseByte2HexStr
对比一下原始的反编译效果如下
以下是修复后的效果
更多【通过DVM指令还原壳的抽空类】相关视频教程:www.yxfzedu.com