Windows 平台反调试相关的技术方法总结—part 3
字数 1297 2025-08-05 08:19:19

Windows平台反调试技术及绕过方法详解

1. SEH(结构化异常处理)反调试技术

1.1 SEH检查原理

SEH(结构化异常处理)是Windows平台的一种异常处理机制,反调试技术可以通过检查SEH处理程序的调用堆栈来检测调试器。

1.2 典型调用堆栈

0:000> kn
# ChildEBP RetAddr
00 0059f06c 775100b1 AntiDebug!ExceptionRoutine
01 0059f090 77510083 ntdll!ExecuteHandler2+0x26
02 0059f158 775107ff ntdll!ExecuteHandler+0x24
03 0059f158 003b11a5 ntdll!KiUserExceptionDispatcher+0xf
04 0059fa90 003d7f4e AntiDebug!main+0xb5

1.3 绕过方法

  1. ntdll!ExecuteHandler2+0x24处设置断点:
0:000> u ntdll!ExecuteHandler2+24 L3
ntdll!ExecuteHandler2+0x24:
775100af ffd1            call    ecx
775100b1 648b2500000000  mov     esp,dword ptr fs:[0]
775100b8 648f0500000000  pop     dword ptr fs:[0]
0:000> bp 775100af
  1. 分析每个调用SEH处理程序的代码

2. VEH(向量化异常处理)反调试技术

2.1 VEH原理

VEH是Windows XP引入的SEH变体,处理程序列表存储在ntdll!LdrpVectorHandlerList未导出变量中。

2.2 关键API

PVOID WINAPI AddVectoredExceptionHandler(
    ULONG FirstHandler,
    PVECTORED_EXCEPTION_HANDLER VectoredHandler);

ULONG WINAPI RemoveVectoredExceptionHandler(
    PVOID Handler);

LONG CALLBACK VectoredHandler(
    PEXCEPTION_POINTERS ExceptionInfo);

2.3 典型实现示例

LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
    PCONTEXT ctx = ExceptionInfo->ContextRecord;
    if (ctx->Dr0 != 0 || ctx->Dr1 != 0 || ctx->Dr2 != 0 || ctx->Dr3 != 0) {
        std::cout << "Stop debugging program!" << std::endl;
        exit(-1);
    }
    ctx->Eip += 2;
    return EXCEPTION_CONTINUE_EXECUTION;
}

int main()
{
    AddVectoredExceptionHandler(0, ExceptionHandler);
    __asm int 1h;
    return 0;
}

2.4 绕过方法

  1. 钩取KiUserExceptionDispatcher函数:
typedef VOID (NTAPI *pfnKiUserExceptionDispatcher)(
    PEXCEPTION_RECORD pExcptRec,
    PCONTEXT ContextFrame
);

pfnKiUserExceptionDispatcher g_origKiUserExceptionDispatcher = NULL;

VOID NTAPI HandleKiUserExceptionDispatcher(
    PEXCEPTION_RECORD pExcptRec,
    PCONTEXT ContextFrame)
{
    if (ContextFrame && (CONTEXT_DEBUG_REGISTERS & ContextFrame->ContextFlags)) {
        ContextFrame->Dr0 = 0;
        ContextFrame->Dr1 = 0;
        ContextFrame->Dr2 = 0;
        ContextFrame->Dr3 = 0;
        ContextFrame->Dr6 = 0;
        ContextFrame->Dr7 = 0;
        ContextFrame->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS;
    }
}

__declspec(naked) VOID NTAPI HookKiUserExceptionDispatcher()
{
    __asm {
        mov eax, [esp + 4]
        mov ecx, [esp]
        push eax
        push ecx
        call HandleKiUserExceptionDispatcher
        jmp g_origKiUserExceptionDispatcher
    }
}

3. NtSetInformationThread反调试技术

3.1 原理

使用ThreadHideFromDebugger(0x11)信息类隐藏线程,使线程停止发送调试事件通知。

3.2 实现代码

