[轉]Android逆向之旅---動態方式破解apk前奏篇(Eclipse動態調試smail源碼)

分類:
 
 

1、前言

今天咱們開始apk破解的另一種方式:動態代碼調試破解,以前其實已經在一篇文章中說到如何破解apk了:android

Android中使用靜態方式破解Apk  主要採用的是靜態方式,步驟也很簡單,首先使用apktool來反編譯apk,獲得smail源碼,而後分析smail代碼,採用代碼注入技術來跟蹤代碼,而後找到關鍵方法進行修改,進而破解,同時還可使用一些開源的hook框架,好比:Xposed和Cydia Substrate,來進行關鍵方法的hook。因此這裏咱們能夠看到咱們破解的第一步是使用apktool來進行成功的反編譯,而後是須要了解smali語法,不過關於smali語法其實很簡單,網上有不少教程。算法

 

2、知識概要分析

那麼今天咱們就用另一種方式來破解apk:動態方式,關於動態方式其實很廣義的,由於動態方式相對於靜態方式來講,難度大一點,可是他比靜態方式高效點,可以針對更過的破解範圍。固然動態方式不少,因此這裏就分爲三篇文章來說解這塊:ubuntu

一、動態方式破解apk前奏篇(Eclipse動態調試smail源碼)api

二、動態方式破解apk升級篇(IDA動態調試so源碼)數組

三、動態方式破解apk終極篇(應對加固的apk破解方法)安全

從這三篇文章可以讓咱們破解通常的apk沒有任何問題,不過不能表明可以破解全部的apk,由於沒有絕對的安全,也是沒有絕對的破解,兩方都在進步,咱們只能具體問題具體分析。好了,下面咱們就來看第一篇文章,也是今天的重點:Eclipse動態調試smali源碼服務器

首先須要解釋一下,這裏爲何說是調試smali源碼,不是Java源碼,由於咱們弄過反編譯的人知道,使用apktool反編譯apk以後,會有一個smali文件夾,這裏就存放了apk對應的smali源碼,關於smali源碼這裏不解釋了,網上有介紹。微信

 

3、案例分析

由於這一篇是一個教程篇,因此不能光說,那樣會很枯燥的,因此這裏用一個例子來介紹一下:

咱們就用阿里2014年安全挑戰賽的第一題:AliCrack_one.apk


看到這張圖了,阿里還挺會製造氛圍的,那麼其實很簡單,咱們輸入密碼就能夠破解了,下面咱們就來看看如何獲取這個密碼。

第一步:使用apktool來破解apk

java -jar apktool_2.0.0rc4.jar d -d AliCraceme_1.apk -o out


這裏的命令不作解釋了,可是有一個參數必須帶上,那就是:-d

由於這個參數表明咱們反編譯獲得的smali是java文件,這裏說的文件是後綴名是java,若是不帶這個參數的話,後綴名是smali的,可是Eclipse中是不會識別smali的,而是識別java文件的,因此這裏必定要記得加上這個參數。

反編譯成功以後,咱們獲得了一個out目錄,以下:


源碼都放在smali文件夾中,咱們進入查看一下文件:


看到了,這裏全是Java文件的,其實只是後綴名爲java了,內容仍是smali的:


 

二、修改AndroidManifest.xml中的debug屬性和在入口代碼中添加waitDebug

上面咱們反編譯成功了,下面咱們爲了後續的調試工做,因此仍是須要作兩件事:

1》修改AndroidManifest.xml中的Android:debuggable="true"


關於這個屬性,咱們前面介紹run-as命令的時候,也提到了,他標識這個應用是不是debug版本,這個將會影響到這個應用是否能夠被調試,因此這裏必須設置成true。

2》在入口處添加waitForDebugger代碼進行調試等待。

這裏說的入口處,就是程序啓動的地方,就是咱們通常的入口Activity,查找這個Activity的話,方法太多了,好比咱們這裏直接從上面獲得的AndroidManifest.xml中找到,由於入口Activity的action和category是固定的。


