1. 程式人生 > >修改Android手機核心,繞過反除錯

修改Android手機核心,繞過反除錯

0x1.手機裝置環境

Model number: Nexus 5
OS Version: Android 4.4.4 KTU84P
Kernel Version: 3.4.0-gd59db4e

0x2.Android核心提取

查詢Android裝置的boot分割槽檔案。高通晶片的裝置可以通過下面的命令進行查詢。

cd /home/androidcode/AndroidDevlop/modifyNexus5Boot

adb shell

ls -al /dev/block/platform/msm_sdcc.1/by-name


root許可權下,用 dd 將其dump到Nexus 5手機的sdcard資料夾下,然後匯出到檔案 /home/androidcode/AndroidDevlop/modifyNexus5Boot

下:

adb shell
su

dd if=/dev/block/mmcblk0p19 of=/sdcard/boot.img

exit
exit

adb pull /sdcard/boot.img boot.img


使用abootimg工具對boot.img檔案進行解包處理,解包之後得到的 zImage 檔案即為Android的核心檔案。

abootimg工具的github地址:https://github.com/ggrandou/abootimg
abootimg工具的直接安裝命令:sudo apt-get install build-essential abootimg  

abootimg -x boot.img  
  
ls -al  


將zImage檔案拷貝一份作為檔名為 kernel.gz 的檔案,並使用 WinHex 工具查詢十六進位制 1F 8B 08 00,找到之後把前面的資料部分全刪掉,使kernel.gz檔案變成標準的gzip壓縮檔案,這樣子就可以使用  gunzip/gzip 命令進行解壓核心檔案了。

cp ./zImage  ./kernel.gz

# 去掉解包的核心檔案kernel.gz中前面的垃圾資料

gzip -d kernel_new.gz

ls -al

使用WinHex查詢十六進位制資料:


刪除掉解包的核心檔案kernel.gz中的前面的垃圾資料,然後重新儲存修改後的 kernel.gz檔案為 kernel_new.gz

.


修改後的gzip格式的 kernel_new.gz 檔案的解壓得到kernel_new核心檔案


提示:關於gzip格式檔案的解壓,既可以使用 gzip 命令也可以使用 gunzip 命令,都一樣。有關gzip/gunzip 命令的引數使用說明,如下:

$ gzip -h
Usage: gzip [OPTION]... [FILE]...
Compress or uncompress FILEs (by default, compress FILES in-place).

Mandatory arguments to long options are mandatory for short options too.

  -c, --stdout      write on standard output, keep original files unchanged
  -d, --decompress  decompress
  -f, --force       force overwrite of output file and compress links
  -h, --help        give this help
  -k, --keep        keep (don't delete) input files
  -l, --list        list compressed file contents
  -L, --license     display software license
  -n, --no-name     do not save or restore the original name and time stamp
  -N, --name        save or restore the original name and time stamp
  -q, --quiet       suppress all warnings
  -r, --recursive   operate recursively on directories
  -S, --suffix=SUF  use suffix SUF on compressed files
  -t, --test        test compressed file integrity
  -v, --verbose     verbose mode
  -V, --version     display version number
  -1, --fast        compress faster
  -9, --best        compress better
  --rsyncable       Make rsync-friendly archive

With no FILE, or when FILE is -, read standard input.

Report bugs to <[email protected]>.


關於gzip檔案格式的說明和原始碼的解析可以參考 gzip檔案格式解析及原始碼分析,進行深入的研究和學習。


0x3.Android核心檔案的逆向修改

將解壓後的Android核心檔案 kernel_new  拖入到IDA Pro 中進行分析,設定處理器型別為ARM Little-endian


 在 ROM start addressLoading address 處填上 0xc0008000,然後點選 OK 。


IDA顯示效果如下圖所示,沒有函式名,不方便定位程式碼,顯示不友好需要新增Android核心的核心符號。


為了要獲取Android核心中所有的核心符號資訊,可以通過在root許可權下,修改Andriod裝置中的/proc/sys/kernel/kptr_restrict 的值來實現,去掉Android核心符號的資訊遮蔽。

adb shell  
su  
  
# 檢視預設值  
cat /proc/sys/kernel/kptr_restrict  
  
# 關閉核心符號遮蔽  
echo 0 > /proc/sys/kernel/kptr_restrict   
  
# 檢視修改後的值  
cat /proc/sys/kernel/kptr_restrict  
  
cat /proc/kallsyms 

關閉Android裝置的核心符號的遮蔽以後,再次執行 cat /proc/kallsyms ,發現被隱藏的核心符號資訊都顯示出來了。


在root許可權下,將Android裝置中的核心符號資訊dump出來,匯出到 /home/androidcode/AndroidDevlop/modifyNexus5Boot/syms.txt檔案中。因此,Android核心檔案的核心符號資訊都儲存在syms.txt檔案中了。

# cat /proc/kallsyms > /sdcard/syms.txt  
  
# exit  
$ exit  
  
$ adb pull /sdcard/syms.txt syms.txt  


我們已經將Androd核心檔案中的核心符號資訊都dump出來,下面將大有用武之地。因此,向IDA中匯入之前提取出來的核心符號資訊就可以看到對應的函式名稱了。需要用到下面的Python指令碼:

ksyms = open("C:\Users\Fly2016\Desktop\Android核心的提取和逆向\syms.txt")  
for line in ksyms:  
    addr = int(line[0:8],16)  
    name = line[11:]  
    idaapi.set_debug_name(addr,name)  
    MakeNameEx(addr,name,SN_NOWARN)  
    Message("%08X:%sn"%(addr,name))  

在IDA的 File->Script Command中執行上述python指令碼,之後就可以在IDA中成功新增核心符號資訊使IDA顯示出正確的系統呼叫的函式名稱來。


Android核心中隱藏的系統函式呼叫的名稱在IDA中顯示出來了。


現在來聊一聊修改Android的核心檔案繞過反除錯,很多的Android加固都會通過檢視當前程序的 /proc/pid/status 的狀態資訊,來進行判斷當前程序是否被除錯的依據。如果當前程序被偵錯程式所除錯,那麼cat /proc/self/status 顯示的狀態如下圖所示,比較常見的Android反除錯也就是通過 TracerPid 的值在除錯狀態和非除錯狀態的不同且非除錯狀態該值為0而除錯狀態為非0,來判斷是否被偵錯程式所除錯。


這裡修改Android核心繞過反除錯也就只是考慮  TracerPid 的值不同的這種情況,真真的也過掉這些檢測的反除錯還是需要從具體的Android加固的檢測邏輯程式碼入手,沒準現在有些Android加固還會檢測State的值的不同呢!修改Android核心繞過Android加固的反除錯,其實還是要依賴具體的開源的Android核心程式碼來進行對照著分析,否則根本不知道哪個地方是/proc/pid/status 的值根據除錯狀態改變的程式碼位置,因此這裡通過修改Android核心檔案繞過反除錯還是基於Android核心原始碼檔案 /kernel/msm/fs/proc/array.c 中 的程式碼實現進行對照著修改的。

/kernel/msm/fs/proc/array.c檔案中,檢測除錯修改TracerPid的值的Android核心原始碼:

/*
 * The task state array is a strange "bitmap" of
 * reasons to sleep. Thus "running" is zero, and
 * you can test for combinations of others with
 * simple bit tests.
 */
static const char * const task_state_array[] = {
	"R (running)",		/*   0 */
	"S (sleeping)",		/*   1 */
	"D (disk sleep)",	/*   2 */
	"T (stopped)",		/*   4 */
	"t (tracing stop)",	/*   8 */
	"Z (zombie)",		/*  16 */
	"X (dead)",		/*  32 */
	"x (dead)",		/*  64 */
	"K (wakekill)",		/* 128 */
	"W (waking)",		/* 256 */
};

static inline const char *get_task_state(struct task_struct *tsk)
{
	unsigned int state = (tsk->state & TASK_REPORT) | tsk->exit_state;
	const char * const *p = &task_state_array[0];

	BUILD_BUG_ON(1 + ilog2(TASK_STATE_MAX) != ARRAY_SIZE(task_state_array));

	while (state) {
		p++;
		state >>= 1;
	}
	return *p;
}

static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
				struct pid *pid, struct task_struct *p)
{
	struct group_info *group_info;
	int g;
	struct fdtable *fdt = NULL;
	const struct cred *cred;
	pid_t ppid, tpid;

	rcu_read_lock();
	ppid = pid_alive(p) ?
		task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
	tpid = 0;
	if (pid_alive(p)) {
		struct task_struct *tracer = ptrace_parent(p);
		if (tracer)
			// 逆向Android核心檔案需要關注的地方
			tpid = task_pid_nr_ns(tracer, ns);
	}
	cred = get_task_cred(p);
	seq_printf(m,
		"State:\t%s\n"
		"Tgid:\t%d\n"
		"Pid:\t%d\n"
		"PPid:\t%d\n"
		"TracerPid:\t%d\n"
		"Uid:\t%d\t%d\t%d\t%d\n"
		"Gid:\t%d\t%d\t%d\t%d\n",
		get_task_state(p),
		task_tgid_nr_ns(p, ns),
		pid_nr_ns(pid, ns),
		ppid, tpid,
		cred->uid, cred->euid, cred->suid, cred->fsuid,
		cred->gid, cred->egid, cred->sgid, cred->fsgid);

	task_lock(p);
	if (p->files)
		fdt = files_fdtable(p->files);
	seq_printf(m,
		"FDSize:\t%d\n"
		"Groups:\t",
		fdt ? fdt->max_fds : 0);
	rcu_read_unlock();

	group_info = cred->group_info;
	task_unlock(p);

	for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
		seq_printf(m, "%d ", GROUP_AT(group_info, g));
	put_cred(cred);

	seq_putc(m, '\n');
}
因此,通過上面的Android核心原始碼的實現可以知道,如圖所示的位置是我們應該修改的地方:



通過對Android核心原始碼的研究知道了我們在Android核心檔案中修改的地方,在IDA中通過字串搜尋 TracerPid 即查詢上面提到的特徵字串組。


在IDA中通過對特徵字串的引用功能可以定位到我們需要關注的程式碼的位置。


通過IDA的F5功能分析Android核心根據檢測除錯狀態修改TracerPid值的程式碼位置。


通過IDA具體細緻的看下,我們需要關注的程式碼位置處的ARM彙編指令。


通過逆向分析程式碼的流程可以知道,只要 ROM:C02BA5C0 EC FE FF 0A   BEQ  Jmp_C02BA178  處改為直接跳轉到地址C02BA178處執行,沒有機會執行下面的程式碼既可以繞過反除錯檢測。通過IDA的二進位制修改的功能,實現了ARM彙編程式碼的修改,修改後的程式碼如下圖:


Android核心檔案kernel_new在修改前後的程式碼的對比結果示意圖:


0x4.將逆向修改的Android核心刷回Android裝置

對修改後的Android核心檔案 kernel_new 進行gzip的壓縮處理得到壓縮檔案 kernel_new.gz 

# -n, --no-name     do not save or restore the original name and time stamp 
# -f, --force       force overwrite of output file and compress links
# -9, --best        compress better
gzip -n -f -9 kernel_new


使用WinHex工具將kernel_new.gz檔案的二進位制資料覆蓋到原來的zImage檔案的 1F 8B 08 00 處的位置開始到結束的地方(新的kernel_new.gz檔案必須比原kernel_new.gz檔案小,並且回寫回去時不能改變原zImage檔案的大小及修改原zImage檔案中後面的內容,否則會很麻煩),這時得到了zImage檔案。

上面這句話,可能不太好理解,但是也很好理解,可以參考一下作者 lcweik 給出的理解的例子:


通過WinHex工具檢視kernel_new.gz檔案的大小為 0x6AB190,zImage檔案中 1F 8B 08 00 處的位置起始偏移為0x48B4,因此在zImage檔案中kernel_new.gz檔案的起始位置偏移為0x48B4,結束位置偏移為0x6AFA43。使用WinHex工具先將zImage檔案中0x48B4~0x6AFA43處的資料刪除,然後將kernel_new.gz檔案中的資料全部拷貝到0x48B4~0x6AFA43的範圍中,即zImage檔案中偏移0x48B3後面的位置開始覆蓋。


使用abootimg打包工具,重新對解包的boot.img的檔案進行打包處理。

abootimg --create myboot.img -f bootimg.cfg -k zImage -r initrd.img

將修改後重新打包的 myboot.img映象 檔案,更新到Android裝置上。

adb reboot bootloader
fastboot flash boot myboot.img


0x5.手機刷成磚的還原

直接修改Android核心的二進位制檔案比較危險,很容易導致Android裝置變磚的。如果不幸Android裝置變磚了,只需要將前面的步驟中備份的原始boot.img映象檔案重新輸入Android裝置即可。

adb reboot bootloader
fastboot flash boot boot.img

0x6.逆向修改Android核心的總結。

這篇博文主要是參考:逆向修改手機核心,繞過反除錯,原文的作者方法說的很詳細,但是我的操作步驟有些地方和原作者的不同。

1.找目的碼和目標函式的方法不同,原作者通過關閉Android裝置中核心符號遮蔽然後拿到關鍵函式 proc_pid_status_proc_pid_status_(獲取偵錯程式程序的pid)的系統呼叫的地址,在IDA進行查詢定位到需要逆向分析的關鍵程式碼的位置。


2.在修改二進位制程式碼繞過反除錯的方法上,我和原作者修改的地方稍有一處不同,原作者的修改如下圖。


3.按照作者的操作步驟,修改Andorid核心成功繞過反除錯耳朵檢測,但是我按照自己改進後的操作,修改Android核心成功但是刷機重啟直接變磚,哈哈。說實話,這麼逆向修改Android核心繞過反除錯只是提供一種思路吧,實際幹活是吃力不討好而且要真的繞過這種反除錯的檢測還需要修改其他的地方,而且其他的檢測位置修改也不方便。這種open 情況下的反除錯檢測,其實手動patch記憶體過掉也是很簡單的事情。

0x7.關於ARM彙編BL指令的計算

ARM彙編下BL類指令的修改以及偏移的計算具體可以參考:【求助】arm指令BL指令對應的機器碼問題ARM中跳轉指令BL/BLX偏移值計算規則 ,由於在前面的操作步驟中涉及到B類跳轉指令的修改,特此提到一下。提醒兩點:1.一定要善於利用IDA能夠顯示ARM指令機器碼的特點,2.在記憶體中ARM指令的存放是按小尾端存放的。



參考資料

相關推薦

修改Android手機核心繞過除錯

0x1.手機裝置環境 Model number: Nexus 5 OS Version: Android 4.4.4 KTU84P Kernel Version: 3.4.0-gd59db4e 0x2.Android核心提取 查詢Android裝置的boot分割槽

逆向修改手機核心繞過除錯

逆向修改手機核心,繞過反除錯Android應用反除錯裡最常用的一種反除錯方法是檢視/proc/self/status的資訊,如果TracerPid不為0,就判斷為正在被除錯。如果自己擁有核心原始碼,就可以自己編譯生成zImage去替換核心就能正常運行了,但可惜的是,很多手

修改系統核心 繞過除錯 TracerPid為0

感謝作者整理,親測可用 坐著用的mac 現在改成windows下操作 裝置nexus5 系統android 4.4 如果 裝置與上不符 按照以下方法獲取boot.img 一、  提取ker核心檔案

Android native除錯方式及使用IDA繞過除錯

    0x00     為了避免我們的so檔案被動態分析,我們通常在so中加入一些反除錯程式碼,常見的Android native反除錯方法有以下幾種。     1、直接呼叫ptrace(PTRACE_TRACEME, 0, 0, 0),參考Android Native反除

修改android手機文件權限

用戶 文件的 方式 應用 blog style 進入 刪除 文件夾 修改android手機文件權限 默認情況下,一個應用肯定是讀取不了另外一個應用的數據的,因為權限不夠。但是我們一定要讀,怎麽辦? 修改我們要讀取文件的權限。 Android是基於Linux的,所以修改權限的

Android手機用wifi連線adb除錯的方法

ic_adb_green_black_48dp.png 0x0 前言 Android開發肯定要連線pc的adb進行除錯,傳統的方法是用usb與pc進行連線,操作簡單即插即用,缺點是pc上必須得有對應手機的usb驅動程式,對於谷歌親兒子系列和三星摩托等外國品牌而言這不是什麼

修改Android系統原始碼優化開機速度。

下面部分寫的比較零散,整合了一下,可以移步到最新一篇: 通常情況下,Android系統開機保持在20s~25s應該算是合格比較好的狀態。 最近幾天在看關於Android系統開機啟動過程的相關內容。做個筆記。 關於有話Android系統開機時間有話,採取三個措施有話,修

如何修改android手機電池容量顯示資訊

使用battery monitor等軟體讀取電池電量,顯示電池容量與實際容量不符  修改framwork/base/core/res/res/xml/power_profile.xml中的 <

逆向修改MIUI(X64)核心制TracerPID除錯踩坑指南

0x00、前言 ​ 刷CTF時經常能遇到TracerPID反除錯,手動nop掉當然是一種好方法,但是每次都得重新打包難免會覺得煩躁。正好在逛吾愛時發現一篇patch核心繞過反除錯的文章,果斷嘗試一番,於是有了這篇X64版本的patch核心踩坑指南。 ​

你想跨網際網路遠端除錯Android裝置嗎推薦一個遠端控制手機的免費軟體

以前,常常碰到這樣的煩惱問題:我們開發的App應用,明明自己測試好好的,部署到使用者的安卓裝置上之後,總是遇到種種奇怪而又不好找到原因的問題。雖然說Android系統硬體差異大,各個廠商的裝置系統實現細節不盡相同,但作為App開發者,我們總不能把問題這麼推掉吧,App要不斷

android手機上執行自己訓練的MobileNet模型識別手勢數字通過修改官方例程app實現

使用MoblieNet訓練了一個識別數字手勢的模型,先看看識別效果。下面是教程:首先要從git上下載官方的例程,https://github.com/tensorflow/tensorflow之後分為兩步,第一步蒐集足夠多的樣本圖片,使用官方例程中的tensorflow/ex

手機APP制作先選Android還是iOS為什麽?

手機APP制作先選Android還是iOS,為什麽? 創業團隊總是面臨一窮二白的境況,開發制作一款APP都要想一想,先做Android呢還是iOS呢? 移動應用專家APICloud告訴你,這件事不是2選1,而是從0到1的突破過程,首先把這個思維

Delphi 調試連接 任意Android手機/平板/盒子(要安裝Google USB Driver並且還有USB的相關許多文章)

ogl .org blog broadcast 通過 並且 install 無法 設備 Delphi有時候無法連接調試一些手機,解決方案: 1.安裝Google USB Driver 2.通過設備管理器查看手機或平板USB的VID,PID 3.修改你的電腦上的andr

關於Android手機MTP模式連接的一些設置(win7和ubuntu下以紅米1s為例)

sta start .net eno bcm htm web date ati 有些手機的MTP模式在電腦上識別不了,須要一些設置才幹夠,以下就網上收集來的一些設置方法集中貼過來: 一、 win7下 參考:http://blog.ammrli.com/?p=11

APICloud 手機APP制作先選Android還是iOS為什麽?

style 性問題 blank 沒有 於平 hone 更多 oid pic APICloud 手機APP制作先選Android還是iOS,為什麽? 創業團隊總是面臨一窮二白的境況,開發制作一款APP都要想一想,先做Android呢還是iOS呢? 移動應用專家AP

Android 音視頻深入 十六 FFmpeg 推流手機攝像頭實現直播 (附源碼下載)

音視頻 FFmpeg RTMP 直播 Android 源碼地址https://github.com/979451341/RtmpCamera/tree/master 配置RMTP服務器,雖然之前說了,這裏就直接粘貼過來吧 1.配置RTMP服務器 這個我不多說貼兩個博客分別是在mac和win

一行代碼繞過原密碼直接修改win系統密碼bat命令超神奇

今天 user type 文章 一閃而過 你知道 系統管理 超級 proc 其實我一直想學習bat命令,這種批處理,能用的好,省了很多軟件,也省了很多電腦空間。 以後就多發點簡單又強大實用的命令代碼文章,大家一起共勉。 今天要介紹的是,用一行簡單的命令來直接修改Windo

仿Android開發者選項點七下顯示除錯介面

private int clickCount = 0; private long clickTime = 0; sevenClickView.setOnClickListener(new View.OnClickListener() { @Override public void

MAC Android Studio用android手機進行除錯並實時同步在電腦上顯示(錄屏gif體積小清晰)

第一步:Mac電腦使用Android Studio進行真機除錯 第二步:Vysor:一款連線Android裝置和Chrome的神奇工具! 第三步:翻牆(藍燈)下載Vysor chrome外掛 第四步:Vysor chrome外掛破解 1.9.3 (Mac) 破解可以顯示更高清的

android開發時xml檔案中總是提示某一個錯誤修改後仍然提示。

       哎,剛開始學android開發,開發環境好不容易搭建好,自己寫程式碼的時候難免犯錯,特別是xml編寫時如果出現了程式碼錯誤,錯誤提示會一直存在,即使修改了也存在,關掉專案重新開啟也存在,關掉Eclipse 重新啟動還存在。。。。糾結了 有沒有