2种基于异常机制的反调试方法

来源:互联网 发布:相思相见知何日 编辑:程序博客网 时间:2024/04/30 18:46
    如题,一种是利用异常处理例程进行反调试:首先安装好一个异常处理例程,然后人为抛出异常在异常处理例程中通过IsDebuggerPresent来判断程序是否被调试;另一种是利用未处理异常进行反跟踪,其原理是:当异常发生时所有异常处理例程都不能处理异常,系统线程异常处理例程将起作用,它调用 ZwQueryInformationProcess 判断是否被调试, 

如果没有调试并且程序中调用SetUnhandledExceptionFilter安装了最后异常处理例程的话,系统转向对它的调用。

    第一种方法中IsDebuggerPresent是通过返回FS寄存器上记录的地址的一些偏移量来实现的。在debugger中可以任意操作当前进程内存地址上的值,所以只需要用调试器把[[FS:30]:2的值修改成0,IsDebuggerPresent就会返回false,导致判断失败。相比第二种方法中UnhandledExceptionFilter是否调用取决于系统内核的判断。用户态的调试器要想改变这个行为就得颇费功夫了。下面我将依次展示两种反调试方法。

    第一种方法,通过在异常处理例程中判断IsDebuggerPresent的返回值:

#include <windows.h>int AntiDebugInSEH(EXCEPTION_POINTERS* ExceptionInfo){DWORD state = 0x00;__asm{mov eax,dword ptr fs:[30h];movzx eax, byte ptr ds:[eax+2h];mov state,eax;}ExceptionInfo->ContextRecord->Eax = state;ExceptionInfo->ContextRecord->Eip = 0x06+(DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress;return EXCEPTION_CONTINUE_EXECUTION;}int main(){int i=0;__try{__asm{xor eax,eax;mov dword ptr [eax],0; //触发异常}__asm{                    //异常返回后,eax的值为AntiDebugInSEH中ExceptionInfo->ContextRecord->Eax设定的值                                        mov i,eax}if(i==1){}else{MessageBox(NULL,"","",0);}i++;}__except(AntiDebugInSEH(GetExceptionInformation())){}}
上面这段代码,如果正常运行将弹出对话框,如果调试运行对话框是看不到了。文章中也提到了,可以通过修改[[fs:30]:2]处的内存地址使IsDebuggerPresent失效,好的,祭出windbg:

进入异常时,[fs:[30h]:2]处的值为0x0001,即正在调试状态:

0:000> r eaxeax=7ffd50000:000> dd eax7ffd5000  00010000 ffffffff 00400000 76fb88807ffd5010  00291940 00000000 00290000 76fb8380
为了使IsDebuggerPresent失效,修改0x7ffd5000处的内存值:

0:000> ed 7ffd5000  0x000000000:000> dd eax7ffd5000  00000000 ffffffff 00400000 76fb88807ffd5010  00291940 00000000 00290000 76fb8380
当程序从异常处理例程返回时,又可以见到对话框了:


接下来看下第二种反调试方法:

#include <windows.h>LONG WINAPI UnhandledExcept(EXCEPTION_POINTERS *pExpInfo)  {if(pExpInfo->ExceptionRecord->ExceptionCode != EXCEPTION_BREAKPOINT){return EXCEPTION_EXECUTE_HANDLER;}else{pExpInfo->ContextRecord->Eip = (DWORD)(pExpInfo->ContextRecord->Eip+1);pExpInfo->ContextRecord->Eax = 0x0000FEEE;return EXCEPTION_CONTINUE_EXECUTION;}}int main(){HMODULE hMod = LoadLibrary("kernel32.dll");DWORD* funcAddr = (DWORD*)GetProcAddress(hMod,"ExitProcess");SetUnhandledExceptionFilter(UnhandledExcept);_asm int 3;__asm{cmp ax,0xFEEE;jz next;push 0;mov eax,funcAddr;call eax;next:}{MessageBox(NULL,"","",MB_OK);}}
这段代码,还是读者自己试下,我暂时没想到如果绕过检测的方法。

参考连接:

http://www.52pojie.cn/forum.php?mod=viewthread&tid=16609

http://bbs.pediy.com/showthread.php?t=9023

0 0
原创粉丝点击