typedef NTSTATUS (NTAPI *pfnNtSetInformationThread)(
    _In_ HANDLE ThreadHandle,
    _In_ ULONG ThreadInformationClass,
    _In_ PVOID ThreadInformation,
    _In_ ULONG ThreadInformationLength
);

const ULONG ThreadHideFromDebugger = 0x11;

void HideFromDebugger()
{
    HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll"));
    pfnNtSetInformationThread NtSetInformationThread = 
        (pfnNtSetInformationThread)GetProcAddress(hNtDll, "NtSetInformationThread");
    NTSTATUS status = NtSetInformationThread(
        GetCurrentThread(), 
        ThreadHideFromDebugger, 
        NULL, 
        0);
}

3.3 绕过方法

钩取NtSetInformationThread函数:

pfnNtSetInformationThread g_origNtSetInformationThread = NULL;

NTSTATUS NTAPI HookNtSetInformationThread(
    _In_ HANDLE ThreadHandle,
    _In_ ULONG ThreadInformationClass,
    _In_ PVOID ThreadInformation,
    _In_ ULONG ThreadInformationLength)
{
    if (ThreadInformationClass == ThreadHideFromDebugger && 
        ThreadInformation == 0 && 
        ThreadInformationLength == 0) {
        return STATUS_SUCCESS;
    }
    return g_origNtSetInformationThread(
        ThreadHandle, 
        ThreadInformationClass, 
        ThreadInformation, 
        ThreadInformationLength);
}

4. NtCreateThreadEx反调试技术

4.1 原理

使用THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER(0x00000004)标志创建隐藏线程。

4.2 线程创建标志

#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED     0x00000001
#define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH   0x00000002
#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER   0x00000004
#define THREAD_CREATE_FLAGS_HAS_SECURITY_DESCRIPTOR 0x00000010
#define THREAD_CREATE_FLAGS_ACCESS_CHECK_IN_TARGET 0x00000020
#define THREAD_CREATE_FLAGS_INITIAL_THREAD      0x00000080

4.3 绕过方法

钩取NtCreateThreadEx函数并重置THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER标志。

5. 句柄跟踪反调试技术

5.1 原理

Windows XP引入的句柄跟踪机制会在使用无效句柄时生成EXCEPTION_INVALID_HANDLE异常。

5.2 实现示例

EXCEPTION_DISPOSITION ExceptionRoutine(
    PEXCEPTION_RECORD ExceptionRecord,
    PVOID EstablisherFrame,
    PCONTEXT ContextRecord,
    PVOID DispatcherContext)
{
    if (EXCEPTION_INVALID_HANDLE == ExceptionRecord->ExceptionCode) {
        std::cout << "Stop debugging program!" << std::endl;
        exit(-1);
    }
    return ExceptionContinueExecution;
}

int main()
{
    __asm {
        // set SEH handler
        push ExceptionRoutine
        push dword ptr fs:[0]
        mov dword ptr fs:[0], esp
    }
    
    CloseHandle((HANDLE)0xBAAD);
    
    __asm {
        // return original SEH handler
        mov eax, [esp]
        mov dword ptr fs:[0], eax
        add esp, 8
    }
    return 0;
}

6. 堆栈段操作反调试技术

6.1 原理

操作SS堆栈段寄存器时,调试器会跳过指令跟踪。

6.2 实现示例

push ss
pop ss
mov eax, 0xC000C1EE  // 调试器会跳过这行
xor edx, edx         // 调试器会直接跳到这里

7. 调试信息反调试技术

7.1 原理

Windows 10后,OutputDebugString改为使用RaiseException实现,通过检查异常处理情况检测调试器。

7.2 实现示例

#define DBG_PRINTEXCEPTION_WIDE_C 0x4001000A
WCHAR * outputString = L"Any text";
ULONG_PTR args[4] = {0};
args[0] = (ULONG_PTR)wcslen(outputString) + 1;
args[1] = (ULONG_PTR)outputString;

