首页
社区
课程
招聘
[讨论]SEH 程序栈的变化
发表于: 2008-8-6 00:18 5853

[讨论]SEH 程序栈的变化

2008-8-6 00:18
5853
;一个DebugWin的示例程序:
;This program is written by vkim
;vkim@aport2000.ru
;-----------------------------------------------------------------------------
.386
.model flat, stdcall
option casemap: none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
include \masm32\include\debug.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\debug.lib
;DBGWIN_DEBUG_ON = 1 ;turn it off if you don’t want to include debug info into the program
;DBGWIN_EXT_INFO = 1 ;turn it off if you don’t want to include extra debug info into the program
.data
dwVar dword 0
szMessage byte "Message", 0

.code
start:

;-----------------------------------------------------------------------
;the code below shows how to use PrintException macro
;install new seh
assume fs: nothing
push offset SEHproc
push fs:[0]
mov fs:[0], esp
;crash code
xor eax, eax
xchg eax, [eax]
ext:
;restore previous SEH
mov eax, [esp]     ;+----------断点二,考察返回后的栈变化
mov fs:[0], eax
add esp, 8
ret
SEHproc proc C pExcept: dword, pFrame: dword, pContext: dword, pDispatch: dword
PrintException pExcept
mov edx, pContext ; <--------+断点一,考察栈情况
mov (CONTEXT ptr [edx]).regEip, offset ext  ;改变返回的EIP,使得返回执行时不会从错误发生处执行了,而是从ext处执行。
mov eax, ExceptionContinueExecution   ;返回继续执行
ret
SEHproc endp
end start

;略作分析:
;断点一:
00401040 >/> \55 push ebp    ;那个SEH 处理过程
00401041 |. 8BEC mov ebp, esp
...;中间是插入的调试打印语句,透明处理,不影响栈
00401092 |. 8B55 10 mov edx, dword ptr [ebp+10]      ;------------+
00401095 |. C782 B8000000>mov dword ptr [edx+B8], 00401033    ;|
0040109F |. B8 00000000 mov eax, 0                            ;|
004010A4 |. C9 leave                                          ;|
004010A5 \. C3 retn                                           ;|
ss:[0012FC00]=0012FCF0    ;<---------------------数据情况--------+
edx=7C958766 (ntdll.7C958766)
EPI.asm:50. mov edx, pContext

;紧接着下一句的数据情况:
00401033=00401033
ds:[0012FDA8]=00401031 (EPI.00401031)
EPI.asm:51. mov (CONTEXT ptr [edx]).regEip, offset ext

;进入ExceptionHandler函数时的栈情况:
0012FBF0 /0012FC14
0012FBF4 |7C958752 返回到 ntdll.7C958752
0012FBF8 |0012FCD4 ; pExcept
0012FBFC |0012FFBC ;pFrame
0012FC00 |0012FCF0 ;pContext
0012FC04 |0012FCB0 ;pDispatch
0012FC08 |0012FFBC 指向下一个 SEH 记录的指针 ;正常的Exception完成后,返回正常执行的栈顶
0012FC0C |7C958766 SE处理
0012FC10 |0012FFBC
0012FC14 ]0012FCBC

;断点二
;返回后,继续执行时的栈情况
0012FFBC 0012FFE0 指向下一个 SEH 记录的指针
0012FFC0 0040100A SE处理
0012FFC4 7C82F23B 返回到 kernel32.7C82F23B
CONTEXT STRUCT
ContextFlags DWORD ?
iDr0 DWORD ?
iDr1 DWORD ?
iDr2 DWORD ?
iDr3 DWORD ?
iDr6 DWORD ?
iDr7 DWORD ?
FloatSave FLOATING_SAVE_AREA <>
regGs DWORD ?
regFs DWORD ?
regEs DWORD ?
regDs DWORD ?
regEdi DWORD ?
regEsi DWORD ?
regEbx DWORD ?
regEdx DWORD ?
regEcx DWORD ?
regEax DWORD ?
regEbp DWORD ?
regEip DWORD ?
regCs DWORD ?
regFlag DWORD ?
regEsp DWORD ?
regSs DWORD ?
ExtendedRegisters db MAXIMUM_SUPPORTED_EXTENSION dup(?)
CONTEXT ENDS
;程序二:
.586p
.model flat, stdcall
option casemap :none ; case sensitive
include windows.inc ;头部包含文件
include user32.inc
include kernel32.inc
includelib kernel32.lib
includelib user32.lib

