您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關如何分析Android逆向入門中的常見Davlik字節碼,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
破解Android程序流程:反編譯—>分析–>修改–>回編譯–>簽名,這些都是在命令行中操作,當然也有集成了這些操作的工具:
macos:Android-Crack-Tool
Windows:Android Killer
這里解釋下寄存器的概念,寄存器是用來存儲
寄存器是CPU內部用來存放數據的一些小型存儲區域,用來暫時存放參與運算的數據和運算結果。也就是存儲來存儲數據的。現在所有手機都是用的arm芯片
這里說一些題外話:比較常見的CPU有intel的X86架構的CPU的還有arm架構的CPU,其中intel的X86架構的cpu指令集有復雜指令集和精簡指令集,arm中只有精簡指令集。
所謂復雜和簡單就是根據是否要根據程序來設計指令來提高計算機的性能,復雜指令集會根據應用程序來增加一些復雜功能的指令集,這樣也就導致CPU的指令越來越多越設計越復雜造價也越高,而精簡指令集則不會根據程序來設計指令集,那么怎么提高性能?
翻譯成機器碼的工作就是由高級語言的編譯器來做的,把這些工作交給了編譯器。所以兩種區別就是復雜指令集會根據程序來增加自己的指令集達到提高計算機性能的作用,精簡指令集則是交給了編譯器去做指令轉換的工作。由于加入了編譯器的轉換所以運行速度會慢,而且占用的內存也會變多,同樣的程序在arm芯片的手機上和intel芯片的電腦上,手機上占用的空間更多。精簡指令集的arm架構還有一個特點是其寄存器特別多,而davlik虛擬機利用這個特性對原本java虛擬機進行了改動:
java虛擬機中每個線程都會有一個PC計數器和一個java棧,PC計數器用于記錄程序執行到哪個地方,java棧中用來記錄java方法的調用記錄叫做棧幀,每調用一個方法就會分配一個新棧并壓入java棧,每個棧幀都包含局部變量區,求值棧(jvm叫做操作數棧),局部變量區用來存儲方法的參數和局部變量,求值棧用于保存求值的中間結果及調用其他方法的參數。方法運算時從棧中的局部變量區取數據進行運算將結果存放在操作數棧中,最后返回的時候從操作數棧中彈出結果
而davlik虛擬機運行時中也為每一個線程維護了一個PC計數器和一個調用棧,不同的是這個調用棧中維護了一個寄存器列表,至于虛擬寄存器分配多少個是根據方法結構體中的registers字段給出,davlik虛擬機根據這個字段創建一份虛擬的寄存器列表。將java棧幀中的局部變量區和操作數棧換成了寄存器列表來存儲。所以java虛擬機是基于棧架構,而davlik虛擬機基于寄存器架構
1.常見Davlik字節碼:
定義字段類型:
check-cast 寄存器(操作數),定義的類型;
舉例:
check-cast v0,Lcom/android/Launcher2/launcherApplication;代表定義v0的類型為LauncherApplication
字段寫入字段讀取(通用解釋)
總結:指令 目的操作數 源操作數前面代表指令 寄存器中的值(操作數) 所屬類 變量名 變量屬性本質上指令操作的還是操作數,根據指令變量是讀取還是被賦值讀取get:讀取變量賦值給操作數賦值set:賦值變量的值為操作數的值
靜態字段寫入:
const 寄存器 ,值所對應的ID(0X0代表為null)
sput-object 寄存器,字段所屬的類;->字段名字:字段類型
const/4 v3, 0x0
sput-object v3, Lcom/disney/Class1;->globalIapHandler:Lcom/disney/config/GlobalPurchaseHandler;
將0x00(代表null)存入v3寄存器中
將v3寄存器中的值寫入Class1中的globalIapHandler變量,該變量類型為GlobalPurchaseHandler,
也就是Class1.globalIapHandler = null;
靜態字段讀取:
sget -object 寄存器, 字段所屬的類;->字段名稱:字段類型
舉例:
sget-object v0, Lcom/disney/Class1;->PREFS_INSTALLATION_ID:Ljava/lang/String;
讀取Class1中的PREFS_INSTALLATION_ID變量,該變量類型為String
普通字段寫入:
.local v0, args:Landroid/os/Message;
const/4 v1, 0x12
iput v1, v0, Landroid/os/Message;->what:I
將args變量存入v0寄存器中
將0X12傳入到v1寄存器中
設置Message中的what變量為v1的值
相當于 args.what=18;
普通字段讀取:
iget-object 寄存器 p0(代表該變量所在類的示例即this), 字段所屬的類;->字段名字:zidaun1:字段類型
舉例:
iget-object v0, p0, Lcom/disney/Class1;->_view:Lcom/disney/Class2;
從v0寄存器中拿Class1中的_view變量,這個變量類型為Class2
調用方法:
invoke-virtual {寄存器:調用者(p0代表this)和方法參數信息}, 方法所在的類;->方法名(參數) 返回值
舉例:
invoke-virtual {p0},Lcom/android/Launcher2/Launcher;_>getApplication()L android/app/Application;
java實現代碼為:(this.)getApplication();
調用父類方法:
invoke-super {寄存器 :代表調用者和參數},方法所屬的類;->方法名稱(參數類型)返回值【V代表無返回值】
invoke-super {p0,p1},Landroid/app/ActivityGroup;->onCreate(Landroid/os/Bundle;)V
調用接口:
invoke-interface {寄存器【和方法一樣也是調用者和方法參數信息】}, 方法所屬的接口全名;->方法名(參數類型)返回值
invoke-interface {v3,v6,v9},Landroid/content/SharedPreferences;->getBoolean(Ljava/lang/String;Z)Z
java實現代碼為:v3.getBoolean(v6,v9);
判斷語句:
一,if-nez(與if-eqz相反)
if-nez 寄存器(里面存儲的是操作數), :標號處
如果操作數不為null或者不為0或者不相等就跳轉到標號處執行代碼
舉例:
move resule v0 (將上一條命令的結果賦值給v0)
if-nez v0, :cond_0
(判斷其值不為0【條件為真】就跳轉到cond_0標號處,反之程序繼續執行直到執行到return-void指令處)
二,if-eqz
表示在結果為0或者相等時跳轉(與if-nez相反)
方法返回:
return-void 沒有返回值
1.修改完smali文件安裝到手機上
重新編譯,回編譯命令為
apktool b 文件地址
回編譯中常見的錯誤:
1.提示"at brut.androlib.Androlib.buildResourcesFull(Androlib.java:477)"
解釋:該問題為打包資源出錯,程序使用的的API版本號和apkool中framework-res.apk基于Android的版本不一致導致
舉例:程序使用的API版本號為25;而apkttol版本號為2.2.2其對應的framework-res.apk的版本是基于Android6.0的,
其API為23。兩者不一致
解決方法為:找一臺API和程序使用的API版本號一致的android設備,從中獲取framework-res.apk,并把這個apk安裝到本地
使用命令:
(1.)獲取android設備中的framework-res.apk:
adb pull /system/framework/framework-res.apk
(2.)安裝到本地apktool中
apktool if ./framework-res.apk
編譯完生成的APK文件是沒有進行簽名的,所以不能安裝。
通過signapk對APK文件進行簽名
使用命令:
cat /User/android/Program/signapk
#!/bin/sh
java -jar ~/Program/signapk_jar/signapk.jar ~/Program/signapk_jar/testkey.x509.pem ~/Program/signapk_jar/testkey.pk8 $1 signed.apk
這些文件都可以從android源碼中提取。
接著完成apk的簽名操作:
signapk 編譯后未簽名的apk文件地址
簽名后完成后會在上面的文件地址里面生成sign.apk文件
看完上述內容,你們對如何分析Android逆向入門中的常見Davlik字節碼有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。