<逆向工程核心原理> 静态反调试技术总结

来源:互联网 发布:金字塔软件论坛 编辑:程序博客网 时间:2024/06/04 17:43

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可以绕过。


2.ntdll.dll的NtQueryInformationProcess()

#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;}

strongOD->Options中的*KernelMode可以绕过。


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;}

4.NTQueryObject()

#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;}

strongOD->Options中的*KernelMode可以绕过。


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;}


 

0 0
原创粉丝点击