SMALI语法

dalvik字节码有两种类型,原始类型和引用类型。对象和数组是引用类型,其它都是原始类型。
V  void,只能用于返回值类型
Z  boolean
B  byte
S  short
C  char
I  int
J  long(64位)
F  float
D  double(64位)
对象以Lpackage/name/ObjectName;的形式表示。前面的L表示这是一个对象类型,package/name/是该对象所在的包,ObjectName是对象的名字,“;”表示对象名称的结束。相当于java中的package.name.ObjectName。例如:Ljava/lang/String;相当于java.lang.String

数组的表示形式
  [I——表示一个整型一维数组,相当于java中的int[]。
  对于多维数组,只要增加[就行了。[[I相当于int[][],[[[I相当于int[][][]。注意每一维的最多255个。
  对象数组的表示:[Ljava/lang/String;表示一个String对象数组。
方法
表示形式:Lpackage/name/ObjectName;->MethodName(III)Z
  Lpackage/name/ObjectName;表示类型,MethodName是方法名。III为参数(在此是3个整型参数),Z是返回类型(bool型)。
  方法的参数是一个接一个的,中间没有隔开。
一个更复杂的例子:
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
在java中则为:
String method(int, int[][], int, String, Object[])
字段
表示形式:
Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;
即包名,字段名和各字段类型。
寄存器
在dalvik字节码中,寄存器都是32位的,能够支持任何类型。64位类型(Long和Double型)用2个寄存器表示。
有两种方式指定一个方法中有多少寄存器是可用的。.registers指令指定了方法中寄存器的总数。.locals指令表明了方法中非参寄存器的数量。
方法的传参
  当一个方法被调用的时候,方法的参数被置于最后N个寄存器中。如果一个方法有2个参数,5个寄存器(v0-v4),那么参数将置于最后2个寄存器——v3和v4。
  非静态方法中的第一个参数总是调用该方法的对象。
例如,非静态方法LMyObject;->callMe(II)V有2个整型参数,另外还有一个隐含的LMyObject;参数,所以总共有3个参数。假如在该方法中指定了5个寄存器(v0-v4),以.registers方式指定5个或以.locals方式指定2个(即2个local寄存器+3个参数寄存器)。当该方法被调用的时候,调用该方法的对象(即this引用)存放在v2中,第一个整型参数存放在v3中,第二个整型参数存放在v4中。
对于静态方法除了没有隐含的this参数外其它都一样。
寄存器的命名方式
有两种方式——V命名方式和P命名方式。P命名方式中的第一个寄存器就是方法中的第一个参数寄存器。在下表中我们用这两种命名方式来表示上一个例子中有5个寄存器和3个参数的方法。
v0    第一个local register
v1    第二个local register
v2  p0  第一个parameter register
v3  p1  第二个parameter register
v4  p2  第三个parameter register
你可以用任何一种方式来引用参数寄存器——他们没有任何差别。
注意:baksmali默认对参数寄存器使用P命名方式。如果想使用V命名方式,可以使用-pl—no-parameter-registers选项。
使用P命名方式是为了防止以后如果要在方法中增加寄存器,需要对参数寄存器重新进行编号的缺点。
Long/Double值
Long和double类型是64位的,需要2个寄存器(切记切记)。
例如,对于非静态方法LMyObject;->MyMethod(IJZ)V,参数分别是LMyObject;,int,long,bool。故该方法需要5个寄存器来存储参数。

p0  this
p1  I
p2,p3  J
p4  Z 
补充:
# static fields             定义静态变量的标记
# instance fields        定义实例变量的标记
# direct methods       定义静态方法的标记
# virtual methods      定义非静态方法的标记
构造函数的返回类型为V,名字为<init>。
 
if-eq p1, v0, :cond_8 表示如果p1和v0相等,则执行cond_8的流程:
    :cond_8
    invoke-direct {p0}, Lcom/paul/test/a;->d()V
调用com.paul.test.a的d()方法
if-ne p1, v0, :cond_b 表示不相等则执行cond_b的流程:
    :cond_b
    const/4 v0, 0x0
    invoke-virtual {p0, v0}, Lcom/paul/test/a;->setPressed(Z)V
    invoke-super {p0, p1, p2}, Landroid/view/View;->onKeyUp(ILandroid/view/KeyEvent;)Z
    move-result v0
 

大概意思就是调用com.paul.test.a的setPressed方法,然后再调用父类View的onKeyUp方法,最后 return v0 



举两个例子:

sget-object v5, Lcom/google/youngandroid/runtime;->Lit227:Lgnu/mapping/SimpleSymbol;
获取com.google.youngandroid.runtime中的Lit227字段存入v5寄存器,相当于
gnu.mapping.SimpleSymbol localVariable = com.google.youngandroid.runtime.Lit227;

sput-object v0, Lcom/google/youngandroid/runtime;->Lit78:Lkawa/lang/SyntaxTemplate;
Likewise, this is setting the value of a static field. i.e.
设置com.google.youngandroid.runtime.Lit78的值为v0寄存器中的kawa.lang.SyntaxTemplate类型变量的值。相当于com.google.youngandroid.runtime.Lit78 = kawa.lang.SyntaxTemplate localVariable;


一、类型
Dalvik的字节码中有两个主要类型:基类和引用类型。引用类型是对象和数组,其他都是基类
(1)基类
 V void 空类型,仅用做返回类型
 Z boolean布尔型
 Bbyte字节型 
 Sshort短整型 16位
 Cchar字符型 
 Iint整型 
 J long 长整型 64位
 F  float浮点型
 Ddouble双精度型 64位

   (2)对象
Lpackage/name/ObjectName
L表明这是一个对象类型
e.g. "Ljava/lang/String"等同于java.lang.String

   (3)数组(数组维度最多255)
 [I 等同于int[ ]
 [[I等同于int[ ][ ] 
   
二、方法
方法包括方法名,参数类型和返回值
Lpackage/name/ObjectName;-> MethodName( III) Z
Lpackage/name/OjectName表示类
MethodName表示方法名
III表示三个整型参数
Z表示返回值为布尔类型

三、field(一般翻译为字段,我理解的是变量定义)
field包括包名,变量名,变量类型
Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;


四、寄存器
在dalvik字节码中,寄存器都是32位,64位类型(long,double)需要用2个寄存器存放。

有两种方式指定一个方法中有多少寄存器可用。 .registers指令指定了方法中的寄存器总数。 .locals指令指定方法中非参寄存器的数量。

寄存器有两种命名方式,V命名方式和P命名方法。P命名方式中的第一个寄存器就是方法中的第一个参数寄存器
v0    第一个local register
v1    第二个local register
v2  p0  第一个parameter register
v3  p1  第二个parameter register
v4  p2  第三个parameter register

e.g. 对于非静态方法 LMyObject;->MyMethod(IJZ)V, 参数分别是LMyObject,int,long(64位),bool,需要5个寄存器来存储参数
p0  this
p1  I
p2,p3  J
p4  Z 


五、例子
e.g.1
const v0 ,  0
invoke - virtual  {v0 },  Ljava /lang / Object ;->toString ();
相当于
Object blah  =  null ;
blah .toString ();

e.g.2
sget-object v5, Lcom/google/youngandroid/runtime;->Lit227:Lgnu/mapping/SimpleSymbol;
相当于
gnu.mapping.SimpleSymbol localVariable = com.google.youngandroid.runtime.Lit227;
即获取com.google.youngandroid.runtime中的Lit227字段存入v5寄存器

e.g.3
sput-object v0, Lcom/google/youngandroid/runtime;->Lit78:Lkawa/lang/SyntaxTemplate;
相当于
com.google.youngandroid.runtime.Lit78 = kawa.lang.SyntaxTemplate localVariable;
即将v0寄存器中存放的kawa.lang.SyntaxTemplate类型变量的值赋给com.google.youngandroid.runtime.Lit78

六、smali语法高亮
editplus 上smali语法高亮文件 http://www.editplus.com/dn.php?n=smali.rar 
(来自非虫,非常欣赏这位大牛,技术厉害不用说,还乐于分享,在看雪上发布了很多android逆向的教程)
smali语法 - danqingdani - 碳基体
 
smali语法 - danqingdani - 碳基体
 
七、davlik opcode

八、常见源码结构
1. 构造函数

public class example { private static int Counter; public example() { Counter = 16; }

对应的smali
smali语法 - danqingdani - 碳基体
 
 
2.for结构

public static void LoopExample() { for ( int i = 0; i < Counter; i++ ) System.out.println("current val for loop: " + i); }

对应的smali
smali语法 - danqingdani - 碳基体
 
 
3.switch结构

public static void SwitchExample() { int val = 42; switch (val) { case 1: System.out.println("val 1"); break; case 2: System.out.println("val 2"); break; case 42: System.out.println("val 42"); break; case 5: System.out.println("val 5"); break; default: System.out.println("invalid value");break; } }

对应的smali

smali语法 - danqingdani - 碳基体
  smali语法 - danqingdani - 碳基体在smali中,switch结构,首先使用spare-switch解析default分支,接着处理其他分支.这种处理流程,会导致在使用dex2jar进行反编译时(将dex文件转换为jar)出错,使用ded进行反编译的结果会稍微好一点。

4.try-catch

public static void TryCatchExample() { String urlStr = "google.com"; try { // Get the image URL url = new URL(urlStr); InputStream is = url.openStream(); is.close(); } catch (MalformedURLException e) { // Print out the exception that occurred System.out.println("Invalid_URL" + urlStr + " :" + e.getMessage()); } catch (IOException e) { // Print out the exception that occurred System.out.println("Unable?to?execute" + urlStr + ":" + e.getMessage()); } }

catch部分对应的smaili
smali语法 - danqingdani - 碳基体
 同样的, 使用ded进行反编译的结果会稍微好一点

5.数组

public static void ArrayExample() { String someArray[] = new String[5]; someArray[0] = "set value at index 0"; someArray[1] = "index 1 has this value"; if ( someArray[0].equals(someArray[1]) ) { System.out.println("array at index 0 = 1 (wont?happen)"); } }

对应的smali
smali语法 - danqingdani - 碳基体
 

参考:
Android恶意代码分析 claud

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值