1、概述
Smali是Android系統中Dalvik虛擬機指令語言,在apk逆向過程中有許多工具可以把smali代碼轉化成java代碼。但是在學習Smali語法的過程中,有時候需要進行java代碼和smali代碼的對照,如果可以把java代碼轉換成smali代碼,學習起來豈不是很方便。於是網上搜了一把,很失望,都是各種轉smali為java的工具。后來想了想,java變成smali不就是寫android程序—>dex—>smali的過程嘛,然而java代碼編譯完是class文件,如何變成dex文件呢?后來在一本書中找到了答案,記錄如下。
2、java代碼轉smali代碼
把java代碼轉成smali代碼共需要以下三個步驟
1、編譯java代碼為class文件
javac smaliTest.java
這個比較簡單,會生成smaliTest.class文件
2、把class文件轉成dex文件
我們知道apk包里java代碼最后生成的是class.dex文件,把class轉化成dex文件就需要用到android SDK提供的一個工具dx,該jar包位於android-sdk\build-tools\23.0.1\lib,找到該包后執行以下命令
java -jar dx.jar --dex --output=smaliTest.dex smaliTest.class
3、把dex轉化成smali文件
這時候會使用到另外一個工具baksmali,該工具位於android-sdk\platform-tools\,找到該包后執行以下命令
java -jar baksmali.jar smaliTest.dex
OK,完成,此時會生成一個out目錄,在out目錄下的smaliTest.smali就是我們要看到的smali代碼了
3、示例程序
java代碼如下:
public class smaliTest { public static void main(String[] args){ System.out.println("hello smali"); } }
smali代碼如下
.class LsmaliTest; .super Ljava/lang/Object; .source "smaliTest.java" # direct methods .method constructor <init>()V .registers 1 .prologue .line 3 invoke-direct {p0}, Ljava/lang/Object;-><init>()V return-void .end method .method public static main([Ljava/lang/String;)V .registers 3 .parameter .prologue .line 5 sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; const-string v1, "hello smali" invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V .line 6 return-void .end method
4、遇到的問題
我的android環境是在windows下搭建的,jdk版本是1.8,在windows下執行第二步時出現如下錯誤
UNEXPECTED TOP-LEVEL EXCEPTION: java.lang.RuntimeException: Exception parsing classes at com.android.dx.command.dexer.Main.processClass(Main.java:752) at com.android.dx.command.dexer.Main.processFileBytes(Main.java:718) at com.android.dx.command.dexer.Main.access$1200(Main.java:85) at com.android.dx.command.dexer.Main$FileBytesConsumer.processFileBytes( Main.java:1645) at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.j ava:170) at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java :144) at com.android.dx.command.dexer.Main.processOne(Main.java:672) at com.android.dx.command.dexer.Main.processAllFiles(Main.java:574) at com.android.dx.command.dexer.Main.runMonoDex(Main.java:311) at com.android.dx.command.dexer.Main.run(Main.java:277) at com.android.dx.command.dexer.Main.main(Main.java:245) at com.android.dx.command.Main.main(Main.java:106) Caused by: com.android.dx.cf.iface.ParseException: bad class file magic (cafebab e) or version (0034.0000) at com.android.dx.cf.direct.DirectClassFile.parse0(DirectClassFile.java: 472) at com.android.dx.cf.direct.DirectClassFile.parse(DirectClassFile.java:4 06) at com.android.dx.cf.direct.DirectClassFile.parseToInterfacesIfNecessary (DirectClassFile.java:388) at com.android.dx.cf.direct.DirectClassFile.getMagic(DirectClassFile.jav a:251) at com.android.dx.command.dexer.Main.parseClass(Main.java:764) at com.android.dx.command.dexer.Main.access$1500(Main.java:85) at com.android.dx.command.dexer.Main$ClassParserTask.call(Main.java:1684 ) at com.android.dx.command.dexer.Main.processClass(Main.java:749) ... 11 more 1 error; aborting
原因不明,大概是jdk版本不對,然后把baksmali.jar和dx.jar兩個包拷貝到ubuntu上,執行上述三個步驟,運行成功,ubuntu上安裝的jdk版本是1.7