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

來源:互聯網
上載者:User

標籤:sys   host   tac   逆向   用戶端   server   文章   apk升級   list   

一、前言

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

Android中使用靜態方式破解Apk  主要採用的是靜態方式,步驟也很簡單,首先使用apktool來反編譯apk,得到smail源碼,然後分析smail代碼,採用代碼注入技術來跟蹤代碼,然後找到關鍵方法進行修改,進而破解,同時還可以使用一些開源的hook架構,比如:Xposed和Cydia Substrate,來進行關鍵方法的hook。所以這裡我們可以看到我們破解的第一步是使用apktool來進行成功的反編譯,然後是需要瞭解smali文法,不過關於smali文法其實很簡單,網上有很多教程。

 

二、知識概要分析

那麼今天我們就用另外一種方式來破解apk:動態方式,關於動態方式其實很廣義的,因為動態方式相對於靜態方式來說,難度大一點,但是他比靜態方式高效點,能夠針對更過的破解範圍。當然動態方式很多,所以這裡就分為三篇文章來講解這塊:

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

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

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

從這三篇文章能夠讓我們破解一般的apk沒有任何問題,不過不能代表能夠破解所有的apk,因為沒有絕對的安全,也是沒有絕對的破解,兩方都在進步,我們只能具體問題具體分析。好了,下面我們就來看第一篇文章,也是今天的重點:Eclipse動態調試smali源碼

首先需要解釋一下,這裡為什麼說是調試smali源碼,不是Java源碼,因為我們弄過反編譯的人知道,使用apktool反編譯apk之後,會有一個smali檔案夾,這裡就存放了apk對應的smali源碼,關於smali源碼這裡不解釋了,網上有介紹。

 

三、案例分析

因為這一篇是一個教程篇,所以不能光說,那樣會很枯燥的,所以這裡用一個例子來介紹一下:

我們就用阿里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的:

 

2、修改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的對話方塊。不過,我測試的時候,My Phone沒有出現這個對話方塊,而是一個白屏,不過這個不影響,程式運行起來之後,我們看看如何在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

 

四、思路整理

1、我們通過apktool工具進行apk的反編譯,得到smali源碼和AndroidManifest.xml,然後修改AndroidManifest.xml中的debug屬性為true,同時在入口處加上waitForDebug代碼,進行debug等待,一般入口都是先找到入口Activity,然後在onCreate方法中的第一行這裡需要注意的是,apktool工具一定要加上-d參數,這樣反編譯得到的檔案是java檔案,這樣才能夠被Eclipse識別,進行調試

2、修改完成AndroidManifest.xml和添加waitForDebug之後,我們需要在使用apktool進行回編譯,回編譯之後得到的是一個沒有簽名的apk,我們還需要使用signapk.jar來進行簽名,簽名檔案直接使用測試程式的簽名檔案就可以,最後在進行安裝。

3、然後我們將反編譯之後的smali源碼匯入到Eclipse工程中,找到關鍵點,進行下斷點,這裡的關鍵點,一般是我們先大致瞭解程式啟動並執行結構,然後找到我們需要破解的地方,使用View分析工具,或者是使用jd-gui工具直接查看apk源碼(使用dex2jar將dex檔案轉化成jar檔案,然後用jd-gui進行查看),找到代碼的大體位置。然後下斷點,這裡我們可以藉助Eclipse的DDMS內建的View分析工具找到對應控制項的resid,然後在全域搜尋這個控制項的resid,或者直接在values/public.xml中尋找,最終定位到這個控制項位置,在查看他的點擊事件即可。

4、設定遠端偵錯工程,首先運行需要偵錯工具,然後在DDMS中找到對應的調試服務端的連接埠號碼,然後在Debug Configurations中設定遠端偵錯項目,設定對應的調試連接埠和ip地址(一般都是本機pc,那就是localhost),然後紅色小蜘蛛變成綠色的,表示我們的遠端偵錯項目串連關聯上了偵錯工具,這裡需要注意的是,一定需要關聯正確,不然是沒有任何效果的,關聯成功之後,就可以進行操作。

5、操作的過程中,會進入到關鍵的斷點處,通過F6單步,F5單步進入,F7單步跳出,來進行調試,找到關鍵方法,然後通過分析smali文法,瞭解邏輯,如果邏輯複雜的,可以通過查看具體的環境變數的值來觀察,這裡也是最重要的,也是最複雜的,同時這裡也是沒有規章可尋的,這個和每個人的邏輯思維以及破解能力有關係,分析關鍵的加密方法是需要功底的,當然這裡還需要注意一個資訊,就是Log日誌,有時候也是很重要的一個資訊。

6、最後一般當我們知道了核心方法的邏輯,要想得到正確的密碼,還是需要自己用語言去實現邏輯的,比如本文中的加密方法,我們需要手動的code一下加密的逆向方法,才能得到正確的密碼。

 

五、遺留問題

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

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

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

3、有時候我們還會遇到回編譯成功了,然後遇到運行不起來的錯誤,這個就需要使用靜態方式先去剖析器啟動的邏輯,看看是不是程式做了什麼運行限制,比如我們在靜態分析那篇文章中,提到了應用為了防止反編譯在回編譯運行,在程式的入口處作了簽名校正,如果校正失敗,直接kill掉自己的進程,退出程式了,所以這時候我們還是需要使用靜態方式去分析apk。

4、如何做到不修改AndroidManifest.xml中的debug屬性就可以進行調試:

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

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

 

六、總結

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

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.