Android逆向就是反編譯的過程,因為看不懂Android正向編譯後的結果所以CTF中靜態分析的前提是將出現檔案反編譯到我們看得懂一層原始碼,進行靜態分析。
0X01 基礎說明
Android應用程式的邏輯程式碼是由Java來開發,所以是第一層就是java程式碼
Java虛擬機JVM運行的是java檔編譯過後的class文件
Android虛擬機Dalvik並不是執行Java虛擬機JVM編譯後產生的class文件,而是執行再重新整合打包後產生的dex文件編譯之後的smali文件
APK:是編譯完成後的Android應用程式安裝套件
dex檔案:是class檔案的打包檔案
smali檔案:是Dalvik字節碼檔案
class檔案:是JVM字節碼檔
0X02 工具使用
在CTF中Android題目不一定會給你完整編譯完成後的APK,可能是編譯過程中任意檔型,下麵鬥哥分以下文件類型利用工具來得到鬥哥看得懂的java源碼
#類型一:class文件
這種情況比較簡單,推薦工具jd-gui
#直接將class檔案拉進去就可以看到java源碼。
類型二:APK程式
Android工程編譯完成會得到我們想要的APK安裝包,APK檔案其實是一個壓縮包。
修改後綴名為zip後解壓縮,解壓縮後的檔案如下圖所示:
META-INF資料夾:
存放apk簽名訊息,用來保證apk套件的完整性和系統的安全。
res資料夾:
存放資源文件,包括icon,xml文件。
AndroidManifest.xml檔案:
應用程式設定文件,每個應用程式都必須定義和包含的,它描述了應用程式的名字、版本、權限、引用的庫檔案等資訊。
classes.dex檔案:
可以直接在Dalvik虛擬機器上載入執行的文件,由java檔案經過IDE編譯產生。
resources.arsc檔案>
二進位資源文件,包括字串等。
反編譯APK推薦工具ApkIDE、JEB
1. JEB使用:
JEB直接匯入APK,反編譯完成看到smali檔案。
很多Android逆向工具就反編譯到smali檔案這一步。
JEB選取smali檔案中按Q,就可以看到java檔。
優點:從smali檔案反編譯成的java檔案程式碼結構清晰。
缺點:無法修改。
2. ApkIDE使用:
專案->開啟Apk
等待反編譯完成。
看到smali檔案。
選擇要java原始碼的smali文件,點選下圖按鈕,開啟Java原始碼。
ApkIDE關聯了jd-gui,點擊後將跳到jd-gui。
ApkIDE是將APK反編譯到class再用jd-gui拿到Java原始碼。
在ApkIDE的ApkIDE_v3.3\ApkIDE\Worksrc的專案目錄下可以看到反編譯後的class檔案。
優點:功能強大,可以修改反編譯出來的smali文件,重新編譯產生APK。
缺點:編譯成後的java程式碼不夠清晰。
3.反編譯區別
Smali檔案是由Smali語法編寫,Smali語法寬鬆式的語法
所以反編譯過程不同,工具不同,java原始碼肯定不同
下面是同一個APK用上面兩個工具逆向的結果:
#鬥哥當一個Java開發的愛好者喜歡JEB的逆向結果,看著比較舒服。
類型三:dex文件
推薦工具dex2.jar
classes.dex文件,這個是Android源碼編譯過的字節碼包
##################試著使用dex2.jar工具拿到java原始碼指令如下######.\d2j-dex2jar.bat C:\Users\lin\Desktop\classes.dex###jar檔案可以理解為classes檔案的壓縮包,java虛擬機器可以直接運作
用Jd-gui開啟classes-dex2jar. jar就可以看到java原始碼
類型四:smali檔案
當只有一個單獨的smali檔案時就無法用上述的工具直接進行反編譯
鬥哥想到ApkIDE可以對一個APK進行反編譯到smali文件,對smali文件進行增刪改查的操作
於是用ApkIDE打開任一個完整的APK接著加入smali檔案(APK可以用自己開發的)
#將smali檔案加入ApkIDE專案中。
重新編譯產生APK。
編譯成功後將在原始APK目錄產生一個APK。
再用JEB等工具開啟就能看到Ezreal.smali檔。
其他工具:
編輯器:notepad 、Sublime等
Android模擬器:夜神模擬器等
0X04 例題分析
將應用程式安裝到模擬器查看介面是否有提示。
在文字方塊中輸入字元點擊按鈕提示錯誤,猜想是否用來判斷正確的flag。
使用JEB工具編譯成java文件,Android檔案下方是sdk文件,我們要分析是com套件下的原始碼檔案。
程式碼量不多就三個類,先從程式入口MainActivity分析,找到關鍵程式碼區塊。
這句if就是判斷flag是否正確。
搜尋類別查看哪裡呼叫了此方法。
分析得到arg12就是介面要輸入的參數,這時我們知道了v5的值就是我們要的flag。
onCreate函數呼叫了checkSN方法並傳入兩個參數為:
MainActivity.this.edit_userName.trim()
MainActivity.this.edit_sn.getText().toString().trim()
//OnCreate是Android中的一個特別的函數,用來“表示一個視窗正在產生” 。
//其不產生窗口,只是在視窗顯示前設定窗口的屬性如風格、位置顏色等。
public void onCreate(Bundle arg3) {
super.onCreate(arg3);
this.setContentView(0x7F040019);
## this.setTitle( 0x7F06001D); this.edit_userName = "Tenshine"; this.edit_sn = this.findViewById(0x7F0C0051);##o#1020> ; this.btn_register.setOnClickListener(new View$OnClickListener() { public void onClick(View arg5) {.Main .this.edit_userName.trim(), MainActivity.this.edit_sn.getText().toString().trim())) { Toast.makeText(MainActivity.this, 0x7F Toast.makeText(MainActivity.this,00x7F 601,006). ); }# else {# MainActivity.this. btn_register.setEnabled(false); MainActivity.this.setTitle(0x7F060019);#
#}
分析v5的值,v5是由v3和v4產生的,v4是一個int並直接賦值為0用於循環就可以直接使用
而v3則是toHexString方法的回傳值,並且要傳入,v1是v1.update(arg11.getBytes());產生
arg11就是傳入的參數"Tenshine"
private boolean checkSN(String arg11, String arg12) {
# boolean v7 = false;
if(arg11 != null) {
# # if(arg11 != null) {
# # if #
if(arg11.length() == 0) { return v7;##> == null) { 返回v7; }回v7;
}
MessageDigest v1 = MessageDigest.getInstance("MD5");
v1.reset();
# String v3 = MainActivity.toHexString(v1.digest(), ""); StringBuilder v5 = new StringBuilder(); 1 v4 v5.append(v3.charAt(v4)); " v5.toString() "}".equalsIgnoreCase(arg12)) { return v7; 1 SuchAlgorithmException v2 ) { 前往label_40; } v7 = true;# }## label_40: v2.printStackTrace(); return v7;}將上面的分析結果,取出產生v5的關係碼都是純java程式碼,不需要Android的套件引入,只需引入java的依賴套件。import java.security.MessageDigest;import java.security.NoSuchAlgorithmException ;公共類代碼{ static String toHexString(byte[] arg8, String arg9) { StringBuilder v3 = new StringBuilder(); byte[] v0 = arg8; int v5 = v0.length; int v4; for(v4 = 00; v4 String v2 = Integer.toHexString(v0[v4] & 255); if(v2.length() == 1) { v3.追加('0'); } v3.append(v2).append(arg9) ); } public static void main(String[] args) throws NoSuchAlgorithmException{ Message#igest v1 = Message#1. ## v1.reset(); v1.reset(); v1.update("Tenshine".getBytes()); String v3 = Code.toHex.String v3 = Code.toHex.1.
StringBuilder v5 = new StringBuilder();
int v4;
for(v4 = 0; v4 # v5.append(v3.charAt(v4));
} System.out.println("flagSystem.out.println("flag
System.out.println("flag)" v### }
}
用IDEA編輯執行,得到flag。
#
以上是Android中怎麼進行靜態分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!