将安全君呀设为"星标⭐️"
第一时间收到文章更新
声明: 安全君呀 公众号文章中的技术只做研究之用,禁止用来从事非法用途,如有使用文章中的技术从事非法活动,一切后果由使用者自负,与本公众号无关。
文章声明:本篇文章内容部分选取网络,如有侵权,请告知删除。
什么是Smali
Smali--破解的重中之重
Smali,Baksmali分别是指安卓系统里的Java虚拟机(Dalvik)所使用的一种。dex格式文件的汇编器,反汇编器。其语法是一种宽松式的Jasmin/dedexer语法,而且它实现了.dex格式所有功能(注解,调试信息,线路信息等)
当我们对APK文件进行反编译后,便会生成此类的文件。其中在Davlik字节码中,寄存器都是32位的,能够支持任何类型,64位类型(Long/Double)用2个寄存器表示;Dalvik字节码有两种类型:原始类型;引用类型(包括对象和数组)
Smali的数据类型
原始类型
B---byte
C---char
D---double
F---float
I---int
J---long
S---short
V---void
Z---boolean
[XXX---array
Lxxx/yyy---object
Smali的数组表示
在基本类型前加上前中括号“[”即表示该类型的数组;如
[I:表示整型I的数组;
[F:表示浮点型float的数组;
如果是对象类型,则以L作为开头,格式是LpackageName/objectName;如
Ljava/lang/String; :表示String对象。其中java/lang对应java.lang包,String是该包的一个对象。
类对象表示为LpackageName/objectName;类对象中的内部类则使用“$”来连接
Smali方法的定义
方法的一般定义为
Func-Name (Para-Type1Para-Type2Para-Type3...)Return-Type
参数与参数之间没有任何的间隔;如
Hello()V
表示:void hello()
Hello(III)Z
表示:Boolean hello(int,int,int)
Hello(Z[I[ILjava/lang/String;J)Ljava/lang/String;
表示:String hello(boolean,int[],int[],String,long)
Smali的一些关键词
.field private isFlag:z 定义变量
.method 方法
.parameter 方法参数
.prologue 方法开始
.line 123 此方法位于第123行
invoke-super 调用父函数
const/high16 v0, 0x7fo3 把0x7fo3赋值给v0
invoke-direct 调用函数
return-void 函数返回void
.end method 函数结束
new-instance 创建实例
iput-object 对象赋值
iget-object 调用对象
invoke-static 调用静态函数
Smali的条件跳转
"if-eq vA, vB, :cond_**" 如果vA等于vB则跳转到:cond_**
"if-ne vA, vB, :cond_**" 如果vA不等于vB则跳转到:cond_**
"if-ltvA, vB, :cond_**" 如果vA小于vB则跳转到:cond_**
"if-gevA, vB, :cond_**" 如果vA大于等于vB则跳转到:cond_**
"if-gtvA, vB, :cond_**" 如果vA大于vB则跳转到:cond_**
"if-le vA, vB, :cond_**" 如果vA小于等于vB则跳转到:cond_**
"if-eqzvA, :cond_**" 如果vA等于0则跳转到:cond_**
"if-nezvA, :cond_**" 如果vA不等于0则跳转到:cond_**
"if-ltzvA, :cond_**" 如果vA小于0则跳转到:cond_**
"if-gezvA, :cond_**" 如果vA大于等于0则跳转到:cond_**
"if-gtzvA, :cond_**" 如果vA大于0则跳转到:cond_**
"if-lez vA, :cond_**" 如果vA小于等于0则跳转到:cond_**
Smali类的信息
.class public Lcom/aaaaa;
.super Lcom/bbbbb;
.source "ccccc.java"
这是一个由ccccc.java编译得到的smali文件(第3行)
它是com.aaaaa这个package下的一个类(第1行)
继承自com.bbbbb这个类(第2行)
Smali中内部类声明
一般来说在Smali文件中是这个样子的:
# annotations
.annotation system Ldalvik/annotation/MemberClasses;
value = {
Lcom/aaa$qqq;,
Lcom/aaa$www;
}
.end annotation
这个声明是内部类的声明:aaa这个类它有两个成员内部类——qqq和www。
Smali方法中寄存器语法
在smali里的所有操作都必须经过寄存器来进行
本地寄存器:用v开头数字结尾的符号来表示,如v0,v1,v2…v15..,用于方法内数值之间的传递;
参数寄存器:用p开头数字结尾的符号来表示,如p0,p1,p2…,表示该方法依次接收过来的参数值。
特别注意:p0不一定是函数中的第一个参数。在非static函数中,p0代指“this”,p1表示函数的第一个参数,p2代表函数中的第二个参数…而在static函数中p0才对应第一个参数。因为Java的static方法中没有this方法。
Smali寄存器简单实例分析
•const/4 v0, 0x1
•iput-boolean v0, p0, Lcom/aaa;->IsRegistered:Z
•我们来分析一下上面的两句smali代码,首先它使用了v0本地寄存器,并把值0x1存到v0中,然后第二句用iput-boolean这个指令把v0中的值存放到com.aaa.IsRegistered这个成员变量中。
•即相当于:this.IsRegistered= true;(上面说过,在非static函数中p0代表的是“this”,在这里就是com.aaa实例)。
Smali类中成员变量表示和操作
•成员变量格式是:
•.field public/private [static] [final] varName:<类型>。
•对于不同的成员变量也有不同的指令。
•获取的指令有:iget、sget、iget-boolean、sget-boolean、iget-object、sget-object等。
•写入的指令有:iput、sput、iput-boolean、sput-boolean、iput-object、sput-object等。
•没有“-object”后缀的表示操作的成员变量对象是基本数据类型,带“-object”表示操作的成员变量是对象类型,特别地,boolean类型则使用带“-boolean”的指令操作。
Smali成员变量指令简析
•sget-object v0, Lcom/aaa;->ID:Ljava/lang/String;
•sget-object用来获取变量值并保存到紧接着的参数的寄存器中,本例中,它获取ID这个String类型的成员变量并放到v0这个寄存器中。
•注意:前面需要该变量所属的类的类型,后面需要加一个冒号和该成员变量的类型,中间是“->”表示所属关系。
• iget-object v0, p0, Lcom/aaa;->view:Lcom/aaa/view;
•可以看到iget-object指令比sget-object多了一个参数,就是该变量所在类的实例,在这里就是p0即“this”。
Smali代码函数的调用
1.invoke-static:用于调用static函数
const-string v0, "NDKLIB"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
调用static void System.loadLibrary(String)来加载NDK编译的so库用的方法,这里v0就是参数"NDKLIB"。
2.invoke-super:调用父类方法用的指令,一般用于调用onCreate、onDestroy等方法。
3.invoke-direct:调用private函数:
invoke-direct {p0}, Landroid/app/TabActivity;-><init>()V
这里init()就是定义在TabActivity中的一个private函数
4.invoke-virtual:用于调用protected或public函数。
sget-object v0, Lcom/dddd;->bbb:Lcom/ccc;
invoke-virtual {v0, v1}, Lcom/ccc;->Messages(Ljava/lang/Object;)V
v0是bbb:Lcom/ccc
v1是传递给Messages方法的Ljava/lang/Object参数。
5.invoke-xxxxx/range:当方法的参数多于5个时(含5个),不能直接使用以上的指令,而是在后面加上“/range”,range表示范围,使用方法也有所不同:
invoke-direct/range {v0 .. v5}, Lcmb/pb/ui/PBContainerActivity;->h(ILjava/lang/CharSequence;Ljava/lang/String;Landroid/content/Intent;I)Z
需要传递v0到v5一共6个参数,这时候大括号内的参数采用省略形式,且需要连续。
Smali返回结果的操作
在Java代码中调用函数和返回函数结果可以用一条语句完成,而在Smali里则需要分开来完成,在使用上述指令后,如果调用的函数返回非void,那么还需要用到move-result(返回基本数据类型)和move-result-object(返回对象)指令:
const-string v0, "Eric"
invoke-static {v0}, Lcmb/pbi;->t(Ljava/lang/String;)Ljava/lang/String;
move-result-object v2
v2保存的就是调用t方法返回的String字符串。
Smali完整函数分析示例-if语句
.method private ifRegistered()Z
.locals 2 //在这个函数中本地寄存器的个数
.prologue
const/4 v0, 0x1 // v0赋值为1
.local v0, tempFlag:Z
if-eqz v0, :cond_0 // 判断v0是否等于0,等于0则跳到cond_0执行
const/4 v1, 0x1 // 符合条件分支
:goto_0 //标签
return v1 //返回v1的值
:cond_0 //标签
const/4 v1, 0x0 // cond_0分支
goto :goto_0 //跳到goto_0执行 即返回v1的值 这里可以改成return v1 也是一样的
.end method
操作实例
•操作要点 (00.跳过界面.apk/01.登录Crack.apk):
•熟悉最基本的破解语法
跳转
赋值
过程
很多的Android开发是使用Java语言的开发
Java 有类 、 函数 、成员变量 等等
MainAcitvity.java
Login.java
+
res
+
lib
+
assets
=> .apk
.dex
语法关键词
Java -> time System run
1.能够标识类型:字符串string int long float
[xx ARRAY
[B 标识byte数组
[i 标识int数组
Lxxx/yyy---object
Hello (Z [I [I Ljava/lang/String; J) Ljava/lang/String;
String Hello(Boolean,int[],int[],String,long)
int jiafa(int,int)int
{
....
}
开始判断
获取输入框的内容
1.符合条件 让我进去
2.不符合条件 不让我进去
smali语法表示
if(str=password){
第一个代码块
//进来
}else{
第二个代码块
//进这边来
}
eq ===equal
ne ===not equal
lt ===less
ge ===greater equal
gt
le
eqz === euqal zero
nez === not equal zero
# virtual methods
.method protected m()Ljava/lang/String;
.locals 1
const-string v0, "DesktopCal"
return-object v0
.end method
smali在进行逻辑运算的时候,使用的寄存器;
假如:a+b=ab
a -> v0
b -> v1
a+b -> v0+v1
欢迎大家在下面评论点赞加关注,让我们一起在网安之路越走越远!!!
原文始发于微信公众号(安全君呀):【Android(安卓)安全逆向03】逆向基础 | Smali语法
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论