要留意的是,假如配置了/ INCREMENTAL:NO链接器选项,那么在获取函数地点来计较校验和的环境下,将会获得相对跳转地点:
- DebuggeeFunction:
- 013C16DB jmp DebuggeeFunction (013C4950h)
g_origCrc全局变量包括已由CalcFuncCrc函数计较的crc。为了终止检测函数,我们行使了存根函数的能力。按着函数代码次序分列,DebuggeeFunction函数的末端是DebuggeeFunctionEnd函数的开头。我们还行使#pragma auto_inline(off)指令来防备编译器的嵌入函数。
怎样避开软件断点搜查
因为今朝还没有一个通用的要领,所觉得了避开此掩护,应该找到代码计较校验和并用常量替代返回的值,以及存储函数校验和的全部变量的值。
硬件断点
在Windows x86架构中,开拓职员在搜查和调试代码时行使了一组调试寄存器。这些寄存器应承在会见内存读取或写入时刻断措施执行并将节制传输到调试器。调试寄存器是一种特权资源,只能在具有特权级别CPL = 0的实模式或安详模式下由措施行使。8字节的调试寄存器DR0-DR7有:
1.DR0-DR3 -断点寄存器
2.DR4,DR5 -蕴藏
3.DR6 -调试状态
4.DR7 – 调试节制
DR0-DR3包括断点的线性地点,这些地点的较量是在物理地点转换之前举办的。这些断点中的每一个城市在DR7寄存器中被单独描写。 DR6寄存器会指示哪个断点被激活。 DR7通过会见模式界说断点激活模式:读,写,执行。以下是硬件断点搜查的示例:
- CONTEXT ctx = {};
- ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
- if (GetThreadContext(GetCurrentThread(), &ctx))
- {
- if (ctx.Dr0 != 0 || ctx.Dr1 != 0 || ctx.Dr2 != 0 || ctx.Dr3 != 0)
- {
- std::cout << "Stop debugging program!" << std::endl;
- exit(-1);
- }
- }
也可以通过SetThreadContext函数重置硬件断点,以下是硬件断点重置示例:
- CONTEXT ctx = {};
- ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
- SetThreadContext(GetCurrentThread(), &ctx);
我们可以看到,全部DRx寄存器都配置为了0。
怎样避开硬件断点搜查和重置
假如我们看看GetThreadContext函数,我们会大白它挪用了NtGetContextThread函数:
- 0:000> u KERNELBASE!GetThreadContext L6
- KERNELBASE!GetThreadContext:
- 7538d580 8bff mov edi,edi
- 7538d582 55 push ebp
- 7538d583 8bec mov ebp,esp
- 7538d585 ff750c push dword ptr [ebp+0Ch]
- 7538d588 ff7508 push dword ptr [ebp+8]
- 7538d58b ff1504683975 call dword ptr [KERNELBASE!_imp__NtGetContextThread (75396804)]
假如反调试掩护在Dr0-Dr7中吸取到零值,应该在CONTEXT布局的ContextFlags字段中重置CONTEXT_DEBUG_REGISTERS标识,然后在原始的NtGetContextThread函数挪用后规复其值。对付GetThreadContext函数,它在内部挪用NtSetContextThread。以下就是避开硬件断点的搜查和重置:
- typedef NTSTATUS(NTAPI *pfnNtGetContextThread)(
- _In_ HANDLE ThreadHandle,
- _Out_ PCONTEXT pContext
- );
- typedef NTSTATUS(NTAPI *pfnNtSetContextThread)(
- _In_ HANDLE ThreadHandle,
- _In_ PCONTEXT pContext
- );
- pfnNtGetContextThread g_origNtGetContextThread = NULL;
- pfnNtSetContextThread g_origNtSetContextThread = NULL;
- NTSTATUS NTAPI HookNtGetContextThread(
- _In_ HANDLE ThreadHandle,
- _Out_ PCONTEXT pContext)
- {
- DWORD backupContextFlags = pContext->ContextFlags;
- pContext->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS;
- NTSTATUS status = g_origNtGetContextThread(ThreadHandle, pContext);
- pContext->ContextFlags = backupContextFlags;
- return status;
- }
- NTSTATUS NTAPI HookNtSetContextThread(
- _In_ HANDLE ThreadHandle,
- _In_ PCONTEXT pContext)
- {
- DWORD backupContextFlags = pContext->ContextFlags;
- pContext->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS;
- NTSTATUS status = g_origNtSetContextThread(ThreadHandle, pContext);
- pContext->ContextFlags = backupContextFlags;
- return status;
- }
- void HookThreadContext()
- {
- HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll"));
- g_origNtGetContextThread = (pfnNtGetContextThread)GetProcAddress(hNtDll, "NtGetContextThread");
- g_origNtSetContextThread = (pfnNtSetContextThread)GetProcAddress(hNtDll, "NtSetContextThread");
- Mhook_SetHook((PVOID*)&g_origNtGetContextThread, HookNtGetContextThread);
- Mhook_SetHook((PVOID*)&g_origNtSetContextThread, HookNtSetContextThread);
- }
SEH(布局化非常处理赏罚) (编辑:湖南网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|