代码如下:
LONG __stdcall _UnhandledExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo) { MessageBox(0,NULL,NULL,0); return EXCEPTION_EXECUTE_HANDLER; } int main() { SetUnhandledExceptionFilter(&_UnhandledExceptionFilter); int *p = NULL; *p = 100; return 0; }
先下个断点:
0:000> x *!UnhandledExceptionFilter 00be3588 ThreadsTest!UnhandledExceptionFilter (<no parameter info>) 74e5d2e0 KERNELBASE!UnhandledExceptionFilter (<no parameter info>) 0:000> bp 74e5d2e0 0:000> bl 0 e 00be1113 0001 (0001) 0:**** ThreadsTest!ILT+270(_mainCRTStartup) 1 e 74e5d2e0 0001 (0001) 0:**** KERNELBASE!UnhandledExceptionFilter
运行g,第一次异常发生:
0:000> g (12e4.2858): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=00000000 ebx=010a3000 ecx=c76d0000 edx=ffffffff esi=012ff978 edi=012ffa50 eip=00be145c esp=012ff978 ebp=012ffa50 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246 ThreadsTest!main+0x3c: 00be145c c70064000000 mov dword ptr [eax],64h ds:002b:00000000=????????
再次运行g,第二次异常发现,断到UnhandledExceptionFilter
0:000> g Breakpoint 1 hit eax=74e5d2e0 ebx=00000000 ecx=74e5d2e0 edx=00000000 esi=74e5d2e0 edi=00000000 eip=74e5d2e0 esp=012ff360 ebp=012ffb04 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 KERNELBASE!UnhandledExceptionFilter: 74e5d2e0 6a68 push 68h
0:000> x ntdll!NtQueryInformationProcess 7799e740 ntdll!NtQueryInformationProcess (<no parameter info>)UnhandledExceptionFilter是通过NtQueryInformationProcess来判断进程在EPROCESS.DebugPort是否有值的
0:000> dt _EPROCESS -y debug* ntdll!_EPROCESS +0x268 DebugPort : Ptr32 Void
0:000> g 7799e740 eax=012ff2c8 ebx=00000001 ecx=7560b4f1 edx=00000000 esi=00000000 edi=00000000 eip=7799e740 esp=012ff2ac ebp=012ff2cc iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 ntdll!NtQueryInformationProcess: 7799e740 b819000000 mov eax,19h 0:000> kv L4 # ChildEBP RetAddr Args to Child 00 012ff2a8 74e5cf6b ffffffff 00000007 012ff2c8 ntdll!NtQueryInformationProcess (FPO: [5,0,0]) 01 012ff2cc 74e5d3a3 1d3df10b 00000000 74e5d2e0 KERNELBASE!BasepIsDebugPortPresent+0x1d (FPO: [Non-Fpo]) 02 012ff35c 779ce0bd 012ff38c 779a2a80 012ffb04 KERNELBASE!UnhandledExceptionFilter+0xc3 (FPO: [Non-Fpo])g xxx ,xxx表示要断点的地址,很容易看出,这里是由UnhandledExceptionFilter调入的NtQueryInformationProcess
把NtQueryInformationProcess的返回值改成0x80000000就OK了
观察RetAddr
74e5cf6b 85c0 test eax,eax即把eax改掉就好了
0:000> bp 74e5cf6b 0:000> g Breakpoint 2 hit eax=00000000 ebx=00000001 ecx=4ad80000 edx=00fce488 esi=00000000 edi=00000000 eip=74e5cf6b esp=012ff62c ebp=012ff634 iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206 KERNELBASE!BasepIsDebugPortPresent+0x1d: 74e5cf6b 85c0 test eax,eax 0:000> r eax=0x80000000 0:000> r eax eax=80000000
OK,进入了我们的异常处理函数了
0:000> x *!_UnhandledExceptionFilter 00be13b0 ThreadsTest!_UnhandledExceptionFilter (struct _EXCEPTION_POINTERS *) 0:000> bp 00be13b0 0:000> g Breakpoint 3 hit eax=00000001 ebx=00000001 ecx=00be10ff edx=00000220 esi=00000000 edi=00000000 eip=00be13b0 esp=012ff634 ebp=012ff6c4 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 ThreadsTest!_UnhandledExceptionFilter: 00be13b0 55 push ebp