固然還有其餘方式,好比aapt查看apk的內容方式,或者是安裝apk以後用adb dumpsys activity top命令查看都是能夠的。

找到入口Activity以後,咱們直接在他的onCreate方法的第一行加上waitForDebugger代碼便可,找到對應的MainActivity的smali源碼:

而後添加一行代碼:

invoke-static {}, Landroid/os/Debug;->waitForDebugger()V

這個是smali語法的,其實對應的Java代碼就是:android.os.Debug.waitForDebugger();


這裏把Java語言翻譯成smali語法的,不難,網上有smali的語法解析,這裏不想再解釋了。

 

第三步:回編譯apk而且進行簽名安裝

java -jar apktool_2.0.0rc4.jar b -d out -o debug.apk

仍是使用apktool進行回編譯


編譯完成以後,將獲得debug.apk文件,可是這個apk是沒有簽名的,因此是不能安裝的,那麼下面咱們須要在進行簽名,這裏咱們使用Android中的測試程序的簽名文件和sign.jar工具進行簽名:


關於簽名的相關知識,能夠看這篇文章:Android中的簽名機制詳解

java -jar .\sign\signapk.jar .\sign\testkey.x509.pem .\sign\testkey.pk8 debug.apk debug.sig.apk


簽名以後,咱們就能夠進行安裝了。

 

第四步:在Eclipse中新建一個Java工程,導入smali源碼

這裏咱們新建一個Java工程,記住不是Android工程,由於咱們最後調試實際上是藉助於Java的調試器,而後勾選掉Use default location選項,選擇咱們的smali源碼目錄,也就是咱們上面反編譯以後的out目錄,點擊完成


咱們導入源碼以後的項目工程結構:


主要看MainActivity類:


 

第五步:找到關鍵點,而後打斷點

這一步咱們看到,其實說的比較廣義了,這個要具體問題具體分析了,好比這個例子中,咱們知道當咱們輸入密碼以後,確定要點擊按鈕,而後觸發密碼的校驗過程,那麼這裏咱們知道找到這個button的定義的地方,而後進入他的點擊事件中就能夠了。這裏分爲三步走:

1》使用Eclipse自帶的View分析工具找到Button的ResId


點擊以後,須要等待一會,分析View以後的結果:


看到了,這裏咱們可以看到整個當前的頁面的所有佈局,已經每一個控件的屬性值,咱們須要找到button的resource-id

這裏咱們看到定義是@+id/button這個值。

2》咱們獲得這個resId以後,可否在smali工程中全局搜索這個值,就能夠定位到這個button的定義的地方呢?

而後咱們看看搜到的結果:

這時候咱們實際上是在資源文件中搜到了這個id的定義,這個id值對應的是0x7F05003E。

固然除了這種方式,咱們還有一種方式能快速找到這個id對應的整型值,那就是在反編譯以後的values/public.xml文件中:


這個文件頗有用的,他是真個apk中全部資源文件定義的映射內容,好比drawable/string/anim/attr/id 等這些資源文件定義的值,名字和整型值對應的地方:


這個文件很重要,是咱們在尋找突破口的重要關鍵,好比咱們有時候須要經過字符串內容來定位到關鍵點,這裏就能夠經過string的定義來找到對應的整型值便可。

當咱們找到了button對應的id值了以後,咱們就能夠用這個id值在一次全局搜索一下,由於咱們知道,Android中編譯以後的apk,在代碼中用到的resId都是用一個整型值代替的,這個整型值就是在R文件中作了定義,將資源的id和一個值對應起來,而後代碼裏面通常使用R.id.button這樣的值,在編譯出apk的時候,這個值就會被替換成對應的整型值,因此在全局搜索0x7F05003E


搜索的結果以下:


看到了,這裏就定位到了代碼中用到的這個button,咱們進入代碼看看:


在這裏,看到了,使用了findViewById的方式定義Button,咱們在往下面簡單分析一下smali語法,下面是給button添加一個按鈕事件,這裏用的是內部類MainActivity$1,咱們到這個類看看,他確定實現了OnClickListener接口,那麼直接搜onClick方法:


