Android逆向之旅---應用的"反調試"方案解析(附加修改IDA調試端口和修改內核信息)

一、前言

在前一篇文章中詳細介紹了 Android現階段可以採用的幾種反調試方案策略,我們在破解逆向應用的時候,一般現在第一步都回去解決反調試,不然後續步驟無法進行,當然如果你是靜態分析的話獲取就沒必要了。但是有時候必須要藉助動態調試方可破解,就需要進行操作了。現階段反調試策略主要包括以下幾種方式:

  • 第一、自己附加進程,先佔坑,ptrace(PTRACE_TRACEME, 0, 0, 0)!

  • 第二、簽名校驗不可或缺的一個選擇,本地校驗和服務端校驗雙管齊下!

  • 第三、藉助系統api判斷應用調試狀態和調試屬性,最基礎的防護!

  • 第四、輪訓檢查android_server調試端口信息和進程信息,防護IDA的一種有效方式!

  • 第五、輪訓檢查自身status中的TracerPid字段值,防止被其他進程附加調試的一種有效方式!

所以本文就來一一講解如何解決這幾種方式的反調試方案。

 

二、方法總結

第一種:找到關鍵方法,註釋代碼

這種方式需要採用靜態方式分析代碼,找到關鍵方法進行反調試代碼功能註釋,這種方式可以應對與上面所有的反調試方案,但是對於輪訓檢查這種方式就不太適合了,爲什麼?操作過的同學會發現,在去除反調試功能的時候那種痛苦了。所以這種註釋代碼,個人覺得只適用於以下幾種反調試:

第一、自己附加進程

這個可以IDA打開關鍵so代碼,找到這段代碼處:ptrace(PTRACE_TRACEME, 0, 0, 0),直接nop掉即可。這個沒什麼難度,因爲就一行代碼,說白了就幾條arm指令罷了。IDA靜態分析so也是無壓力的。

第二、簽名校驗

最後總結了一個比較簡單的過濾簽名校驗的方法:先在Jadx中打開應用之後,全局搜字符串內容:"signatures",這個就可以定位到獲取應用簽名信息的地方了,然後可以依次跟蹤校驗的地方了。找到具體地方代碼直接註釋即可。但是如果服務端交互信息中攜帶了簽名校驗,而簽名校驗又在so中,那麼就需要另外操作了,這部分知識點將在後面單獨一篇文章詳細介紹如何破解。

第三、調用系統api判斷當前應用是否處於調試狀態

這種方式看到我們實現的邏輯還是比較簡單的,直接調用系統的android.os.Debug.isDebuggerConnected()方法和判斷當前應用屬性:ApplicationInfo.FLAG_DEBUGGABLE,那麼可以依然採用全局搜索反編譯之後的應用內容,找到這部分內容,然後直接註釋代碼即可。

 

第二種:修改IDA通信端口

上面分析完了,直接使用靜態方式+註釋代碼功能解決了之前提到的三種反調試方案。但是還有兩種沒有解決,下面就會詳細介紹一種非常靠譜方便永久的方法。而這部分內容纔是本文的重點。首先來看看如何解決之前提到的利用檢查IDA調試端口23946這個反調試方案。這個其實思路很簡單,因爲你檢查的端口號是默認的23946,所以我們如果能把這個端口號改成其他值,那麼其實就解決了。修改這個端口號,也比較簡單:網上有一種方案就是android_server本身支持自定義端口號的,命令很簡單:./android_server -p12345;直接加上-p參數即可,注意端口號和參數之間沒空格:

有的人說,這方法這麼簡單,那下面就不介紹了,當然不是,我寫文章的目的不是爲了簡單,而是爲了讓大家瞭解更多的知識,寧願多走彎路,走多條路出來。而且上面的這種方式每次都加-p比較麻煩,我想用另外一種方式去一次性解決問題,同時我更想在這個過程中熟悉一下IDA的使用,使用IDA打開android_server文件,其實他是elf格式的,打開無壓力,打開之後使用Shift+12查看字符串內容界面:

找到這三處關鍵字符串內容,我們可以通過以往運行過android_server之後的提示信息察覺:

找到這三處字符串內容,下面就簡單了,一處一處進行修改,雙擊字符串條目內容:

選中按X鍵,進行切換:

選擇第一個跳轉到arm指令處:

這是graph視圖,可以使用空格鍵進行切換:

看到arm指令了,LDR R5,=0x5D8A;其中0x5D8A就是十進制的23946,也就是默認端口號,所以這裏我們只需要將這個arm指令,改成MOVS R5,#0xDD;可對R5進行重新賦值,這裏賦值爲DD,也就是221;這裏有個小問題就是如何進行修改,IDA中可以切換到Hex View視圖進行修改編輯二進制,但是這樣修改不會生效到源文件中,所以我們這裏還得藉助一個二進制編輯工具010Editor,我們使用這個軟件打開android_server之後,使用Ctrl+G可以直接跳轉到指定地址,使用Ctrl+F可以跳轉到搜索內容處,記住以下這兩個快捷鍵。

 

