本篇文章同時收錄在我的個人部落格:smali 檔案格式
HelloWorld
首先寫一個 HelloWorld 類:
package jiuyou.hello.info;
public class HelloWorld {
public static void main(String[] args){
System.out.println("hello world");
}
}複製程式碼
然後生成 apk 再用 apktool 工具轉成 smali 檔案:
.class public Ljiuyou/hello/info/HelloWorld; #定義類名
.super Ljava/lang/Object; #定義父類
.source "HelloWorld.java" #原始檔名
# direct methods #直接方法 (# virtual methods 為虛方法)
.method public constructor <init>()V #建構函式
.locals 0 #方法中使用到的區域性變數個數
.prologue #程式碼起始指令
.line 8 #原始碼所在行數
invoke-direct {p0}, Ljava/lang/Object;-><init>()V #呼叫父類構造方法
return-void #返回空
.end method #方法結束
.method public static main([Ljava/lang/String;)V #對應 main 方法
.locals 2 #方法包含兩個區域性 v0,v1
.param p0, "args" # [Ljava/lang/String; # main 方法的引數 agrs 標記為 p0
.prologue #程式碼起始指令
.line 10
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; #將 System.out 這個靜態變數賦給 v0
const-string v1, "hello world" #構造字串
#方法呼叫(呼叫 v0 的方法 println ,v1 是引數)
invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
.line 11
return-void
.end method複製程式碼
欄位
靜態欄位格式如下:
# static fields
.field <訪問許可權> static [修飾關鍵字] <欄位名>:<欄位型別>複製程式碼
例項欄位格式如下:
# instance fields
.field <訪問許可權> [修飾關鍵字] <欄位名>:<欄位型別>複製程式碼
舉個例子
java :
private String name;
private final String sex="男";
public static int age;複製程式碼
smali :
# static fields
.field public static age:I
# instance fields
.field private name:Ljava/lang/String;
.field private final sex:Ljava/lang/String;複製程式碼
方法
方法有直接方法和虛方法兩種,兩者格式基本相同:
# direct methods (virtual methods)
.method <訪問許可權> [修飾關鍵字] <方法原型>
<.locals>
[.parameter] or [.param]
[.prologue]
[.line]
<程式碼體>
.end method複製程式碼
.locals:區域性變數個數
.parameter or .param:指定每個引數
.prologue:程式碼的開始處,混淆過的程式碼可能沒有該指令
.line:指定了該處指令在原始碼中的行號,混淆過的程式碼可能沒有該指令
舉個例子:
java
public String test(int a){
int b=a+10;
return "test";
}複製程式碼
smali
# virtual methods
.method public test(I)Ljava/lang/String;
.locals 2
.param p1, "a" # I
.prologue
.line 11
add-int/lit8 v0, p1, 0xa
.line 12
.local v0, "b":I
const-string v1, "test"
return-object v1
.end method複製程式碼
介面
interface 格式如下:
# interfaces
.implements <介面名>複製程式碼
舉個例子:
java
public interface If {
int demo(String s);
}
public class InterfaceTest implements If {
@Override
public int demo(String s) {
return 0;
}
}複製程式碼
smali :
If.smali
# virtual methods
.method public abstract demo(Ljava/lang/String;)I
.end method複製程式碼
InterfaceTest.smali
# interfaces
.implements Ljiuyou/hello/info/If;
# virtual methods
.method public demo(Ljava/lang/String;)I
.locals 1
.param p1, "s" # Ljava/lang/String;
.prologue
.line 11
const/4 v0, 0x0
return v0
.end method複製程式碼
註解
格式如下:
.annotation [註解屬性] <註解類名>
[註解欄位 = 值]
.end annotation複製程式碼
如果註解的作用範圍是類, .annotation
指令會直接定義在 smali 檔案中,如果作用範圍是方法或者欄位,則會包含在方法或欄位定義中。
舉個例子:
java
@Deprecated
public class AnnotationTest {
@At(value = "tom")
public String name;
}複製程式碼
smali
# annotations
.annotation runtime Ljava/lang/Deprecated;
.end annotation
# instance fields
.field public name:Ljava/lang/String;
.annotation runtime Ljiuyou/hello/info/At;
value = "tom"
.end annotation
.end field複製程式碼