
本公众号分享的所有技术仅用于学习交流,请勿用于其他非法活动,如有错漏,欢迎留言指正
Java层逆向分析方法和技巧
一、smali汇编
1. Dalvik字节码
- java字节码、Dalvik字节码、机器码之间的关系?
- 在Android上,
Java代码
首先经过编译器编译成Java字节码
,然后再经过dx工具转换成Dalvik字节码
,并打包到apk文件中(存储在DEX(Dalvik Executable)文件中),Dalvik字节码最终转换为机器码
Android设备上运行。(因为大多数Android设备都是使用ARM处理器。因此,Android系统对应用程序的代码进行编译时,生成的是与ARM处理器兼容的机器码
。)
- 编译器编译Java代码成
Java字节码
是为了将Java代码转换成机器无关
的中间代码,使得编译后的代码可以在任何支持JVM的系统上运行,不受机器的体系结构的限制。
- 而
Dalvik字节码
是专门为Android系统优化的字节码,它比Java字节码更加高效。Dalvik字节码在一定程度上是Java字节码的一个子集
。
- Java字节码和Dalvik字节码是两种不同的字节码格式,它们的区别主要体现在
文件格式
(java字节码文件扩展名为.class,Dalvik字节码文件扩展名为.dex。),存储方式
(Java字节码在Java虚拟机中一次性加载,并在内存中存储;Dalvik字节码是以dalvik指令为单位存储的,仅加载需要的部分。),运行方式
等方面(Java字节码直接在Java虚拟机中执行,Dalvik字节码在Dalvik虚拟机中执行,但需要经过dalvik指令集解释执行
(Dalvik字节码->arm机器码)。)
- Dalvik字节码和smali的关系?
Smali
是一种对Dalvik字节码
进行编码的人类可读的汇编语言,是对Dalvik指令的高级抽象。
Dalvik字节码
是以二进制形式存在于 .dex
文件中,而 smali
是以文本形式存在于磁盘文件中,是将 Dalvik字节码
反编译回文本文件的结果。
- 为什么有了
ART
虚拟机,为什么还需要学Dalvik
字节码?
- Dalvik虚拟机是在
启动应用程序时
,将Dalvik字节码动态编译
成机器码来实现运行的。所以对于每次打开一个应用程序,是需要进行编译的。
- 在Android 5.0以后的版本,ART已经取代了Dalvik作为Android的默认虚拟机。
- ART虚拟机机是在
安装应用程序时
,将Dalvik字节码预先编译
成机器码来实现运行的。因此不再需要在每次启动应用程序时进行编译,提高运行速度。
- 可以看到只是编译的时机不同而已。无论是Dalvik虚拟机还是ART虚拟机,
dex文件是没有变的
,即还是Dalvik
字节码,反汇编得到Smali汇编,可以通过Smali汇编语言重写和修改应用程序的Dalvik字节码,以实现各种定制化效果和优化性能。2. Smali汇编
寄存器命名方法:V与P
- JAVA虚拟机使用了
栈架构
,Java字节码被执行时通过一个操作栈来进行解释,每个方法在运行时都有一个私有的操作栈。
- Dalvik (ART)虚拟机基于
寄存器架构
,不是使用操作栈来执行字节码,而是使用寄存器,速度快,节省代码。
- V命名法:所有变量(局部,参数都用V0,1,...命名)
- P命名法:
局部变量用V
,参数用P
,容易判断局部变量和参数

