反調試(一)
阿新 • • 發佈:2017-09-22
put nbsp api ring 位置 fsd font length ctx
反調試
- IsDebuggerPresent()
- __readgsqword(0x60)得到指向PEB64的指針,pPeb->BeingDebugged .__readfsdword(0x30)
- CheckRemoteDebuggerPresent(GetCurrentProcess(), &bIsDbgPresent)
- BOOL HeapFlags(),64位下,得到指向PEB的地址加上0x30的偏移得到pProcessHeap,由於pHeapFlags在不同版本的操作系統中位置不一,需要IsWindowsVistaOrGreater()判斷大概版本,高於VISTA的版本pProcessHeap解星號加上0x70的偏移得到pHeapFlags,低於高於VISTA的版本pProcessHeap解星號加上0x14的偏移得到pHeapFlags
32位下,得到指向PEB的地址加上0x18的偏移得到pProcessHeap,由於pHeapFlags在不同版本的操作系統中位置不一,需要IsWindowsVistaOrGreater()判斷大概版本,高於VISTA的版本pProcessHeap解星號加上0x40的偏移得到pHeapFlags,低於VISTA的版本pProcessHeap解星號加上0x0C的偏移得到pHeapFlags。判斷*pHeapFlags > 2 是否為真 - __readgsqword(0x30)得到TEB64指針.*(DWORD64*)(_teb64 + 0x60)得到PEB64結構體,PEB64取偏移0xBC得到NTGlobalFlag。
__readfsdword(0x18)得到TEB32指針.*(DWORD64*)(_teb32 + 0x30)得到PEB32結構體,PEB32取偏移0x68得到NTGlobalFlag
假如是wow64下的__readfsdword(0x18)得到TEB64指針.*(DWORD64*)(_teb64 + 0x60)得到PEB64結構體,PEB64取偏移0xBC得到NTGlobalFlag當進程被調試時,NTGlobalFlag會被置為FLG_HEAP_ENABLE_TAIL_CHECK (0x10), FLG_HEAP_ENABLE_FREE_CHECK(0x20), 和 FLG_HEAP_VALIDATE_PARAMETERS(0x40)即0x70 - BOOL HeapForceFlags(),64位下,得到指向PEB的地址加上0x30的偏移得到pProcessHeap,由於pHeapForceFlags在不同版本的操作系統中位置不一,需要IsWindowsVistaOrGreater()判斷大概版本,高於VISTA的版本pProcessHeap解星號加上0x74的偏移得到pHeapFlags,低於高於VISTA的版本pProcessHeap解星號加上0x18的偏移得到pHeapFlags
32位下,得到指向PEB的地址加上0x18的偏移得到pProcessHeap,由於pHeapForceFlags在不同版本的操作系統中位置不一,需要IsWindowsVistaOrGreater()判斷大概版本,高於VISTA的版本pProcessHeap解星號加上0x44的偏移得到pHeapForceFlags,低於VISTA的版本pProcessHeap解星號加上0x10的偏移得到pHeapFlags。判斷*pHeapFlags > 2 是否為真 - 通過LoadLibrary 得到ntdll的句柄hNtdll,通過GetProcAddress從ntdll模塊中得到NtQueryInformationProcess const int ProcessDbgPort = 7;
NtQueryInfoProcess(GetCurrentProcess(),
ProcessDbgPort,
&IsRemotePresent,
dProcessInformationLength,
NULL) 當IsRemotePresent不等於0時 進程被調試 - 通過LoadLibrary 得到ntdll的句柄hNtdll,通過GetProcAddress從ntdll模塊中得到NtQueryInformationProcess const int ProcessDebugFlags = 0x1f;
NtQueryInfoProcess(GetCurrentProcess(),
ProcessDebugFlags,
&NoDebugInherit,
sizeof(DWORD),
NULL);NoDebugInherit精確等於0時,被調試 - 通過LoadLibrary 得到ntdll的句柄hNtdll,通過GetProcAddress從ntdll模塊中得到NtQueryInformationProcess const int ProcessDebugObjectHandle = 0x1e;NtQueryInfoProcess(GetCurrentProcess(), ProcessDebugObjectHandle, &hDebugObject, dProcessInformationLength, NULL);hDebugObject不為空
- 通過GetProcAddress從ntdll模塊中得到NtSetInformationThread將ThreadInformationClass設置為0x11(ThreadHideFromDebugger),用於隱藏調試器中的線程,調用之後調試器與該線程不再關聯 NtSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, NULL, 0);當函數成功時,被調試
- CloseHandle_InvalideHandle()當進程被調試時,調用CloseHandle並傳入無效句柄,會得到一個STATUS_INVALID_HANDLE的異常,函數返回TRUE。__try {NtClose_((HANDLE)0x99999999);}__except (EXCEPTION_EXECUTE_HANDLER) {return TRUE;}
- UnhandledExcepFilterTest () 設置一個SetUnhandledExceptionFilter。然後利用RaiseException提出一個異常交給異常處理機制 由於沒有設置相應的異常處理程序 當進程被調試時,會通知進程的調試器,而不會調用UnhandledExceptionFilter
- OutputDebugStringAPI(),只在XP或2000中適用。OutputDebugString()用於輸出字符串給調試器顯示。若GetLastError被置為Val,說明調試器與進程關聯。
- HardwareBreakpoints(),初始化PCONTEXT ctx,將ctx->ContextFlags = CONTEXT_DEBUG_REGISTERS。通過GetThreadContext(GetCurrentThread(), ctx)得到寄存器信息,硬件斷點,用Dr0-Dr7七個寄存器控制。Dr1-Dr3存放了斷點地址,若有一個寄存器存放了斷點地址說明 被調試
反調試(一)