.data
szTitle db "Structured Exception Handler example",0
szMessage db "Intercepted General Protection Fault!",0
.code
start:
call setupSEH ; 标准的方法。。。。

exceptionhandler:
mov esp,[esp+8] ;不明白别问我

push 00000000h ; 引发MessageBoxA
push offset szTitle
push offset szMessage
push 00000000h
call MessageBoxA
push 00000000h
call ExitProcess ; 退出
assume fs:nothing
setupSEH:
push dword ptr fs:[0] ; 得到SEH局柄
mov fs:[0],esp ;创建新局柄

mov ebx,0BFF70000h ; 写入核地址
mov eax,012345678h
xchg eax,[ebx]
end start

;开始的部分
00401010 >|> \E8 1E000000 call 00401033
00401015 |. 8B6424 08 mov esp, dword ptr [esp+8] ; <-----------+ 断点一
00401019 |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
0040101B |. 68 00404000 push offset szTitle ; |Title = "Structured Exception Handler example"
00401020 |. 68 25404000 push offset szMessage ; |Text = "Intercepted General Protection Fault!"
ss:[0012FBFC]=0012FFBC
esp=0012FBF4
exce.asm:23. mov esp,[esp+8] ;不明白别问我

0012FBF4 7C958752 返回到 ntdll.7C958752
0012FBF8 0012FCD4
0012FBFC 0012FFBC
0012FC00 0012FCF0
0012FC04 0012FCB0
0012FC08 0012FFBC 指向下一个 SEH 记录的指针
0012FC0C 7C958766 SE处理
0012FC10 0012FFBC

comment *------------------------------
调整无非是仿照正常的SEH程化:
以看到是返回正常执行的,应当是刚入Exception Handler[esp+C]的值,也是OD 中执行dd [esp+c]得到的值。
正常情况下,它应当是正常Exception Handler数的入参数中的pFrame,正常的Exception Handler会自动调整的,但程二作
在Exception Handler中行,所以要mov esp,pFrame使Exception Handler中的环境正常的环境一致。
至于作的为什么是 [esp+8] 呢,因为作的程不是正常的SEH处理,不是个子过程,没有入子过程push ebp,所以刚好差了4
-------*

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 257
活跃值: (56)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2
朋友对seh很有研究嘛,谢谢你的文章了,晚了没时间看了,注释一下以后慢慢看:)
2008-8-22 01:49
0
雪    币: 220
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
至于作者的为什么是 [esp+8] 呢?
是因为这个正好是传入的EXCEPTION_REGISTRATION指针
setupSEH:
push dword ptr fs:[0] ; 得到SEH局柄
mov fs:[0],esp ;创建新局柄
2008-8-22 09:24
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
4
看不懂想表达什么精神
要方便套用macro : 若发生例外时显示讯息, 然后离开 ?
2008-8-22 11:10
0
雪    币: 257
活跃值: (56)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
这么底层的分析相当有用哦。
不是为了发生例外时显示讯息, 然后离开,而是研究发生例外时程序内部的调用结构,深入了解SEH
2008-8-22 12:29
0
雪    币: 390
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
6
最近也在搞这个,想利用seh结构在mingw下略过异常

不过mingw的库函数对堆栈好象有破坏,暂时还得不出什么结论
2008-10-16 09:21
0
游客
登录 | 注册 方可回帖
返回
//