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

一、前言
在前一篇文章中詳細介紹了Android現階段可以采用的幾種反調試方案策略,我們在破解逆向應用的時候,一般現在第一步都回去解決反調試,不然后續步驟無法進行,當然如果你是靜態分析的話獲取就沒必要了。但是有時候必須要借助動態調試方可破解,就需要進行操作了。現階段反調試策略主要包括以下幾種方式:
第一、自己附加進程,先占坑,ptrace(PTRACE_TRACEME, 0, 0, 0)!第二、簽名校驗不可或缺的一個選擇,本地校驗和服務端校驗雙管齊下!第三、借助系統api判斷應用調試狀態和調試屬性,最基礎的防護!第四、輪訓檢查android_server調試端口信息和進程信息,防護IDA的一種有效方式!第五、輪訓檢查自身status中的TracerPid字段值,防止被其他進程附加調試的一種有效方式!
所以本文就來一一講解如何解決這幾種方式的反調試方案。

二、方法總結
第一種:找到關鍵方法,注釋代碼
這種方式需要采用靜態方式分析代碼,找到關鍵方法進行反調試代碼功能注釋,這種方式可以應對與上面所有的反調試方案,但是對于輪訓檢查這種方式就不太適合了,為什么?因為大家如果看過這篇文章:脫掉360加固應用保護殼;操作過的同學會發現,在去除反調試功能的時候那種痛苦了。所以這種注釋代碼,個人覺得只適用于以下幾種反調試:
第一、自己附加進程
這個可以IDA打開關鍵so代碼,找到這段代碼處:ptrace(PTRACE_TRACEME, 0, 0, 0),直接nop掉即可。這個沒什么難度,因為就一行代碼,說白了就幾條arm指令罷了。IDA靜態分析so也是無壓力的。
第二、簽名校驗
這個在之前的文章中介紹過了,不了解的同學可以查看這篇文章:Android中破解某應用的簽名校驗邏輯;最后總結了一個比較簡單的過濾簽名校驗的方法:先在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.imgdd if=/dev/block/mmcblk0p8 of=/data/local/boot.imgadb 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",讓應用可調試了。
Android逆向之旅---應用的"反調試"方案解析(附加修改IDA調試端口和修改內核信息)
當時說到這個工具有一個弊端就是他只能修改內存中的值,當設備重啟就會失效,那么現在我們可以讓他永久有效,其實這個屬性值,是在系統根目錄下的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

六、總結
本文介紹的內容主要是如何解決反調試問題,主要是三種方案,最后一種修改手機內核文件的操作比較繁瑣,遇到的問題也會比較多。但是如果要是成功了,以后進行破解逆向就方便多了。所以就努力看文章,自己手動操作一次。看完文章之后,記得多多點贊和分享擴散,要是有打賞就最好啦啦!

更多內容:點擊這里

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

編碼美麗技術圈
微信掃一掃進入我的"技術圈"世界

掃一掃加小編微信添加時請注明:“編碼美麗”非常感謝!


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容