這裏看到了99 4D就是:LDR R5, =0x5D8A 對應的指令十六進制值,關於指令和十六進制值之間轉化可以去網上搜一個小工具即可。我們想將其變成 MOVS R5,#0xDD 指令,對應的十六進制是:DD 25,其中DD就是立即數值,25表示MOVS R5指令。所以下面就可以直接進行修改即可:

修改完成之後,進行保存即可,這樣我們就修改好了一處,還有兩處操作一模一樣:

繼續修改init_sockets處,命令都是一樣的,記住地址:B98A,去010Editor中進行修改即可:

然後繼續修改IDA Android 32-bit...處

記住地址:B64C,去010Editor進行修改即可:

 

這樣我們就全部改好了,保存android_server文件,再次使用IDA打開,找到一個地方查看修改是否成功:

的確修改成功了,下面我們把android_server拷貝到設備中運行,看看端口是否爲221(0xDD):

看到了,這裏成功的修改了,android_server監聽端口了,主要當打開IDA進行連接的時候需要注意端口是221,而不是23946了,或者你可以用adb forward tcp:221...命令進行轉發也可以!

 

第三種:修改boot.img文件,跳過反調試

這種方式是爲了解決現在常用的反調試策略,就是輪訓檢查進程的TracerPid值,所以我們需要修改設備的boot.img文件,將這個值直接寫死爲0即可。關於如何修改操作,看雪上已經有大神講解了非常詳細的過程,我就是按照這個流程進行操作的:http://bbs.pediy.com/thread-207538.htm,因爲每個設備的boot.img都不一樣,所以在操作的過程中可能遇到很多問題,所以下面就把我操作的過程中遇到的問題講解一下,順便精煉的說一下步驟:

第一步,你得有一個可以折騰的root手機

因爲現在是在玩boot.img了,後面得刷機,所以你得搞一個你覺得沒多大意義的設備,即使成磚頭了也無妨。當然一般不會成爲磚頭。

第二步:root環境下提取zImage內核文件

這裏我用的是三星note2設備,自己刷了一個CM4.4系統,按照大神的貼中先去找到系統boot的文件位置,這個路徑一定要注意:/dev/block/platform/[每個設備目錄不一樣]/by-name;其中platform目錄中的子目錄因爲每個設備都不一樣,所以需要注意,查看自己設備目錄名稱,然後進入到by-name之後,使用 ls -l 命令查看詳情,找到一項BOOT,記住link的路徑地址,這裏是/dev/block/mmcblk0p8,然後使用命令,將boot導出爲boot.img
dd if=/dev/block/mmcblk0p8 of=/data/local/boot.img
adb pull /data/local/boot.img boot.img

這裏可能有人會遇到一個問題就是,看到多個BOOT,比如BOOT1,BOOT2,這裏可以選擇BOOT即可,也有的人會發現沒這個選項,那麼只能在刷個其他系統進行操作了。

第三步:藉助bootimg.exe工具解壓boot.img文件

這個工具我會在後面一起給出壓縮包,命令用法很簡單,

解包是:bootimg.exe --unpack-boot boot.img

壓包是:bootimg.exe --repack-boot

這裏有一個坑,我找到兩個版本,第一個版本工具操作之後刷機總是黑屏啓動失敗,最後找到了第二個版本工具才成功的。其實這些工具原理很簡單,就是解析boot.img文件格式罷了,因爲boot和recovery映像並不是一個完整的文件系統,它們是一種android自定義的文件格式,該格式包括了2K的文件頭,後面緊跟着是用gzip壓縮過的內核,再後面是一個ramdisk內存盤,然後緊跟着第二階段的載入器程序(這個載入器程序是可選的,在某些映像中或許沒有這部分):

我們想要的是kernel內核信息。所以用這個工具進行操作之後,會發現有這麼幾個目錄和文件:

解壓之後有一個kernel文件,這個就是內核文件,而ramdisk.gz就是釋放到設備目錄內容,也就是initrd目錄,進入查看內容:

看到了吧,這就是最終設備的目錄結構,可以看到這裏有init.rc啓動文件,default.prop配置文件等。

 

接下來我們就要對kernel內核文件進行特別處理了:將kernel文件複製爲文件名爲zImage.gz的文件,並使用010Editor工具,Ctrl+F快捷鍵查找十六進制內容1F 8B 08 00,找到後把前面的數據全刪掉,使zImage.gz文件變成標準的gzip壓縮文件,這樣子就可以使用gunzip解壓了。命令:gunzip zImage.gz;這時候獲取到了解壓之後的zImage纔是我們要處理的最終文件。

 