类型描述符
C
表示字符(char),用来存储 8 位字符,用一个32位的Dalvik寄存器来存储。
l
表示布尔型(boolean),用来存储 8 位布尔型,用一个32位的Dalvik寄存器来存储。
S
表示短整型(short),用来存储 16 位短整型,用一个32位的Dalvik寄存器来存储。
I
表示整型(int),用来存储 32 位有符号整数。用一个32位的Dalvik寄存器来存储。
J
表示长整型(long),用来存储 64
位有符号整数。用两个相邻的32位Dalvik寄存器来存储。
F
表示单精度浮点类型(float),用来存储 32 位单精度浮点数。用一个32位的Dalvik寄存器来存储。
D
表示双精度浮点类型(double),用来存储 64
位双精度浮点数。用两个相邻的32位Dalvik寄存器来存储。
v
表示无返回值的void类型
[
表示数组类型,后面跟着一个 Smali 类型描述符,代表这个数组存储的数据类型。
[I
表示int []
[II
表示int[][]
,每多一维就加一个方括号,最多可以设置255维。
L
+对象的全限定名
表示对象类型(L``Package/Name/ObjectName;
注意后面分号结束)
- 比如String,其完整名称是
java.lang.String
,那么其全限定名就是java/lang/String;
,即java.lang.String
的”.”用”/”代替,并在末尾添加分号”;”做结束符.
- 成员:
Lcom/MyClass;``->``name:Ljava/lang/String;
(`对象类型;->成员名:成员类型)``
- 方法:
LPackage/Name/objectName;``->``myFunc(III)Z
(对象类型;->函数名:(参数类型)返回值
)III
表示3int参数
- 函数:fun(
Z
[I
[II
Ljava/lang/String;
J
[Ljava/lang/Object;
)Ljava/lang/String;
(string fun(boolean, int[],int[][],String,long,Object[]
))
- 直接方法:static、构造、包含静态语句块(比如静态数组初始化)
- 虚方法
指令
- 数据定义指令
- 数据操作指令
- 实例操作指令
- 数组操作指令
- 比较指令
- 跳转指令
- 字段操作指令
- 数据转换指令
- 算术指令
- 空指令锁指令
- 异常指令
- 方法调用指令
- 返回指令
3. smali文件详解
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | . class public Lcom / example / helloworld / HelloWorld;
. super Ljava / lang / Object ;
.method public static main([Ljava / lang / String;)V
.registers 4
.parameter 1
. locals 3
.prologue
nop
const / 16 v0, 0x8
const / 4 v1, 0x5
const / 4 v2, 0x3
move v1, v2
new - array v0, v0, [I
array - length v1, v0
new - instance v1, Ljava / lang / StringBuilder;
invoke - direct {v1}, Ljava / lang / StringBuilder; - ><init>()V
if - nez v0, :cond_0
goto :goto_0
:cond_0
int - to - float v2, v2
add - float v2, v2, v2
cmpl - float v0, v2, v2
sget - object v0, Ljava / lang / System; - >out:Ljava / io / PrintStream;
const - string v1, "Hello World"
invoke - virtual {v0, v1}, Ljava / io / PrintStream; - >println(Ljava / lang / String;)V
:goto_0
return - void
.end method
|
还原成java代码
更多内容请移步公众号:坚毅猿
386K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0M7q4)9J5k6i4N6W2K9i4S2A6L8W2)9J5k6i4q4I4i4K6u0W2j5$3!0E0i4K6u0r3M7#2)9K6c8W2)9#2k6W2)9#2k6X3u0A6P5W2)9K6c8p5#2*7g2e0g2z5P5V1f1J5e0X3A6y4P5f1#2%4i4K6y4p5i4K6y4p5i4K6t1$3j5h3#2H3i4K6y4n7L8h3W2V1i4K6y4p5x3U0t1@1y4K6b7^5y4K6f1K6y4#2)9J5y4X3q4E0M7q4)9K6b7X3W2V1P5q4)9K6c8o6q4Q4x3U0k6S2L8i4m8Q4x3@1u0K6L8W2)9K6c8o6t1$3k6o6W2X3k6h3p5K6k6o6V1K6j5e0g2V1z5e0V1^5j5$3c8U0y4h3p5K6x3e0M7#2y4K6g2X3z5o6x3@1i4K6t1$3j5h3#2H3i4K6y4n7j5$3S2C8M7$3#2Q4x3@1c8X3k6e0f1$3j5K6q4S2k6r3x3&6x3U0p5@1z5r3u0T1j5U0x3K6k6U0l9K6x3K6f1$3z5e0k6S2y4r3j5J5k6U0p5@1x3o6y4V1y4X3x3I4k6X3c8U0y4$3u0U0x3U0l9K6y4X3t1@1x3U0f1H3z5o6M7$3j5e0y4T1k6o6S2U0x3U0y4S2z5r3p5%4x3K6x3I4j5$3j5#2i4K6t1$3j5h3#2H3i4K6y4n7M7r3q4&6M7X3g2S2k6s2c8A6j5$3E0W2N6q4)9K6c8p5S2s2g2@1)9H3h3W2W2v1j5W2u0*7c8X3E0Z5y4s2f1I4c8g2c8t1y4V1N6q4g2V1#2c8K9$3V1J5x3X3E0w2c8@1u0K9N6Y4k6c8c8e0k6K6y4X3&6S2N6U0g2r3M7K6u0n7h3Y4N6J5g2W2g2J5P5e0S2g2x3i4m8t1x3h3E0k6M7i4m8*7x3i4S2%4i4K6t1K6M7X3b7`.
[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!
最后于 2023-2-9 11:04
被公众号坚毅猿编辑
,原因: