[TOC]ide
特色:通常在調試開始時阻攔調試者,調試只須要找到緣由後就能夠一次性突破函數
PEB
:star:工具
BeginDebug
: 調試標誌位// 經過檢查 PEB.BeingDebuged 字段判斷是否被調試 // 能夠在目標程序運行以前修改對應的字段爲 0 進行反反調試 bool CheckBeingDebugged() { __asm { ; 獲取到 PEB 的內容 mov eax, fs:[0x30] ; 獲取 PEB 內偏移爲 2 大小爲 1 字節的字段 movzx eax, byte ptr[eax + 2] } } int main() { if (CheckBeingDebugged()) printf("當前處於[被]調試狀態\n"); else printf("當前處於[非]調試狀態\n"); system("pause"); return 0; }
// 使用 IsDebuggerPresent 原理一樣是判斷 PEB.BeingDebuged // 經過 HOOK 函數和修改對應字段的方式能夠進行反調試 int main() { if (IsDebuggerPresent()) printf("當前處於[被]調試狀態\n"); else printf("當前處於[非]調試狀態\n"); system("pause"); return 0; }
Ldr
內存狀態Heap
(Flags
, Force Flags
): 堆狀態NtGlobalFlag
: 內核全局標記
PEB.NtGlobalFlag
判斷是否被調試,當處於被調試狀態時PEB.NtGlobalFlag
保存的是 0x70
,能夠經過修改標誌反反調試bool CheckNtGlobalFlag() { __asm { ; 獲取到 PEB, 保存在 FS :[0x30] mov eax, fs : [0x30] ;獲取到 NtGlobalFlag 字段的內容 mov eax, [eax + 0x68] } } int main() { if (CheckNtGlobalFlag()) printf("當前處於[被]調試狀態\n"); else printf("當前處於[非]調試狀態\n"); system("pause"); return 0; }
TEB
spa
StaticUnicodeString
:靜態緩衝區使用原始 API
插件
NtQuerySystemInformationProcess()
ProcessDebugPort(0x07)
: 獲取調試端口ProcessDebugObjectHandle(0x1E)
: 獲取調試句柄ProcessDebugFlag(0x1F)
: 獲取調試標記NtQuerySystemInformation()
:
SystemKernelDeBuggerInformation(0x23)
:獲取系統調試狀態 (雙機)NtQueryObject()
: 遍歷系統內核攻擊調試器調試
NtSetInformationThread()
ThreadHideFormDebugger(0x11)
打開進程檢查code
SetDebugPrivilege
:arrow_right: 檢查進程是否具備調試權限利用**TLS
**回調函數orm
使用普通API
進程
Explorer.exe
,也就是資源管理器,若是判斷不是,就可能被調試,提供參考。bool CheckParentProcess() { struct PROCESS_BASIC_INFORMATION { ULONG ExitStatus; // 進程返回碼 PPEB PebBaseAddress; // PEB 地址 ULONG AffinityMask; // CPU 親和性掩碼 LONG BasePriority; // 基本優先級 ULONG UniqueProcessId; // 本進程PID ULONG InheritedFromUniqueProcessId; // 父進程PID }stcProcInfo; // 查詢到目標進程的對應信息,主要是 父進程 ID NtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &stcProcInfo, sizeof(stcProcInfo), NULL); // 查詢資源管理器對應的 PID DWORD ExplorerPID = 0; DWORD CurrentPID = stcProcInfo.InheritedFromUniqueProcessId; GetWindowThreadProcessId(FindWindow(L"Progman", NULL), &ExplorerPID); // 比對兩個 PID 的值,相同就OK,不一樣就可能被調試 return ExplorerPID == CurrentPID ? false : true; } int main() { if (CheckParentProcess()) printf("當前處於[被]調試狀態\n"); else printf("當前處於[非]調試狀態\n"); system("pause"); return 0; }
int main() { if (FindWindow(NULL, L"OllyDbg")) printf("存在調試器\n"); else printf("沒檢測到調試器\n"); return 0; }
EPROCESS
結構體中相關的字段,由於不能在 R3
修改 R0
的數據,因此只能 HOOK
bool CheckProcessDebugPort() { int nDebugPort = 0; NtQueryInformationProcess( GetCurrentProcess(), // 目標進程句柄 ProcessDebugPort, // 查詢信息類型(7) &nDebugPort, // 輸出查詢信息 sizeof(nDebugPort), // 查詢類型大小 NULL); // 實際返回數據大小 // 若是返回的是 -1 ,那麼就被調試了 return nDebugPort == 0xFFFFFFFF ? true : false; } int main() { if (CheckProcessDebugPort()) printf("當前處於[被]調試狀態\n"); else printf("當前處於[非]調試狀態\n"); system("pause"); return 0; }
SEH
SetUnhandleedExceptionFilter()
OllyDbg
插件編寫一般以DLL
的方式存在的,可是後綴名可能會有變化內存
全部的插件都應該被保護到具體的路徑中