1.PEB
#include "stdio.h" #include "windows.h" #include "tchar.h" void PEB() { HMODULE hMod = NULL; FARPROC pProc = NULL; LPBYTE pTEB = NULL; LPBYTE pPEB = NULL; BOOL bIsDebugging = FALSE; //<span style="color:#ff0000;">[pPEB+0x2]==0x1</span> // IsDebuggerPresent() bIsDebugging = IsDebuggerPresent(); printf("IsDebuggerPresent() = %d\n", bIsDebugging); if( bIsDebugging ) printf(" => Debugging!!!\n\n"); else printf(" => Not debugging...\n\n"); // Ldr xp特有 pProc = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCurrentTeb"); pTEB = (LPBYTE)(*pProc)(); // address of TEB pPEB = (LPBYTE)*(LPDWORD)(pTEB+0x30); // address of PEB printf("PEB.Ldr\n"); DWORD pLdrSig[4] = { 0xEEFEEEFE, 0xEEFEEEFE, 0xEEFEEEFE, 0xEEFEEEFE }; LPBYTE pLdr = (LPBYTE)*(LPDWORD)(<span style="color:#ff0000;">pPEB+0xC</span>); __try { while( TRUE ) { if( !memcmp(pLdr, pLdrSig, sizeof(pLdrSig)) ) { printf(" => Debugging!!!\n\n"); break; } pLdr++; } } __except (EXCEPTION_EXECUTE_HANDLER) { printf(" => Not debugging...\n\n"); } // Process Heap - Flags xp特有 bIsDebugging = FALSE; LPBYTE pHeap = (LPBYTE)*(LPDWORD)(<span style="color:#ff0000;">pPEB+0x18</span>); DWORD dwFlags = *(LPDWORD)(<span style="color:#ff0000;">pHeap+0xC</span>); printf("PEB.ProcessHeap.Flags = 0x%X\n", dwFlags); if( dwFlags != 0x2 ) printf(" => Debugging!!!\n\n"); else printf(" => Not debugging...\n\n"); // Process Heap - ForceFlags xp特有 bIsDebugging = FALSE; DWORD dwForceFlags = *(LPDWORD)(<span style="color:#ff0000;">pHeap+0x10</span>); printf("PEB.ProcessHeap.ForceFlags = 0x%X\n", dwForceFlags); if( dwForceFlags != 0x0 ) printf(" => Debugging!!!\n\n"); else printf(" => Not debugging...\n\n"); // NtGlobalFlag bIsDebugging = FALSE; DWORD dwNtGlobalFlag = *(LPDWORD)(<span style="color:#ff0000;">pPEB+0x68</span>); printf("PEB.NtGlobalFlag = 0x%X\n", dwNtGlobalFlag); if( (dwNtGlobalFlag & 0x70) == 0x70 ) printf(" => Debugging!!!\n\n"); else printf(" => Not debugging...\n\n"); } int _tmain(int argc, TCHAR* argv[]) { PEB(); printf("\npress any key to quit...\n"); _gettch(); return 0; }
strongOD->Options中的HidePEB可以绕过。
#include "stdio.h" #include "windows.h" #include "tchar.h" enum PROCESSINFOCLASS { ProcessBasicInformation = 0, ProcessQuotaLimits, ProcessIoCounters, ProcessVmCounters, ProcessTimes, ProcessBasePriority, ProcessRaisePriority, ProcessDebugPort = 7, ProcessExceptionPort, ProcessAccessToken, ProcessLdtInformation, ProcessLdtSize, ProcessDefaultHardErrorMode, ProcessIoPortHandlers, ProcessPooledUsageAndLimits, ProcessWorkingSetWatch, ProcessUserModeIOPL, ProcessEnableAlignmentFaultFixup, ProcessPriorityClass, ProcessWx86Information, ProcessHandleCount, ProcessAffinityMask, ProcessPriorityBoost, MaxProcessInfoClass, ProcessWow64Information = 26, ProcessImageFileName = 27, ProcessDebugObjectHandle = 30, ProcessDebugFlags = 31, SystemKernelDebuggerInformation = 35 }; void MyNtQueryInformationProcess() { typedef NTSTATUS (WINAPI *NTQUERYINFORMATIONPROCESS)( HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength ); NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess = NULL; pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS) GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationProcess"); // ProcessDebugPort (0x7) DWORD dwDebugPort = 0; pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort, &dwDebugPort, sizeof(dwDebugPort), NULL); printf("NtQueryInformationProcess(ProcessDebugPort) = 0x%X\n", dwDebugPort); if( dwDebugPort != 0x0 ) printf(" => Debugging!!!\n\n"); else printf(" => Not debugging...\n\n"); // ProcessDebugObjectHandle (0x1E) HANDLE hDebugObject = NULL; pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugObjectHandle, &hDebugObject, sizeof(hDebugObject), NULL); printf("NtQueryInformationProcess(ProcessDebugObjectHandle) = 0x%X\n", hDebugObject); if( hDebugObject != 0x0 ) printf(" => Debugging!!!\n\n"); else printf(" => Not debugging...\n\n"); // ProcessDebugFlags (0x1F) BOOL bDebugFlag = TRUE; pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags, &bDebugFlag, sizeof(bDebugFlag), NULL); printf("NtQueryInformationProcess(ProcessDebugFlags) = 0x%X\n", bDebugFlag); if( bDebugFlag == 0x0 ) printf(" => Debugging!!!\n\n"); else printf(" => Not debugging...\n\n"); } int _tmain(int argc, TCHAR* argv[]) { MyNtQueryInformationProcess(); printf("\npress any key to quit...\n"); _gettch(); return 0; }
3.NTQuerySystemInformation()
#include "stdio.h" #include "windows.h" #include "tchar.h" void MyNtQuerySystemInformation() { //检测当前OS是否运行在调试模式下,WinDbg typedef NTSTATUS (WINAPI *NTQUERYSYSTEMINFORMATION)( ULONG SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION { BOOLEAN DebuggerEnabled; BOOLEAN DebuggerNotPresent; } SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION; NTQUERYSYSTEMINFORMATION NtQuerySystemInformation; NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION) GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation"); ULONG SystemKernelDebuggerInformation = 0x23; ULONG ulReturnedLength = 0; SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo = {0,}; NtQuerySystemInformation(SystemKernelDebuggerInformation, (PVOID) &DebuggerInfo, sizeof(DebuggerInfo), // 2 bytes &ulReturnedLength); printf("NtQuerySystemInformation(SystemKernelDebuggerInformation) = 0x%X 0x%X\n", DebuggerInfo.DebuggerEnabled, DebuggerInfo.DebuggerNotPresent); if( DebuggerInfo.DebuggerEnabled ) printf(" => Debugging!!!\n\n"); else printf(" => Not debugging...\n\n"); } int _tmain(int argc, TCHAR* argv[]) { //基于调试环境检测反调试 // boot.ini /debug MyNtQuerySystemInformation(); printf("\npress any key to quit...\n"); _gettch(); return 0; }
#include "stdio.h" #include "windows.h" #include "tchar.h" typedef enum _OBJECT_INFORMATION_CLASS { ObjectBasicInformation, ObjectNameInformation, ObjectTypeInformation, <span style="color:#ff0000;"> ObjectAllTypesInformation,</span> ObjectHandleInformation } OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS; void MyNtQueryObject() { //基于检测调试环境 //系统中的某个调试器调试进程时,会创建1个调试对象类型的内核对象。检测该对象 //是否存在即可判断是否有进程正在被调试(注意不是当前进程)。 typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING; typedef NTSTATUS (WINAPI *NTQUERYOBJECT)( HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength ); #pragma pack(1) typedef struct _OBJECT_TYPE_INFORMATION { UNICODE_STRING TypeName; ULONG TotalNumberOfHandles; ULONG TotalNumberOfObjects; }OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; typedef struct _OBJECT_ALL_INFORMATION { ULONG NumberOfObjectsTypes; OBJECT_TYPE_INFORMATION ObjectTypeInformation[1]; } OBJECT_ALL_INFORMATION, *POBJECT_ALL_INFORMATION; #pragma pack() POBJECT_ALL_INFORMATION pObjectAllInfo = NULL; void *pBuf = NULL; ULONG lSize = 0; BOOL bDebugging = FALSE; NTQUERYOBJECT pNtQueryObject = (NTQUERYOBJECT) GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryObject"); // Get the size of the list pNtQueryObject(NULL, ObjectAllTypesInformation, &lSize, sizeof(lSize), &lSize); // Allocate list buffer pBuf = VirtualAlloc(NULL, lSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); // Get the actual list pNtQueryObject((HANDLE)0xFFFFFFFF, ObjectAllTypesInformation, pBuf, lSize, NULL); pObjectAllInfo = (POBJECT_ALL_INFORMATION)pBuf; UCHAR *pObjInfoLocation = (UCHAR *)pObjectAllInfo->ObjectTypeInformation; POBJECT_TYPE_INFORMATION pObjectTypeInfo = NULL; for( UINT i = 0; i < pObjectAllInfo->NumberOfObjectsTypes; i++ ) { pObjectTypeInfo = (POBJECT_TYPE_INFORMATION)pObjInfoLocation; <span style="color:#ff0000;"> if( wcscmp(L"DebugObject", pObjectTypeInfo->TypeName.Buffer) == 0 ) { bDebugging = (pObjectTypeInfo->TotalNumberOfObjects > 0) ? TRUE : FALSE; break; }</span> // calculate next struct pObjInfoLocation = (UCHAR*)pObjectTypeInfo->TypeName.Buffer; pObjInfoLocation += pObjectTypeInfo->TypeName.Length; pObjInfoLocation = (UCHAR*)(((ULONG)pObjInfoLocation & 0xFFFFFFFC) + sizeof(ULONG)); } if( pBuf ) VirtualFree(pBuf, 0, MEM_RELEASE); printf("NtQueryObject(ObjectAllTypesInformation)\n"); if( bDebugging ) printf(" => Debugging!!!\n\n"); else printf(" => Not debugging...\n\n"); } int _tmain(int argc, TCHAR* argv[]) { MyNtQueryObject(); printf("\npress any key to quit...\n"); _gettch(); return 0; }
5.ZwSetInformationThread()
#include "stdio.h" #include "windows.h" #include "tchar.h" void DetachDebugger() { //强制分离被调试者和调试器的技术。调试器与被调试进程同时终止 typedef enum _THREAD_INFORMATION_CLASS { ThreadBasicInformation, ThreadTimes, ThreadPriority, ThreadBasePriority, ThreadAffinityMask, ThreadImpersonationToken, ThreadDescriptorTableEntry, ThreadEnableAlignmentFaultFixup, ThreadEventPair, ThreadQuerySetWin32StartAddress, ThreadZeroTlsCell, ThreadPerformanceCount, ThreadAmILastThread, ThreadIdealProcessor, ThreadPriorityBoost, ThreadSetTlsArrayAddress, ThreadIsIoPending, <span style="color:#ff0000;"> ThreadHideFromDebugger // 17 (0x11)</span> } THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS; typedef NTSTATUS (WINAPI* ZWSETINFORMATIONTHREAD)( HANDLE ThreadHandle, THREAD_INFORMATION_CLASS ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength ); ZWSETINFORMATIONTHREAD pZwSetInformationThread = NULL; pZwSetInformationThread = (ZWSETINFORMATIONTHREAD) GetProcAddress(GetModuleHandle(L"ntdll.dll"), "ZwSetInformationThread"); pZwSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, NULL, 0); printf("ZwSetInformationThread() -> Debugger detached!!!\n\n"); } int _tmain(int argc, TCHAR* argv[]) { DetachDebugger(); printf("\npress any key to quit...\n"); _gettch(); return 0; }经过测试,此方法在XP可行,但在WIN7无效。
6.TLS回调函数
7.检测窗口 FindWindow,FindWindowEx 检测进程 CreateToolHelp32Snapshoot
#include "stdio.h" #include "windows.h" #include "tchar.h" void FindDebuggerWindow() { BOOL bDebugging = FALSE; // using ClassName if( FindWindow(L"OllyDbg", NULL) || // OllyDbg FindWindow(L"TIdaWindow", NULL) || // IDA Pro FindWindow(L"WinDbgFrameClass", NULL) ) // Windbg bDebugging = TRUE; printf("FindWindow()\n"); if( bDebugging ) printf(" => Found a debugger window!!!\n\n"); else printf(" => Not found a debugger window...\n\n"); // using WindowName bDebugging = FALSE; TCHAR szWindow[MAX_PATH] = {0,}; HWND hWnd = GetDesktopWindow(); hWnd = GetWindow(hWnd, GW_CHILD); hWnd = GetWindow(hWnd, GW_HWNDFIRST); while( hWnd ) { if( GetWindowText(hWnd, szWindow, MAX_PATH) ) { if( _tcsstr(szWindow, L"IDA") || _tcsstr(szWindow, L"OllyDbg") || _tcsstr(szWindow, L"WinDbg") ) { bDebugging = TRUE; break; } } hWnd = GetWindow(hWnd, GW_HWNDNEXT); } printf("GetWindowText()\n"); if( bDebugging ) printf(" => Found a debugger window!!!\n\n"); else printf(" => Not found a debugger window...\n\n"); } int _tmain(int argc, TCHAR* argv[]) { FindDebuggerWindow(); printf("\npress any key to quit...\n"); _gettch(); return 0; }