1. 程式人生 > >反調試(一)

反調試(一)

put nbsp api ring 位置 fsd font length ctx

反調試

  1. IsDebuggerPresent()
  2. __readgsqword(0x60)得到指向PEB64的指針,pPeb->BeingDebugged .__readfsdword(0x30)
  3. CheckRemoteDebuggerPresent(GetCurrentProcess(), &bIsDbgPresent)
  4. 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 是否為真
  5. __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
  6. 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 是否為真
  7. 通過LoadLibrary 得到ntdll的句柄hNtdll,通過GetProcAddress從ntdll模塊中得到NtQueryInformationProcess const int ProcessDbgPort = 7;
    NtQueryInfoProcess(GetCurrentProcess(),
    ProcessDbgPort,
    &IsRemotePresent,
    dProcessInformationLength,
    NULL) 當IsRemotePresent不等於0時 進程被調試
  8. 通過LoadLibrary 得到ntdll的句柄hNtdll,通過GetProcAddress從ntdll模塊中得到NtQueryInformationProcess const int ProcessDebugFlags = 0x1f;
    NtQueryInfoProcess(GetCurrentProcess(),
    ProcessDebugFlags,
    &NoDebugInherit,
    sizeof(DWORD),
    NULL);NoDebugInherit精確等於0時,被調試
  9. 通過LoadLibrary 得到ntdll的句柄hNtdll,通過GetProcAddress從ntdll模塊中得到NtQueryInformationProcess const int ProcessDebugObjectHandle = 0x1e;NtQueryInfoProcess(GetCurrentProcess(), ProcessDebugObjectHandle, &hDebugObject, dProcessInformationLength, NULL);hDebugObject不為空
  10. 通過GetProcAddress從ntdll模塊中得到NtSetInformationThreadThreadInformationClass設置為0x11(ThreadHideFromDebugger),用於隱藏調試器中的線程,調用之後調試器與該線程不再關聯 NtSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, NULL, 0);當函數成功時,被調試
  11. CloseHandle_InvalideHandle()當進程被調試時,調用CloseHandle並傳入無效句柄,會得到一個STATUS_INVALID_HANDLE的異常,函數返回TRUE。__try {NtClose_((HANDLE)0x99999999);}__except (EXCEPTION_EXECUTE_HANDLER) {return TRUE;}
  12. UnhandledExcepFilterTest () 設置一個SetUnhandledExceptionFilter。然後利用RaiseException提出一個異常交給異常處理機制 由於沒有設置相應的異常處理程序 當進程被調試時,會通知進程的調試器,而不會調用UnhandledExceptionFilter
  13. OutputDebugStringAPI(),只在XP或2000中適用。OutputDebugString()用於輸出字符串給調試器顯示。若GetLastError被置為Val,說明調試器與進程關聯。
  14. HardwareBreakpoints(),初始化PCONTEXT ctx,將ctx->ContextFlags = CONTEXT_DEBUG_REGISTERS。通過GetThreadContext(GetCurrentThread(), ctx)得到寄存器信息,硬件斷點,用Dr0-Dr7七個寄存器控制。Dr1-Dr3存放了斷點地址,若有一個寄存器存放了斷點地址說明 被調試

反調試(一)