__try {
    RaiseException(DBG_PRINTEXCEPTION_WIDE_C, 0, 4, args);
    printf("Debugger detected");
}
__except (EXCEPTION_EXECUTE_HANDLER) {
    printf("Debugger NOT detected");
}

8. 其他反调试技术

  1. 自调试过程:程序自身作为调试器运行
  2. FindWindow检测:查找调试器窗口
  3. 时间计算方法:检测代码执行时间异常
  4. NtQueryObject:查询调试对象信息
  5. BlockInput:阻止用户输入
  6. NtSetDebugFilterState:设置调试过滤状态
  7. 自修改代码:动态修改代码防止分析

9. 总结

本文详细介绍了Windows平台常见的反调试技术及其绕过方法,包括:

  1. SEH/VEH异常处理检测
  2. 线程隐藏技术(NtSetInformationThread/NtCreateThreadEx)
  3. 句柄跟踪检测
  4. 堆栈段操作技巧
  5. 调试信息异常检测

每种技术都有相应的检测方法和绕过策略,但需要注意的是,没有绝对安全的保护方法,反调试技术的主要目的是增加逆向工程的难度。实际应用中通常会组合多种技术来提高保护强度。

Windows平台反调试技术及绕过方法详解 1. SEH(结构化异常处理)反调试技术 1.1 SEH检查原理 SEH(结构化异常处理)是Windows平台的一种异常处理机制,反调试技术可以通过检查SEH处理程序的调用堆栈来检测调试器。 1.2 典型调用堆栈 1.3 绕过方法 在 ntdll!ExecuteHandler2+0x24 处设置断点: 分析每个调用SEH处理程序的代码 2. VEH(向量化异常处理)反调试技术 2.1 VEH原理 VEH是Windows XP引入的SEH变体,处理程序列表存储在 ntdll!LdrpVectorHandlerList 未导出变量中。 2.2 关键API 2.3 典型实现示例 2.4 绕过方法 钩取 KiUserExceptionDispatcher 函数: 3. NtSetInformationThread反调试技术 3.1 原理 使用 ThreadHideFromDebugger (0x11)信息类隐藏线程,使线程停止发送调试事件通知。 3.2 实现代码 3.3 绕过方法 钩取 NtSetInformationThread 函数: 4. NtCreateThreadEx反调试技术 4.1 原理 使用 THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER (0x00000004)标志创建隐藏线程。 4.2 线程创建标志 4.3 绕过方法 钩取 NtCreateThreadEx 函数并重置 THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 标志。 5. 句柄跟踪反调试技术 5.1 原理 Windows XP引入的句柄跟踪机制会在使用无效句柄时生成 EXCEPTION_INVALID_HANDLE 异常。 5.2 实现示例 6. 堆栈段操作反调试技术 6.1 原理 操作SS堆栈段寄存器时,调试器会跳过指令跟踪。 6.2 实现示例 7. 调试信息反调试技术 7.1 原理 Windows 10后, OutputDebugString 改为使用 RaiseException 实现,通过检查异常处理情况检测调试器。 7.2 实现示例 8. 其他反调试技术 自调试过程 :程序自身作为调试器运行 FindWindow检测 :查找调试器窗口 时间计算方法 :检测代码执行时间异常 NtQueryObject :查询调试对象信息 BlockInput :阻止用户输入 NtSetDebugFilterState :设置调试过滤状态 自修改代码 :动态修改代码防止分析 9. 总结 本文详细介绍了Windows平台常见的反调试技术及其绕过方法,包括: SEH/VEH异常处理检测 线程隐藏技术(NtSetInformationThread/NtCreateThreadEx) 句柄跟踪检测 堆栈段操作技巧 调试信息异常检测 每种技术都有相应的检测方法和绕过策略,但需要注意的是,没有绝对安全的保护方法,反调试技术的主要目的是增加逆向工程的难度。实际应用中通常会组合多种技术来提高保护强度。