第四步:IDA打開zImage內核文件進行修改

有了上面一步得到的內核文件zImage,直接使用IDA打開,但是打開的時候需要注意設置選項:

然後設置開始地址爲0xC0008000

這裏爲什麼要設置成這個起始地址,因爲Linux啓動內核的地址爲0xC0008000;打開之後,我們可以直接Shift+F12,查看字符串內容,因爲我們想改TracerPid值,所以直接搜字符串"TracerPid"值

雙擊進入,這時候我們可以記下這個地址,然後減去剛剛我們那個偏移地址0xC0008000:

也就是0xC0A3853C-0xC0008000=0xA3053C,這裏沒有像看雪大神操作那麼複雜,先去定位函數位置,修改指令,因爲每個設備不一樣,指令代碼就不一樣,不具備通用性,所以這裏有一個更好的方案:就是直接改TracerPid的格式字符串值,原始格式化字符串內容爲:

\t%s\nTgid:\t%d\nPid:\t%d\nPPid:\t%d\nTracerPid:\t0\t\nUid:\t%d\t%d\t%d\t%d\nGid:\t%d\t%d\t%d\t%d\n

 

這裏應該用到了C語言中的佔位符%d,來進行值的填充,那麼我們可以把TracerPid那一項的佔位符%d,改成'0',但是'%d'是兩個字符,所以我們可以改成'00',或者'0\t',或者'0\n';只要保證修改後的字符串內容對其就好。這樣TracerPid這一項的值佔位符就失效,值永遠都是0了。而上面計算的地址就是我們要去010Editor中操作的地址,用010Editor打開zImage文件,Ctrl+G跳轉到0xA3053C處:

這裏我們將其改成'0\t'值,對應的十六進制就是:30 09;這樣我們就修改成功了。

 

第五步:生成修改後的boot.img文件

這裏操作其實就是一個相反的過程,首先使用gzip命令壓縮上面修改好的內核文件zImage:gzip -n -f -9 zImage;然後使用010Editor將壓縮好的zImage.gz的二進制數據覆蓋到原kernel文件的1F 8B 08 00處的位置(回寫回去時不能改變原kernel文件的大小及修改原kernel文件後面的內容,否則會很麻煩),這時得到了新的kernel文件內容。這裏需要特別強調一下,也就是我踩過的坑:比如kernel原來是10M大小,1F8B0800之前刪除的是1M,我們修改之後的zImage.gz大小是8M,那麼我們回寫覆蓋的時候一定是1M~9M的位置,而kernel的前面1M內容和後面1M內容不能有任何改動,搞錯的話,刷機會出現啓動失敗的情況。下面用我操作的案例講解一下:

這是我修改之後的壓縮好的zImage.gz文件,最後一個數據是0x65E18D,然後全選內容複製好,記住之後,再去原來的kernel內容:

在kernel中的1F8B0800位置是0x47A0,那麼我們就需要把剛剛賦值的內容從這裏開始替換,到哪裏結束呢?將這兩個地址相加即可:0x65E18D+0x47A0=0x66292D;也就是到0x66292D結束:

這樣原來的kernel內容大小肯定不會發生變化了,始終都是0x662967,所以在替換內容的時候內容一定不能發生變化。替換完成之後,將新的kernel文件替換原來的kernel文件,在使用之前提到的bootimg.exe工具生成新的boot.img文件即可。

 

第六步:刷機boot.img文件

這裏有一個坑,在刷機的時候用到的是fastboot命令,但是遇到最多的問題就是這個錯誤:

這個是因爲設備還沒有啓動fastboot,關於每個設備啓動fastboot不一樣操作,比如小米是電源鍵+音量減,三星是音量減+HOME鍵+電源鍵;具體設備可以自行網上搜索即可。到了fastboot界面再次運行fastboot就可以了:

fastboot flash boot boot-new.img

然後在運行fastboot reboot重啓設備即可。有的同學在操作的時候,始終進入fastboot失敗,導致fastboot命令運行錯誤,這個真解決不了那就換個手機試一下吧。

 

這時候我們啓動設備,然後調試一個app,發現他的TracerPid值永遠都是0了,因爲我之前將TracerPid改成'00'字符串了,也是可以的:

因爲感覺不正規,所以就有重新改成了'0\t'值了。都是可以的。

注意:一定要保存原始提取的內核文件boot.img,當你把設備弄成磚頭啓動失敗的時候,可以在把這個原始的boot.img刷回去就可!

 

三、內容延展

不知道大家以前在看:脫360加固應用的保護殼 文章的時候當時說到了一個工具mprop,作用就是能夠改寫系統的內存中的ro.debuggable這個屬性值,這樣我們就沒必要每次反編譯app,然後在AndroidManifest.xml中添加android:debuggable="true",讓應用可調試了。