在這裏咱們就能夠下個斷點了,這裏就是觸發密碼校驗過程。

 

第六步:運行程序,設置遠程調試工程

在第五步中,咱們找到了關鍵點,而後打上斷點,下面咱們就來運行程序,而後在Eclipse中設置遠程調試的工程

首先咱們運行程序,由於咱們加入了waitForDebug的代碼,因此啓動的時候會出現一個Wait debug的對話框。不過,我測試的時候,個人手機沒有出現這個對話框,而是一個白屏,不過這個不影響,程序運行起來以後,咱們看看如何在Eclipse中設置遠程調試工程,首先咱們找到須要調試的程序對應遠程調試服務端對應的端口:


這裏咱們看到有幾個點:

1》在程序等待遠程調試服務器的時候,前面會出現一個紅色的小蜘蛛

2》在調試服務端這裏咱們會看到兩個端口號:8600/8700,這裏須要解釋一下,爲何會有兩個端口號呢?

首先在這裏的端口號,表明的是,遠程調試服務器端的端口,下面在簡單來看一下,Java中的調試系統:


這裏咱們看到,這裏有三個角色:

111》JDB Client端(被調試的客戶端),這裏咱們能夠認爲咱們須要破解的程序就是客戶端,若是一個程序能夠被調試,當啓動的時候,會有一個jdwp線程用來和遠程調試服務端進行通訊


這裏咱們看到,咱們須要破解的程序啓動了JDWP線程,注意這個線程也只有當程序是debug模式下才有的,也就是AndroidManifest.xml中的debug屬性值必須是true的時候,也就是一開始爲何咱們要修改這個值的緣由。

222》JDWP協議(用於傳輸調試信息的,好比調試的行號,當前的局部變量的信息等),這個就能夠說明,爲何咱們在一開始的時候,反編譯成java文件,由於爲了Eclipse導入可以識別的Java文件,而後爲何可以調試呢?由於smali文件中有代碼的行號和局部變量等信息,因此能夠進行調試的。

333》JDB Server端(遠程調試的服務端,通常是有JVM端),就是開啓一個JVM程序來監聽調試端,這裏就能夠認爲是本地的PC機,固然這裏必須有端口用來監聽,那麼上面的8600端口就是這個做用,並且這裏端口是從8600開始,後續的程序端口後都是依次加1的,好比其餘調試程序:


那麼有了8600端口,爲何還有一個8700端口呢?他是幹什麼的?

其實他的做用就是遠程調試端備用的基本端口,也就是說好比這裏的破解程序,咱們用8600端口能夠鏈接調試,8700也是能夠的,可是其餘程序,好比demo.systemapi他的8607端口能夠鏈接調試,8700也是能夠的:


因此呀,能夠把8700端口想象成你們均可以用於鏈接調試的一個端口,不過,在實際過程當中,仍是建議使用程序獨有的端口號8600,咱們能夠查看8600和8700端口在遠程調試端(本地pc機)的佔用狀況:


看到了,這裏的8600端口和8700端口號都是對應的javaw程序,其實javaw程序就是啓動一個JVM來進行監聽的。

好了,到這裏咱們就弄清楚了,Java中的調試系統以及遠程調試的端口號。

注意:

其實咱們可使用adb jdwp命令查看,當前設備中能夠被調試的程序的進程號信息:


 

下面繼續,咱們知道了遠程調試服務端的端口:8600,以及ip地址,這裏就是本地ip:localhost/127.0.0.1

咱們能夠在Eclipse中新建一個遠程調試項目,將咱們的smali源碼工程和設備中須要調試的程序關聯起來:

右擊被調試的項目=》選擇Debug Configurations:


而後開始設置調試項目


選擇Romote Java Application,在Project中選擇被調試的smali項目,在Connection Type中選擇SocketAttach方式,其實還有一種方式是Listener的,關於這兩種方式其實很好理解:

Listner方式:是調試客戶端啓動就準備好一個端口,當調試服務端準備好了,就鏈接這個端口進行調試

