逆向修改MIUI(X64)核心,反制TracerPID反除錯踩坑指南
0x00、前言
刷CTF時經常能遇到TracerPID反除錯,手動nop掉當然是一種好方法,但是每次都得重新打包難免會覺得煩躁。正好在逛吾愛時發現一篇patch核心繞過反除錯的文章,果斷嘗試一番,於是有了這篇X64版本的patch核心踩坑指南。
本次踩坑環境Redmi Note2 ,MIUI 9 8.4.19 |開發版 ,Android 5.0.2 。
0x01、boot.img 提取
方案一、adb
adb shell
cd /dev/block/platform/mtk-msdc.0/by-name
mtk-msdc.0不同的機型是不一樣的,但是platform下一般就只有一個資料夾,很容易就能找出。
dd if=/dev/block/mmcblk0p7 of=/data/local/boot.img
exit
adb pull /data/local/boot.img e:\boot.img
在E盤就能找到提取出來的boot.img。
方案二、Flashify
什麼?你說你是手殘黨,覺得手動提取boot.img太麻煩,那我們可以使用Flashify來提取。只需安裝Flashify,在BACKUP/RESTORE下就可以一鍵備份核心。
備份後pull到電腦就可以操作了。
兩種方式都必須擁有root許可權。
0x02、解包boot.img提取zImage
方案一、bootimg-tools 、mkbootimg
在Linux下可以使用mkbootimg 或bootimg-tools來解包boot.img。以下解包操作引用自文章《逆向修改核心,繞過TracerPID反除錯》。
bootimg-tools工具是一款基於mkbootimg開發的boot.img 解包重打包C語言工具
git clone https://github.com/pbatard/bootimg-tools.git
下載後進入bootimg-tools目錄,執行make 命令編譯該專案,在 makebootimg目錄下生成了相應的二進位制執行檔案。
解包
將kernel檔案複製為檔名為zImage.gz的檔案,並使用010editor查詢十六進位制1f 8b 08 00,找到後把前面的資料全刪掉,使檔案變成標準的gzip壓縮檔案,這樣子就可以使用gunzip解壓了。
命令:gunzip zImage.gz
生成檔案就是祼二進位制檔案zImage。
方案二、Android Image Kitchen
如果是在Windows下的話可以使用Android Image Kitchen。該工具使用非常簡單,下載並解壓該工具後只需將boot.img拖入unpacking.bak即可解包。
在生成的split_img下即可找到boot.img-zImage(因為ROM的緣故,解包後該檔案已經是標準的gz格式,可以直接解壓,如果不是標準的,請參照方案一的 方式提取出gz後解壓)。
使用解壓軟體直接將其解壓即可得到zImage
解包的工具有跟多並且選擇哪個無關緊要,三個解包工具我都嘗試過,最終的結果都一樣,純看個人喜好。
0x03、Patch kernel
在修改核心前我們需要了解核心的基址。
32 bit: 0xC0008000
64 bit: 0xffffffc000080000
如果不清到底應該用哪個也沒關係
回到adb shell 中
echo 0 > /proc/sys/kernel/kptr_restrict
cat /proc/kallsyms |grep proc_pid_status
cat /proc/kallsyms |grep __task_pid_nr_ns
記錄下這兩個重要的地址,從地址也可以看出應該使用哪個基址。用IDA開啟我們剛提取出的zImage檔案(此處我解壓後的的檔名為boot),processor type 選擇ARM Little-endian
之後更改ROM start address 和 Loading address為我們上面提到的核心基址。我的機型是64位的,所以選擇0xffffffc000080000。
開啟後左邊Function窗一片空白。
但是不要方,向下一路摁c便可解析出函式
摁g跳轉到0xffffffc0000bb488(__task_pid_nr_ns的地址)
選中sub_FFFFFFC0000BB488後摁x檢視引用,search搜尋ffffffc0001fb8a4(proc_pid_status的地址)。
然而IDA並沒有分析出該函式
摁g跳轉到ffffffc0001fb8a4(proc_pid_status的地址),之後摁p強制解析該函式。
之後g跳轉回到0xffffffc0000bb488(__task_pid_nr_ns的地址),選中sub_FFFFFFC0000BB488後摁x檢視引用,已經可以發現proc_pid_status對其的引用。
跟進去,經過分析找到需要修改的兩個地方,應該修改為MOV W1, #0和MOV W25, #0
對應的16進位制修改位置
0xFFFFFFC0001FBE90h-0xFFFFFFC000080000h=0x17BE90h
得出要修改的地址,用010Editor開啟zImage檔案,Ctrl+g跳轉到17BE90,摁下insert轉為overwrite模式修改上圖兩處。修改的機器碼為 01 00 80 52 和 19 00 80 52。
如果你實在是手抖,看到十六進位制就眼花,那麼修改完後可以丟入IDA檢視是否修改正確。
穩到不行(逃)
0x04、重新打包成boot.img
將修改後的zImage(此處我的檔名為boot)在Linux下用gzip
gzip -n -f -9 zImage
重打包成boot.gz。
boot.gz 必須比原來的boot.img-zImage小否則會造成不必要的麻煩。
此處有兩種重新打包的方法。
方案一、覆蓋boot.img-zImage
用010Editor同時開啟原boot.img-zImage和boot.gz。記錄下boot.gz的結束地址0x664C8A並複製boot.gz的全部內容,在boot.img-zImage跳轉到該地址,摁下insert改為overwrite模式,選中該地址之前的全部資料之後貼上覆蓋。
結果如下,記得儲存。
後面的內容千萬不要動,後面的內容千萬不要動,後面的內容千萬不要動,之後就可以使用Android Image Kitchen中的repackimg.bat重新打包便可生成image-new.img,重新命名為boot.img即可。
在這裡會發現一個不是問題的問題,新生成boot.img比原來的boot.img小了一半,但是實測並不會影響使用。
方案二、覆蓋原boot.img(強迫症福音)
此方案是為了解決上一個不是問題的問題而提出的,用010Editor同時開啟原boot.img和boot.gz。在boot.img中搜索1F 8B 08 00 (gz的開頭),會搜尋出兩個結果,一般是第一個,不放心的話可以用010Editor對照一下原boot.img-zImage。
回到boot.gz看到boot.gz結束地址是0x664C8A
所以我們修改到的最終地址是0x800h+0x664C8Ah=0x66548Ah
選中0x800h到0x66548Ah間的資料用boot.gz的資料覆蓋,結果如下
後面的內容千萬不要動,後面的內容千萬不要動,後面的內容千萬不要動…….儲存即可。
此方法獲得的boot.img和原版大小無異,極大地滿足了強迫症的需求(大霧)
0x05、刷入boot.img
在刷入之前一定要記得備份原boot.img,刷入錯誤的boot.img雖說不會變磚,但是會無限重啟。
刷入的方法有很多,強烈推薦使用fastboot 刷入。
fastboot flash boot boot.img
萬一手抖引起的修改失誤引發了無限重啟,只需用上述命令重刷原版boot.img就可以解決。
當然Flashify,TWRP等工具也是可以刷入的,在此就不詳細展開了,有興趣的自己嘗試。
最終IDA除錯時的效果
於是便可解放雙手,開心地刷CTF了(大霧)…….
參考連結:
感謝上述文章作者的無私分享。