Android逆向不可不知的smali语言

1.smali语言简介

smali是Dalvik的寄存器语言,smali代码是安卓apk反编译而来的,两者文件是一一对应的,获取smali需要ApkTool工具。
smali语言比较简单,如果你会java和Android相关知识,就可以通过修改smali语言来改变java的代码,进而可以修改apk文件。

2.smali语法

.class public LHelloWorld;
.super Ljava/lang/Object;
.method public static main([Ljava/lang/String;])V
  • 前三行指明了类名,父类名,和源文件名。
  • 类名以“L”开头相信熟悉Jni的童鞋都比较清楚。
  • “#”是smali中的注释。
  • “.method”和“.end method”类似于Java中的大括号,包含了方法的实现代码段。
  • 方法的括号后面指明了返回类型,这同样类似与Jni的调用。
  • “.locals”指明了这个方法用到的寄存器数量,当然寄存器可以重复利用,从“V0”起算。
  • “.prologue”指定了代码开始处。
  • “.line”表明这是在java源码中的第几行,其实这个值无所谓是多少,可以任意修改,主要用于调试。
  • “invoke-direct”这是对方法的调用,可以看到这里调用了是Android.app.Activity的init方法,这在java里是隐式调用的。
  • “return-void”表明了返回类型,这和java不一样,即使没有返回值,也需要这样写。
  • 接下来是onCreate方法,“.parameter”指明了参数名,但是一般没有用,需要注意的是p0代表的是this,p1开始代表函数参数,静态函数没有this,所以从p0开始就代表参数。
  • 在实现里先是调用了父类的方法,然后再调用setContentView,注意这里给了一个传参。整形的传参,这个值是先赋给寄存器v0,然后再调用的使用传递进去的。smali中都是这么使用,所有的值必须通过寄存器来中转。这点和汇编很像。

2.1 基本数据类型

smali类型 java类型
V void
Z boolean
B byte
S short
C char
I int
J long (64位 需要2个寄存器存储)
F float
D double (64位 需要2个寄存器存储)

2.2 对象

smali对象 java对象
Lpackage/name/ObjectName; package.name.ObjectName
Ljava/lang/String; java.lang.String

注:L 表示对象类型
package/name 表示包名
; 表示结束

2.3 数组

smali数组 java数组
[I int[] 一维数组
[[I int[][] 二维数组
[Ljava/lang/String String[] 对象数组

注:每一维最多255个

2.4 类字段/变量

Lpackage/name/ObjectName;——>FieldName:Ljava/lang/String;

smali字段 java字段
public f1:Z public boolean f1;
public f2:I public int f2;
public f3:L java/lang/String; public String f3;

2.5 类方法/函数

smali方法 java方法
myMethod([I)Ljava/lang/String; String myMethod(int[])
//Java代码
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
}
#samli代码
.method protected onCreate(Landroid/os/Bundle;)V
.locals 1
.parameter "savedInstanceState"
.prologue
.line 8
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
.line 9
const/high16 v0, 0x7f03
invoke-virtual {p0, v0}, Lcom/fusijie/helloworld/MainActivity;->setContentView(I)V
.line 10
return-void
.end method

2.6 条件判断语句(if)

if-eq p1, v0, :c1
:c1
invoke-direct {p0}, Lcom/paul/test/a;->d()V

解读:如果p1和v0相等,则执行c1流程

if-ne p1, v0, :c2
:c2
invoke-direct {p0}, Lcom/paul/test/a;->c()V

解读:表示不相等,则执行c2流程

if-gt 大于
if-ge 大于等于
if-lt 小于
if-le 小于等于
"if-eq vA, vB, :cond_**"   如果vA等于vB则跳转到:cond_**
"if-ne vA, vB, :cond_**"   如果vA不等于vB则跳转到:cond_**
"if-lt vA, vB, :cond_**"    如果vA小于vB则跳转到:cond_**
"if-ge vA, vB, :cond_**"   如果vA大于等于vB则跳转到:cond_**
"if-gt vA, vB, :cond_**"   如果vA大于vB则跳转到:cond_**
"if-le vA, vB, :cond_**"    如果vA小于等于vB则跳转到:cond_**
"if-eqz vA, :cond_**"   如果vA等于0则跳转到:cond_**
"if-nez vA, :cond_**"   如果vA不等于0则跳转到:cond_**
"if-ltz vA, :cond_**"    如果vA小于0则跳转到:cond_**
"if-gez vA, :cond_**"   如果vA大于等于0则跳转到:cond_**
"if-gtz vA, :cond_**"   如果vA大于0则跳转到:cond_**
"if-lez vA, :cond_**"    如果vA小于等于0则跳转到:cond_**

推荐AS中的插件java2smali

地址:https://plugins.jetbrains.com/plugin/7385-java2smali

个人总结

smali比java复杂很多,但是不难,相当于把java语言中更多的信息给还原出来,同时显式地指定了很多细节。

Dalvik虚拟机

Android4.4系统是个分水岭,ART模式很多机制是和Dalvik。
Dalvik是心脏,
寄存器,内存,

你可能感兴趣的:(android,smali,逆向,逆向,android,smali)