android載入dex
『壹』 Android開發如何將asset文件打入dex包
1.解包dex
2.重新打包dex
c:\Documents and Settings\Anminstrator>choice /c:21'choice' 不是內部或外部命令,也不是可運行程序或批處理文件。
『貳』 android怎麼動態調試dex
1.1 安裝JDK
java環境的搭建請自行查找資料,這里不做詳述。
1.2 安裝Android SDK
下載地址:http://developer.android.com/sdk/index.html。
下載完安裝包後解壓到任意一目錄,然後點擊運行SDK Manager.exe,然後選擇你需要的版本進行安裝,如圖:
1.3 安裝Eclipse集成開發環境
下載地址:http://www.eclipse.org/downloads。選擇Eclipse for Mobile Developers,解壓到任意目錄即可。
1.4 創建Android Virtual Device
動態調試可以用真實的手機來做調試環境,也可以用虛擬機來做調試環境,本文採用虛擬機環境。因此創建虛擬機步驟如下:
1打開Eclipse –>windows->Android Virtual Device
2點擊Create,然後選擇各個參數如圖:
這里Target 就是前面步驟中安裝的SDK 選擇任意你覺得喜歡的版本就可以。點擊OK 就創建完畢。
1.5 安裝 APK改之理
這個是一個很好用的輔助調試的軟體,請自行搜索下載。
1.6 安裝 IDA6.6
IDA6.6開始支持安卓APP指令的調試,現該版本已經提供免費下載安裝,請自行搜搜。
0x02 Dalvik指令動態調試
2.1 准備工作
安卓APP應用程序後綴為apk,實際上是一個壓縮包,我們把它改後綴為rar打開如圖:
其中classes.dex是應用的主要執行程序,包含著所有Dalvik指令。我們用APK改之理打開apk,軟體會自動對其進行反編譯。反編譯後會有很多smail文件,這些文件保存的就是APP的Dalvik指令。
在APK改之理里雙擊打開AndroidManifest.xml,為了讓APP可調試,需要在application 標簽里添加一句android:debuggable="true" 如圖:
然後點擊保存按鈕,然後編譯生成新的apk文件。接著打開Eclipse –>windows->Android Virtual Device,選擇剛才創建的虛擬機,然後點擊start,虛擬機便開始運行。偶爾如果Eclipse啟動失敗,報錯,可以同目錄下修改配置文件:
把配置參數原本為512的改為256 原本為1024的改為512,然後再嘗試啟動。
在SDK安裝目錄有個命令行下的調試工具adb shell,本機所在目錄為E:\adt-bundle-windows-x86-20140702\sdk\platform-tools,把adb.exe注冊到系統環境變數中,打開dos命令行窗口執行adb shell 就可以進入APP命令行調試環境,或者切換到adb所在目錄來執行adb shell。
這里先不進入adb shell,在DOS命令行下執行命令:adb install d:\1.apk 來安裝我們剛才重新編譯好的APK文件。安裝完畢會有成功提示。
2.2 利用IDA動態調試
將APP包里的classes.dex解壓到任意一目錄,然後拖進IDA。等待IDA載入分析完畢,點擊Debugger->Debugger Options如圖
按圖所示勾選在進程入口掛起,然後點擊Set specific options 填入APP包名稱和入口activity 如圖:
其中包的名稱和入口activity 都可以通過APK改之理里的AndroidManifest.xml 文件獲取:
1
2
3
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.simpleencryption">
<application android:allowBackup="true" android:debuggable="true" android:icon="@drawable/creakme_bg2" android:label="@string/app_name" android:theme="@style/AppTheme">
<activity android:label="@string/app_name" android:name=".MainActivity">
然後在IDA點擊Debugger->Process Options
其他默認不變,埠這里改為8700。這里默認埠是23946,我在這里困擾了很久,就是因為這個埠沒有改為8700所致。然後我們看看這個8700埠是怎麼來的。在Android SDK里提供了一款工具DDMS,用來監視APP的運行狀態和結果。在SDK的TOOLS目錄有個DDMS.BAT的腳步,運行後就會啟動DDMS。由於我的本機安裝了SDK的ADT插件,DDMS集成到了Eclips中,打開Eclips->Open perspective->ddms就啟動了DDMS。
如圖所示:
在DDMS選中某個進程後面就會注釋出它的調試埠,本機這里是8700。
到此所有的工作就准備就緒,然後就可以下斷點來調試該APP了。我們在APK改之理中在com目錄下查看smali文件 發現MainActivity.smali里有一個感興趣的函數getPwdFromPic(),那麼我們就對它下斷以跟蹤APP的運行。
在IDA里搜索字元串getPwdFromPic,發現onClick有調用該函數
我們在onClick 函數開始位置按F2下斷如圖:
然後點擊上圖中綠色三角形按鈕啟動調試如圖:
調試過程中有一個問題出現了很多次,浪費了我大量的時間,就在寫文章的時候,操作時還是遇到了這樣的問題。就是點擊啟動後IDA提示can』t bind socket,琢磨了很久終於找到原因了,當打開過一次DDMS後 每次啟動Eclips都會啟動DDMS 而8700埠正是被這個DDMS給佔用了,然後每次都會啟動失敗,解決辦法就是 虛擬機運行起來後關閉掉Eclips,這時一切就正常了!
事例中是一個APP crackme 提示輸入密碼才能進入正確界面。這個時候我們輸入123,點擊登陸,IDA中斷在了我們設置斷點的地方,這時選中ida->debugger->use source level debugger,然後點擊ida->debugger->debugger windows->locals打開本地變數窗口,如圖:
然後按F7或F8單步跟蹤程序流程,同時可以觀察到變數值的變化,也可以在IDA右鍵選擇圖形視圖,可以看到整個APP執行的流程圖:
如上圖所示 變數窗口中我們輸入了123 被轉化成的密碼是么廣亡,pw變數也顯示出了正確的密碼,其實這個時候已經很容易判斷出正確密碼了。
0x03 Andoid原生動態鏈接庫動態調試
通常為了加密保護等措施,有時dex執行過程中會調用動態鏈接庫文件,該文件以so為後綴,存在於APP文件包里。
這里我們以動態附加的方式來調試原生庫。
3.1 准備工作
1、將IDA->dbgsrv目錄下的android_server拷貝到虛擬機里,並賦予可執行許可權
DOS命令分別為:
adb shell pull d:\ android_server /data/data/sv
adb shell chmod 755 /data/data/sv
2、啟動調試伺服器android_server
命令:adb shell /data/data/sv
伺服器默認監聽23946埠。
3、重新打開DOS窗口進行埠轉發,命令:
adb forward tcp:23946 tcp:23946 如圖:
3.2 利用IDA進行動態調試
1、虛擬機里啟動要調試的APP 2、啟動IDA,打開debugger->attach->remote Armlinux/andoid debugger
埠改為23946 其他保持不變,點擊OK
如上圖,選中要調試的APP 的數據包名,然後點擊OK。
正常情況下,IDA會把APP進程掛起。
3、由於當前程序不是在動態鏈接庫領空,這時我們要重新打開一個IDA,用它打開需要調試的so文件,找到需要下斷的位置的文件偏移,並做記錄,然後關閉後面打開的這個IDA。
4、在原IDA界面按下ctrl+s鍵,找到並找到需要調試的so,同時記錄該文件的載入基址。然後點擊OK 或者cancel按鈕關閉對話框。
5、按下快捷鍵G 輸入基址+文件偏移所得地址,點擊OK 就跳轉到SO文件需要下斷的地方,這時按下F2鍵設置斷點。當APP執行到此處時便可以斷下來。
3.3 在反調試函數運行前進行動態調試
程序載入so的時候,會執行JNI_OnLoad函數,做一系列的准備工作。通常反調試函數也會放到JNI_OnLoad函數里。進行4.2中第2步時也許會遇到如下情況:
這時APP檢測到了調試器,會自動退出,那麼這時調試策略需要有所改變。
接著4.1第3步後,在DOS命令行執行命令:
adb shell am start -D -n com.yaotong.crackme/com.yaotong.crackme.MainActivity
來以調試模式啟動APP 如圖:
com.yaotong.crackme是APP包名稱,com.yaotong.crackme.MainActivity是執行入口 這些可以用APK改之理查看。
這時由於APP還未運行,那麼反調試函數也起不了作用,按照4.2中第2步把APP掛起。這時IDA會中斷在某個位置
然後點擊debugger->debugger opions設置如下:
點擊OK 後按F9運行APP,然後再DOS命令下執行命令:
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
這時APP會斷下來,然後按照4.2中的3、4、5補找到JNI_OnLoad函數的地址並下斷,然後按F9 會中斷下來。然後便可以繼續動態跟蹤調試分析。
『叄』 android dex文件 怎麼打開
apk文件是把android
sdk編譯的工程打包成一個安裝程序文件,格式為apk。
APK文件其實是zip格式,但後綴名被修改為apk,通過UnZip解壓後,可以看到Dex文件,Dex即Android
Dalvik執行程序,你可以在安裝Android操作系統的手機中執行即可安裝。
望採納
『肆』 android手機的apk文件中的class.dex文件是什麼是做什麼用的呢
簡單說就是優化後的android版.exe。每個apk安裝包里都有。相對於PC上的java虛擬機能運行.class;android上的Davlik虛擬機能運行.dex。
作用
讓dalvik能夠運行。
dex好處
可以直接用DexClassLoader類載入,動態載入。於是只要在dex上加殼,在程序運行時脫殼,就可以規避靜態反編譯的風險。
(4)android載入dex擴展閱讀
使用dex文件的原因
在Android系統中,一個App的所有代碼都在一個Dex文件裡面。Dex是一個類似Jar的包,存儲了很多Java編譯位元組碼的歸檔文件。
因為Android系統使用Dalvik虛擬機,所以需要把使用Java Compiler編譯之後的class文件轉換成Dalvik能夠執行的class文件。
『伍』 哪位朋友能告知一下,dex文件如何安裝在安卓手機上
因字數限制,因此無法詳述,請參看這個鏈接,介紹非常詳細:
http://..com/question/262114879.html
『陸』 Android上,怎麼用16進制加密apk的dex文件讓別人無法反編譯或進內部查看原代碼
可以在Dex文件頭隱藏另一個DEX數據並在運行時載入附帶DEX數據。
構建非規范的Dex文件
通過反射調用DexFile類的方法載入附帶DEX數據
通過反射實際調用DexFile的openDexFile方法
該種方式允許通過byte[]解析dex數據,而無須在再把DEX數據存儲在設備的某個文件。
可以從安裝APK文件、內存或dalvik-cache等讀取dex數據。
該種方式將給自動化分析工具帶來一個問題,自動化工具會按照dex格式處理DEX文件而不會處理附帶的dex數據。需要特定的工具、16進制編輯器或手工提取嵌入的dex數據。
我們可以採用各種不同的方式增加嵌入數據的提取難度,比如:
對嵌入的DEX數據進行加密;
嵌入的DEX數據加密後在對其進行ZIP壓縮;
使用native代碼解密,直接從內存載入;
......等等
該種隱藏方式可以通過判斷Dex文件頭長度是否大於0x70檢測。
『柒』 android dex何時載入
1 問題
在Android系統中,一個App的所有代碼都在一個Dex文件裡面。Dex是一個類似Jar的存
儲了多有Java編譯位元組碼的歸檔文件。因為Android系統使用Dalvik虛擬機,所以需要把
使用Java Compiler編譯之後的class文件轉換成Dalvik能夠執行的class文件。這里需要強
調的是,Dex和Jar一樣是一個歸檔文件,裡面仍然是Java代碼對應的位元組碼文件。
當Android系統啟動一個應用的時候,有一步是對Dex進行優化,這個過程有一個專門的
工具來處理,叫DexOpt。DexOpt的執行過程是在第一次載入Dex文件的時候執行的。這
個過程會生成一個ODEX文件,即Optimised Dex。執行ODex的效率會比直接執行Dex文
件的效率要高很多。但是在早期的Android系統中,DexOpt有一個問題,也就是這篇文
章想要說明並解決的問題。DexOpt會把每一個類的方法id檢索起來,存在一個鏈表結構
裡面。但是這個鏈表的長度是用一個short類型來保存的,導致了方法id的數目不能夠超過
65536個。當一個項目足夠大的時候,顯然這個方法數的上限是不夠的。盡管在新版本的
Android系統中,DexOpt修復了這個問題,但是我們仍然需要對老系統做兼容。
2 思路
一種有效的解決思路是把Dex文件分割成多個較小的Dex。這就如同很多項目會把自己分
割成多個Jar文件一樣,不同的功能在不同的Jar文件裡面,通過一些配置和額外的操作,
可以讓虛擬機有選擇性的載入Jar文件。但是在Android系統中,一個應用是只允許有一
個Dex文件的。也就是說在編譯期的時候,所有的Jar文件最終會被合並成一個Dex文件。
我們沒有辦法在Apk文件裡面打包兩個Dex,讓DexOpt分別對兩個Dex文件做處理,而
Android系統也不會同時為一個Apk載入兩個Dex。
1
2.1 動態載入
如果我們把Dex分成多個文件,然後在程序運行的時候,再把多的那幾個動態的載入進來
是否可行呢?也就是說我們能否在運行時階段把代碼加入虛擬機中。對於虛擬機來說,其
實所有的代碼都是在運行時被載入進來的。而不同於C語言還存在著靜態鏈接。虛擬機在
所有Java代碼執行之前被啟動,然後開始把位元組碼載入到環境中執行,我們可以理解成所
有的代碼都是動態載入到虛擬機里的。
而說到載入,不得不說的是ClassLoader。它的工作就是載入.class文件。在Android的
Dalvik環境中,對應的是DexClassLoader,它們的功能是完全一樣的。ClassLoader的
一大特點就是它是一個樹狀結構。每個ClassLoader都有一個父親ClassLoader。也就是
說,ClassLoader不是把所有的Class放到一個巨大的數組或別的什麼數據結構中來處理。
ClassLoader在載入一個Jar中的類的時候,需要制定另一個ClassLoader作為父親節點,
當我們需要通過ClassLoader得到一個類類型的時候,ClassLoader會把請求優先交給父
親ClassLoader來處理,而父親ClassLoader又會交給它的父親,一直到根ClassLoader。
如果根ClassLoader有這個類,而返回這個類的類類型,否則把這個請求交給這個請求的
來源子ClassLoader。這是一種向上傳遞,向下分發的機制。這種情況下,對於調用著來
說,子ClassLoader永遠都是包含最多Class的ClassLoader。有一點我們需要注意,父親
ClassLoader只會向請求來源分發自己的處理結果。所以如果來源是自己,那麼如果沒有
請求類它就會返回空,而不是遍歷所有子ClassLoader去請求是否有被請求的類。
在Android系統中,對於一個應用來說,其實有兩個ClassLoader,一個是SystemClassLoader,這個ClassLoader裡面除了Java標準的類庫之外,還有一個android.jar,所有
Android Framework層的類都在這里。而另外一個重要的ClassLoader就是基於Android
Context的ClassLoader。所有屬於當前應用的類都是用這個ClassLoader來載入的,我們
可以在Android源碼中看到,所有的Activity,Service,View都是使用這個ClassLoader
來反射並創建的。我們暫時把它叫做ContextClassLoader。
3 載入外部Dex
3.1 構建一個Dex文件
這一步並不復雜,首先我們把所需要的.class文件或者是Jar文件和一些源碼一起編譯生
成一個Jar文件。然後使用Android SDK提供的dx工具把Jar文件轉成Dex文件。我們可以
提前對它進行ODex操作,讓它在被DexClassLoader載入的時候,跳過DexOpt的部分工
作,從而加快載入的過程。
2
3.2 DexClassLoader
現在的工作就是在運行時載入這個Dex文件了。我們可以在Application啟動的onCreate
方法裡面載入Dex,但是如果你的Dex太大,那麼它會讓你的App啟動變慢。我們也可以
使用線程去載入,但我們必須保證載入完成之後再進行某個外部類的請求。當然也可以真
正等到需要某個外部類的時候再進行Dex載入。這根本上取決於Dex文件本身的大小,太
大了可以預載入,而比較小可以等到實際需要的時候再載入。我們暫且把這個載入了外部
Dex的ClassLoader成為ExternalClassLoader
上面我們提到了樹形結構和系統中的多個ClassLoader,當我們載入外部Dex的時候,我
們是否需要指定一個父ClassLoader呢?我們當然需要一個父ClassLoader,否則我們ExternalClassLoader連一些基本的Java類都沒有,它根本不可能成功的載入一個Dex。進一
步的,我們要選擇哪一個ClassLoader來作為我們的父親呢?是SystemClassLoader還是
ExternalClassLoader?這是根據情況來定的,如果外部的Dex文件里沒有任何和Android
相關的代碼,那麼SystemClassLoader是我們的首選,否則我們就應該用ContextClassLoader。如果是後者的情況,我們的樹可以被看成一個鏈表。
3.3 外部的View, Acitivity等
我們知道,我們編寫的四大組建都不是由我們自己來創建的,是由系統來給我們構造並
管理其生命周期的。那麼這個過程是什麼樣的呢?拿Activity來舉例,我們需要通過調用
當前Activity/Context的startActivity,傳入一個Intent來調用啟動一個新的Activity。系
統有一個ActivityManager來處理這里的邏輯。這里的邏輯相當的復雜,但簡單來說,
ActivityManager會收到並處理這個Intent,從而決定是是啟動一個新的,還是把舊的放
到前台。它會先查找這個Activity在哪個應用裡面,這是通過掃描每個應用的AndroidManifest來確定。這些信息是在PackageManager裡面被檢索的。總之如果這個Activity
不再任何的manifest裡面,它就不可能被啟動。所以僅有一個Activity類是不夠的,我們
需要在manifest裡面聲明它。
上面是Activity的情況,Service之類的也是同理。那麼View怎麼辦?盡管我們可以直接創
建View,但是大部分的View都不是我們創建的,而是通過XML布局文件Inflate出來的。
也就是說,我們在XML定義了一些外部Dex裡面的View,那麼顯然這個XML是不能被成
功的Inflate的。因為除非系統會使用我們的ExternalClassLoader,否則它肯定是找不到
我們的類的:ContextClassLoader裡面並沒有外部Dex中的類。
也就是說問題的根本在於,對於那些Android系統為我們創建的對象,它是不能包含在外
部Dex裡面的。而Android系統中大部分的組建類的生命周期都交給了系統來管理。我們
3
不可能自己來創建這些類對象。那麼另一種思路:我們是不是可以通過使用我們的ExternalClassLoader來代替ContextClassLoader呢?盡管系統的ContextClassLoader是私有
的,但是我們可以通過反射強制的把它替換成我們的ExternalClassLoader。而對於那些
外部的組建(Activity等),盡管我們沒有它們的類,但是並不影響我們在AndroidManifest裡面聲明這個Activity。因為Android系統只是把它作為一個檢索,並不會真正檢查它
裡面的組建是不是真的在虛擬機環境中已經被載入了,只有真正使用Intent啟動某個組建
的時候才會去檢查。而只要我們保證這個時候我們已經載入了外部的ClassLoader,那麼
這個組建就可以被正常的啟動。
還有一點,除了我們要為外部可能有的組建在AndroidManifest裡面做聲明一外,那些外
部組建可能用到的許可權我們也需要一一聲明,例如如果外部Activity使用了相機功能,那
么如果我們的Manifest裡面沒有聲明使用相機功能的許可權的話,即便這個Activity能成功
為載入出來,仍然是不能使用的。
4 核心代碼段
載入外部Dex
mClassLoader = new DexClassLoader ( f . getAbsolutePath ( ) ,
mContext . getCacheDir ( ) . getAbsolutePath ( ) ,
null , mContext . getClassLoader ( ) ) ;
讓系統使用ExternalClassLoader
t r y {
F ie ld mMainThread = ge t F ie ld ( A c t i v i t y . class , 」mMainThread」) ;
Object mainThread = mMainThread . get ( a c t i v i t y ) ;
Class t hreadClass = mainThread . get Class ( ) ;
F ie ld mPackages = ge t F ie ld ( threadClass , 」mPackages」) ;
WeakReference<?> r e f ;
Map< St ring , ?> map =(Map< St ring , ? >) mPackages . get (mainThread ) ;
r e f = (WeakReference<? >) map . get (mContext . getPackageName ( ) ) ;
Object apk = r e f . get ( ) ;
Class apkClass = apk . get Class ( ) ;
F ie ld mClassLoader = ge t F ie ld ( apkClass , 」mClassLoader」) ;
mClassLoader . set (apk , classLoader ) ;
} catch ( I llegalArgument Except ion e) {
i f (DEBUG) {
e . print St ackTrace ( ) ;
}
} catch ( I llega lAc c essEx c ept ion e) {
i f (DEBUG) {
4
e . print St ackTrace ( ) ;
}
}
5
『捌』 android程序class.dex文件無法訪問
Java 文件 ----- - 應用程序源文件
android 本身相當一部分都是用 java 編寫而成 ( 基本上架構圖里頭藍色的部份都是用
Java 開發的 ) , android 的應用必須使用 java 來開發。
Class 文件 ------Java 編譯後的目標文件
不像 J2se , java 編譯成 class 就可以直接運行, android 平台上 class 文件不能直接
在 android 上運行。由於 Google 使用了自己的 Dalvik 來運行應用,所以這里的 class 也
肯定不能在 AndroidDalvik 的 java 環境中運行, android 的 class 文件實際上只是編譯
過程中的中間目標文件,需要鏈接成 dex 文件後才能在 dalvik 上運行。
Dex 文件-----Android 平台上的可執行文件
Android 虛擬機 Dalvik 支持的位元組碼文件格式 Google 在新發布的 Android 平台上使用
了自己的 Dalvik 虛擬機來定義,這種虛擬機執行的並非Java 位元組碼,而是另一種位元組碼:
dex 格式的位元組碼。在編譯 Java 代碼之 後 ,通過 Android 平台上的工具可以將 Java 字
節碼轉換成 Dex 位元組碼。雖然 Google 稱 Dalvik 是為了移動設備定做的,但是業界很多人
認為這是為了規避向 sun 申請 Javalicense 。這個 DalvikVM 針對手機程式 /CPU 做過 最
佳化,可以同時執行許多 VM 而不會佔用太多 Resource 。
Apk 文件 -Android 上的安裝文件
Apk 是 Android 安裝包的擴展名,一個 Android 安裝包包含了與某個 Android 應用程序相
關的所有文件。 apk 文件將 AndroidManifest.xml 文件、應用程序代碼 (.dex 文件 ) 、
資源文件和其他文件打成一個壓縮包。
『玖』 android dexclassloader 能不能卸載
不能,這個是用來載入dex文件中的類文件的,android5.0以前版本的應用程序文件都是以dex格式存在的,所以最好不要卸載,
『拾』 Android手機的apk文件中的class.dex文件是什麼是做什麼用的呢
簡單說就是優化後的android版.exe。每個apk安裝包里都有。相對於PC上的java虛擬機能運行.class;android上的Davlik虛擬機能運行.dex。
作用
讓dalvik能夠運行。
dex好處
可以直接用DexClassLoader類載入,動態載入。於是只要在dex上加殼,在程序運行時脫殼,就可以規避靜態反編譯的風險。
(10)android載入dex擴展閱讀
使用dex文件的原因
在Android系統中,一個App的所有代碼都在一個Dex文件裡面。Dex是一個類似Jar的包,存儲了很多Java編譯位元組碼的歸檔文件。
因為Android系統使用Dalvik虛擬機,所以需要把使用Java Compiler編譯之後的class文件轉換成Dalvik能夠執行的class文件。