當時說到這個工具有一個弊端就是他只能修改內存中的值,當設備重啓就會失效,那麼現在我們可以讓他永久有效,其實這個屬性值,是在系統根目錄下的default.prop文件中的,設備啓動就會解析存入內存中。所以如果我們能夠把這個文件中的值改成1,那麼就永久有效了。在上面解包boot.img的時候,說到了有一個initrd目錄,其實default.prop就是在這個目錄下:

這裏我們直接將其改成1,因爲我們現在已經進行了修改boot.img操作,那就順便把這個功能也給改了。多方便呀!

 

四、提取內核操作總結

第一步:設備root之後,查看設備的內核文件路徑: cd /dev/block/platform/[具體設備具體查看]/by-name,然後使用命令ls -l 查看boot屬性的,記住路徑

第二步:dd if=/dev/block/[你的內核路徑] of=/data/local/boot.img

adb pull /data/local/boot.img boot.img

第三步:使用bootimg.exe工具進行boot.img解包;得到kernel文件,將kernel文件複製爲文件名爲zImage.gz的文件,並使用010Editor工具,Ctrl+F快捷鍵查找十六進制內容1F 8B 08 00,找到後把前面的數據全刪掉,使zImage.gz文件變成標準的gzip壓縮文件,這樣子就可以使用gunzip解壓了。命令:gunzip zImage.gz

第四步:使用IDA打開zImage內核文件,記得設置選項和起始地址:0xC0008000;打開之後,使用shift+F12查找到字符串“TracerPid”值,記住文件起始地址,然後減去0xC0008000;在使用010Editor打開內核文件,Ctrl+G跳轉到這個地址,進行內容修改,將TracerPid那個佔位符‘%d’改成‘0\t’保存即可

第五步:首先使用gzip命令壓縮上面修改好的內核文件zImage:gzip -n -f -9 zImage;然後使用010Editor將壓縮好的zImage.gz的二進制數據覆蓋到原kernel文件的1F 8B 08 00處的位置(回寫回去時不能改變原kernel文件的大小及修改原kernel文件後面的內容,否則會很麻煩)

第六步:啓動設備爲fastboot模式,然後使用fastboot命令進行刷機:fastboot flash boot boot-new.img,然後在重啓即可

 

總結一張圖(點擊查看高清無碼大圖):

 

踩過的坑

坑一:一定保留最原始提取的內核文件boot.img,爲了防止你刷失敗了,可以還原操作。
坑二:修改TracerPid值時,只需要將‘%d’佔位符改成‘0\t’即可,無需改動arm命令操作。
坑三:在還原kernel文件的使用一定要記得不能改變原始kernel文件的大小。
坑四:fastboot命令運行失敗,設備必須處於fastboot模式,如果還不行那就換個手機吧。

 

五、技術總結

第一:關於反調試的第一種解決方案比較簡單,就是靜態分析代碼,找到反調試的位置,然後註釋代碼即可。

第二:對於監聽IDA端口反調試,通過修改android_server的啓動端口,這裏也學會了如何修改端口號操作。

第三:修改內核文件,讓TracerPid始終爲0,ro.debuggable屬性值始終爲1,這個操作過程還是有點繁瑣的,遇到的問題肯定很多,而且每個人遇到的問題可能不一樣,但是這是一個鍛鍊的過程,如果成功了意味着你學會了提取內核操作,瞭解內核文件結構,學會分析內核文件,修改內核文件。意義重大。比如你還可以修改設備的啓動圖,慢慢的你可以定製自己的rom了。

第四:在以上操作中,也熟悉了IDA工具使用,瞭解到了字符串內容永遠都是尋找問題的最好突破口,IDA中查找字符串Shirt+F12即可,010Editor中Ctrl+G和Ctrl+F查找快捷鍵。

 

本文的目的只有一個就是學習更多的逆向技巧和思路,如果有人利用本文技術去進行非法商業獲取利益帶來的法律責任都是操作者自己承擔,和本文以及作者沒關係,本文涉及到的代碼項目可以去編碼美麗小密圈自取,歡迎加入小密圈一起學習探討技術

 

解包boot.img文件的工具下載地址:

http://download.csdn.net/detail/jiangwei0910410003/9793611

 

六、總結

本文介紹的內容主要是如何解決反調試問題,主要是三種方案,最後一種修改手機內核文件的操作比較繁瑣,遇到的問題也會比較多。但是如果要是成功了,以後進行破解逆向就方便多了。所以就努力看文章,自己手動操作一次。

 

《Android應用安全防護和逆向分析》

點擊立即購買:京東  天貓  

更多內容:點擊這裏

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章