自己做了一个SEH相关的一个小程序,顺便在调试的时候观察一下

0:000> g $exentry
ModLoad: 75a90000 75ab5000   C:\Windows\SysWOW64\IMM32.DLL
eax=001bf840 ebx=00300000 ecx=00851010 edx=00851010 esi=00851010 edi=00851010
eip=00851010 esp=001bf7e8 ebp=001bf7f4 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
Project1!_Start:
00851010 6764a10000      mov     eax,dword ptr fs:[00000000h] fs:0053:00000000=001bf840
_
_Start:
    assume fs:nothing
	mov eax,fs:[0]         ;<---IP
    push offset myHandler
    push fs:[0]
    mov fs:[0],esp
    mov ecx,-1
    mov [eax],ecx
    xor eax,eax
    mov [eax],eax
    retn
END	_Start
_0:000> !exchain
001bf840: ntdll!_except_handler4+0 (775da040)
  CRT scope  0, filter: ntdll!__RtlUserThreadStart+3ad46 (7760293b)
                func:   ntdll!__RtlUserThreadStart+3addf (776029d4)
001bf858: ntdll!FinalExceptionHandlerPad54+0 (775e8ff6)
Invalid exception stack at ffffffff
_Start:
    assume fs:nothing
	mov eax,fs:[0]         
    push offset myHandler
    push fs:[0]
    mov fs:[0],esp        
    mov ecx,-1       ;<---IP
    mov [eax],ecx
    xor eax,eax
    mov [eax],eax
    retn
END	_Start
0:000> !exchain
001bf7e0: Project1!_Start+fffffffffffffff0 (00851000)
001bf840: ntdll!_except_handler4+0 (775da040)
  CRT scope  0, filter: ntdll!__RtlUserThreadStart+3ad46 (7760293b)
                func:   ntdll!__RtlUserThreadStart+3addf (776029d4)
001bf858: ntdll!FinalExceptionHandlerPad54+0 (775e8ff6)
Invalid exception stack at ffffffff

发现handler函数在0x00851000处,反汇编一下

0:000> u 00851000
Project1!_Start+0xffffffff`fffffff0 [D:\seh\Project1\KillSeh.asm @ 24]:
00851000 6a04            push    4
00851002 6a00            push    0
00851004 6803408500      push    offset Project1!messuc (00854003)
00851009 6a00            push    0
0085100b e82e000000      call    Project1!MessageBoxA (0085103e)
Project1!_Start [D:\seh\Project1\KillSeh.asm @ 34]:
00851010 6764a10000      mov     eax,dword ptr fs:[00000000h]
00851015 6800108500      push    offset Project1!_Start+0xffffffff`fffffff0 (00851000)
0085101a 6764ff360000    push    dword ptr fs:[0000h]

然后发现我这个程序没有返回,由于在汇编中我写在start前面,所以会错上加错,在ash链上的函数应该返回一个_EXCEPTION_CONTINUE让程序继续搜索下一个异常处理程序(_excep_handler4)

于是乎我定义了一下ExceptionContinueSearch = 1(估计库里面也有)

mov eax,ExceptionContinueSearch

retn

再继续调试,这次终于找到元凶了

ntdll!_except_handler4:
775da040 8bff            mov     edi,edi
775da042 55              push    ebp
775da043 8bec            mov     ebp,esp
775da045 ff7514          push    dword ptr [ebp+14h]
775da048 ff7510          push    dword ptr [ebp+10h]
775da04b ff750c          push    dword ptr [ebp+0Ch]
775da04e ff7508          push    dword ptr [ebp+8]
775da051 68603f5d77      push    offset ntdll!__security_check_cookie (775d3f60)
775da056 6860336877      push    offset ntdll!__security_cookie (77683360)
775da05b e870bcffff      call    ntdll!_except_handler4_common (775d5cd0)
775da060 83c418          add     esp,18h
775da063 5d              pop     ebp
775da064 c3              ret

又是security_check,这玩意一般是防止栈溢出用的,这里我也没调过,接着看下一个函数

ntdll!_except_handler4_common

发现了一个函数用来调用seh链上的异常处理函数

ntdll!ExecuteHandler2:
775e8e4c 55              push    ebp
775e8e4d 8bec            mov     ebp,esp
775e8e4f ff750c          push    dword ptr [ebp+0Ch]
775e8e52 52              push    edx          ;难道用栈改seh这么常见吗,分分钟被hook掉(bushi),有空可以试一试
775e8e53 64ff3500000000  push    dword ptr fs:[0]
775e8e5a 64892500000000  mov     dword ptr fs:[0],esp
775e8e61 ff7514          push    dword ptr [ebp+14h]
775e8e64 ff7510          push    dword ptr [ebp+10h]
775e8e67 ff750c          push    dword ptr [ebp+0Ch]
775e8e6a ff7508          push    dword ptr [ebp+8]
775e8e6d 8b4d18          mov     ecx,dword ptr [ebp+18h]
775e8e70 ffd1            call    ecx
775e8e72 648b2500000000  mov     esp,dword ptr fs:[0]
775e8e79 648f0500000000  pop     dword ptr fs:[0]
775e8e80 8be5            mov     esp,ebp
775e8e82 5d              pop     ebp
775e8e83 c21400          ret     14h

再上一级函数

;ntdll!RtlpExecuteHandlerForException
ntdll!ExecuteHandler:
775e8e20 53              push    ebx
775e8e21 56              push    esi
775e8e22 57              push    edi
775e8e23 33c0            xor     eax,eax
775e8e25 33db            xor     ebx,ebx
775e8e27 33f6            xor     esi,esi
775e8e29 33ff            xor     edi,edi
775e8e2b ff742420        push    dword ptr [esp+20h]
775e8e2f ff742420        push    dword ptr [esp+20h]
775e8e33 ff742420        push    dword ptr [esp+20h]
775e8e37 ff742420        push    dword ptr [esp+20h]
775e8e3b ff742420        push    dword ptr [esp+20h]
775e8e3f e808000000      call    ntdll!ExecuteHandler2 (775e8e4c)
775e8e44 5f              pop     edi
775e8e45 5e              pop     esi
775e8e46 5b              pop     ebx
775e8e47 c21400          ret     14h

再上一级,其实就是栈回溯。。

如果用ida可以的话就方便多了,下次找找ida的可行调试方法,ida调试老是报错不知道为啥