[目]学习SEH手法,另书中是用SoftICE调试,看起来不习惯.根据原文内容重新整理下,便于和我样菜鸟们起学习.
今天下决心,好好学习,这是就算是个开始吧!感觉学明白确很不容易!
[注释]?--为不能理解地方,请大侠们指点下.学习过程中,有理解地方,肯请大侠们多多指教.
[练习对象]加密和加密 2版第10章,光盘配套练习软件Software:seh.exeseh2.exe
[writer] ytcswb 2005.2.1 感谢看学及论坛大侠们为我们提供这么好学习资料
1.例子seh.exe学习:
00401000>$ 8D4424F8 leaeax,dwordptrss:[esp-8]//入口!根据下面代码分析,这里显然可以
//理解为开辟8字节空间,并把栈顶指针保存到eax
//相当于subesp,8;leaeax,dwordptrss:[esp]
00401004 . 64:870500000>xchgdwordptrfs:[0],eax //记住fs[0]永远是指向当前err结构指针,
//执行完成后,fs[0]指向栈顶,准备在堆栈中构造1个err结构
//eax等于原fs[0],即指向原来err结构指针,即那个err结构地址
0040100B . BB2E104000 movebx,Seh.0040102E //地址40102e-->ebx,建议在此地址上设断点,才能正常跟踪入seh代码中
00401010 . 53 pushebx //压入堆栈,即当前err结构handler成员,当前异常处理代码入口地址
00401011 . 50 pusheax //压入原fs[0],即当前err结构prev成员,即下个err结构地址
此时堆栈:
0012FFBC 0012FFE0 指针到下个SEH记录//0012FFE0是个指针,看看就知道指向下个err结构,数值上等于下个err结构地址
0012FFC0 0040102E SE句柄 //建立了1个当前err结构
0012FFE0 FFFFFFFF SEH链尾部
0012FFE4 77E74809 SE句柄
err结构定义[在Essup.INC源文件中定义---VCCRT(CRT含义:CRunTimelibrary)]:
_EXCEPTION_REGISTERATIONstru
prev dd?//指向下个err结构指针,数值上等于下个err结构首地址(在堆栈中)
handlerdd?//指向异常处理代码指针,数值上等于异常处理代码入口地址即首地址
_EXCEPTION_REGISTERATIONends
00401012 . BE00000000 movesi,0 //简单赋值语句
00401017 . 8B06 moveax,dwordptrds:[esi] //读取线性地址0,产生异常
//执行后,windows检查到异常,执行线程马上被中段,从用户模式转到内核模式
//控制权交到操作系统异常调试(exceptiondispatcher),由它负责找到
//处理这个异常思路方法,即所有应用异常最终都是由windwos来处理,
//同个版本windows有固定异常处理代码.
//如果你把这句nop掉了,也就等于去除了异常.会接着执行到下面代码,并显示"SEHFail"!
00401019 . 6A00 push0 ;/Style=MB_OK|MB_APPLMODAL
0040101B . 6800304000 pushSeh.00403000 ;|Title="OK"
00401020 . 6810304000 pushSeh.00403010 ;|Text="SEHFail"
00401025 . 6A00 push0 ;|hOwner=NULL
00401027 . E81C000000 call<jmp.&USER32.MessageBoxA> ;MessageBoxA
0040102C . EB13 jmpSeh.00401041
0040102E . 6A00 push0 ;/Style=MB_OK|MB_APPLMODAL
00401030 . 6800304000 pushSeh.00403000 ;|Title="OK"
00401035 . 6803304000 pushSeh.00403003 ;|Text="SEHSucceed"
0040103A . 6A00 push0 ;|hOwner=NULL
0040103C . E807000000 call<jmp.&USER32.MessageBoxA> ;MessageBoxA
00401041 > 6A00 push0 ;/ExitCode=0
00401043 . E806000000 call<jmp.&KERNEL32.ExitProcess> ;ExitProcess
00401048 $-FF2508204000jmpdwordptrds:[<&USER32.MessageBoxA>]; USER32.MessageBoxA
0040104E .-FF2500204000jmpdwordptrds:[<&KERNEL32.ExitProcess>; kernel32.ExitProcess
00401054 00 db00
00401055 00 db00
---------------------------------------------------------------------------------------------------
00401017 . 8B06 moveax,dwordptrds:[esi]
//读取线性地址0,产生异常
//执行完这1条指令,od状态行可以看到,产生了什么异常.状态行内容如下:
//访问违反:读取[00000000],使用sht+F7/F8/F9键跳过异常以继续执行.
//windows检测到了这个异常,就会向堆栈压入3个结构.压入顺序为EXCEPTION_RECORD,EXCEPTION_CONTEXT,EXCEPTION_POINTERS
//EXCEPTION_POINTERS结构就在栈顶,其定义如下:
typedefstrut_EXCEPTION_POINTERS{
+0pEXCEPTION_RECORDExceptionRecordDWORD?//指针,指向EXCEPTION_RECORD结构,即EXCEPTION_RECORD首地址
+4pCONTEXTContextRecord DWORD?//指针,指向EXCEPTION_CONTEXT结构,即EXCEPTION_CONTEXT首地址
}_EXCEPTION_POINTERSends
在看看EXCEPTION_RECORD结构:EXCEPTION_RECORDstruct{ //共6个成员
+0 DWORDExceptionCode //异常代码,定义了产生异常原因
+4 DWORDExceptionFlags //异常标志?
+8 structEXCEPTION_RECORD //指针,指向另个EXCEPTION_RECORD结构
+C DVOIDExceptionAddress //异常发生地址
+10DWORDNumberParameters //和异常联系参数个数(0~15)般=0?
+14ULONG_PTRExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS] //异常信息?
}EXCEPTION_RECORDends
//执行完401017指令后,我们在od代码窗口看到代码如下:
77FB4DAF> 8B4C2404 movecx,dwordptrss:[esp+4]
77FB4DB3 8B1C24 movebx,dwordptrss:[esp]//来到了ntdll领空,即系统领空
{
//马上看看堆栈:
0012FCCC 0012FCD4-|//指针,指向EXCEPTION_RECORD结构,即EXCEPTION_RECORD首地址-----这就是EXCEPTION_POINTERS
0012FCD0 0012FCF0-|//指针,指向EXCEPTION_CONTEXT结构,即EXCEPTION_CONTEXT首地址---
0012FCD4 C0000005---------------1--异常代码.这里开始就是EXCEPTION_RECORD结构
0012FCD8 00000000 2--异常标志=0
0012FCDC 00000000 3--指针,指向另个EXCEPTION_RECORD结构,这里=0
没有另个EXCEPTION_RECORD结构,为NULL指针.
0012FCE0 00401017 Seh.004010174--异常发生地址,这就是发生异常那条指令地址.
0012FCE4 00000002 5--和异常联系参数个数=2?
0012FCE8 00000000 6--异常信息?
0012FCEC 00000000---------------
0012FCF0 0001003F---------------这里开始就是EXCEPTION_CONTEXT结构,ContextFlags
0012FCF4 00000000 Dr0
0012FCF8 00000000 Dr1
0012FCFC 00000000 Dr2
0012FD00 00000000 Dr3
0012FD04 0000A000 Dr6
0012FD08 00000000 Dr7
我们重点看看0012FCF0+B8=12FDA8 0012FDA4 0012FFF0
0012FDA8 00401017 Seh.00401017异常发生地址,这就是发生异常那条指令地址.
0012FDAC 0000001B
}
继续跟踪:77FB4DB6 51 pushecx//指针,指向EXCEPTION_CONTEXT结构
77FB4DB7 53 pushebx//指针,指向EXCEPTION_RECORD结构
77FB4DB8 E8ACBDFAFF callntdll.77F60B69//如果f8过,会出现SEHsucceed提示窗口,即执行了自己异常代码,
//为了看系统是如何处理,我们f7进入
77FB4DBD 0AC0 oral,al
77FB4DBF 740C jentdll.77FB4DCD
77FB4DC1 5B popebx
77FB4DC2 59 popecx
77FB4DC3 6A00 push0
77FB4DC5 51 pushecx
77FB4DC6 E8480BFCFF callntdll.ZwContinue
77FB4DCB EB0B jmpntdll.77FB4DD8
77FB4DCD 5B popebx
77FB4DCE 59 popecx
77FB4DCF 6A00 push0
77FB4DD1 51 pushecx
77FB4DD2 53 pushebx
77FB4DD3 E8F213FCFF callntdll.ZwRaiseException
77FB4DD8 83C4EC addesp,-14
77FB4DDB 890424 movdwordptrss:[esp],eax
77FB4DDE C744240401000>movdwordptrss:[esp+4],1
77FB4DE6 895C2408 movdwordptrss:[esp+8],ebx
77FB4DEA C744241000000>movdwordptrss:[esp+10],0
77FB4DF2 54 pushesp
77FB4DF3 E8AFC2F9FF callntdll.RtlRaiseException
77FB4DF8 C20800 retn8
继续跟到这段代码里:77F79B7E 55 pushebp
77F79B7F 8BEC movebp,esp
77F79B81 FF750C pushdwordptrss:[ebp+C]
77F79B84 52 pushedx
77F79B85 64:FF350000000>pushdwordptrfs:[0]
77F79B8C 64:89250000000>movdwordptrfs:[0],esp
{
//堆栈建立了1个err结构
0012FC04 0012FFBC 指针到下个SEH记录//enter键看看
0012FC08 77F79BB8 SE句柄
0012FFBC 0012FFE0 指针到下个SEH记录
0012FFC0 0040102E SE句柄//熟悉这个地址吧
0012FFE0 FFFFFFFF SEH链尾部
0012FFE4 77E74809 SE句柄
}
77F79B93 FF7514 pushdwordptrss:[ebp+14]
77F79B96 FF7510 pushdwordptrss:[ebp+10]
77F79B99 FF750C pushdwordptrss:[ebp+C]
77F79B9C FF7508 pushdwordptrss:[ebp+8]
77F79B9F 8B4D18 movecx,dwordptrss:[ebp+18]
{
//此时我们马上看看堆栈:
0012FBF4 0012FCD4//指针,指向EXCEPTION_RECORD结构,即EXCEPTION_RECORD首地址 -----回调参数1
0012FBF8 0012FFBC//指向err结构.可以看看上面我们截取SEH链表 -----回调参数2
0012FBFC 0012FCF0//指针,指向EXCEPTION_CONTEXT结构,即EXCEPTION_CONTEXT首地址-----回调参数3
0012FC00 0012FCAC//参数4 _lpDispatchrContext?最先被压入堆栈.
0012FC04 0012FFBC 指针到下个SEH记录
0012FC08 77F79BB8 SE句柄
0012FC0C 0012FFBC
}
77F79BA2 FFD1 callecx //Seh.0040102E到这里执行,就是自己异常处理代码,f7
//这就是异常处理回调,其参数含义请往下看.
{
0040102C ./EB13 jmpSeh.00401041
0040102E .|6A00 push0 ;/Style=MB_OK|MB_APPLMODAL
00401030 .|6800304000 pushSeh.00403000 ;|Title="OK"
00401035 .|6803304000 pushSeh.00403003 ;|Text="SEHSucceed"
0040103A .|6A00 push0 ;|hOwner=NULL
0040103C .|E807000000 call<jmp.&USER32.MessageBoxA> ;MessageBoxA
00401041 >6A00 push0 ;/ExitCode=0
00401043 . E806000000 call<jmp.&KERNEL32.ExitProcess> ;ExitProcess
00401048 $-FF2508204000jmpdwordptrds:[<&USER32.MessageBoxA>]; USER32.MessageBoxA
0040104E .-FF2500204000jmpdwordptrds:[<&KERNEL32.ExitProcess>; kernel32.ExitProcess
}
77F79BA4 64:8B250000000>movesp,dwordptrfs:[0]
77F79BAB 64:8F050000000>popdwordptrfs:[0]
77F79BB2 8BE5 movesp,ebp
77F79BB4 5D popebp
77F79BB5 C21400 retn14
[整理总结]//读取线性地址0,产生异常
//执行后,windows检查到异常,执行线程马上被中段,从用户模式转到内核模式
//控制权交到操作系统异常调试(exceptiondispatcher),由它负责找到
//处理这个异常思路方法,即所有应用异常最终都是由windwos来处理,
//那么同个版本windows就有固定异常处理代码.跟踪seh保护时,以此为切入点,可以轻而举地找到关键!
2.例子seh2.exe学习:
00401000>/$ 6851104000 pushseh2.00401051 ; SEhandleration发生异常后到这里执行
//看学强调:提前在这个handler设个断点,否则容易跑飞!
//只有这样才能正常跟进seh处理代码!
00401005 |. 64:FF3500000>pushdwordptrfs:[0]
0040100C |. 64:892500000>movdwordptrfs:[0],esp //构造1个err结构
0012FFBC 0012FFE0 指针到下个SEH记录//fs:[0]=esp=0x0012FFBC
0012FFC0 00401051 SE句柄
0012FFE0 FFFFFFFF SEH链尾部
0012FFE4 77E74809 SE句柄
00401013 |. BE00000000 movesi,0
00401018 |. 8B06 moveax,dwordptrds:[esi]//产生异常
//这里实际是故意引发个异常,为就是通过修改CONTEXT,来实现反跟踪及改变流程(设置暗桩吗?)
0040101A |. 6A00 push0 ;/Style=MB_OK|MB_APPLMODAL
0040101C |. 6800304000 pushseh2.00403000 ;|Title="SEH"
00401021 |. 680F304000 pushseh2.0040300F ;|Text="SEH没有运行"
00401026 |. 6A00 push0 ;|hOwner=NULL
00401028 |. E857000000 call<jmp.&USER32.MessageBoxA> ;MessageBoxA
0040102D |. 6A00 push0 ;/Style=MB_OK|MB_APPLMODAL
0040102F |. 6800304000 pushseh2.00403000 ;|Title="SEH"
00401034 |. 6804304000 pushseh2.00403004 ;|Text="Hello,SEH!"
00401039 |. 6A00 push0 ;|hOwner=NULL
0040103B |. E844000000 call<jmp.&USER32.MessageBoxA> ;MessageBoxA
00401040 |. 64:8F0500000>popdwordptrfs:[0]
00401047 |. 83C404 addesp,4
0040104A |. 6A00 push0 ;/ExitCode=0
0040104C . E839000000 call<jmp.&KERNEL32.ExitProcess> ;ExitProcess
00401051 /$ 55 pushebp ; Structuredexceptionhandler
00401052 |. 8BEC movebp,esp
00401054 |. 53 pushebx
00401055 |. 8B4510 moveax,dwordptrss:[ebp+10]
00401058 |. 8D1D2D104000leaebx,dwordptrds:[40102D]
0040105E |. 8998B8000000movdwordptrds:[eax+B8],ebx
00401064 |. 33DB xorebx,ebx
00401066 |. 895804 movdwordptrds:[eax+4],ebx
00401069 |. 895808 movdwordptrds:[eax+8],ebx
0040106C |. 89580C movdwordptrds:[eax+C],ebx
0040106F |. 895810 movdwordptrds:[eax+10],ebx
00401072 |. C7401855010>movdwordptrds:[eax+18],155
00401079 |. B800000000 moveax,0
0040107E |. 5B popebx
0040107F |. C9 leave
00401080 . C21000 retn10
00401083 CC 3
发生异常,就来到这里:
最新评论