结构化异常处理(StructuredExceptionHandling,SEH)是Windows操作系统处理程序错误或异常的技术
。SEH是Windows操作系统的一种系统机制,与特定的程序设计语言无关。
外壳程序里大量地使用了SEH,如果不了解SEH,将会使你跟踪十分困难。
由于Ollydbg 对SEH处理异常灵活,因此脱壳用Ollydbg会大大提高效率。
附CONTEXT结构环境:
代码:typedefstruct_CONTEXT{
/*000*/DWORD ContextFlags;
/*004*/DWORD Dr0;
/*008*/DWORD Dr1;
/*00C*/DWORD Dr2;
/*010*/DWORD Dr3;
/*014*/DWORD Dr6;
/*018*/DWORD Dr7;
/*01C*/FLOATING_SAVE_AREAFloatSave;
/*08C*/DWORD SegGs;
/*090*/DWORD SegFs;
/*094*/DWORD SegEs;
/*098*/DWORD SegDs;
/*09C*/DWORD Edi;
/*0A0*/DWORD Esi;
/*0A4*/DWORD Ebx;
/*0A8*/DWORD Edx;
/*0AC*/DWORD Ecx;
/*0B0*/DWORD Eax;
/*0B4*/DWORD Ebp;
/*0B8*/DWORD Eip;
/*0BC*/DWORD SegCs;
/*0C0*/DWORD EFlags;
/*0C4*/DWORD Esp;
/*0C8*/DWORD SegSs;
/*0CC*/ BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
/*2CC*/}CONTEXT;
[工具]flyod1.10
[目的]学习SEH的手法,另书中是用SoftICE调试的,看起来不习惯.根据原文内容重新整理一下,便于和我一样的菜鸟们一起学习.
今天下决心,好好学习,这是就算是个开始吧!感觉学明白的确很不容易!
[注释]?--为不能理解的地方,请大侠们指点一下.学习过程中,有理解错误的地方,肯请大侠们多多指教.
[练习对象]加密与加密二版第10章,光盘配套的练习软件: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源文件中定义的---VC++CRT(CRT含义:C++RunTimelibrary)]:
_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 jmpshortSeh.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],使用shift+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 jeshortntdll.77FB4DCD
77FB4DC1 5B popebx
77FB4DC2 59 popecx
77FB4DC3 6A00 push0
77FB4DC5 51 pushecx
77FB4DC6 E8480BFCFF callntdll.ZwContinue
77FB4DCB EB0B jmpshortntdll.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 jmpshortSeh.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 ; SEhandlerinstallation发生异常后到这里执行
//看学强调:提前在这个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 int3
发生异常,就来到这里:
看堆栈:
0012FCCC 0012FCD4 //指针,指向EXCEPTION_RECORD结构,即EXCEPTION_RECORD的首地址-----这就是EXCEPTION_POINTERS
0012FCD0 0012FCF0 //指针,指向EXCEPTION_CONTEXT结构,即EXCEPTION_CONTEXT的首地址---
0012FCD4 C0000005 ---------------1--异常代码.这里开始就是EXCEPTION_RECORD结构
0012FCD8 00000000
0012FCDC 00000000
0012FCE0 00401018 seh2.00401018 4--异常发生的地址,这就是发生异常的那条指令的地址.
0012FCE4 00000002
0012FCE8 00000000
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
0012FD0C FFFF027F
77FB4DB3 8B1C24 movebx,dwordptrss:[esp]
77FB4DB6 51 pushecx
77FB4DB7 53 pushebx
77FB4DB8 E8ACBDFAFF callntdll.77F60B69//f7
77FB4DBD 0AC0 oral,al
77FB4DBF 740C jeshortntdll.77FB4DCD
77FB4DC1 5B popebx
77FB4DC2 59 popecx
77FB4DC3 6A00 push0
77FB4DC5 51 pushecx
77FB4DC6 E8480BFCFF callntdll.ZwContinue
77FB4DCB EB0B jmpshortntdll.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
77FB4DFB>^E97DBCFAFF jmpntdll.77F60A7D
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
77F79B93 FF7514 pushdwordptrss:[ebp+14]//参数4 _lpDispatchrContext?
77F79B96 FF7510 pushdwordptrss:[ebp+10]//参数3 _lpDContext,指向Context结构
77F79B99 FF750C pushdwordptrss:[ebp+C] //参数2 _lpSEH,指向ERR结构
77F79B9C FF7508 pushdwordptrss:[ebp+8] //参数1 _lpExceptionRecord,指向ExceptionRecord结构
77F79B9F 8B4D18 movecx,dwordptrss:[ebp+18]
77F79BA2 FFD1 callecx ;seh2.00401051转到这里了f7
//这就是异常处理回调函数,执行当前异常处理代码即401051处
//注:回调函数都是由windows调用的!
//看学强调:在此回调函数上设断点,可以轻易地对付一些加壳的反跟踪代码!!!!!
77F79BA4 64:8B250000000>movesp,dwordptrfs:[0]//恢复原来的SEH链表
77F79BAB 64:8F050000000>popdwordptrfs:[0]
77F79BB2 8BE5 movesp,ebp
77F79BB4 5D popebp
77F79BB5 C21400 retn14
00401051 /$ 55 pushebp ; Structuredexceptionhandler
00401052 |. 8BEC movebp,esp
00401054 |. 53 pushebx
00401055 |. 8B4510 moveax,dwordptrss:[ebp+10]//eax是CONTEXT结构的指针
00401058 |. 8D1D2D104000leaebx,dwordptrds:[40102D]//通过修改CONTEXT.EIP,希望到这里执行!
0040105E |. 8998B8000000movdwordptrds:[eax+B8],ebx//修改CONTEXT.EIP,改变程序执行线路,这大概就是利用seh的常用手法!
//没改时,是401018即发生异常的指令地址,经过1轮处理又会到这里执行
//又产生异常
00401064 |. 33DB xorebx,ebx
00401066 |. 895804 movdwordptrds:[eax+4],ebx//DR0清零,使断点失效,这大概也是利用seh的常用手法,实现反跟踪!
00401069 |. 895808 movdwordptrds:[eax+8],ebx//DR1
0040106C |. 89580C movdwordptrds:[eax+C],ebx//DR2
0040106F |. 895810 movdwordptrds:[eax+10],ebx//DR3
00401072 |. C7401855010>movdwordptrds:[eax+18],155//DR7
00401079 |. B800000000 moveax,0//回调处理函数的返回值ExceptionContinueExcetion-->eax
//ExceptionContinueExcetion=0 回调函数返回后,系统将线程环境恢复到_lpContext参数指定的CONTEXT结构并继续执行.
即,表示已经修复,从异常处继续执行,如果前面没有修改CONTEXT.EIP的值,就会到401018即异常发生处
继续执行,由于前面修改了CONTEXT.EIP=40102D,所以就转到40102D处继续执行了.
//ExceptionContinueExcetion=1 回调函数拒绝处理这个异常,系统将通过err结构的prev指针得到前一个回掉函数的地址并继续执行它
也就是转到前一个err结构的异常处理代码处继续执行.
//ExceptionContinueExcetion=2 回调函数在执行中又发生了异常,即嵌套异常
//ExceptionContinueExcetion=3 发生嵌套的展开操作?
0040107E |. 5B popebx
0040107F |. C9 leave
00401080 . C21000 retn10
[总结]
//看学强调:在此回调函数上设断点,可以轻易地对付一些加壳的反跟踪代码!!!!!
//看学强调:要提前在err结构的handler地址上设断点,否则代码就可能跑飞跟踪seh的关键断点!!!!
//看学提示:可修改CONTEXT结构成员,来实现反跟踪及改变程序流程(设置暗桩吗?)
**************************************************************************
[附录]跟踪到异常处理回调函数的过程:
注:windowsxp-sp1平台.只要是同样平台,就可以按下面步骤,来到系统的异常处理回调函数.
熟悉一下这段代码,应该有好处,当发生异常时,可以快速找到那个callecx异常处理回调函数,从而找到程序自己的异常处理代码。
00401000>/$ 6851104000 pushseh2.00401051// SEhandlerinstallation
//只有在这个401051上设断点,才能跟到异常处理代码(SEH代码)处.
//即要提前在err结构的handler地址上设断点,否则代码就可能跑飞!
//跟踪seh的关键断点!!!!
00401005 |. 64:FF3500000>pushdwordptrfs:[0]
0040100C |. 64:892500000>movdwordptrfs:[0],esp
00401013 |. BE00000000 movesi,0
00401018 |. 8B06 moveax,dwordptrds:[esi] //产生异常,来到代码[1]
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
代码[1]
77FB4DB3 8B1C24 movebx,dwordptrss:[esp]
77FB4DB6 51 pushecx
77FB4DB7 53 pushebx
77FB4DB8 E8ACBDFAFF callntdll.77F60B69//F7进入,来到代码[2]
77FB4DBD 0AC0 oral,al
77FB4DBF 740C jeshortntdll.77FB4DCD
77FB4DC1 5B popebx
77FB4DC2 59 popecx
77FB4DC3 6A00 push0
77FB4DC5 51 pushecx
77FB4DC6 E8480BFCFF callntdll.ZwContinue//代码[5],F7进入,回到代码[6]
77FB4DCB EB0B jmpshortntdll.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
77FB4DFB>^E97DBCFAFF jmpntdll.77F60A7D
代码[2]
77F60B69 55 pushebp
77F60B6A 8BEC movebp,esp
77F60B6C 83EC60 subesp,60
77F60B6F 56 pushesi
77F60B70 FF750C pushdwordptrss:[ebp+C]
77F60B73 8B7508 movesi,dwordptrss:[ebp+8]
77F60B76 56 pushesi
77F60B77 E8AA000000 callntdll.77F60C26
77F60B7C 84C0 testal,al
77F60B7E 0F85EB6F0200 jnzntdll.77F87B6F
77F60B84 53 pushebx
77F60B85 57 pushedi
77F60B86 8D45F8 leaeax,dwordptrss:[ebp-8]
77F60B89 50 pusheax
77F60B8A 8D45FC leaeax,dwordptrss:[ebp-4]
77F60B8D 50 pusheax
77F60B8E E83C910100 callntdll.77F79CCF
77F60B93 E852910100 callntdll.77F79CEA
77F60B98 83650800 anddwordptrss:[ebp+8],0
77F60B9C 8BD8 movebx,eax
77F60B9E 83FBFF cmpebx,-1
77F60BA1 0F844A1C0100 jentdll.77F727F1
77F60BA7 3B5DFC cmpebx,dwordptrss:[ebp-4]
77F60BAA 0F82481C0100 jbntdll.77F727F8
77F60BB0 8D4308 leaeax,dwordptrds:[ebx+8]
77F60BB3 3B45F8 cmpeax,dwordptrss:[ebp-8]
77F60BB6 0F873C1C0100 jantdll.77F727F8
77F60BBC F6C303 testbl,3
77F60BBF 0F85331C0100 jnzntdll.77F727F8
77F60BC5 8B4304 moveax,dwordptrds:[ebx+4]
77F60BC8 3B45FC cmpeax,dwordptrss:[ebp-4]
77F60BCB 7209 jbshortntdll.77F60BD6
77F60BCD 3B45F8 cmpeax,dwordptrss:[ebp-8]
77F60BD0 0F82221C0100 jbntdll.77F727F8
77F60BD6 F6054A32FC778>testbyteptrds:[77FC324A],80
77F60BDD 0F85936F0200 jnzntdll.77F87B76
77F60BE3 FF7304 pushdwordptrds:[ebx+4]
77F60BE6 8D45F0 leaeax,dwordptrss:[ebp-10]
77F60BE9 50 pusheax
77F60BEA FF750C pushdwordptrss:[ebp+C]
77F60BED 53 pushebx
77F60BEE 56 pushesi
77F60BEF E8528F0100 callntdll.77F79B46 //F4下,F7进入,来到代码[3]
77F60BF4 F6054A32FC778>testbyteptrds:[77FC324A],80
77F60BFB 8BF8 movedi,eax
77F60BFD 0F85896F0200 jnzntdll.77F87B8C
77F60C03 395D08 cmpdwordptrss:[ebp+8],ebx
77F60C06 0F848E6F0200 jentdll.77F87B9A
77F60C0C 8BC7 moveax,edi
77F60C0E 33C9 xorecx,ecx
77F60C10 2BC1 subeax,ecx
77F60C12 0F843E340100 jentdll.77F74056
77F60C18 48 deceax
77F60C19 0F85886F0200 jnzntdll.77F87BA7
77F60C1F 8B1B movebx,dwordptrds:[ebx]
77F60C21 ^E978FFFFFF jmpntdll.77F60B9E
77F60C26 55 pushebp
77F60C27 8BEC movebp,esp
77F60C29 51 pushecx
77F60C2A 51 pushecx
77F60C2B 57 pushedi
77F60C2C BF1032FC77 movedi,ntdll.77FC3210
77F60C31 393D1032FC77 cmpdwordptrds:[77FC3210],edi
77F60C37 0F8548E80100 jnzntdll.77F7F485
77F60C3D 32C0 xoral,al
77F60C3F 5F popedi
77F60C40 C9 leave
77F60C41 C20800 retn8
77F60C44> 55 pushebp
代码[3]
77F79B46 BAB89BF777 movedx,ntdll.77F79BB8
77F79B4B EB07 jmpshortntdll.77F79B54
77F79B4D BADF9BF777 movedx,ntdll.77F79BDF
77F79B52 8D09 leaecx,dwordptrds:[ecx]
77F79B54 53 pushebx
77F79B55 56 pushesi
77F79B56 57 pushedi
77F79B57 33C0 xoreax,eax
77F79B59 33DB xorebx,ebx
77F79B5B 33F6 xoresi,esi
77F79B5D 33FF xoredi,edi
77F79B5F FF742420 pushdwordptrss:[esp+20]
77F79B63 FF742420 pushdwordptrss:[esp+20]
77F79B67 FF742420 pushdwordptrss:[esp+20]
77F79B6B FF742420 pushdwordptrss:[esp+20]
77F79B6F FF742420 pushdwordptrss:[esp+20]
77F79B73 E806000000 callntdll.77F79B7E////F4下,F7进入,来到代码[4]
77F79B78 5F popedi
77F79B79 5E popesi
77F79B7A 5B popebx
77F79B7B C21400 retn14
代码[4]
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
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]
77F79BA2 FFD1 callecx //这就是异常处理回调函数!
77F79BA4 64:8B250000000>movesp,dwordptrfs:[0]
77F79BAB 64:8F050000000>popdwordptrfs:[0]
77F79BB2 8BE5 movesp,ebp
77F79BB4 5D popebp
77F79BB5 C21400 retn14//返回后继续跟,回到代码[5]处
代码[6]
77F75913> B820000000 moveax,20
77F75918 BA0003FE7F movedx,7FFE0300
77F7591D FFD2 calledx//f7,到代码[8]
77F7591F C20800 retn8
代码[8]
7FFE0300 8BD4 movedx,esp
7FFE0302 0F34 sysenter
7FFE0304 C3 retn//返回到代码[9]
代码[9]
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//f7,进入,到代码[10]
代码[10]-----这段代码,任何程序只要执行了exitprocess都会看到!留个印象吧!
77E598FD> 55 pushebp
77E598FE 8BEC movebp,esp
77E59900 6AFF push-1
77E59902 68B0F3E877 pushkernel32.77E8F3B0
77E59907 FF7508 pushdwordptrss:[ebp+8]
77E5990A E886FFFFFF callkernel32.77E59895//结束了应用程序的生命!
77E5990F ^E9A47DFEFF jmpkernel32.TerminateProcess
77E59914 -FF25F413E477 jmpdwordptrds:[<&ntdll.LdrShutdownProcess>] ;ntdll.LdrShutdownProcess
77E5991A 391DA470EB77 cmpdwordptrds:[77EB70A4],ebx
77E59920 0F8499150000 jekernel32.77E5AEBF
77E59926 53 pushebx
77E59927 53 pushebx
77E59928 53 pushebx
77E59929 E8D2F4FEFF callkernel32.WriteProfileStringW
77E5992E E98C150000 jmpkernel32.77E5AEBF
77E59933> 837C240400 cmpdwordptrss:[esp+4],0
77E59938 0F84C4730200 jekernel32.77E80D02
77E5993E FF742408 pushdwordptrss:[esp+8]
77E59942 FF742408 pushdwordptrss:[esp+8]
77E59946 FF156814E477 calldwordptrds:[<&ntdll.NtTerminateThread>] ;ntdll.ZwTerminateThread
77E5994C 85C0 testeax,eax
77E5994E 0F8CB7730200 jlkernel32.77E80D0B
77E59954 33C0 xoreax,eax
77E59956 40 inceax
77E59957 C20800 retn8
***************************************************************