1. 程式人生 > >逆向修改MIUI(X64)核心,反制TracerPID反除錯踩坑指南

逆向修改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了(大霧)…….

參考連結:

感謝上述文章作者的無私分享。