笔记转博文
还是以 Java hello world 为例,本文将展示从 Java -> class -> dex -> smali 的过程。
新建 com/dezng/Hello.java 文件。
package com.dezng;
public class Hello {
public static void main(String[] args){
System.out.println("Hello");
}
}
1. Java -> class
使用 javac 编译得到 class 文件。执行看到输出 Hello
javac com/dezng/Hello.java
java com.dezng.Hello # Hello
2. class -> dex
class 到 dex 是通过 Android sdk 中提供的工具完成。位于 build-tools/{VERSION}/dx
。
这里需要注意的是不同版本 sdk 支持的 java 版本不一样,可能会出现
bad class file magic (cafebabe) or version (0034.0000)
类似的错误,此错误信息是我用 23.0.1 转换 java 8 的字节码时出现的错误,26.0.0 以上版本可以使用 java 8,24和25没有安装,没有测试。
dx --dex --output=Hello.dex com/dezng/Hello.class
file Hello.dex # file 命令查看 dex 文件
# Hello.dex: Dalvik dex file version 035
在 Android sdk 中,和 dx 命令相同位置还存在一个 dexdump 的命令,可以用于查看 dex 中包含的内容,类似 javap。
dexdump Hello.dex
2.1 dex 文件的执行:
dex 文件是 Android 平台的可执行文件,可以在 Android 中直接执行。
adb push Hello.dex /data/local/tmp/
# Hello.dex: 1 file pushed, 0 skipped. 0.9 MB/s (832 bytes in 0.001s)
adb shell # 进入 Android 终端
cd /data/local/tmp
/data/local/tmp $ dalvikvm -cp Hello.dex com.dezng.Hello
# Hello
3. dex -> smali
dex 文件的反编译,需要使用到 baksmali
java -jar baksmali.jar -o Hello.smali.out Hello.dex
之后在 Hello.smali.out 目录下可以看到文件 com/dezng/Hello.smali 文件。
.class public Lcom/dezng/Hello;
.super Ljava/lang/Object;
.source "Hello.java"
# annotations
.annotation runtime Ljava/lang/Deprecated;
.end annotation
# direct methods
.method public constructor <init>()V
.registers 1
.prologue
.line 4
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
.method public static main([Ljava/lang/String;)V
.registers 3
.prologue
.line 6
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v1, "Hello"
invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
.line 7
return-void
.end method
具体语法请参考 官方文档,想要系统学习,必看书籍Android软件安全与逆向分析
4. smali -> dex
将 smali 打包成 dex 需要用到 smali
java -jar smali.jar -o Hello.smali.dex Hello.smali.out
将以上 dex push 到手机,执行正常。