当前位置:文档之家› SEH 结构化异常处理

SEH 结构化异常处理

标 题: 【原创】加密与解密二版菜鸟学习笔记(2) - SEH 结构化异常处理 作 者: ytcswb 时 间: 2005-02-01,16:40:24 链 接: http://bbs.pediy.com/showthread.php?t=10651

看学加密与解密二版学习笔记(2) - SEH 结构化异常处理 [ 工 具 ] flyod1.10 [ 目 的 ] 学习SEH的手法,另书中是用SoftICE调试的,看起来不习惯.根据原文内容重新整理一下,便于和我一样的菜鸟们一起学习. 今天下决心,好好学习,这是就算是个开始吧!感觉学明白的确很不容易!

[ 注 释 ] ?--为不能理解的地方,请大侠们指点一下.学习过程中,有理解错误的地方,肯请大侠们多多指教.

[练习对象] 加密与加密二版第10章,光盘配套的练习软件:seh.exe seh2.exe [ writer ] ytcswb 2005.2.1 感谢看学及论坛的大侠们为我们提供这么好的学习资料。 1.例子seh.exe学习: 00401000 > $ 8D4424 F8 lea eax,dword ptr ss:[esp-8] //程序入口!根据下面的代码分析,这里显然可以 //理解为开辟8字节的空间,并把栈顶指针保存到eax //相当于sub esp,8 ; lea eax,dword ptr ss:[esp] 00401004 . 64:8705 00000>xchg dword ptr fs:[0],eax //记住fs[0]永远是指向当前err结构的指针, //执行完成后,fs[0]指向栈顶,准备在堆栈中构造1个err结构 //eax等于原fs[0],即指向原来的err结构的指针,即那个err结构的地址 0040100B . BB 2E104000 mov ebx,Seh.0040102E //地址40102e-->ebx,建议在此地址上设断点,才能正常跟踪入seh代码中 00401010 . 53 push ebx //压入堆栈,即当前err结构的handler成员,当前异常处理代码的入口地址 00401011 . 50 push eax //压入原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++RunTime library)]: _EXCEPTION _REGISTERATION stru prev dd ? //指向下一个err结构的指针,数值上等于下一个err结构的首地址(在堆栈中) handler dd ? //指向异常处理代码的指针,数值上等于异常处理代码的入口地址即首地址 _EXCEPTION _REGISTERATION ends

00401012 . BE 00000000 mov esi,0 //简单的赋值语句 00401017 . 8B06 mov eax,dword ptr ds:[esi] //读取线性地址0,产生异常 //执行后,windows检查到异常,执行线程马上被中段,从用户模式转到内核模式 //控制权交到操作系统的异常调试程序(exception dispatcher),由它负责找到 //处理这个异常的方法,即所有应用程序的异常最终都是由windwos来处理的, //同一个版本的windows有固定的异常处理代码. //如果你把这句nop掉了,也就等于去除了异常.会接着执行到下面的代码,并显示"SEH Fail"!

00401019 . 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL 0040101B . 68 00304000 push Seh.00403000 ; |Title = "OK" 00401020 . 68 10304000 push Seh.00403010 ; |Text = "SEH Fail" 00401025 . 6A 00 push 0 ; |hOwner = NULL 00401027 . E8 1C000000 call ; \MessageBoxA 0040102C . EB 13 jmp short Seh.00401041 0040102E . 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL 00401030 . 68 00304000 push Seh.00403000 ; |Title = "OK" 00401035 . 68 03304000 push Seh.00403003 ; |Text = "SEH Succeed " 0040103A . 6A 00 push 0 ; |hOwner = NULL 0040103C . E8 07000000 call ; \MessageBoxA 00401041 > 6A 00 push 0 ; /ExitCode = 0 00401043 . E8 06000000 call ; \ExitProcess 00401048 $- FF25 08204000 jmp dword ptr ds:[<&USER32.MessageBoxA>] ; USER32.MessageBoxA 0040104E .- FF25 00204000 jmp dword ptr ds:[<&KERNEL32.ExitProcess>; kernel32.ExitProcess 00401054 00 db 00 00401055 00 db 00 --------------------------------------------------------------------------------------------------- 00401017 . 8B06 mov eax,dword ptr ds:[esi] //读取线性地址0,产生异常 //执行完这1条指令,od的状态行可以看到,产生了什么异常.状态行的内容如下: //访问违反:读取[00000000],使用shift+F7/F8/F9键跳过异常以继续执行程序. //windows检测到了这个异常,就会向堆栈压入3个结构.压入顺序为 EXCEPTION_RECORD,EXCEPTION_CONTEXT,EXCEPTION_POINTERS //EXCEPTION_POINTERS结构就在栈顶,其定义如下:

typedef strut_EXCEPTION_POINTERS{ +0 pEXCEPTION_RECORD ExceptionRecord DWORD ? //指针,指向EXCEPTION_RECORD结构,即EXCEPTION_RECORD的首地址 +4 pCONTEXT ContextRecord DWORD ? //指针,指向EXCEPTION_CONTEXT结构,即EXCEPTION_CONTEXT的首地址 }_EXCEPTION_POINTERS ends

在看看EXCEPTION_RECORD结构: EXCEPTION_RECORD struct{ //共6个成员 +0 DWORD ExceptionCode //异常代码,定义了产生异常的原因 +4 DWORD ExceptionFlags //异常标志 ? +8 struct EXCEPTION_RECORD //指针,指向另一个EXCEPTION_RECORD结构 +C DVOID ExceptionAddress //异常发生的地址 +10 DWORD NumberParameters //与异常联系的参数个数(0~15)一般=0 ? +14 ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS] //异常信息 ? }EXCEPTION_RECORD ends

//执行完401017指令后,我们在od的代码窗口的看到代码如下: 77FB4DAF > 8B4C24 04 mov ecx,dword ptr ss:[esp+4] 77FB4DB3 8B1C24 mov ebx,dword ptr ss:[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

相关主题