前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

Smali语法入门教程(smali基本语法)

qiguaw 2024-11-01 13:05:41 资源文章 18 ℃ 0 评论

作者:mutepig

预估稿费:300RMB(不服你也来投稿啊!)

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

0x01 smali生成


使用apktool反编译apk后,会在反编译工程目录下生成一个smali文件夹

其中android下存放所调用库的smali文件,com才是我们自己写的代码的smali文件。

0x02 基础语法


a.文件基本格式

基本信息

1234567891011.class <访问权限> <类名>.super <父类名>.source <源文件名># eg..class public Lcom/reoky/crackme/challengeone/activities/ChallengeActivity; .super Landroid/support/v4/app/FragmentActivity; .source "ChallengeActivity.java" //经过混淆后这项可能为空

类变量声明

1234567.field <访问权限> <变量名>:<变量类型># eg..field actionBar:Landroid/app/ActionBar; <=对应源码=> ActionBar actionBar;局部变量声明:.local <初始值>,<变量名>:<变量类型>#eg.local v0, "ans":Ljava/lang/String; <=对应源码=> String ans="";

类方法声明

12345678910111213141516171819.method <访问权限> <方法名>(参数原型) <方法原型> [.prologue] // 指定代码开始位置 [.param] // 指定方法参数 [.line] // 指定代码在源代码中的行数,混淆后可能不存在 [.locals] // 使用的局部变量个数 <代码体>.end method# eg.method public onTabReselected(Landroid/app/ActionBar$Tab;Landroid/app/FragmentTransaction;)V .locals 0 .param p1, "tab" # Landroid/app/ActionBar$Tab; .param p2, "fragmentTransaction" # Landroid/app/FragmentTransaction; .prologue .line 55 //可能经过混淆后不存在 return-void.end method <=对应源码=>public void onTabReselected(ActionBar$Tab tab, FragmentTransaction fragmentTransaction){}

b.原始类型

