检查操作系统版本的功能代码如下:
- WORD GetVersionWord()
- {
- OSVERSIONINFO verInfo = { sizeof(OSVERSIONINFO) };
- GetVersionEx(&verInfo);
- return MAKEWORD(verInfo.dwMinorVersion, verInfo.dwMajorVersion);
- }
- BOOL IsWin8OrHigher() { return GetVersionWord() >= _WIN32_WINNT_WIN8; }
- BOOL IsVistaOrHigher() { return GetVersionWord() >= _WIN32_WINNT_VISTA; }
如何避开IsDebuggerPresent检查
为了做到这一点,在执行检查代码之前,需要将0置于BeingDebugged。例如,可以使用DLL注入:
- mov eax, dword ptr fs:[0x30]
- mov byte ptr ds:[eax+2], 0
Windows X64里的进程如下:
- DWORD64 dwpeb = __readgsqword(0x60);
- *((PBYTE)(dwpeb + 2)) = 0;
TLS回调
其实,在主函数中检查调试器的存在不是最好的方法,因为TLS回调处于反汇编列表时反向工具的第一个位置。它实施的检查可以由nop指令擦除,从而解除保护。如果使用CRT库,则在将控制权转移到主函数之前,主线程就已经有一个调用堆栈了。执行调试器存在检查的一个方法便是TLS回调。如下图所示,在可执行模块入口调用之前就已经调用回调函数。
- #pragma section(".CRT$XLY", long, read)
- __declspec(thread) int var = 0xDEADBEEF;
- VOID NTAnopPI TlsCallback(PVOID DllHandle, DWORD Reason, VOID Reserved)
- {
- var = 0xB15BADB0; // Required for TLS Callback call
- if (IsDebuggerPresent())
- {
- MessageBoxA(NULL, "Stop debugging program!", "Error", MB_OK | MB_ICONERROR);
- TerminateProcess(GetCurrentProcess(), 0xBABEFACE);
- }
- }
- __declspec(allocate(".CRT$XLY"))PIMAGE_TLS_CALLBACK g_tlsCallback = TlsCallback;
NtGlobalFlag
在Windows NT中,存在一组标识,它们存储在全局变量NtGlobalFlag中。在系统启动时,NtGlobalFlag全局系统变量将使用系统注册表项中的值进行初始化:
- [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerGlobalFlag]
该变量值用于系统跟踪,调试和控制。虽然变量标识未记录,但SDK包括gflags实用程序,它允许对一个全局标识值进行编辑。 PEB结构还包括NtGlobalFlag字段,其位结构不对应于NtGlobalFlag全局系统变量。在调试期间,这些标识在NtGlobalFlag字段中的设置如下:
- FLG_HEAP_ENABLE_TAIL_CHECK (0x10)
- FLG_HEAP_ENABLE_FREE_CHECK (0x20)
- FLG_HEAP_VALIDATE_PARAMETERS (0x40)
(编辑:ASP站长网)
|