您的位置:首页 > 其它

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

2015-03-23 16:34 537 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