本篇文章同时收录在我的个人博客:smali 文件格式
首先写一个 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 ()V #构造函数
.locals 0 #方法中使用到的局部变量个数
.prologue #代码起始指令
.line 8 #源代码所在行数
invoke-direct {p0}, Ljava/lang/Object;->()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