首页/电脑软件/ 几种反调试手法及自写OD插件对其进行绕过

几种反调试手法及自写OD插件对其进行绕过

作者:神奇   分类:电脑软件   时间:2020-10-11 01:27:56  标签:



BeginDebugged利用调试器加载程序时调试器会通过CreateProcess()创建调试进程,同时会创建调试内核对象并保存在当前线程环境块的DbgSsReserved[1]字段中,此时此线程就不同于普通线程了(一般称为调试器线程)。接着CreateProcess()会判断是否有调试器,无则直接返回,有则调用PspCreateProcess(),此函数会根据DbgSsReserved[1]字段设置创建进程的EPROCESS的DebugPort字段,这样此被创建进程就可以称为被调试进程。接着PspCreateProcess()会调用MmCreatePeb(),此函数会根据EPROCESS的Debugport字段设置PEB的BeingDebuged字段。(无调试器时其值为0)
我们可以直接通过内联汇编来访问BeingDebuged字段,也可以通过IsDebuggerPresent()这个API来得到此字段的值。下面是示例程序。int main(int argc, char *argv[]){ DWORD dwBeingDebuged; TCHAR szTest[] = TEXT("已检测到调试器!"); TCHAR szSuccess[] = TEXT("运行正常!"); dwBeingDebuged = IsDebuggerPresent(); if(0 != dwBeingDebuged) { MessageBox(NULL, szTest, NULL, MB_OK); ExitProcess(NULL); } MessageBox(NULL, szSuccess, NULL, MB_OK); return 0;}NtGlobalFlag当BeingDebuged被设为“TRUE”后会将PEB的NtGlobalFlag设置0x70h标志,我们通过内联汇编检测进程环境快的NtGlobalFlag字段。int main(int argc, char *argv[]){ DWORD dwNtGlobalFlag; TCHAR szTest[] = TEXT("已检测到调试器!"); TCHAR szSuccess[] = TEXT("运行正常!"); dwNtGlobalFlag = _AntiDebug(); if(0 != dwNtGlobalFlag) { MessageBox(NULL, szTest, NULL, MB_OK); ExitProcess(NULL); } MessageBox(NULL, szSuccess, NULL, MB_OK); return 0;}//反调试DWORD _AntiDebug(){ _asm{ mov eax,fs:[0x30] mov eax,[eax + 0x68] and eax,0x70 }}ProcessHeap的Flags和ForceFlags当NtGlobalFlag字段被设置0x70标志后,其会改变PEB的字段ProcessHeap所指向的Flags和ForceFlags的值。
对于x86平台而言Flags和ForceFlags偏移地址分别是相对于ProcessHeap指向地址的0x40和0x44处。当程序未被调试器调试时Flags的值应包含0x00000002标志,ForceFlags的值应为0,下面是通过内联汇编检测二者的值。int main(int argc, char *argv[]){ DWORD dwReturn; TCHAR szTest[] = TEXT("已检测到调试器!"); TCHAR szSuccess[] = TEXT("运行正常!"); dwReturn = _AntiDebug(); if(0 != dwReturn) { MessageBox(NULL, szTest, NULL, MB_OK); ExitProcess(NULL); } MessageBox(NULL, szSuccess, NULL, MB_OK); return 0;}//反调试DWORD _AntiDebug(){ _asm{ push ebx mov eax,fs:[0x30] mov eax,[eax + 0x18] mov ebx,dword ptr [eax + 0x40] //Flags and ebx,0x00000002 cmp ebx,0 je end0 mov ebx,dword ptr [eax + 0x44] //ForceFlags cmp ebx,0 jne end0 xor eax,eax jmp endend0: mov eax,1end: pop ebx }}自写OD插件绕过此插件时基于OD1.10版本的,当然也可以参考此插件写法编写基于OD2.0版本的。插件思路为:我们通过IATHOOK OD的WaitForDebugEvent( )函数,将WaitForDebugEvent函数替换为我们的MyWaitForDebugEvent(),当检测到第一次接收到EXCEPTION_DEBUG_EVENT异常调试事件时将BeginDebugged,
NtGlobalFlag,Flags和ForceFlags清除。
替换WaitForDebugEvent()的函数即MyWaitForDebugEvent()代码如下。BOOL _stdcall MyWaitForDebugEvent(LPDEBUG_EVENT lpDebugEvent, DWORD dwMilliseconds){ static DWORD stPid; //进程PID static DWORD dwFlag = 0; BOOL Return; Return = WaitForDebugEvent(lpDebugEvent,dwMilliseconds); //调用原WaitForDebugEvent switch(lpDebugEvent->dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: //创建进程 stPid = lpDebugEvent->dwProcessId; break; case EXCEPTION_DEBUG_EVENT: //调试异常 dwFlag++; if(dwFlag == 1) _DetourAnti(stPid); //清除BeingDebugged,NtGlobalFlag,HeapFlags,ForceFlags break; case EXIT_PROCESS_DEBUG_EVENT: //程序退出 dwFlag = 0; } return Return;}_DetourAnti( )函数利用OD接口将BeingDebugged,NtGlobalFlag,HeapFlags,ForceFlags标志清除。//绕过反调试void _DetourAnti(DWORD dwPid){ HANDLE hProcess; //进程句柄 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); //获取权限 DWORD dwFlag = 0; t_thread * stMainThread ; stMainThread = _Findthread(_Plugingetvalue(VAL_MAINTHREADID)); DWORD dwTibAddress = stMainThread->datablock; DWORD dwPebAddress; DWORD dwAddress; _Readmemory(&dwPebAddress,(dwTibAddress + 0x30), 4, MM_RESTORE); //PEB _Writememory(&dwFlag,(dwPebAddress + 0x02), 1, MM_RESTORE); //DebugPresent _Writememory(&dwFlag,(dwPebAddress + 0x68), 4, MM_RESTORE); //NtGlobalFlag _Readmemory(&dwAddress,(dwPebAddress + 0x18), 4, MM_RESTORE); //ProcessHeap _Readmemory(&dwFlag,(dwAddress + 0x40), 4, MM_RESTORE); dwFlag = dwFlag | 0x2; _Writememory(&dwFlag,(dwAddress + 0x40), 4, MM_RESTORE); //HeapFlags _Readmemory(&dwFlag,(dwAddress + 0x44), 4, MM_RESTORE); dwFlag = 0; _Writememory(&dwFlag,(dwAddress + 0x44), 4, MM_RESTORE); //ForceFlags}IATHook代码在这里就不贴出了,可自行查看附件代码。将插件DLL放入OD1.10版本的plugin目录中运行OD会弹出DLL成功加载。我们利用BeingDebugged,NtGlobalFlag,HeapFlags,ForceFlags标志写了一个综合反调试程序,将测试程序用OD加载其将绕过所有反调试正常运行。
实际我们相当于实现了和知名插件HideOD的HideNtDebugBit选项的功能
参考资料:《软件调试》《加密与解密》
温馨提示如有转载或引用以上内容之必要,敬请将本文链接作为出处标注,谢谢合作!

评论:

发表评论:

code