碳基体

奋斗在产品安全第一线的安全妹子

smali语法

来自smali的wiki说明

一、类型

Dalvik的字节码中有两个主要类型:基类和引用类型。引用类型是对象和数组,其他都是基类

(1)基类


   (2)对象

Lpackage/name/ObjectName

L表明这是一个对象类型

e.g. "Ljava/lang/String"等同于java.lang.String


   (3)数组(数组维度最多255)

   

二、方法

方法包括方法名,参数类型和返回值

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语法高亮文件 https://www.editplus.com/dn.php?n=smali.rar 

(来自非虫,非常欣赏这位大牛,技术厉害不用说,还乐于分享,在看雪上发布了很多android逆向的教程)

 

 

七、davlik opcode

https://pallergabor.uw.hu/androidblog/dalvik_opcodes.html 


八、常见源码结构

1. 构造函数

public class example {
private static int Counter;

public example() { Counter = 16; }

对应的smali

   

2.for结构

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

对应的smali

   

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中,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

 同样的,使用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

 


参考:

https://code.google.com/p/smali/wiki/TypesMethodsAndFields 

https://bbs.pediy.com/showthread.php?t=151769 

Android恶意代码分析 claud

来源:碳基体

评论