Attach方式:是調試服務端開始就啓動一個端口,等待調試端來鏈接這個端口


咱們通常都是選擇Attach方式來進行操做的。

好了,咱們設置完遠程調試的工程以後,開始運行,擦發現,設備上的程序仍是白屏,這是爲何呢?看看DDMS中調試程序的狀態:


擦,關聯到了這個進程,緣由也很簡單,咱們是上面使用的是8700端口號,這時候咱們選中了這個進程,因此就把smali調試工程關聯到了這個進程,因此破解的進程沒反應了,咱們立馬改一下,用8600端口:


好了,這下成功了,咱們看到紅色的小蜘蛛變成綠色的了,說明調試端已經鏈接上遠程調試服務端了。

注意:

咱們在設置遠程調試項目的時候,必定要注意端口號的設置,否則沒有將調試項目源碼和調試程序關聯起來,是沒有任何效果的

 

第七步:開始運行調試程序,進入調試

下面咱們就開始操做了,在程序的文本框中輸入:gggg內容,點擊開始:


好了,到這裏咱們看到期待已久的調試界面出來了,到了咱們開始的時候加的斷點處,這時候咱們就能夠開始調試了,使用F6單步調試,F5單步跳入,F7單步跳出進行操做:


看到了,這裏使用v3變量保存了咱們輸入的內容


這裏有一個關鍵的地方,就是調用MainActivity的getTableFromPic方法,獲取一個String字符串,從變量的值來看,貌似不是規則的字符串內容,這裏先不用管了,繼續往下走:


這裏又遇到一個重要的方法:getPwdFromPic,從字面意義上看,應該是獲取正確的密碼,用於後面的密碼字符串比對。


查看一下密碼的內容,貌似也是一個不規則的字符串,可是咱們能夠看到和上面獲取的table字符串內容格式很像,接着往下走:


這裏還有一個信息就是,調用了系統的Log打印,log的tag就是v6保存的值:lil


這時候,咱們看到v3是保存的咱們輸入的密碼內容,這裏使用utf-8獲取他的字節數組,而後傳遞給access$0方法,咱們使用F5進入這個方法:


在這個方法中,還有一個bytesToAliSmsCode方法,使用F5進入:


那麼這個方法其實看上去仍是很簡單的,就是把傳遞進來的字節數組,循環遍歷,取出字節值,而後轉化成int類型,而後在調用上面獲取到的table字符串的chatAt來獲取指定的字符,使用StringBuilder進行拼接,而後返回便可。

按F7跳出,查看,咱們返回來加密的內容是:日日日日,也就是說gggg=>日日日日


最後再往下走,能夠看到是進行代碼比對的工做了。

 

那麼上面咱們就分析完了全部的代碼邏輯,還不算複雜,咱們來梳理一下流程:

A>調用MainActivity中的getTableFromPic方法,獲取一個table字符串

咱們能夠進入看看這個方法的實現:


這裏能夠大致瞭解了,他是讀取asset目錄下的一個logo.png圖片,而後獲取圖片的字節碼,在進行操做,獲得一個字符串,那麼咱們從上面的分析能夠知道,其實這裏的table字符串相似於一個密鑰庫。

B>經過MainActivity中的getPwdFromPic方法,獲取正確的密碼內容

C>獲取咱們輸入內容的utf-8的字節碼,而後調用access$0方法,獲取加密以後的內容

D>access$0方法中在調用bytesToAliSmsCode方法,獲取加密以後的內容

這個方法是最核心的,咱們經過分析知道,他的邏輯是,經過傳遞進來的字節數組,循環遍歷數組,拿到字節轉化成int類型,而後在調用密鑰庫字符串table的charAt獲得字符,使用StringBuilder進行拼接。

經過上面的分析以後,咱們知道獲取加密以後的輸入內容和正確的密碼內容作比較,那麼咱們如今有的資源是:

密鑰庫字符串和正確的加密以後的密碼,以及加密的邏輯

