这是第一篇vmp系列,下一篇估计要很久很久以后。
https://bbs.kanxue.com/thread-270799.htm#msg_header_h1_6
看了一下,目前市面上关于dex vmp还原就我兄弟写的这一个,我不得不佩服他巨强的二级制分析能力。关于dex vmp 他的大部分都写了,但是,他搞的实在是太复杂了,他的分析基本都是基于静态的数据流向分析,这种对于二进制vmp都有杀伤力的,只能说杀鸡焉用牛刀,而且他的牛刀还没发借给我,这是最气的。
另外一个360大佬在看雪峰会上发的关于dex vmp的ppt演讲,他这个我没看得很懂,技术有限。前面都是大佬,一看就会,一学就废。
vmp目前基本可以说是逆向分析中代码混淆的巅峰,顶点,最高里程碑,dex vmp在我看来是比较简单一点的vmp了,所以我们从这里入门。
vmp是一种虚拟机保护壳,如果你第一次听过,估计直接蒙了,他其实就是一个虚拟的执行机器,就比如java虚拟机,他们的原理是一样的。java虚拟机可以叫vmp是保护的意思,所以叫vmp。这种虚拟机一般有两部分:
vmp虽然设计理念上跟别的虚拟机没什么差别,但是他很简陋,基本只有能转换虚拟机的bytecode然后进行运行的能力。写个伪代码示意一下
就是这样一直循环
在vmp执行实体中,可以看到有个bytecode_buff,虚拟机为什么能识别他,因为加固软件将源码,转变成虚拟机的bytecode,然后将虚拟机和bytecode一起打包到需要加固的软件中。
对于一个vmp,我们的目标只有一个,那就是还原,还原成c也好,汇编也好,java也好,反正就是去除vmp化。这就是最务实的目标,所以这篇博客的目的就是如何将dex vmp 还原成java代码。
首先看入口函数,如果看过我上面提到过的dex vmp 你就该知道,这个pro.getxxx,其实就是调用的dex vmp函数的入口,而第一个参数,其实就是代表了当前这个函数,用这个数字来索引已经被虚拟化的代码来执行。
然后再看看这个函数的定义,这个如果你经验丰富,经常写java代码和别的代码的交互,你就会发现,这是一个java 和c的交互代码,写了这么多类型,就是可以从c 层返回任何一种类型的java对象,看不出来也没事。
这个本来不想写的,但是其实其实比较简单,有人多人去hook NativeRegister,很多加固去通过各种奇葩的手段绕过NativeRegister进行注册,但是其实没必要,java方法的native地址根本无法隐藏。分享一个frida脚本寻找native方法的地址。
这个函数是我们主要的分析,怎么寻找native函数,so动态下发分析不讲了,直接找native函数地址开始分析流程
拿到这个包以后,已经找到要逆向的函数,所以直接用上面的frida 脚本找到函数的偏移,然后ida直接附加进程,在这个位置下断点,确实没问题,函数在这里断下来了,trace了一下,程序直接崩溃了,有反调试,无所谓,停掉所有其他的线程trace,这个getobjresult函数有时候能跑完,有时候跑不完。但是trace确实完成了,第一次trace 90w,第二次2700w行。trace代码的长度,流程都不一样。经过代码一段时间的汇编分析(比较简单),我发现出问题代码这个地方开始不一致。
为什么要贴这段汇编那,其实不贴也可以。因为假如你有一天去你想vmp,并且发现这种br x8,这种,不断取x23内容,加上x22地址,是dex vmp,我调研过有几个类似样本都这样。
然后就进入完全看不懂的乱序执行
有很多图,全部都是乱的。开始我以为是混淆,经过分析以后发现,并没有混淆。但是这个执行顺序完全是乱飞,我们一般对于1个函数,或者说c编译的函数,识别的他的方法是开栈和闭栈并且栈平衡,这是一个完整的函数,但是这个函数全是乱的,没有开栈也没有闭栈。
对于一个未知的加固方案,如果你想从汇编完全暴力破解他,把他撸出来,而且还是2700w行汇编,难度太高了。所以第一个是识别他,然后去网上找大神的破解方法来对症下药。如何识别那,不断的运行,进行猜测,这个过程会很久,经过分析我发现他里面有大量的jni函数
很多很多,在运行中分析这些数据发现他调用很多java的代码,各种各样,有很多我甚至都没有用过。
到这里基本破案了,256条指令对应了256个Dalvik 指令的opcode,虽然很多没用。
前面我们说了我们的目标,就是将某一段代码还原。而vmp,还原的方法只能去分析整个vmp的框架,进行功能含义分析,然后通过某一段vm的指令,将他手工转化成java代码。说白了就是一个vmp的反向过程。
我签名写的这个,就是vmp简单的执行示意,它必然需要不断的循环运行,来执行基本单元指令,除非基本单元指令退出,否则会无线循环。
但是实际分析过程中,我发现没有while循环,也没有这种wile里读指令,然后根据不同的指令跳转到不同的vmp基本单元指令。(猜测失败的代价就是对自己的技术产生怀疑)
然后我去研究了一下trace,看一下他这个指令之间是如何关联起来的,上一条指令如何跳转到下一条指令。(研究过多条指令,很长的函数还没有间隔,完全不知道出口在哪里,但是很幸运的是有比较短的)
不多贴了,他们的尾部都是一样的,x20 当前指令,x22 data_rel,x23 指令数据表。他是通过上一条指令的内容计算下一条指令的地址,然后读取数据数据,和指令处理的地址,用x8跳过去,他不是一个while模式。写个运行的伪代码的例子
这样一旦开始执行,除非遇到退出指令,否则函数会一直执行下去。android dvm虚拟机以前读源码的时候见过这种模式,这种计算指令长度的方式,davlik也确实可以这样搞。他每个指令长度都是可以提前写死的,没有变长的可能。
我们知道了他的基本单元指令,以及基本单元指令的函数,这个时候我们对基本单元指令进行一个一个的分析,然后将某一个vmp化的java函数vmp指令进行反向转化。
以前听说360还原用的是对照表。但是逆向到我这个地步,写对照表已经属于浪费时间了,而且对照表还要对着opcode一个一个的改,懒得搞了。我直接写了一个小型的opcode 转smali语言的ida脚本,将vmp指令转变为smali指令,然后写道对应的dex中反编译的smali工程中,进行回编译。直接贴脚本,这是一个的半自动化+手工来进行指令还原的脚本,扔给你们做参考吧。
效果图,我就不贴
大致讲一下这个脚本原理思路和使用
这个脚本需要在vmp已经装载完成以后调用,找到还原的dex和对应的vmp指令地址,可以直接循环翻译成smali指令。具体的指令是有具体的长度写在代码里的。smali函数结束都有smali指令的返回指令(return类指令),可以随便找个smali工程看一下,函数结束都有一个return类指令.也有可能是其中的一个返回,通过跳转指令结合分析
dex vmp 虽然跟二进制vmp的原理一样,但是他的逆向难度和vmp却不是一个量级的。为什么会出现这种情况
这个已知保护措施是dex vmp在可被逆向的情况下,如果提高一些安全性
分析vmp指令,对他进行还原的时候,并没有非常具体的写。在这里一切写,这是一些写davlik指令,或者说反编译分析davlik的一些经验。
davlik指令是非常容易分析的,基本不太存在保护的价值,因为一般的防护扛不住静态分析工具的分析,这个他的设计是有很大关系的。
dalvik中的部分指令有很强的关联性。比如
前面这个invoke-static ,如果有返回值,必会跟这后面这条指令,甚至可以说他们是一条指令
变量在定义之后,有大概率在下一条就会使用,当然不是绝对
这是new一个对象的代码,会立即调用init方法
函数结束必有return指令,当然遇到return不一定是结束。但是进行人工还原的时候通过上下文分析函数结束位置,还是非常有价值的。
有很多操作相同,但是操作类型却不同的指令
这一条aget指令,针对于各种不同的类型有不同的指令。在指令中有个对应的索引,我们甚至可以直接查看这个类型来反向推理这个指令操作的是什么类型。这种设计也从侧面给说明了,dalvik一个指令只有一个解释,没有歧义性,不想汇编,c,不知道类型,更不知道操作具体是什么,只是数据进行了操作。即使是一些虚函数,java中你可能分不出来他具体调用的是那个类的,但是在dalvik中,这个类的类型已经写死在索引中了。
虽然dalvik号称256个opcode,但是有很多不用的,还有一些是同一个功能,但是不同类型
这是smali解析的dalvik指令,就上面这些功能,不算多。
dalvik的指令如果想要运行,必须在一个method里,不可能超出一个函数的范围,更不可能先汇编语言那样全局的大跳,动态跳转地址,每一个函数都是一个密封的黑盒,当然可能会有一些类变量什么的,但是就代码含义分析这一块基本没问题。
一般在这个位置都是要吹牛逼的,但是我发现牛逼可能成真,就留个悬念。
如果真的觉得可以就关注一下公众号吧。也不发图推广了。
哦,对了,我这脚本配合人工半自动换,是可以做到一个函数一个函数还原的,我经过测试了,图,就不贴,怕人找,虽然目前没人找过。
我随便找的其中的某个样本,发的照片,很多样本好像都差不多,都是这个逆向思路
while
(
1
){
/
/
一旦进入虚拟机就会开始读取字节码,除非遇到退出指令,否则一直执行下去
bytecode_ins
=
read(bytecode_buff);
/
/
不断的读取指令
exe(bytecode_ins)
/
/
运行指令
}
while
(
1
){
/
/
一旦进入虚拟机就会开始读取字节码,除非遇到退出指令,否则一直执行下去
bytecode_ins
=
read(bytecode_buff);
/
/
不断的读取指令
exe(bytecode_ins)
/
/
运行指令
}
var offset
=
-
1
/
/
这个函数是用来做偏移矫正的
function get_android_api_jnioffset() {
if
(offset !
=
-
1
){
return
offset
}
var native_addr
=
Module.findExportByName(
"libandroid_runtime.so"
,
"_Z32android_os_Process_getUidForNameP7_JNIEnvP8_jobjectP8_jstring"
)
/
/
console.log(
"native_addr:"
,native_addr)
var className
=
"android.os.Process"
;
var classResult
=
Java.use(className).
class
;
var methodArr
=
classResult.getDeclaredMethods();
for
(var i
=
0
; i < methodArr.length; i
+
+
) {
var methodName
=
methodArr[i].toString();
var flags
=
methodArr[i].getModifiers()
if
(flags &
256
) {
if
(methodName.indexOf(
"getUidForName"
)!
=
-
1
){
var artmethod
=
methodArr[i].getArtMethod();
for
(var i
=
0
; i <
30
; i
=
i
+
1
) {
var jni_native_addr
=
Memory.readPointer(ptr(artmethod
+
i))
if
(native_addr.equals(jni_native_addr)){
offset
=
i
return
i
}
}
}
}
}
return
-
1
}
遍历一个类的所有native 方法并打印地址
function get_jni_native_method_addr(classResult) {
var jnioffset
=
get_android_api_jnioffset()
var methodArr
=
classResult.getDeclaredMethods();
for
(var i
=
0
; i < methodArr.length; i
+
+
) {
var methodName
=
methodArr[i].toString();
var flags
=
methodArr[i].getModifiers()
if
(flags &
256
) {
var artmethod
=
methodArr[i].getArtMethod();
var native_addr
=
Memory.readPointer(ptr(artmethod
+
jnioffset))
/
/
找到本手机系统中artmethod的便宜地址,然后用
20
+
偏移
var module
var offset
console.log(
"methodName->"
, methodName);
try
{
module
=
Process.getModuleByAddress(native_addr)
offset
=
native_addr
-
module.base
console.log(
"Func.offset=="
, module.name, offset);
} catch (err) {
}
console.log(
"Func.getArtMethod->native_addr:"
, native_addr);
/
/
打印出java方法jni函数调用的native函数地址
console.log(
"Func.flags->"
, flags);
}
}
}
var offset
=
-
1
/
/
这个函数是用来做偏移矫正的
function get_android_api_jnioffset() {
if
(offset !
=
-
1
){
return
offset
}
var native_addr
=
Module.findExportByName(
"libandroid_runtime.so"
,
"_Z32android_os_Process_getUidForNameP7_JNIEnvP8_jobjectP8_jstring"
)
/
/
console.log(
"native_addr:"
,native_addr)
var className
=
"android.os.Process"
;
var classResult
=
Java.use(className).
class
;
var methodArr
=
classResult.getDeclaredMethods();
for
(var i
=
0
; i < methodArr.length; i
+
+
) {
var methodName
=
methodArr[i].toString();
var flags
=
methodArr[i].getModifiers()
if
(flags &
256
) {
if
(methodName.indexOf(
"getUidForName"
)!
=
-
1
){
var artmethod
=
methodArr[i].getArtMethod();
for
(var i
=
0
; i <
30
; i
=
i
+
1
) {
var jni_native_addr
=
Memory.readPointer(ptr(artmethod
+
i))
if
(native_addr.equals(jni_native_addr)){
offset
=
i
return
i
}
}
}
}
}
return
-
1
}
遍历一个类的所有native 方法并打印地址
function get_jni_native_method_addr(classResult) {
var jnioffset
=
get_android_api_jnioffset()
var methodArr
=
classResult.getDeclaredMethods();
for
(var i
=
0
; i < methodArr.length; i
+
+
) {
var methodName
=
methodArr[i].toString();
var flags
=
methodArr[i].getModifiers()
if
(flags &
256
) {
var artmethod
=
methodArr[i].getArtMethod();
var native_addr
=
Memory.readPointer(ptr(artmethod
+
jnioffset))
/
/
找到本手机系统中artmethod的便宜地址,然后用
20
+
偏移
var module
var offset
console.log(
"methodName->"
, methodName);
try
{
module
=
Process.getModuleByAddress(native_addr)
offset
=
native_addr
-
module.base
console.log(
"Func.offset=="
, module.name, offset);
} catch (err) {
}
console.log(
"Func.getArtMethod->native_addr:"
, native_addr);
/
/
打印出java方法jni函数调用的native函数地址
console.log(
"Func.flags->"
, flags);
}
}
}
.text:
000000000001AD18
FC
6F
BA A9 STP X28, X27, [SP,
.text:
000000000001AD1C
FA
67
01
A9 STP X26, X25, [SP,
.text:
000000000001AD20
F8
5F
02
A9 STP X24, X23, [SP,
.text:
000000000001AD24
F6
57
03
A9 STP X22, X21, [SP,
.text:
000000000001AD28
F4
4F
04
A9 STP X20, X19, [SP,
.text:
000000000001AD2C
FD
7B
05
A9 STP X29, X30, [SP,
.text:
000000000001AD30
FD
43
01
91
ADD X29, SP,
.text:
000000000001AD34
FF
83
07
D1 SUB SP, SP,
.text:
000000000001AD38
48
D0
3B
D5 MRS X8,
.text:
000000000001AD3C
E8
07
00
F9
STR
X8, [SP,
.text:
000000000001AD40
08
15
40
F9 LDR X8, [X8,
.text:
000000000001AD44
F9
03
01
AA MOV X25, X1
.text:
000000000001AD48
FA
03
00
AA MOV X26, X0
.text:
000000000001AD4C
A8
03
1A
F8 STUR X8, [X29,
.text:
000000000001AD50
37
A0
40
A9 LDP X23, X8, [X1,
.text:
000000000001AD54
29
0C
40
F9 LDR X9, [X1,
.text:
000000000001AD58
E8
5B
00
F9
STR
X8, [SP,
.text:
000000000001AD5C
28
14
40
F9 LDR X8, [X1,
.text:
000000000001AD60
E9
0F
00
F9
STR
X9, [SP,
.text:
000000000001AD64
E8
5F
00
F9
STR
X8, [SP,
.text:
000000000001AD68
28
00
40
F9 LDR X8, [X1]
.text:
000000000001AD6C
E8
57
00
F9
STR
X8, [SP,
.text:
000000000001AD70
28
8F
44
78
LDRH W8, [X25,
.text:
000000000001AD74
68
00
00
34
CBZ W8, loc_1AD80
.text:
000000000001AD74
.text:
000000000001AD78
E8
03
00
32
MOV W8,
.text:
000000000001AD7C
28
E0
01
39
STRB W8, [X1,
.text:
000000000001AD7C
.text:
000000000001AD80
.text:
000000000001AD80
loc_1AD80 ; CODE XREF: bl_x8
+
5C
↑j
.text:
000000000001AD80
F4
02
40
79
LDRH W20, [X23]
.text:
000000000001AD84
28
60
02
91
ADD X8, X1,
.text:
000000000001AD88
F6
02
00
B0 ADRP X22,
.text:
000000000001AD8C
E8
53
00
F9
STR
X8, [SP,
.text:
000000000001AD90
88
1E
40
92
AND X8, X20,
.text:
000000000001AD94
D6 C2
19
91
ADD X22, X22,
.text:
000000000001AD98
38
40
02
91
ADD X24, X1,
.text:
000000000001AD9C
C8
7A
68
F8 LDR X8, [X22,X8,LSL
.text:
000000000001ADA0
29
00
03
91
ADD X9, X1,
.text:
000000000001ADA4
F8 A7
08
A9 STP X24, X9, [SP,
.text:
000000000001ADA8
29
A0
02
91
ADD X9, X1,
.text:
000000000001ADAC
E9
4F
00
F9
STR
X9, [SP,
.text:
000000000001ADB0
29
80
02
91
ADD X9, X1,
.text:
000000000001ADB4
3B
C0
02
91
ADD X27, X1,
.text:
000000000001ADB8
E9
67
07
A9 STP X9, X25, [SP,
.text:
000000000001ADBC
29
40
03
91
ADD X9, X1,
.text:
000000000001ADC0
E9
37
00
F9
STR
X9, [SP,
.text:
000000000001ADC4
E1
27
00
F9
STR
X1, [SP,
.text:
000000000001ADC8
FA
43
00
F9
STR
X26, [SP,
.text:
000000000001ADCC
FB
1F
00
F9
STR
X27, [SP,
.text:
000000000001ADD0
00
01
1F
D6 BR X8
.text:
000000000001AD18
FC
6F
BA A9 STP X28, X27, [SP,
.text:
000000000001AD1C
FA
67
01
A9 STP X26, X25, [SP,
.text:
000000000001AD20
F8
5F
02
A9 STP X24, X23, [SP,
.text:
000000000001AD24
F6
57
03
A9 STP X22, X21, [SP,
.text:
000000000001AD28
F4
4F
04
A9 STP X20, X19, [SP,
.text:
000000000001AD2C
FD
7B
05
A9 STP X29, X30, [SP,
.text:
000000000001AD30
FD
43
01
91
ADD X29, SP,
.text:
000000000001AD34
FF
83
07
D1 SUB SP, SP,
.text:
000000000001AD38
48
D0
3B
D5 MRS X8,
.text:
000000000001AD3C
E8
07
00
F9
STR
X8, [SP,
.text:
000000000001AD40
08
15
40
F9 LDR X8, [X8,
.text:
000000000001AD44
F9
03
01
AA MOV X25, X1
.text:
000000000001AD48
FA
03
00
AA MOV X26, X0
.text:
000000000001AD4C
A8
03
1A
F8 STUR X8, [X29,
.text:
000000000001AD50
37
A0
40
A9 LDP X23, X8, [X1,
.text:
000000000001AD54
29
0C
40
F9 LDR X9, [X1,
.text:
000000000001AD58
E8
5B
00
F9
STR
X8, [SP,
.text:
000000000001AD5C
28
14
40
F9 LDR X8, [X1,
.text:
000000000001AD60
E9
0F
00
F9
STR
X9, [SP,
.text:
000000000001AD64
E8
5F
00
F9
STR
X8, [SP,
.text:
000000000001AD68
28
00
40
F9 LDR X8, [X1]
.text:
000000000001AD6C
E8
57
00
F9
STR
X8, [SP,
.text:
000000000001AD70
28
8F
44
78
LDRH W8, [X25,
.text:
000000000001AD74
68
00
00
34
CBZ W8, loc_1AD80
.text:
000000000001AD74
.text:
000000000001AD78
E8
03
00
32
MOV W8,
.text:
000000000001AD7C
28
E0
01
39
STRB W8, [X1,
.text:
000000000001AD7C
.text:
000000000001AD80
.text:
000000000001AD80
loc_1AD80 ; CODE XREF: bl_x8
+
5C
↑j
.text:
000000000001AD80
F4
02
40
79
LDRH W20, [X23]
.text:
000000000001AD84
28
60
02
91
ADD X8, X1,
.text:
000000000001AD88
F6
02
00
B0 ADRP X22,
.text:
000000000001AD8C
E8
53
00
F9
STR
X8, [SP,
.text:
000000000001AD90
88
1E
40
92
AND X8, X20,
.text:
000000000001AD94
D6 C2
19
91
ADD X22, X22,
.text:
000000000001AD98
38
40
02
91
ADD X24, X1,
.text:
000000000001AD9C
C8
7A
68
F8 LDR X8, [X22,X8,LSL
.text:
000000000001ADA0
29
00
03
91
ADD X9, X1,
.text:
000000000001ADA4
F8 A7
08
A9 STP X24, X9, [SP,
.text:
000000000001ADA8
29
A0
02
91
ADD X9, X1,
.text:
000000000001ADAC
E9
4F
00
F9
STR
X9, [SP,
.text:
000000000001ADB0
29
80
02
91
ADD X9, X1,
.text:
000000000001ADB4
3B
C0
02
91
ADD X27, X1,
.text:
000000000001ADB8
E9
67
07
A9 STP X9, X25, [SP,
.text:
000000000001ADBC
29
40
03
91
ADD X9, X1,
.text:
000000000001ADC0
E9
37
00
F9
STR
X9, [SP,
.text:
000000000001ADC4
E1
27
00
F9
STR
X1, [SP,
.text:
000000000001ADC8
FA
43
00
F9
STR
X26, [SP,
.text:
000000000001ADCC
FB
1F
00
F9
STR
X27, [SP,
.text:
000000000001ADD0
00
01
1F
D6 BR X8
switch ( v63 )
{
case
'B'
:
v72
=
(v55
-
>functions
-
>NewByteArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'C'
:
v72
=
(v55
-
>functions
-
>NewCharArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'D'
:
v72
=
(v55
-
>functions
-
>NewDoubleArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'F'
:
v72
=
(v55
-
>functions
-
>NewFloatArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'I'
:
v72
=
(v55
-
>functions
-
>NewIntArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'J'
:
v72
=
(v55
-
>functions
-
>NewLongArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'S'
:
v72
=
(v55
-
>functions
-
>NewShortArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'Z'
:
v72
=
(v55
-
>functions
-
>NewBooleanArray)(v55, v57, a3, a4, a5, a6, a7, a8);
LABEL_24:
switch ( v63 )
{
case
'B'
:
v72
=
(v55
-
>functions
-
>NewByteArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'C'
:
v72
=
(v55
-
>functions
-
>NewCharArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'D'
:
v72
=
(v55
-
>functions
-
>NewDoubleArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'F'
:
v72
=
(v55
-
>functions
-
>NewFloatArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'I'
:
v72
=
(v55
-
>functions
-
>NewIntArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'J'
:
v72
=
(v55
-
>functions
-
>NewLongArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'S'
:
v72
=
(v55
-
>functions
-
>NewShortArray)(v55, v57, a3, a4, a5, a6, a7, a8);
goto LABEL_24;
case
'Z'
:
v72
=
(v55
-
>functions
-
>NewBooleanArray)(v55, v57, a3, a4, a5, a6, a7, a8);
LABEL_24:
cls_name
=
v58
-
>functions
-
>FindClass(v58, v100);
functions
=
v58
-
>functions;
v103
=
v58;
cls_name_2
=
cls_name;
v105
=
v58;
obj
=
*
(a39
+
8
*
a22);
functions
-
>ExceptionClear(&v105
-
>functions);
free(v100);
method_id
=
v103
-
>functions
-
>GetMethodID(&v103
-
>functions, cls_name_2, method_name, fun_sign);
free(fun_sign);
if
( method_id )
{
a40
=
0.0
;
v57
=
a32;
if
( v95 )
{
switch (
*
return_type )
{
case
'B'
:
v110
=
env
-
>functions
-
>CallNonvirtualByteMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_74;
case
'C'
:
v115
=
env
-
>functions
-
>CallNonvirtualCharMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_87;
case
'D'
:
env
-
>functions
-
>CallNonvirtualDoubleMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_89;
case
'F'
:
env
-
>functions
-
>CallNonvirtualFloatMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_78;
case
'I'
:
v112
=
env
-
>functions
-
>CallNonvirtualIntMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_81;
case
'J'
:
v113
=
COERCE_DOUBLE(env
-
>functions
-
>CallNonvirtualLongMethodA(env, obj, cls_name_2, method_id, args));
goto LABEL_84;
case
'L'
:
case
'['
:
v108
=
env;
v109
=
COERCE_DOUBLE(env
-
>functions
-
>CallNonvirtualObjectMethodA(env, obj, cls_name_2, method_id, args));
goto LABEL_68;
case
'S'
:
v117
=
env
-
>functions
-
>CallNonvirtualShortMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_92;
case
'V'
:
env
-
>functions
-
>CallNonvirtualVoidMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_93;
case
'Z'
:
v114
=
env
-
>functions
-
>CallNonvirtualBooleanMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_96;
default:
goto LABEL_97;
}
}
switch (
*
return_type )
{
case
'B'
:
v110
=
CallNonvirtualByteMethodV(env, obj, cls_name_2, method_id);
LABEL_74:
v44
=
v110;
goto LABEL_75;
case
'C'
:
v115
=
CallNonvirtualCharMethodV(env, obj, cls_name_2, method_id);
LABEL_87:
v44
=
v115;
cls_name
=
v58
-
>functions
-
>FindClass(v58, v100);
functions
=
v58
-
>functions;
v103
=
v58;
cls_name_2
=
cls_name;
v105
=
v58;
obj
=
*
(a39
+
8
*
a22);
functions
-
>ExceptionClear(&v105
-
>functions);
free(v100);
method_id
=
v103
-
>functions
-
>GetMethodID(&v103
-
>functions, cls_name_2, method_name, fun_sign);
free(fun_sign);
if
( method_id )
{
a40
=
0.0
;
v57
=
a32;
if
( v95 )
{
switch (
*
return_type )
{
case
'B'
:
v110
=
env
-
>functions
-
>CallNonvirtualByteMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_74;
case
'C'
:
v115
=
env
-
>functions
-
>CallNonvirtualCharMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_87;
case
'D'
:
env
-
>functions
-
>CallNonvirtualDoubleMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_89;
case
'F'
:
env
-
>functions
-
>CallNonvirtualFloatMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_78;
case
'I'
:
v112
=
env
-
>functions
-
>CallNonvirtualIntMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_81;
case
'J'
:
v113
=
COERCE_DOUBLE(env
-
>functions
-
>CallNonvirtualLongMethodA(env, obj, cls_name_2, method_id, args));
goto LABEL_84;
case
'L'
:
case
'['
:
v108
=
env;
v109
=
COERCE_DOUBLE(env
-
>functions
-
>CallNonvirtualObjectMethodA(env, obj, cls_name_2, method_id, args));
goto LABEL_68;
case
'S'
:
v117
=
env
-
>functions
-
>CallNonvirtualShortMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_92;
case
'V'
:
env
-
>functions
-
>CallNonvirtualVoidMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_93;
case
'Z'
:
v114
=
env
-
>functions
-
>CallNonvirtualBooleanMethodA(env, obj, cls_name_2, method_id, args);
goto LABEL_96;
default:
goto LABEL_97;
}
}
switch (
*
return_type )
{
case
'B'
:
v110
=
CallNonvirtualByteMethodV(env, obj, cls_name_2, method_id);
LABEL_74:
v44
=
v110;
goto LABEL_75;
case
'C'
:
v115
=
CallNonvirtualCharMethodV(env, obj, cls_name_2, method_id);
LABEL_87:
v44
=
v115;
while
(
1
){
/
/
一旦进入虚拟机就会开始读取字节码,除非遇到退出指令,否则一直执行下去
bytecode_ins
=
read(bytecode_buff);
/
/
不断的读取指令
exe(bytecode_ins)
/
/
运行指令
}
while
(
1
){
/
/
一旦进入虚拟机就会开始读取字节码,除非遇到退出指令,否则一直执行下去
bytecode_ins
=
read(bytecode_buff);
/
/
不断的读取指令
exe(bytecode_ins)
/
/
运行指令
}
.text:
00000076F68DBDD4
nop ; DATA XREF: .data.rel.ro:
00000076F6938940
↓o
.text:
00000076F68DBDD4
F7
0A
00
91
ADD X23, X23,
.text:
00000076F68DBDD8
F4
02
40
79
LDRH W20, [X23]
.text:
00000076F68DBDDC
88
1E
40
92
AND X8, X20,
.text:
00000076F68DBDE0
C8
7A
68
F8 LDR X8, [X22,X8,LSL
.text:
00000076F68DBDE4
00
01
1F
D6 BR X8
.text:
00000076F68DBDD4
nop ; DATA XREF: .data.rel.ro:
00000076F6938940
↓o
.text:
00000076F68DBDD4
F7
0A
00
91
ADD X23, X23,
.text:
00000076F68DBDD8
F4
02
40
79
LDRH W20, [X23]
.text:
00000076F68DBDDC
88
1E
40
92
AND X8, X20,
.text:
00000076F68DBDE0
C8
7A
68
F8 LDR X8, [X22,X8,LSL
.text:
00000076F68DBDE4
00
01
1F
D6 BR X8
.text:
00000076F68E0C0C
C9
02
00
B0 ADRP X9,
.text:
00000076F68E0C10
CB
02
00
B0 ADRP X11,
.text:
00000076F68E0C14
29
01
47
F9 LDR X9, [X9,
.text:
00000076F68E0C18
6B
45
47
F9 LDR X11, [X11,
.text:
00000076F68E0C1C
88
2E
48
D3 UBFX X8, X20,
.text:
00000076F68E0C20
8A
3E
4C
D3 UBFX X10, X20,
.text:
00000076F68E0C24
28
69
68
38
LDRB W8, [X9,X8]
.text:
00000076F68E0C28
69
69
6A
38
LDRB W9, [X11,X10]
.text:
00000076F68E0C2C
28
6D
1C
33
BFI W8, W9,
.text:
00000076F68E0C30
13
1D
00
13
SXTB W19, W8
.text:
00000076F68E0C34
F3
00
F8
36
TBZ W19,
.text:
00000076F68E0C34
.text:
00000076F68E0C38
28
03
40
39
LDRB W8, [X25]
.text:
00000076F68E0C3C
A8
00
20
36
TBZ W8,
.text:
00000076F68E0C3C
.text:
00000076F68E0C40
E8
5B
40
F9 LDR X8, [SP,
.text:
00000076F68E0C44
E0
27
40
F9 LDR X0, [SP,
.text:
00000076F68E0C48
17
01
1F
F8 STUR X23, [X8,
.text:
00000076F68E0C4C
F4 C8
00
94
BL sub_76F691301C
.text:
00000076F68E0C4C
.text:
00000076F68E0C50
.text:
00000076F68E0C50
loc_76F68E0C50 ; CODE XREF: goto
+
28
↑j
.text:
00000076F68E0C50
; goto
+
30
↑j
.text:
00000076F68E0C50
F7 C6
33
8B
ADD X23, X23, W19,SXTW
.text:
00000076F68E0C54
F4
02
40
79
LDRH W20, [X23]
.text:
00000076F68E0C58
88
1E
40
92
AND X8, X20,
.text:
00000076F68E0C5C
C8
7A
68
F8 LDR X8, [X22,X8,LSL
.text:
00000076F68E0C60
00
01
1F
D6 BR X8
.text:
00000076F68E0C0C
C9
02
00
B0 ADRP X9,
.text:
00000076F68E0C10
CB
02
00
B0 ADRP X11,
.text:
00000076F68E0C14
29
01
47
F9 LDR X9, [X9,
.text:
00000076F68E0C18
6B
45
47
F9 LDR X11, [X11,
.text:
00000076F68E0C1C
88
2E
48
D3 UBFX X8, X20,
.text:
00000076F68E0C20
8A
3E
4C
D3 UBFX X10, X20,
.text:
00000076F68E0C24
28
69
68
38
LDRB W8, [X9,X8]
.text:
00000076F68E0C28
69
69
6A
38
LDRB W9, [X11,X10]
.text:
00000076F68E0C2C
28
6D
1C
33
BFI W8, W9,
.text:
00000076F68E0C30
13
1D
00
13
SXTB W19, W8
.text:
00000076F68E0C34
F3
00
F8
36
TBZ W19,
.text:
00000076F68E0C34
.text:
00000076F68E0C38
28
03
40
39
LDRB W8, [X25]
.text:
00000076F68E0C3C
A8
00
20
36
TBZ W8,
.text:
00000076F68E0C3C
.text:
00000076F68E0C40
E8
5B
40
F9 LDR X8, [SP,
.text:
00000076F68E0C44
E0
27
40
F9 LDR X0, [SP,
.text:
00000076F68E0C48
17
01
1F
F8 STUR X23, [X8,
.text:
00000076F68E0C4C
F4 C8
00
94
BL sub_76F691301C
.text:
00000076F68E0C4C
.text:
00000076F68E0C50
.text:
00000076F68E0C50
loc_76F68E0C50 ; CODE XREF: goto
+
28
↑j
.text:
00000076F68E0C50
; goto
+
30
↑j
.text:
00000076F68E0C50
F7 C6
33
8B
ADD X23, X23, W19,SXTW
.text:
00000076F68E0C54
F4
02
40
79
LDRH W20, [X23]
.text:
00000076F68E0C58
88
1E
40
92
AND X8, X20,
.text:
00000076F68E0C5C
C8
7A
68
F8 LDR X8, [X22,X8,LSL
.text:
00000076F68E0C60
00
01
1F
D6 BR X8
data_rel
=
指令数据数组(fun1,fun2,fun3)
fun1(){
XXXXXX正文内容
下一套指令地址
=
read(data_rel(当前的数据)
+
fun1函数这个指令的长度)
bl 下一套指令地址
}
fun2(){
XXXXXX正文内容
下一套指令地址
=
read(data_rel(当前的数据)
+
fun1函数这个指令的长度)
bl 下一套指令地址
}
fun3(){
XXXXXX正文内容
下一套指令地址
=
read(data_rel(当前的数据)
+
fun1函数这个指令的长度)
bl 下一套指令地址
}
call fun1
data_rel
=
指令数据数组(fun1,fun2,fun3)
fun1(){
XXXXXX正文内容
下一套指令地址
=
read(data_rel(当前的数据)
+
fun1函数这个指令的长度)
bl 下一套指令地址
}
fun2(){
XXXXXX正文内容
下一套指令地址
=
read(data_rel(当前的数据)
+
fun1函数这个指令的长度)
bl 下一套指令地址
}
fun3(){
XXXXXX正文内容
下一套指令地址
=
read(data_rel(当前的数据)
+
fun1函数这个指令的长度)
bl 下一套指令地址
}
call fun1
v62
=
(
*
(
*
a30
+
0x58LL
)
+
*
(
*
(
*
a30
+
16LL
)
+
4
*
v59));
do
v64
=
*
v62
+
+
;
while
( (v64 &
0x80000000
) !
=
0
);
v62
=
(
*
(
*
a30
+
0x58LL
)
+
*
(
*
(
*
a30
+
16LL
)
+
4
*
v59));
do
v64
=
*
v62
+
+
;
while
( (v64 &
0x80000000
) !
=
0
);
import
idaapi
global_table
=
0x78D05D8E80
fun_id
=
158
fun_addr_ref
=
0x0
instr_fun_table
=
0x0
translator_8_12
=
[
3
,
2
,
1
,
0
,
7
,
6
,
5
,
4
,
0xb
,
0xA
,
9
,
8
,
0xF
,
0xE
,
0xD
,
0xC
]
translator_12_16
=
[
0xB
,
0xA
,
9
,
8
,
0xF
,
0xE
,
0xD
,
0xC
,
3
,
2
,
1
,
0
,
7
,
6
,
5
,
4
]
def
aget(instr_addr,x10):
print
(
"aget"
,
"arg:"
)
return
4
def
const_4(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
arg0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
]
arg1
=
translator_12_16[instr_0_2 >>
12
]
print
(
"const/4 v%d, %d"
%
(arg0,arg1))
return
2
def
const_16(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
arg0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
print
(
"const/16 v%d, %d"
%
(arg0,instr_2_4))
return
4
def
const(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
arg0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
print
(
"const v%d, %d"
%
(arg0,instr_2_4))
return
6
def
const_string(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
v60
=
instr_0_2 >>
12
v61
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
v63
=
16
*
(translator_12_16[v60] &
0xF
)
v75
=
v63 | v61
a38_index_11
=
read_mem_to_Int(x10
+
0x58
,
8
)
a38_index_2
=
read_mem_to_Int(x10
+
0x10
,
8
)
v3
=
read_mem_to_Int(instr_2_4
*
4
+
a38_index_2,
4
)
string
=
v3
+
a38_index_11
print
(
"const-string v%d, %s"
%
(v75,
hex
(string)))
return
4
def
xor(instr_addr,x10):
print
(
"xor"
,
"arg:"
)
return
4
def
move_16(instr_addr,x10):
print
(
"move-16"
,
"arg:"
)
return
2
def
iput_object(instr_addr,x10):
print
(
"iput_object"
,
"arg:"
)
return
4
def
aput_object(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v37
=
(instr_0_2 >>
8
) &
0xF
v38
=
instr_0_2 >>
12
v40
=
translator_8_12[v37];
v41
=
translator_12_16[v38];
arg_v1
=
v40 &
0xF
| (
16
*
(v41 &
0xF
))
arg_v2
=
read_mem_to_Int(instr_addr
+
2
,
1
)
arg_v3
=
read_mem_to_Int(instr_addr
+
3
,
1
)
print
(
"aput-object v%d, v%d, v%d"
%
(arg_v1,arg_v2,arg_v3))
return
4
def
goto(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v3
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
if
v3 >
=
128
:
int_num
=
(v3
-
256
)
*
2
else
:
int_num
=
v3
*
2
print
(
"goto"
,
"arg:"
,
hex
(instr_addr
+
int_num),int_num)
return
2
def
rsub(instr_addr,x10):
print
(
"rsub"
,
"arg:"
)
return
4
def
cmp
(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v1
=
read_mem_to_Int(instr_addr
+
2
,
1
)
v2
=
read_mem_to_Int(instr_addr
+
3
,
1
)
v3
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
print
(
"cmp"
,
"arg:"
,v3,v1,v2)
return
4
def
invoke_super(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_add_4
=
read_mem_to_Int(instr_addr
+
4
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
register_size
=
v63 >>
4
arg1
=
instr_add_4 &
0xF
arg2
=
instr_add_4 >>
4
&
0xF
arg3
=
(instr_add_4 >>
8
) &
0xf
arg4
=
instr_add_4 >>
12
arg5
=
v63 &
0xF
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
classname_str
=
get_class_name(x10,ref_index)
method_name_str
=
get_method_name(x10,ref_index)
type_name_str
=
get_proto_type_name(x10, ref_index)
print
(
"invoke-super "
,classname_str
+
"->"
+
method_name_str
+
type_name_str,
"method_ref_index"
,
hex
(ref_index),
"register:"
,register_size,
"arg1:"
,arg1,
"arg2:"
,arg2,
"arg3:"
,arg3,
"arg4:"
,arg4,
"arg5:"
,arg5)
return
6
def
invoke_direct(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_add_4
=
read_mem_to_Int(instr_addr
+
4
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
register_size
=
v63 >>
4
arg1
=
instr_add_4 &
0xF
arg2
=
instr_add_4 >>
4
&
0xF
arg3
=
(instr_add_4 >>
8
) &
0xf
arg4
=
instr_add_4 >>
12
arg5
=
v63 &
0xF
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
classname_str
=
get_class_name(x10,ref_index)
method_name_str
=
get_method_name(x10,ref_index)
type_name_str
=
get_proto_type_name(x10, ref_index)
print
(
"invoke-direct "
,classname_str
+
"->"
+
method_name_str
+
type_name_str,
"method_ref_index"
,
hex
(ref_index),
"register:"
,register_size,
"arg1:"
,arg1,
"arg2:"
,arg2,
"arg3:"
,arg3,
"arg4:"
,arg4,
"arg5:"
,arg5)
return
6
def
invoke_static(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_add_4
=
read_mem_to_Int(instr_addr
+
4
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
register_size
=
v63 >>
4
arg1
=
instr_add_4 &
0xF
arg2
=
instr_add_4 >>
4
&
0xF
arg3
=
(instr_add_4 >>
8
) &
0xf
arg4
=
instr_add_4 >>
12
arg5
=
v63 &
0xF
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
classname_str
=
get_class_name(x10,ref_index)
method_name_str
=
get_method_name(x10,ref_index)
type_name_str
=
get_proto_type_name(x10, ref_index)
print
(
"invoke-static "
,classname_str
+
"->"
+
method_name_str
+
type_name_str,
"method_ref_index"
,
hex
(ref_index),
"register:"
,register_size,
"arg1:"
,arg1,
"arg2:"
,arg2,
"arg3:"
,arg3,
"arg4:"
,arg4,
"arg5:"
,arg5)
return
6
def
invoke_interface(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_add_4
=
read_mem_to_Int(instr_addr
+
4
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
register_size
=
v63 >>
4
arg1
=
instr_add_4 &
0xF
arg2
=
instr_add_4 >>
4
&
0xF
arg3
=
(instr_add_4 >>
8
) &
0xf
arg4
=
instr_add_4 >>
12
arg5
=
v63 &
0xF
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
classname_str
=
get_class_name(x10,ref_index)
method_name_str
=
get_method_name(x10,ref_index)
type_name_str
=
get_proto_type_name(x10, ref_index)
print
(
"invoke-interface "
,classname_str
+
"->"
+
method_name_str
+
type_name_str,
"method_ref_index"
,
hex
(ref_index),
"register:"
,register_size,
"arg1:"
,arg1,
"arg2:"
,arg2,
"arg3:"
,arg3,
"arg4:"
,arg4,
"arg5:"
,arg5)
return
6
def
invoke_virutal(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_add_4
=
read_mem_to_Int(instr_addr
+
4
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
register_size
=
v63 >>
4
arg1
=
instr_add_4 &
0xF
arg2
=
instr_add_4 >>
4
&
0xF
arg3
=
(instr_add_4 >>
8
) &
0xf
arg4
=
instr_add_4 >>
12
arg5
=
v63 &
0xF
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
classname_str
=
get_class_name(x10,ref_index)
method_name_str
=
get_method_name(x10,ref_index)
type_name_str
=
get_proto_type_name(x10, ref_index)
print
(
"invoke-virtual "
,classname_str
+
"->"
+
method_name_str
+
type_name_str,
"method_ref_index"
,
hex
(ref_index),
"register:"
,register_size,
"arg1:"
,arg1,
"arg2:"
,arg2,
"arg3:"
,arg3,
"arg4:"
,arg4,
"arg5:"
,arg5)
return
6
def
rem_doule(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
print
(
"rem-doule"
,
hex
(v_arg_0),
hex
(instr_2_4))
return
4
def
move_result_object(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
print
(
"move-result-object v%d"
%
v_arg_0)
return
2
def
MonitorEnter(instr_addr,x10):
print
(
"MonitorEnter"
,
"arg:"
)
return
2
def
return_object(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
print
(
"return-object v%d"
%
v_arg_0)
return
2
def
move_object(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
];
v_arg_1
=
translator_12_16[instr_0_2 >>
12
]
print
(
"move-object v%d, v%d"
%
(v_arg_0,v_arg_1))
return
2
def
new_instance(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
dex_base_addr
=
read_mem_to_Int(x10
+
0x58
,
8
)
dex_type_off
=
read_mem_to_Int(x10
+
0x18
,
8
)
dex_string_list_off
=
read_mem_to_Int(x10
+
0x10
,
8
)
classname_str
=
byIndexGet_dex_type_name(dex_base_addr,dex_type_off,dex_string_list_off,ref_index)
print
(
"new-instance v%d, %s"
%
(v_arg_0,classname_str))
return
4
def
move_result(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
print
(
"move-result v%d"
%
v_arg_0)
return
2
def
new_array(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_size
=
translator_12_16[instr_0_2 >>
12
]
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
];
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
dex_base_addr
=
read_mem_to_Int(x10
+
0x58
,
8
)
dex_type_off
=
read_mem_to_Int(x10
+
0x18
,
8
)
dex_string_list_off
=
read_mem_to_Int(x10
+
0x10
,
8
)
classname_str
=
byIndexGet_dex_type_name(dex_base_addr,dex_type_off,dex_string_list_off,ref_index)
print
(
"new-array v%d, v%d, %s"
%
(v_arg_0,v_arg_size,classname_str))
return
4
def
if_ne(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
arg1
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
];
arg2
=
translator_12_16[instr_0_2 >>
12
];
print
(
"if-ne v%d, v%x, %x"
%
(arg1,arg2,instr_addr
+
instr_2_4
*
2
))
return
4
def
if_eqz(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
print
(
"if-eqz v%d, %x"
%
(v63,instr_addr
+
instr_2_4
*
2
))
return
4
def
if_gt(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
arg1
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
];
arg2
=
translator_12_16[instr_0_2 >>
12
];
print
(
"if-gt v%d, v%x, %x"
%
(arg1,arg2,instr_addr
+
instr_2_4
*
2
))
return
4
def
if_lt(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
arg1
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
];
arg2
=
translator_12_16[instr_0_2 >>
12
];
print
(
"if-lt v%d, v%x, %x"
%
(arg1,arg2,instr_addr
+
instr_2_4
*
2
))
return
4
def
if_lez(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
print
(
"if-lez v%d, %x"
%
(v63,instr_addr
+
instr_2_4
*
2
))
return
4
def
if_nez(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
print
(
"if-nez v%d, %x"
%
(v63,instr_addr
+
instr_2_4
*
2
))
return
4
def
iput(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
filed_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
v_arg_0
=
translator_12_16[instr_0_2 >>
12
]
v_arg_1
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
]
dex_filed_off
=
read_mem_to_Int(x10
+
0x20
,
8
)
class_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off,
2
)
filed_type_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off
+
2
,
2
)
name_string_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off
+
4
,
2
)
dex_base_addr
=
read_mem_to_Int(x10
+
0x58
,
8
)
dex_type_off
=
read_mem_to_Int(x10
+
0x18
,
8
)
dex_string_list_off
=
read_mem_to_Int(x10
+
0x10
,
8
)
class_type_string
=
byIndexGet_dex_type_name(dex_base_addr, dex_type_off, dex_string_list_off, class_index)
filed_type_string
=
byIndexGet_dex_type_name(dex_base_addr, dex_type_off, dex_string_list_off, filed_type_index)
name_string
=
byIndexGet_dex_string_name(dex_base_addr,dex_string_list_off,name_string_index)
print
(
"iput-object v%d, v%d, %s"
%
(v_arg_1,v_arg_0,class_type_string
+
"->"
+
name_string
+
":"
+
filed_type_string
+
" filed_index: "
+
filed_index))
return
4
def
aget_object(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
arg_1
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
arg_v2
=
read_mem_to_Int(instr_addr
+
2
,
1
)
arg_v3
=
read_mem_to_Int(instr_addr
+
3
,
1
)
print
(
"aget-object v%d, v%d, v%d"
%
(arg_1,arg_v2,arg_v3))
return
4
def
iget_object(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
filed_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
v_arg_0
=
translator_12_16[instr_0_2 >>
12
]
v_arg_1
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
]
dex_filed_off
=
read_mem_to_Int(x10
+
0x20
,
8
)
class_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off,
2
)
filed_type_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off
+
2
,
2
)
name_string_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off
+
4
,
2
)
dex_base_addr
=
read_mem_to_Int(x10
+
0x58
,
8
)
dex_type_off
=
read_mem_to_Int(x10
+
0x18
,
8
)
dex_string_list_off
=
read_mem_to_Int(x10
+
0x10
,
8
)
class_type_string
=
byIndexGet_dex_type_name(dex_base_addr, dex_type_off, dex_string_list_off, class_index)
filed_type_string
=
byIndexGet_dex_type_name(dex_base_addr, dex_type_off, dex_string_list_off, filed_type_index)
name_string
=
byIndexGet_dex_string_name(dex_base_addr,dex_string_list_off,name_string_index)
print
(
"iget-object v%d, v%d, %s"
%
(v_arg_1,v_arg_0,class_type_string
+
"->"
+
name_string
+
":"
+
filed_type_string
+
" filed_index: "
+
filed_index))
return
4
def
check_cast(instr_addr,x10):
type_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
dex_base_addr
=
read_mem_to_Int(x10
+
0x58
,
8
)
dex_type_off
=
read_mem_to_Int(x10
+
0x18
,
8
)
dex_string_list_off
=
read_mem_to_Int(x10
+
0x10
,
8
)
type_string
=
byIndexGet_dex_type_name(dex_base_addr, dex_type_off, dex_string_list_off, type_index)
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
print
(
"check-cast v%d, %s"
%
(v_arg,type_string))
return
4
def
sget_object(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
filed_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
dex_filed_off
=
read_mem_to_Int(x10
+
0x20
,
8
)
class_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off,
2
)
filed_type_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off
+
2
,
2
)
name_string_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off
+
4
,
2
)
dex_base_addr
=
read_mem_to_Int(x10
+
0x58
,
8
)
dex_type_off
=
read_mem_to_Int(x10
+
0x18
,
8
)
dex_string_list_off
=
read_mem_to_Int(x10
+
0x10
,
8
)
class_type_string
=
byIndexGet_dex_type_name(dex_base_addr, dex_type_off, dex_string_list_off, class_index)
filed_type_string
=
byIndexGet_dex_type_name(dex_base_addr, dex_type_off, dex_string_list_off, filed_type_index)
name_string
=
byIndexGet_dex_string_name(dex_base_addr,dex_string_list_off,name_string_index)
print
(
"sget-object v%d, %s"
%
(v_arg_0,class_type_string
+
"->"
+
name_string
+
":"
+
filed_type_string))
return
4
def
sget_boolean(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
filed_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
dex_filed_off
=
read_mem_to_Int(x10
+
0x20
,
8
)
class_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off,
2
)
filed_type_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off
+
2
,
2
)
name_string_index
=
read_mem_to_Int(
8
*
filed_index
+
dex_filed_off
+
4
,
2
)
dex_base_addr
=
read_mem_to_Int(x10
+
0x58
,
8
)
dex_type_off
=
read_mem_to_Int(x10
+
0x18
,
8
)
dex_string_list_off
=
read_mem_to_Int(x10
+
0x10
,
8
)
class_type_string
=
byIndexGet_dex_type_name(dex_base_addr, dex_type_off, dex_string_list_off, class_index)
filed_type_string
=
byIndexGet_dex_type_name(dex_base_addr, dex_type_off, dex_string_list_off, filed_type_index)
name_string
=
byIndexGet_dex_string_name(dex_base_addr,dex_string_list_off,name_string_index)
print
(
"sget-boolean v%d, %s"
%
(v_arg_0,class_type_string
+
"->"
+
name_string
+
":"
+
filed_type_string))
return
4
def
nop(instr_addr,x10):
print
(
"nop"
)
return
2
def
return_void(instr_addr,x10):
print
(
"return-void"
)
return
2
def
throw(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
print
(
"throw v%d"
%
v_arg_0)
return
2
def
throw_2(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
print
(
"move-exception v%d"
%
v_arg_0)
return
2
def
array_length(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
arg_0
=
translator_12_16[instr_0_2 >>
12
]
arg_1
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
]
print
(
"array-length v%d, v%d"
%
(arg_1,arg_0))
return
2
switch
=
{
0x0
:iput,
0x1
:invoke_super,
0x2
:aget,
0x3
:xor,
0x4
:move_16,
0x5
:iput_object,
0x5a
:nop,
0xd
:goto,
0xda
:aput_object ,
0x7
:rsub,
0x8
:
cmp
,
0x1e
:if_lez,
0x2b
:if_nez,
0x3e
:if_eqz,
0x3c
:if_gt,
0x21
:if_lt,
0x44
:const_16,
0xc3
:const,
0x5e
:move_result ,
0x68
:invoke_direct,
0xA6
:invoke_virutal,
0xAA
:new_instance,
0xc7
:move_result_object,
0xbb
:return_object,
0x92
:return_void,
0xfc
:move_object,
0x79
:invoke_interface,
0xf9
:check_cast,
0xf0
:const_4,
0xfa
:if_ne,
0x93
:sget_object,
0xc2
:sget_boolean,
0x9a
:invoke_static,
0x9b
:const_string,
0x1f
:new_array,
0x19
:iget_object,
0x9d
:MonitorEnter,
0xc4
:array_length,
0x6b
:aget_object,
0xf5
:throw,
0xee
:throw_2}
def
ByFunIDgetFunAddr(
id
):
offset_mem
=
int
.from_bytes(idaapi.dbg_read_memory(
4
*
id
+
global_table,
4
),byteorder
=
'little'
)
method_addr
=
global_table
+
offset_mem
print
(
"fun_id:"
,
hex
(
id
),
"method_addr:"
,
hex
(offset_mem),
"method_addr:"
,
hex
(method_addr))
return
method_addr
def
read_mem_to_String(addr,size):
mem
=
idaapi.dbg_read_memory(addr,size)
return
mem
def
read_mem_to_Int(addr, size):
mem
=
int
.from_bytes(idaapi.dbg_read_memory(addr,size),byteorder
=
'little'
)
return
mem
def
get_proto_type_name(x10, type_index):
dex_method_off
=
read_mem_to_Int(x10
+
0x28
,
8
)
dex_string_list_off
=
read_mem_to_Int(x10
+
0x10
,
8
)
dex_type_off
=
read_mem_to_Int(x10
+
0x18
,
8
)
dex_base_addr
=
read_mem_to_Int(x10
+
0x58
,
8
)
dex_proto_off
=
read_mem_to_Int(x10
+
0x30
,
8
)
proto_index
=
read_mem_to_Int(
8
*
type_index
+
dex_method_off
+
2
,
2
)
return_type_index
=
read_mem_to_Int(dex_proto_off
+
12
*
proto_index
+
4
,
4
)
pararm_off
=
read_mem_to_Int(dex_proto_off
+
12
*
proto_index
+
8
,
4
)
sign_type_string_list
=
"("
if
pararm_off !
=
0
:
pararm_size
=
read_mem_to_Int(dex_base_addr
+
pararm_off,
4
)
for
i
in
range
(pararm_size):
pararm_type_index
=
read_mem_to_Int(dex_base_addr
+
pararm_off
+
4
+
i
*
2
,
2
)
pararm_type_string
=
byIndexGet_dex_type_name(dex_base_addr, dex_type_off, dex_string_list_off, pararm_type_index)
sign_type_string_list
=
sign_type_string_list
+
pararm_type_string
return_type_string
=
byIndexGet_dex_type_name(dex_base_addr,dex_type_off,dex_string_list_off,return_type_index)
sign_type_string_list
=
sign_type_string_list
+
")"
+
return_type_string
return
sign_type_string_list
def
byIndexGet_dex_type_name(dex_base_addr,dex_type_off,dex_string_list_off,pararm_type_index):
string_index
=
read_mem_to_Int(pararm_type_index
*
4
+
dex_type_off,
4
)
type_string
=
byIndexGet_dex_string_name(dex_base_addr,dex_string_list_off,string_index)
return
type_string
def
byIndexGet_dex_string_name(dex_base_addr,dex_string_list_off,string_index):
v3
=
read_mem_to_Int(string_index
*
4
+
dex_string_list_off,
4
)
cla_len
=
read_mem_to_Int(dex_base_addr
+
v3,
1
)
class_str
=
idaapi.dbg_read_memory(dex_base_addr
+
v3
+
1
, cla_len).decode(
'utf-8'
)
print
(
"byIndexGet_dex_string_name:"
,
hex
(dex_base_addr
+
v3))
return
class_str
def
get_class_name(x10,class_index):
a38_index_5
=
read_mem_to_Int(x10
+
0x28
,
8
)
a38_index_2
=
read_mem_to_Int(x10
+
0x10
,
8
)
a38_index_3
=
read_mem_to_Int(x10
+
0x18
,
8
)
a38_index_11
=
read_mem_to_Int(x10
+
0x58
,
8
)
v1
=
read_mem_to_Int(
8
*
class_index
+
a38_index_5,
2
)
v2
=
read_mem_to_Int(v1
*
4
+
a38_index_3,
4
)
v3
=
read_mem_to_Int(v2
*
4
+
a38_index_2,
4
)
class_str_addr
=
v3
+
a38_index_11
cla_len
=
read_mem_to_Int(class_str_addr,
1
)
class_str
=
idaapi.dbg_read_memory(class_str_addr
+
1
, cla_len).decode(
'utf-8'
)
return
class_str
def
get_method_name(x10, method_index):
a38_index_5
=
read_mem_to_Int(x10
+
0x28
,
8
)
a38_index_2
=
read_mem_to_Int(x10
+
0x10
,
8
)
a38_index_3
=
read_mem_to_Int(x10
+
0x18
,
8
)
a38_index_11
=
read_mem_to_Int(x10
+
0x58
,
8
)
v1
=
read_mem_to_Int(
8
*
method_index
+
a38_index_5
+
4
,
2
)
v3
=
read_mem_to_Int(v1
*
4
+
a38_index_2,
4
)
method_name_str_addr
=
v3
+
a38_index_11
method_name_str_len
=
read_mem_to_Int(method_name_str_addr,
1
)
method_name_str
=
idaapi.dbg_read_memory(method_name_str_addr
+
1
, method_name_str_len).decode(
'utf-8'
)
return
method_name_str
def
get_method_arg(x10, index):
a38_index_5
=
read_mem_to_Int(x10
+
0x28
,
8
)
a38_index_2
=
read_mem_to_Int(x10
+
0x10
,
8
)
a38_index_3
=
read_mem_to_Int(x10
+
0x18
,
8
)
a38_index_11
=
read_mem_to_Int(x10
+
0x58
,
8
)
a38_index_6
=
read_mem_to_Int(x10
+
0x30
,
8
)
v0
=
read_mem_to_Int(
8
*
index
+
a38_index_5
+
2
,
2
)
v80
=
read_mem_to_Int(a38_index_6
+
12
*
v0
+
8
,
4
)
print
(
"arg_addr a38_index_5:"
,
hex
(a38_index_5))
print
(
"arg_addr a38_index_2:"
,
hex
(a38_index_2))
print
(
"arg_addr a38_index_3:"
,
hex
(a38_index_3))
print
(
"arg_addr a38_index_11:"
,
hex
(a38_index_11))
print
(
"arg_addr a38_index_6:"
,
hex
(a38_index_6))
print
(
"arg_addr v80:"
,v80)
v81
=
v80
+
a38_index_11
v1
=
read_mem_to_Int(v81
+
2
,
4
)
v2
=
read_mem_to_Int(v1
*
4
+
a38_index_3,
4
)
v3
=
read_mem_to_Int(v2
*
4
+
a38_index_2,
4
)
return_type
=
v3
+
a38_index_11
print
(
"arg_addr:"
,return_type)
return
return_type
def
get_segment_address(segment_name):
seg
=
idaapi.get_segm_by_name(segment_name)
if
seg
is
not
None
:
return
seg.start_ea, seg.end_ea
else
:
return
None
def
main():
method_addr
=
ByFunIDgetFunAddr(fun_id)
register_size
=
read_mem_to_Int(method_addr,
2
)
ins_size
=
read_mem_to_Int(method_addr
+
2
,
2
)
insns_size
=
read_mem_to_Int(method_addr
+
12
,
4
)
print
(
"method registers_size:"
,
hex
(register_size))
print
(
"method ins_size:"
,
hex
(ins_size))
print
(
"method insns_size:"
,
hex
(insns_size))
method_addr_2
=
ByFunIDgetFunAddr(fun_id
+
1
)
funSize
=
method_addr_2
-
method_addr
print
(
"method_size:"
,
hex
(funSize))
instr_addr
=
method_addr
+
0x10
print
(
"method_end:"
,
hex
(instr_addr
+
insns_size
*
2
))
while
(
1
):
offset
=
read_mem_to_Int(instr_addr,
2
) &
0xff
instr_fun_addr
=
instr_fun_table
+
offset
*
8
print
(
"-----------------------------------"
)
print
(
"instr_fun_addr:"
,
hex
(instr_fun_addr),
hex
(offset))
instr_handle
=
switch[offset]
print
(
"instr_addr:"
,
hex
(instr_addr))
print
(
hex
(offset))
if
(instr_handle
=
=
None
):
break
instr_len
=
instr_handle(instr_addr, fun_addr_ref)
instr_addr
=
instr_addr
+
instr_len
print
(
hex
(offset))
def
init_var():
global
global_table
global
instr_fun_table
global
fun_addr_ref
bss_start, bss_end
=
get_segment_address(
".bss"
)
qword_78B9BFCDC8
=
read_mem_to_Int(bss_start
+
0x2B8
,
8
)
global_table
=
read_mem_to_Int(bss_start
+
0x270
,
8
)
yaq2__sec
=
read_mem_to_Int(bss_start
+
0x2B0
,
8
)
v6
=
yaq2__sec
+
fun_id
*
12
v6_index_1
=
read_mem_to_Int(v6
+
4
,
4
)
v6_index_2
=
read_mem_to_Int(v6
+
8
,
4
)
fun_addr_ref
=
read_mem_to_Int(
8
*
(v6_index_2
-
1
)
+
qword_78B9BFCDC8,
8
)
instr_fun_table, data_rel_end
=
get_segment_address(
".data.rel.ro"
)
print
(
"qword_78B9BFCDC8"
,
hex
(qword_78B9BFCDC8))
print
(
"global_table"
,
hex
(global_table))
print
(
"v6_index_1"
,
hex
(v6_index_1))
print
(
"v6_index_2"
,
hex
(v6_index_2))
print
(
"fun_addr_ref"
,
hex
(fun_addr_ref))
if
__name__
=
=
'__main__'
:
init_var()
main()
import
idaapi
global_table
=
0x78D05D8E80
fun_id
=
158
fun_addr_ref
=
0x0
instr_fun_table
=
0x0
translator_8_12
=
[
3
,
2
,
1
,
0
,
7
,
6
,
5
,
4
,
0xb
,
0xA
,
9
,
8
,
0xF
,
0xE
,
0xD
,
0xC
]
translator_12_16
=
[
0xB
,
0xA
,
9
,
8
,
0xF
,
0xE
,
0xD
,
0xC
,
3
,
2
,
1
,
0
,
7
,
6
,
5
,
4
]
def
aget(instr_addr,x10):
print
(
"aget"
,
"arg:"
)
return
4
def
const_4(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
arg0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
]
arg1
=
translator_12_16[instr_0_2 >>
12
]
print
(
"const/4 v%d, %d"
%
(arg0,arg1))
return
2
def
const_16(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
arg0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
print
(
"const/16 v%d, %d"
%
(arg0,instr_2_4))
return
4
def
const(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
arg0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
print
(
"const v%d, %d"
%
(arg0,instr_2_4))
return
6
def
const_string(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
v60
=
instr_0_2 >>
12
v61
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
v63
=
16
*
(translator_12_16[v60] &
0xF
)
v75
=
v63 | v61
a38_index_11
=
read_mem_to_Int(x10
+
0x58
,
8
)
a38_index_2
=
read_mem_to_Int(x10
+
0x10
,
8
)
v3
=
read_mem_to_Int(instr_2_4
*
4
+
a38_index_2,
4
)
string
=
v3
+
a38_index_11
print
(
"const-string v%d, %s"
%
(v75,
hex
(string)))
return
4
def
xor(instr_addr,x10):
print
(
"xor"
,
"arg:"
)
return
4
def
move_16(instr_addr,x10):
print
(
"move-16"
,
"arg:"
)
return
2
def
iput_object(instr_addr,x10):
print
(
"iput_object"
,
"arg:"
)
return
4
def
aput_object(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v37
=
(instr_0_2 >>
8
) &
0xF
v38
=
instr_0_2 >>
12
v40
=
translator_8_12[v37];
v41
=
translator_12_16[v38];
arg_v1
=
v40 &
0xF
| (
16
*
(v41 &
0xF
))
arg_v2
=
read_mem_to_Int(instr_addr
+
2
,
1
)
arg_v3
=
read_mem_to_Int(instr_addr
+
3
,
1
)
print
(
"aput-object v%d, v%d, v%d"
%
(arg_v1,arg_v2,arg_v3))
return
4
def
goto(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v3
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
if
v3 >
=
128
:
int_num
=
(v3
-
256
)
*
2
else
:
int_num
=
v3
*
2
print
(
"goto"
,
"arg:"
,
hex
(instr_addr
+
int_num),int_num)
return
2
def
rsub(instr_addr,x10):
print
(
"rsub"
,
"arg:"
)
return
4
def
cmp
(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v1
=
read_mem_to_Int(instr_addr
+
2
,
1
)
v2
=
read_mem_to_Int(instr_addr
+
3
,
1
)
v3
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
print
(
"cmp"
,
"arg:"
,v3,v1,v2)
return
4
def
invoke_super(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_add_4
=
read_mem_to_Int(instr_addr
+
4
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
register_size
=
v63 >>
4
arg1
=
instr_add_4 &
0xF
arg2
=
instr_add_4 >>
4
&
0xF
arg3
=
(instr_add_4 >>
8
) &
0xf
arg4
=
instr_add_4 >>
12
arg5
=
v63 &
0xF
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
classname_str
=
get_class_name(x10,ref_index)
method_name_str
=
get_method_name(x10,ref_index)
type_name_str
=
get_proto_type_name(x10, ref_index)
print
(
"invoke-super "
,classname_str
+
"->"
+
method_name_str
+
type_name_str,
"method_ref_index"
,
hex
(ref_index),
"register:"
,register_size,
"arg1:"
,arg1,
"arg2:"
,arg2,
"arg3:"
,arg3,
"arg4:"
,arg4,
"arg5:"
,arg5)
return
6
def
invoke_direct(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_add_4
=
read_mem_to_Int(instr_addr
+
4
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
register_size
=
v63 >>
4
arg1
=
instr_add_4 &
0xF
arg2
=
instr_add_4 >>
4
&
0xF
arg3
=
(instr_add_4 >>
8
) &
0xf
arg4
=
instr_add_4 >>
12
arg5
=
v63 &
0xF
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
classname_str
=
get_class_name(x10,ref_index)
method_name_str
=
get_method_name(x10,ref_index)
type_name_str
=
get_proto_type_name(x10, ref_index)
print
(
"invoke-direct "
,classname_str
+
"->"
+
method_name_str
+
type_name_str,
"method_ref_index"
,
hex
(ref_index),
"register:"
,register_size,
"arg1:"
,arg1,
"arg2:"
,arg2,
"arg3:"
,arg3,
"arg4:"
,arg4,
"arg5:"
,arg5)
return
6
def
invoke_static(instr_addr, x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_add_4
=
read_mem_to_Int(instr_addr
+
4
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
register_size
=
v63 >>
4
arg1
=
instr_add_4 &
0xF
arg2
=
instr_add_4 >>
4
&
0xF
arg3
=
(instr_add_4 >>
8
) &
0xf
arg4
=
instr_add_4 >>
12
arg5
=
v63 &
0xF
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
classname_str
=
get_class_name(x10,ref_index)
method_name_str
=
get_method_name(x10,ref_index)
type_name_str
=
get_proto_type_name(x10, ref_index)
print
(
"invoke-static "
,classname_str
+
"->"
+
method_name_str
+
type_name_str,
"method_ref_index"
,
hex
(ref_index),
"register:"
,register_size,
"arg1:"
,arg1,
"arg2:"
,arg2,
"arg3:"
,arg3,
"arg4:"
,arg4,
"arg5:"
,arg5)
return
6
def
invoke_interface(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_add_4
=
read_mem_to_Int(instr_addr
+
4
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
register_size
=
v63 >>
4
arg1
=
instr_add_4 &
0xF
arg2
=
instr_add_4 >>
4
&
0xF
arg3
=
(instr_add_4 >>
8
) &
0xf
arg4
=
instr_add_4 >>
12
arg5
=
v63 &
0xF
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
classname_str
=
get_class_name(x10,ref_index)
method_name_str
=
get_method_name(x10,ref_index)
type_name_str
=
get_proto_type_name(x10, ref_index)
print
(
"invoke-interface "
,classname_str
+
"->"
+
method_name_str
+
type_name_str,
"method_ref_index"
,
hex
(ref_index),
"register:"
,register_size,
"arg1:"
,arg1,
"arg2:"
,arg2,
"arg3:"
,arg3,
"arg4:"
,arg4,
"arg5:"
,arg5)
return
6
def
invoke_virutal(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
instr_add_4
=
read_mem_to_Int(instr_addr
+
4
,
2
)
v63
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
));
register_size
=
v63 >>
4
arg1
=
instr_add_4 &
0xF
arg2
=
instr_add_4 >>
4
&
0xF
arg3
=
(instr_add_4 >>
8
) &
0xf
arg4
=
instr_add_4 >>
12
arg5
=
v63 &
0xF
ref_index
=
read_mem_to_Int(instr_addr
+
2
,
2
)
classname_str
=
get_class_name(x10,ref_index)
method_name_str
=
get_method_name(x10,ref_index)
type_name_str
=
get_proto_type_name(x10, ref_index)
print
(
"invoke-virtual "
,classname_str
+
"->"
+
method_name_str
+
type_name_str,
"method_ref_index"
,
hex
(ref_index),
"register:"
,register_size,
"arg1:"
,arg1,
"arg2:"
,arg2,
"arg3:"
,arg3,
"arg4:"
,arg4,
"arg5:"
,arg5)
return
6
def
rem_doule(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
print
(
"rem-doule"
,
hex
(v_arg_0),
hex
(instr_2_4))
return
4
def
move_result_object(instr_addr,x10):
instr_0_2
=
read_mem_to_Int(instr_addr,
2
)
v_arg_0
=
translator_8_12[(instr_0_2 >>
8
) &
0xF
] &
0xF
| (
16
*
(translator_12_16[instr_0_2 >>
12
] &
0xF
))
instr_2_4
=
read_mem_to_Int(instr_addr
+
2
,
2
)
print
(
"move-result-object v%d"
%
v_arg_0)
return
2
def
MonitorEnter(instr_addr,x10):
print
(
"MonitorEnter"
,
"arg:"
)
return
2
def
return_object(instr_addr,x10):
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2024-4-19 23:16
被Thehepta编辑
,原因: