Android反除錯筆記
1)程式碼執行時間檢測
通過取系統時間,檢測關鍵程式碼執行耗時,檢測單步除錯,類似函式有:time,gettimeofday,clock_gettime.
也可以直接使用匯編指令RDTSC讀取,但測試ARM64有相容問題。
time_t t1, t2;
time (&t1);
/* Parts of Important Codes */
time (&t2);
if (t2 - t1 > 2) {
puts ("debugged");
}
2)檢測 procfs 檔案系統變化
程序的狀態資訊能通過 procfs 系統反饋給使用者空間,除錯會使程序狀態發生變化:
char file [PATH_LEN];
char line [LINE_LEN];
snprintf (file, PATH_LEN-1, "/proc/%d/status", pid);
FILE *fp = fopen (file, "r");
while (fgets (line, LINE_LEN-1, fp)) {
if (strncmp (line, "TracerPid:", 10) == 0) {
if (0 != atoi (&line[10])) {
/* encrypt random .TEXT code */
}
break;
}
}
fclose (fp);
類似可以檢測的介面還有:
/proc/pid/status
/proc/pid/task/pid/status
/proc/pid/stat
/proc/pid/task/pid/stat
/proc/pid/wchan
/proc/pid/task/pid/wchan
3)利用訊號機制
ARM程式下斷點,偵錯程式完成兩件事:
- 儲存目標地址處指令
- 將目標地址處指令替換成斷點指令
指令集 | 指令 |
---|---|
Arm | 0x01, 0x00, 0x9f, 0xef |
Thumb | 0x01, 0xde |
Thumb2 | 0xf0, 0xf7, 0x00, 0xa0 |
當命中斷點時,系統產生SIGTRAP訊號,偵錯程式收到訊號後完成下面操作:
- 恢復斷點處原指令
- 回退被跟蹤程序的當前PC
這時當控制權回到被除錯程式時,正好執行斷點位置指令。這就是 ARM 平臺斷點的基本原理。
可以看到,斷點是通過處理 SIGTRAP 訊號來實現的,假如我們自己註冊 SIGTRAP 的訊號處理函式,並在程式中主動執行中斷指令觸發中斷。
在中斷處理函式中,NOP 掉斷點指令,程式可正常執行。但在除錯狀態下,偵錯程式遇到斷點指令時,會去恢復原先指令,由於不是偵錯程式下的斷點,所以恢復會失敗,而偵錯程式會繼續第2步操作,回退PC暫存器,程式會在此處無限迴圈。
4)軟體斷點檢測
斷點會替換記憶體中原有指令,因此通過檢測記憶體中的斷點指令,可以檢測除錯:
#include<stdlib.h>
#include<stdio.h>
#include<elf.h>
#include<string.h>
#include<unistd.h>
#include<dlfcn.h>
voidcheckBreakPoint();
unsignedlonggetLibAddr(constchar *lib);
#define LOG_TAG "ANTIDBG_DEMO"
#include<android/log.h>
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
intmain(){
dlopen ("./libdemo.so", RTLD_NOW);
sleep (60);
checkBreakPoint ();
return 0;
}
unsignedlonggetLibAddr(constchar *lib){
puts ("Enter getLibAddr");
unsigned long addr = 0;
char lineBuf[256];
snprintf (lineBuf, 256-1, "/proc/%d/maps", getpid ());
FILE *fp = fopen (lineBuf, "r");
if (fp == NULL) {
perror ("fopen failed");
goto bail;
}
while (fgets (lineBuf, sizeof(lineBuf), fp)) {
if (strstr (lineBuf, lib)) {
char *temp = strtok (lineBuf, "-");
addr = strtoul (temp, NULL, 16);
break;
}
}
bail:
fclose(fp);
return addr;
}
voidcheckBreakPoint(){
int i, j;
unsigned int base, offset, pheader;
Elf32_Ehdr *elfhdr;
Elf32_Phdr *ph_t;
base = getLibAddr ("libdemo.so");
if (base == 0) {
LOGI ("getLibAddr failed");
return;
}
elfhdr = (Elf32_Ehdr *) base;
pheader = base + elfhdr->e_phoff;
for (i = 0; i < elfhdr->e_phnum; i++) {
ph_t = (Elf32_Phdr*)(pheader + i * sizeof(Elf32_Phdr)); // traverse program header
if ( !(ph_t->p_flags & 1) ) continue;
offset = base + ph_t->p_vaddr;
offset += sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * elfhdr->e_phnum;
char *p = (char*)offset;
for (j = 0; j < ph_t->p_memsz; j++) {
if(*p == 0x01 && *(p+1) == 0xde) {
LOGI ("Find thumb bpt %p", p);
} else if (*p == 0xf0 && *(p+1) == 0xf7 && *(p+2) == 0x00 && *(p+3) == 0xa0) {
LOGI ("Find thumb2 bpt %p", p);
} else if (*p == 0x01 && *(p+1) == 0x00 && *(p+2) == 0x9f && *(p+3) == 0xef) {
LOGI ("Find arm bpt %p", p);
}
p++;
}
}
}
5)inotify 檔案系統監控
inotify 是一個核心用於通知使用者態檔案系統變化的機制,當檔案被訪問,修改,刪除等時使用者態可以快速感知。
1.使用 inotify_init() 初始化一個 inotify 例項並返回檔案描述符,每個檔案描述符都關聯了一個事件佇列:
int fd = inotify_init ();
2.拿到這個檔案描述符後下一步就告訴核心,哪些檔案發生哪些事件時你得通知我,通過函式 inotify_add_watch 實現:
int wd = inotify_add_watch (fd, path, mask);
第一個引數即 inotify_init 返回的檔案描述符,path 表示關注的目標路徑,可以是檔案目錄等。mask 表示關注的事件的掩碼,如 IN_ACCESS 代表訪問,IN_MODIFY 代表修改等
相應的,可以通過 inotify_rm_watch 來刪除一個watch:
int ret = inotify_rm_watch (fd, wd);
這樣,每當監視的檔案發生變化時,核心便給 fd 關聯的事件佇列裡面塞一個檔案事件。檔案事件用一個 inotify_event 結構表示,可以通過 read 來讀取:
structinotify_event {
__s32 wd; /* watch descriptor */
__u32 mask; /* watch mask */
__u32 cookie; /* cookie to synchronize two events */
__u32 len; /* length (including nulls) of name */
char name[0]; /* stub for possible name */
};
size_t len = read (fd, buf, LEN);
-
通過監視
/proc/pid/maps
檔案的開啟事件,可防針對 360 加固的 dump 脫殼 -
檔案變化與事件觸發非必然聯絡,例如
/proc/pid/status
中的TracerPid
值在被除錯時是變化的,但其變化沒有事件發生,原因未知可能與 inofity 的核心實現有關
6)ptrace()
ptrace() 是 Linux 的一個系統呼叫,也是 Linux 下 gdb 等偵錯程式實現的基礎。它提供了 Linux 下一個程序跟蹤另一個程序暫存器、記憶體等的能力。
由於 ptrace() 到一個執行緒後,任何訊號都將導致執行緒STOP 並將控制權交由呼叫者 ,因此如果利用每個執行緒只能有一個ptrace跟蹤 來防止附加的話,需要處理好這個關係:
while (waitpid (g_childPid, &stat, 0) ) {
if (WIFEXITED (stat) || WIFSIGNALED(stat)) {
XXX_DEBUG_LOG ("waitpid : child died\n");
exit (11);
}
ptrace (PTRACE_CONT, g_childPid, NULL, NULL);
}
7)多程序的反除錯實現
相關推薦
Android反除錯筆記
1)程式碼執行時間檢測 通過取系統時間,檢測關鍵程式碼執行耗時,檢測單步除錯,類似函式有:time,gettimeofday,clock_gettime. 也可以直接使用匯編指令RDTSC讀取,但測試ARM64有相容問題。 time_t t1, t2; time (&
一個android反除錯的學習
前言 初學android逆向除錯,用阿里上次的比賽練練手,第二題就是一個包含android反除錯機制的題目,於是仔細除錯分析了一下其反除錯的原理,記錄下來。 除錯方法 這個apk核心功能在so檔案中實現,於是試圖動態除錯so檔案,在關鍵函式下斷點之後,
Android反除錯之 AntiEmulator 檢測安卓模擬器
八種方法檢測是否存在模擬器 檢查特定的幾個關鍵點 0×1 檢測“/dev/socket/qemud”,“/dev/qemu_pipe”這兩個通道 程式碼demo: Java 123456789101112131415161718private
Android 反除錯、so檔案注入
關鍵程式碼: Thread t=new Thread(new Runnable() { @Override public void run() {
Android安全/應用逆向--29--在JNI_onload函式處下斷點避開針對IDA的反除錯
7-6、在JNI_onload函式處下斷點避開針對IDA的反除錯 為了防止apk中的so檔案被動態除錯,開發者往往會使用一些反除錯手段來干擾黑客的動態除錯。其中最常見的就是在so檔案中檢測TracerPid值。通過在JNI_onload下斷點即可避開反除錯。 反
Android學習筆記整理(5)--Android程式除錯
每個Android應用上線之前都會進行一系列的測試,確保應用能夠正常使用。通常使用JUnit單元測試,另外還可以使用LogCat(日誌控制檯)來除錯錯誤。一、JUnit單元測試1.配置JUnit環境在進行JUnit測試時,我們需要在AndroidManifest.xml的&l
Android native反除錯方式及使用IDA繞過反除錯
0x00 為了避免我們的so檔案被動態分析,我們通常在so中加入一些反除錯程式碼,常見的Android native反除錯方法有以下幾種。 1、直接呼叫ptrace(PTRACE_TRACEME, 0, 0, 0),參考Android Native反除
Ubuntu下使用gdb遠端除錯android native程式筆記
使用gdb遠端除錯android native程式1.準備工作:android native程式:demoandroid 上執行的除錯工具:gdbserver,該程式位於ndk目錄/prebuilt/a
android 中 ril 層除錯筆記和理解
這段時間一直在弄android5.0 , 對 SELinux有了一定的瞭解, 上週是在折騰 4G 模組, 搞 ril 層的東西. 以前沒有好好理解 ril 層是怎樣工作的, 以前在網上看關於 ril 的文章, 感覺看不懂, 後來忙其它方面的東西, 沒有深入瞭解 ri
ANDROID反編譯工具APKTOOL原始碼除錯過程
APKTOOL是目前反編譯ANDROID apk的主要工具,可以反編譯出APK裡的資原始檔和smali程式碼,而有些APK開發者為了防止自己的程式碼被反編譯,針對APKTOOL工具加固程式碼,使得APKTOOL無法執行正常,比如這篇文章介紹的Android應用資
阿里雲播放器除錯心得,android的學習筆記
接觸android接近一個月,摸爬滾打實屬不易,加上又有諸多瑣事纏身,讓原本定下的計劃遲遲沒有完成。。 對於基礎知識的急於求成,處於一種有一些功利化的學習心態,所以適時的複習顯得空前重要。。 談談對安卓的理解,不論對錯,只對自己的理解做一些記錄:
android 反編譯 反除錯入門資料
0x01 反編譯出錯 1.插入無效指令是部分逆向工具崩潰 原理:大部分逆向工具都是線性讀取位元組碼並解析, 如dex2jar,baksmali,apktool等,當遇到無效位元組碼時,就會引起反編譯工具解析失敗。例如:新版的dex2jar 遇到這種情況任然沒法轉化成jar,
修改Android手機核心,繞過反除錯
0x1.手機裝置環境 Model number: Nexus 5 OS Version: Android 4.4.4 KTU84P Kernel Version: 3.4.0-gd59db4e 0x2.Android核心提取 查詢Android裝置的boot分割槽
Android:日常學習筆記(7)———探究UI開發(1)
tac calling repl action its 內容 schema lesson try Android:日常學習筆記(7)———探究UI開發(1) 常用控件的使用方法 TextView 說明:TextView是安卓中最為簡單的一個控件,常用來在界面上顯示一段文本信
Android:日常學習筆記(7)———探究UI開發(4)
this 活動 eal enc panel .html http 中間 編寫 Android:日常學習筆記(7)———探究UI開發(4) UI概述 View 和 ViewGrou Android 應用中的所有用戶界面元素都是使用 View 和 ViewGroup 對象
Android:日常學習筆記(9)———探究廣播機制
ora rri enabled cas 管理 encoding protect 其他 acc Android:日常學習筆記(9)———探究廣播機制 引入廣播機制 Andorid廣播機制 廣播是任何應用均可接收的消息。系統將針對系統事件(例如:系統啟動或設備開始充電時)傳
Android:日常學習筆記(10)———使用LitePal操作數據庫
分享 數據 turn find netstat price 彈出 category 模式 Android:日常學習筆記(10)———使用LitePal操作數據庫 引入LitePal 什麽是LitePal LitePal是一款開源的Android數據庫框架,采用了對象關系
android反編譯odex文件
lis 目錄 trac 依賴 andro xheditor span sys 放置 關於android的反編譯工具,相信大家並不陌生 如APK-TOOL,dex2jar APK-TOOL 用於反編譯出布局文件 下載地址http://code.google.co
Android菜鳥筆記- 獲取未安裝的APK圖標、版本號、包名、名稱、是否安裝、安裝、打開
ack ear 例如 start true intent ble post oca 周末閑來無事,把Android的基礎知識拿出來復習復習,今天主題是《獲取未安裝的APK圖標、版本號、包名、名稱、是否安裝、跳轉安裝、打開》 一、獲取APK圖標 通常讀取APK的圖標能夠用
Android群英傳筆記——摘要,概述,新的出發點,溫故而知新,能夠為師矣!
ram hide 基本 pretty 工具 log 透明 scroll 好的 Android群英傳筆記——摘要。概述,新的出發點,溫故而知新。能夠為師矣! 當工作的越久,就越感到力不從心了,基礎和理解才是最重要的,所以買了兩本書,醫生的《An