实验吧smali文件分析
试题网址: http://www.shiyanbar.com/ctf/1871
0x01
首先我们得到了一个hello.dex文件,要把它反编译为smali文件,使用工具baksmali,cmd命令: java -jar baksmali-2.0.3.jar -o class/ Hello.dex ,就在当前目录下生成了一个文件夹,里边有一个hello.smali 代码如下:
.class public LHello;.super Ljava/lang/Object;.source "Hello.java"# direct methods.method public constructor()V .registers 1 .prologue .line 1 invoke-direct {p0}, Ljava/lang/Object;-> ()V return-void.end method.method public static main([Ljava/lang/String;)V .registers 5 .prologue .line 7 new-instance v0, LHello; invoke-direct {v0}, LHello;-> ()V .line 8 sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; //v1存out对象的引用 const/4 v2, 0x5 //把5符号扩展32位赋值给v2 const/4 v3, 0x3 //把3符号扩展32位赋值给v3 invoke-virtual {v0, v2, v3}, LHello;->foo(II)I //调用函数foo move-result v0 //把函数的结果赋值给v0 invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(I)V //打印输出v0 .line 9 return-void.end method# virtual methods.method public foo(II)I .registers 5 .prologue .line 3 add-int v0, p1, p2 // v0=p1+p2 sub-int v1, p1, p2 // v1=p1+p2 mul-int/2addr v0, v1 // v0=v0*v1 return v0.end method。 于是便可以进行分析了.
0x02
在这里首先稍微的科普一下,安卓程序都是由安卓虚拟机来运行的,Dalvik虚拟机有两种不同的寄存器表示方法,p命名法还有v命名法,假如说一个函数fun()使用了5个寄存器,2个显式的参数,并且这个方法是非静态的方法,所以调用的时候会传入一个隐式的fun对象引用,所以有三个参数,局部变量使用前2个寄存器,参数使用后3个,分别为v0,v1,v2,p0,p1,其中p0传入对象的引用。
然后说下Dalvik字节码的类型,方法还有字段表示方法:
1.类型:
V--void Z--boolean B--byte S--short C--char I--int F--float
D--double L--java类型 [--数组类型
其中java类型一般都是LpackageName/name/Objname 来表示具体的那个对象,如Ljava/lang/String相当于java.lang.String
2.方法:
Lpackage/name/Objname;->MethodName(III)Z
III表示三个整型参数,Z表示返回值是boolea型,
3.字段:
字段由类型、字段名、字段类型构成,字段名和字段类型之间使用:隔开
#instance fileds 实例字段
#static fields 静态字段
一些基本语法:
.prologue 方法开始
invoke-direct 调用函数
return-void 函数返回void
.end method 函数结束
new-instance 创建实例
iput-object 对象赋值
iget-object 调用对象
所以最终返回结果 (5+3)*(5-3)=16
当然这里直接反编译成jar然后反汇编为java代码更容易看出来:
import java.io.PrintStream;
public class Hello
{
public static void main(String[] paramArrayOfString)
{
Hello localHello = new Hello();
System.out.println(localHello.foo(5, 3));
}
public int foo(int paramInt1, int paramInt2)
{
return (paramInt1 + paramInt2) * (paramInt1 - paramInt2);
}
}