那麼咱們的破解思路其實很簡單了,至關於,咱們知道了密鑰庫字符串,也知道了,加密以後的字符組成的字符串,那麼能夠經過遍歷加密以後的字符串,循環遍歷,獲取字符,而後再去密鑰庫找到指定的index,而後在轉成byte,保存到字節數組,而後用utf-8獲取一個字符串,那麼這個字符串就是咱們要的密碼。

下面咱們就用代碼來實現這個功能:


代碼邏輯,很簡單吧,其實這個函數至關於上面加密函數的bytesToAliSmsCode的反向實現,運行結果:


OK,獲得了正確的密碼,下面來驗證一下:


哈哈,不要太激動,成功啦啦~~。破解成功。

 

補充:

剛剛咱們在斷點調試的時候,看到了代碼中用了Log來打印日誌,tag是lil,那麼咱們能夠打印這個log看看結果:


看到了,這裏table是密鑰庫,pw是正確的加密以後的密碼,enPassword是咱們輸入以後加密的密碼。

因此從這裏能夠看到,這個例子,其實咱們在破解apk的時候,有時候日誌也是一個很是重要的信息。

 

破解須要的資料,我已經上傳了,下載地址:http://download.csdn.net/detail/jiangwei0910410003/9526113

 

4、思路整理

一、咱們經過apktool工具進行apk的反編譯,獲得smali源碼和AndroidManifest.xml,而後修改AndroidManifest.xml中的debug屬性爲true,同時在入口處加上waitForDebug代碼,進行debug等待,通常入口都是先找到入口Activity,而後在onCreate方法中的第一行這裏須要注意的是,apktool工具必定要加上-d參數,這樣反編譯獲得的文件是java文件,這樣纔可以被Eclipse識別,進行調試

二、修改完成AndroidManifest.xml和添加waitForDebug以後,咱們須要在使用apktool進行回編譯,回編譯以後獲得的是一個沒有簽名的apk,咱們還須要使用signapk.jar來進行簽名,簽名文件直接使用測試程序的簽名文件就能夠,最後在進行安裝。

三、而後咱們將反編譯以後的smali源碼導入到Eclipse工程中,找到關鍵點,進行下斷點,這裏的關鍵點,通常是咱們先大體瞭解程序運行的結構,而後找到咱們須要破解的地方,使用View分析工具,或者是使用jd-gui工具直接查看apk源碼(使用dex2jar將dex文件轉化成jar文件,而後用jd-gui進行查看),找到代碼的大致位置。而後下斷點,這裏咱們能夠藉助Eclipse的DDMS自帶的View分析工具找到對應控件的resid,而後在全局搜索這個控件的resid,或者直接在values/public.xml中查找,最終定位到這個控件位置,在查看他的點擊事件便可。

四、設置遠程調試工程,首先運行須要調試程序,而後在DDMS中找到對應的調試服務端的端口號,而後在Debug Configurations中設置遠程調試項目,設置對應的調試端口和ip地址(通常都是本機pc,那就是localhost),而後紅色小蜘蛛變成綠色的,表示咱們的遠程調試項目鏈接關聯上了調試程序,這裏須要注意的是,必定須要關聯正確,否則是沒有任何效果的,關聯成功以後,就能夠進行操做。

五、操做的過程當中,會進入到關鍵的斷點處,經過F6單步,F5單步進入,F7單步跳出,來進行調試,找到關鍵方法,而後經過分析smali語法,瞭解邏輯,若是邏輯複雜的,能夠經過查看具體的環境變量的值來觀察,這裏也是最重要的,也是最複雜的,同時這裏也是沒有規章可尋的,這個和每一個人的邏輯思惟以及破解能力有關係,分析關鍵的加密方法是須要功底的,固然這裏還須要注意一個信息,就是Log日誌,有時候也是很重要的一個信息。

六、最後通常當咱們知道了核心方法的邏輯,要想獲得正確的密碼,仍是須要本身用語言去實現邏輯的,好比本文中的加密方法,咱們須要手動的code一下加密的逆向方法,才能獲得正確的密碼。

 

5、遺留問題

一、使用apktool工具進行反編譯有時候並非那麼順利,好比像這樣的報錯:


