seh 模拟try catch
fs:[0] 为当前线程tib.exceptionlist
.386
.model flat, stdcall
option casemap:none
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include Advapi32.inc
includelib Advapi32.lib
include msvcrt.inc
includelib msvcrt.lib
.const
szFormatError db 'exception_eip:%x, exception_code:%d, flags:%x',0
szMsg db 'safe',0
.code
;恢复到发生异常的函数
reroll proc lpSeh, lpContext
pushad
; lpContext 为当前线程的context == GetThreadContext
; lpSeh 为fs:[0] , fs:[0] 保存了发生异常函数的esp, 同时又是exception_registration, 因此可以用来恢复
mov esi,lpContext
assume esi:ptr CONTEXT
mov edi,lpSeh ; raise_exception_proc 中的 esp
push [edi+12]
pop [esi].regEbp
push [edi+8]
pop [esi].regEip
push edi
pop [esi].regEsp
assume esi:nothing
popad
ret
reroll endp
;异常处理
seh_handler proc c _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
local buffer[MAX_PATH]:byte
pushad
mov esi,_lpExceptionRecord
mov edi , _lpContext
assume esi : ptr EXCEPTION_RECORD,edi:ptr CONTEXT
invoke wsprintf,addr buffer,addr szFormatError, [edi].regEip,[esi].ExceptionCode,[esi].ExceptionFlags
invoke MessageBox,NULL,addr buffer,NULL,MB_OK
assume esi:nothing,edi:nothing
invoke reroll , _lpSEH,_lpContext
popad
mov eax, ExceptionContinueExecution
ret
seh_handler endp
;发生异常的函数
raise_exception_proc proc
;构建try {} , 相当于在stack中构建一个exception_registration
;fs:[0] 当前线程的tib.Exceptionlist
assume fs:nothing
;2个自定义数据
push ebp
push offset except_block
;2个字段构建一个 exception_registration { prev , handler }
push offset seh_handler ; 构建 exception_registration.handler
push fs:[0] ; 写入exception_registration.prev [ 前一个exception_registration]
; 当前esp 指向首个被调用的异常处理handler [exception_registration-> handler]
; 这个 fs:[0] 将被传递到 handler 中的_lpSEH , 因此可以用他来恢复stack
mov fs:[0], esp
;raise exception
xor ebx,ebx
mov byte ptr [ebx],0
;expect
except_block:
; 在reroll 中已经恢复当前esp,ebp , 下面只需要恢复当前过程的esp
pop fs:[0]
add esp,12
invoke MessageBox,NULL,addr szMsg,addr szMsg,MB_OK
ret
raise_exception_proc endp
main proc
call raise_exception_proc
invoke ExitProcess,NULL
main endp
end main