1234567891011B—byteC—charD—doubleF—floatI—intJ—longS—shortV—voidZ—boolean[XXX—arrayLpackage/name/ObjName—object // 前面表示对象所在包路径

c.寄存器操作

传入的参数寄存器由p表示,而函数内的本地寄存器则由v表示,多个的话则在后面加上0,1,2...

需要注意的是,在非static函数中,p0表示`this`,p1才表示第一个参数。

常量赋值

12345主要是各种constconst v0, 0x7F030018 # R.layout.activity_challenge #从R中取出静态值const/4 v3, 0x2 #4也可以换成16或者high16,表示取整数值const-string v2, "Challenge" # 取字符串const-class v2, Context #把类对象取出

变量间赋值

1234move vx,vy # 将vy的值赋值给vx,也可以是move-object等move-result vx # 将上个方法调用后的结果赋值给vx,也可以是move-result-objectreturn-object vx # 将vx的对象作为函数返回值new-instance v0, ChallengePagerAdapter # 实例化一个对象存入v0中

对象赋值

12345iput-object a,(this),b 将a的值给b,一般用于b的初始化iget-object a,(this),b 将b的值给a,一般用于获取b的地址,接着调用它# eg.iput-object v0, p0, ChallengeActivity->actionBar:ActionBariget-object v0, p0, ChallengeActivity->actionBar:ActionBar

d.函数操作

最基础的函数操作一般有以下四个:

1234567891.private:invoke-direct2.public|protected: invoke-virtual3.static:invoke-static4.parent: invoke-super基本调用形式:invoke-xxx {参数},类;->函数(参数原型)# eg.invoke-super {p0, p1}, Landroid/support/v4/app/FragmentActivity;->onCreate(Landroid/os/Bundle;)V<=对应源码=>super.onCreate(savedInstanceState); // 其中p0是this,其父类是FragmentActivity,p1,是savedInstanceState,其原型是Bundle;即调用p0->onCreate(p1)

0x03 程序语句相关语法


这里列举以下常见程序语句对应的smali语句,并与Android源码相比较分析

a.判断语句

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

b.循环语句

下面列出一个简单的for循环,其他也差不多

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849public void encrypt(String str) { String ans = ""; for (int i = 0 ; i < str.length();i++){ ans += str.charAt(i); } Log.e("ans:",ans);}<=对应smali=># public void encrypt(String str) {.method public encrypt(Ljava/lang/String;)V .locals 4 .param p1, "str"# Ljava/lang/String;.prologue # String ans = "";const-string v0, "" .local v0, "ans":Ljava/lang/String; # for (int i 0 ; i < str.length();i++){# int i=0 =>v1const/4 v1, 0x0.local v1, "i":I:goto_0# for_start_place# str.length()=>v2invoke-virtual {p1}, Ljava/lang/String;->length()Imove-result v2 # i<str.length() if-ge v1, v2, :cond_0 # ans += str.charAt(i); # str.charAt(i) => v2new-instance v2, Ljava/lang/StringBuilder; invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()Vinvoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;move-result-object v2 #str.charAt(i) => v3invoke-virtual {p1, v1}, Ljava/lang/String;->charAt(I)C move-result v3# ans += v3 =>v0invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(C)Ljava/lang/StringBuilder; move-result-object v2 invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;move-result-object v0# i++add-int/lit8 v1, v1, 0x1goto :goto_0# Log.e("ans:",ans);:cond_0const-string v2, "ans:" invoke-static {v2, v0}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)Ireturn-void .end method

c.switch语句

12345678910111213141516171819202122232425262728293031323334353637383940public void encrypt(int flag) { String ans = null; switch (flag){ case 0: ans = "ans is 0"; break; default: ans = "noans"; break; } Log.v("ans:",ans); }<=对应smali=>#public void encrypt(int flag) {.method public encrypt(I)V .locals 2 .param p1, "flag" # I .prologue#String ans = null; const/4 v0, 0x0 .local v0, "ans":Ljava/lang/String;#switch (flag){ packed-switch p1, :pswitch_data_0 # pswitch_data_0指定case区域的开头及结尾#default: ans="noans" const-string v0, "noans"#Log.v("ans:",ans) :goto_0 const-string v1, "ans:" invoke-static {v1, v0}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I return-void#case 0: ans="ans is 0" :pswitch_0 #pswitch_<case的值> const-string v0, "ans is 0" goto :goto_0 # break nop :pswitch_data_0 #case区域的结束 .packed-switch 0x0 #定义case的情况 :pswitch_0 #case 0 .end packed-switch.end method

其中case定义情况有两种:

12345678910111213141.从0开始递增packed-switch p1, :pswitch_data_0...:pswitch_data_0.packed-switch 0x0 :pswitch_0 :pswitch_1 2.无规则switchsparse-switch p1,:sswitch_data_0...sswitch_data_0.sparse-switch 0xa -> : sswitch_0 0xb -> : sswitch_1 # 字符会转化成数组

d.try-catch语句

12345678910111213141516171819202122232425262728293031323334353637public void encrypt(int flag) { String ans = null; try { ans = "ok!"; } catch (Exception e){ ans = e.toString(); } Log.d("error",ans);}<=对应smali=>#public void encrypt(int flag) {.method public encrypt(I)V .locals 3 .param p1, "flag" # I .prologue#String ans = null; const/4 v0, 0x0 .line 20 .local v0, "ans":Ljava/lang/String;#try { ans="ok!"; } :try_start_0 # 第一个try开始, const-string v0, "ok!" :try_end_0 # 第一个try结束(主要是可能有多个try) .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0#Log.d("error",ans); :goto_0 const-string v2, "error" invoke-static {v2, v0}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I return-void#catch (Exception e){ans = e.toString();} :catch_0 #第一个catch move-exception v1 .local v1, "e":Ljava/lang/Exception; invoke-virtual {v1}, Ljava/lang/Exception;->toString()Ljava/lang/String; move-result-object v0 goto :goto_0.end method

0x04 参考资料


http://blog.csdn.net/qq_24349189/article/details/52300419

http://lib.csdn.net/article/android/7043

http://devxeo.lofter.com/post/2da37d_cd7c69

http://www.blogjava.net/midea0978/archive/2012/01/04/367847.html

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表