這個通常都是apktool中解析出現了錯誤,其實這個都是如今apk爲了抵抗apktool,作的apk加固策略,這個後面會寫一篇文章如何應對這些加固策略,如何進行apk修復,其實原理就是分析apktool源碼,找到指定的報錯位置,進行apktool代碼修復便可。

二、本文中說到了Java的調試系統,可是爲了篇幅限制,沒有詳細的講解了整個內容,後面會寫一篇文章具體介紹Java中的調試系統以及Android的調試系統。

三、有時候咱們還會遇到回編譯成功了,而後遇到運行不起來的錯誤,這個就須要使用靜態方式先去分析程序啓動的邏輯,看看是否是程序作了什麼運行限制,好比咱們在靜態分析那篇文章中,提到了應用爲了防止反編譯在回編譯運行,在程序的入口處做了簽名校驗,若是校驗失敗,直接kill掉本身的進程,退出程序了,因此這時候咱們仍是須要使用靜態方式去分析apk。

四、如何作到不修改AndroidManifest.xml中的debug屬性就能夠進行調試:

1》 修改boot.img,從而打開系統調試,這樣就能夠省去給app添加android:debuggable="true",再重打包的步驟了。
2.》直接修改系統屬性,使用setpropex工具在已經root的設備上修改只讀的系統屬性。使用此工具來修改ro.secure和ro.debuggable的值。

這個也會在後面詳細介紹這兩種方法

 

6、總結

這篇文章咱們就介紹瞭如何使用Eclipse去動態調試反編譯以後的smali源碼,這種方式比靜態方式高效不少的,好比本文中的這個例子,其實咱們也可使用靜態方式進行破解的,可是確定效率沒有動態方式高效,因此之後咱們又學會了一個技能,就是動態的調試smali源碼來跟蹤程序的核心點,可是如今市場上的大部分應用沒有這麼簡單就破解了,好比核心的加密算法放到了native層去作,那麼這時候就須要咱們去動態調試so文件跟蹤,這個是咱們下一篇文章的內容,也有的時候,apk進行加固了,直接在apktool進行反編譯就失敗了,這時候咱們就須要先進行apk修復,而後才能後續的操做,這個是咱們下下篇的文章,如何應對apk的加固策略。經過這篇文章咱們能夠看到動態方式破解比靜態方式高效的多,可是有時候咱們還須要使用靜態方式先作一些準備工做,因此在破解apk的時候,動靜結合,才能作到完美的破解。

 

 

更多內容:點擊這裏

 

關注微信公衆號,最新Android技術實時推送

 


 

 

 

 
9
0
 
 
 

 

 
猜你在找
【直播】機器學習&深度學習系統實戰(唐宇迪)
【直播】Kaggle 神器:XGBoost 從基礎到實戰(冒教授)
【直播回放】深度學習基礎與TensorFlow實踐(王琛)
【直播】計算機視覺原理及實戰(屈教授)
【直播】機器學習之凸優化(馬博士)
【直播】機器學習之矩陣(黃博士)
【直播】機器學習之機率與統計推斷(冒教授)
【直播】機器學習之數學基礎
【直播】TensorFlow實戰進階(智亮)
【直播】深度學習30天系統實訓(唐宇迪)

 

 

查看評論
4樓 code_xzh 2016-05-23 17:30發表 [回覆]
樓主來一篇用studio的,畢竟eclipse如今都淘汰了
Re: yuwumo4341 2016-06-02 18:26發表 [回覆]
回覆code_xzh:仍是eclipse間接實用
3樓 starrywz 2016-05-21 18:17發表 [回覆]
在Eclipse中設置遠程調試的工程----請問具體是怎麼操做的
2樓 qq402335257 2016-05-21 09:33發表 [回覆]
膜拜
1樓 Dream_boy_94 2016-05-20 17:39發表 [回覆]
厲害
 
該文章已被禁止評論!
* 以上用戶言論只表明其我的觀點,不表明CSDN網站的觀點或立場
 
 
TOP
相關文章
相關標籤/搜索