看学加密与解密二版学习笔记(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 <jmp.&USER32.MessageBoxA> ; \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 <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401041 > 6A 00 push 0 ; /ExitCode = 0
00401043 . E8 06000000 call <jmp.&KERNEL32.ExitProcess> ; \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
0012FCDC 00000000 \3--指针,指向另一个EXCEPTION_RECORD结构,这里=0
没有另一个EXCEPTION_RECORD结构,为NULL指针.
0012FCE0 00401017 Seh.00401017 \4--异常发生的地址,这就是发生异常的那条指令的地址.
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 push ecx //指针,指向EXCEPTION_CONTEXT结构
77FB4DB7 53 push ebx //指针,指向EXCEPTION_RECORD结构
77FB4DB8 E8 ACBDFAFF call ntdll.77F60B69 //如果f8过,会出现SEH succeed 提示窗口,即执行了程序自己的异常代码,
//为了看系统是如何处理的,我们f7进入
77FB4DBD 0AC0 or al,al
77FB4DBF 74 0C je short ntdll.77FB4DCD
77FB4DC1 5B pop ebx
77FB4DC2 59 pop ecx
77FB4DC3 6A 00 push 0
77FB4DC5 51 push ecx
77FB4DC6 E8 480BFCFF call ntdll.ZwContinue
77FB4DCB EB 0B jmp short ntdll.77FB4DD8
77FB4DCD 5B pop ebx
77FB4DCE 59 pop ecx
77FB4DCF 6A 00 push 0
77FB4DD1 51 push ecx
77FB4DD2 53 push ebx
77FB4DD3 E8 F213FCFF call ntdll.ZwRaiseException
77FB4DD8 83C4 EC add esp,-14
77FB4DDB 890424 mov dword ptr ss:[esp],eax
77FB4DDE C74424 04 01000>mov dword ptr ss:[esp+4],1
77FB4DE6 895C24 08 mov dword ptr ss:[esp+8],ebx
77FB4DEA C74424 10 00000>mov dword ptr ss:[esp+10],0
77FB4DF2 54 push esp
77FB4DF3 E8 AFC2F9FF call ntdll.RtlRaiseException
77FB4DF8 C2 0800 retn 8
继续跟到这段代码里:
77F79B7E 55 push ebp
77F79B7F 8BEC mov ebp,esp
77F79B81 FF75 0C push dword ptr ss:[ebp+C]
77F79B84 52 push edx
77F79B85 64:FF35 0000000>push dword ptr fs:[0]
77F79B8C 64:8925 0000000>mov dword ptr fs:[0],esp
{
//堆栈建立了1个err结构
0012FC04 0012FFBC 指针到下一个 SEH 记录 //enter键看看
0012FC08 77F79BB8 SE 句柄
0012FFBC 0012FFE0 指针到下一个 SEH 记录
0012FFC0 0040102E SE 句柄 // 熟悉这个地址吧
0012FFE0 FFFFFFFF SEH 链尾部
0012FFE4 77E74809 SE 句柄
}
77F79B93 FF75 14 push dword ptr ss:[ebp+14]
77F79B96 FF75 10 push dword ptr ss:[ebp+10]
77F79B99 FF75 0C push dword ptr ss:[ebp+C]
77F79B9C FF75 08 push dword ptr ss:[ebp+8]
77F79B9F 8B4D 18 mov ecx,dword ptr ss:[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 call ecx //Seh.0040102E到这里执行,就是程序的自己的异常处理代码,f7
//这就是异常处理回调函数,其参数含义请往下看.
{
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 <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401041 > \6A 00 push 0 ; /ExitCode = 0
00401043 . E8 06000000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
00401048 $- FF25 08204000 jmp dword ptr ds:[<&USER32.MessageBoxA>] ; USER32.MessageBoxA
0040104E .- FF25 00204000 jmp dword ptr ds:[<&KERNEL32.ExitProcess>; kernel32.ExitProcess
}
77F79BA4 64:8B25 0000000>mov esp,dword ptr fs:[0]
77F79BAB 64:8F05 0000000>pop dword ptr fs:[0]
77F79BB2 8BE5 mov esp,ebp
77F79BB4 5D pop ebp
77F79BB5 C2 1400 retn 14
[总结]
//读取线性地址0,产生异常
//执行后,windows检查到异常,执行线程马上被中段,从用户模式转到内核模式
//控制权交到操作系统的异常调试程序(exception dispatcher),由它负责找到
//处理这个异常的方法,即所有应用程序的异常最终都是由windwos来处理的,
//那么同一个版本的windows就有固定的异常处理代码.跟踪seh保护的程序时,以此为切入点,可以轻而一举地找到关键!
2.例子seh2.exe学习:
00401000 >/$ 68 51104000 push seh2.00401051 ; SE handler installation发生异常后到这里执行
//看学强调:提前在这个handler设个断点,否则程序容易跑飞!
//只有这样才能正常跟进seh处理代码!
00401005 |. 64:FF35 00000>push dword ptr fs:[0]
0040100C |. 64:8925 00000>mov dword ptr fs:[0],esp //构造1个err结构
0012FFBC 0012FFE0 指针到下一个 SEH 记录 //fs:[0]=esp=0x0012FFBC
0012FFC0 00401051 SE 句柄
0012FFE0 FFFFFFFF SEH 链尾部
0012FFE4 77E74809 SE 句柄
00401013 |. BE 00000000 mov esi,0
00401018 |. 8B06 mov eax,dword ptr ds:[esi] //产生异常
//这里实际是故意引发一个异常,为的就是通过修改CONTEXT,来实现反跟踪及改变程序流程(设置暗桩吗?)
0040101A |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
0040101C |. 68 00304000 push seh2.00403000 ; |Title = "SEH"
00401021 |. 68 0F304000 push seh2.0040300F ; |Text = "SEH程序没有运行"
00401026 |. 6A 00 push 0 ; |hOwner = NULL
00401028 |. E8 57000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
0040102D |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
0040102F |. 68 00304000 push seh2.00403000 ; |Title = "SEH"
00401034 |. 68 04304000 push seh2.00403004 ; |Text = "Hello,SEH!"
00401039 |. 6A 00 push 0 ; |hOwner = NULL
0040103B |. E8 44000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401040 |. 64:8F05 00000>pop dword ptr fs:[0]
00401047 |. 83C4 04 add esp,4
0040104A |. 6A 00 push 0 ; /ExitCode = 0
0040104C \. E8 39000000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
00401051 /$ 55 push ebp ; Structured exception handler
00401052 |. 8BEC mov ebp,esp
00401054 |. 53 push ebx
00401055 |. 8B45 10 mov eax,dword ptr ss:[ebp+10]
00401058 |. 8D1D 2D104000 lea ebx,dword ptr ds:[40102D]
0040105E |. 8998 B8000000 mov dword ptr ds:[eax+B8],ebx
00401064 |. 33DB xor ebx,ebx
00401066 |. 8958 04 mov dword ptr ds:[eax+4],ebx
00401069 |. 8958 08 mov dword ptr ds:[eax+8],ebx
0040106C |. 8958 0C mov dword ptr ds:[eax+C],ebx
0040106F |. 8958 10 mov dword ptr ds:[eax+10],ebx
00401072 |. C740 18 55010>mov dword ptr ds:[eax+18],155
00401079 |. B8 00000000 mov eax,0
0040107E |. 5B pop ebx
0040107F |. C9 leave
00401080 \. C2 1000 retn 10
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 mov ebx,dword ptr ss:[esp]
77FB4DB6 51 push ecx
77FB4DB7 53 push ebx
77FB4DB8 E8 ACBDFAFF call ntdll.77F60B69 //f7
77FB4DBD 0AC0 or al,al
77FB4DBF 74 0C je short ntdll.77FB4DCD
77FB4DC1 5B pop ebx
77FB4DC2 59 pop ecx
77FB4DC3 6A 00 push 0
77FB4DC5 51 push ecx
77FB4DC6 E8 480BFCFF call ntdll.ZwContinue
77FB4DCB EB 0B jmp short ntdll.77FB4DD8
77FB4DCD 5B pop ebx
77FB4DCE 59 pop ecx
77FB4DCF 6A 00 push 0
77FB4DD1 51 push ecx
77FB4DD2 53 push ebx
77FB4DD3 E8 F213FCFF call ntdll.ZwRaiseException
77FB4DD8 83C4 EC add esp,-14
77FB4DDB 890424 mov dword ptr ss:[esp],eax
77FB4DDE C74424 04 01000>mov dword ptr ss:[esp+4],1
77FB4DE6 895C24 08 mov dword ptr ss:[esp+8],ebx
77FB4DEA C74424 10 00000>mov dword ptr ss:[esp+10],0
77FB4DF2 54 push esp
77FB4DF3 E8 AFC2F9FF call ntdll.RtlRaiseException
77FB4DF8 C2 0800 retn 8
77FB4DFB >^ E9 7DBCFAFF jmp ntdll.77F60A7D
77F79B7E 55 push ebp
77F79B7F 8BEC mov ebp,esp
77F79B81 FF75 0C push dword ptr ss:[ebp+C]
77F79B84 52 push edx
77F79B85 64:FF35 0000000>push dword ptr fs:[0]
77F79B8C 64:8925 0000000>mov dword ptr fs:[0],esp
77F79B93 FF75 14 push dword ptr ss:[ebp+14] //参数4 _lpDispatchrContext ?
77F79B96 FF75 10 push dword ptr ss:[ebp+10] //参数3 _lpDContext,指向Context结构
77F79B99 FF75 0C push dword ptr ss:[ebp+C] //参数2 _lpSEH ,指向ERR结构
77F79B9C FF75 08 push dword ptr ss:[ebp+8] //参数1 _lpExceptionRecord ,指向ExceptionRecord结构
77F79B9F 8B4D 18 mov ecx,dword ptr ss:[ebp+18]
77F79BA2 FFD1 call ecx ; seh2.00401051 转到这里了 f7
//这就是异常处理回调函数,执行当前异常处理代码即401051处
//注:回调函数都是由windows调用的!
//看学强调: 在此回调函数上设断点,可以轻易地对付一些加壳的反跟踪代码!!!!!
77F79BA4 64:8B25 0000000>mov esp,dword ptr fs:[0] //恢复原来的SEH链表
77F79BAB 64:8F05 0000000>pop dword ptr fs:[0]
77F79BB2 8BE5 mov esp,ebp
77F79BB4 5D pop ebp
77F79BB5 C2 1400 retn 14
00401051 /$ 55 push ebp ; Structured exception handler
00401052 |. 8BEC mov ebp,esp
00401054 |. 53 push ebx
00401055 |. 8B45 10 mov eax,dword ptr ss:[ebp+10] // eax是CONTEXT结构的指针
00401058 |. 8D1D 2D104000 lea ebx,dword ptr ds:[40102D] //通过修改CONTEXT.EIP,希望到这里执行!
0040105E |. 8998 B8000000 mov dword ptr ds:[eax+B8],ebx //修改CONTEXT.EIP,改变程序执行线路,这大概就是利用seh的常用手法!
//没改时,是401018即发生异常的指令地址,经过1轮处理又会到这里执行
//又产生异常
00401064 |. 33DB xor ebx,ebx
00401066 |. 8958 04 mov dword ptr ds:[eax+4],ebx //DR0 清零,使断点失效,这大概也是利用seh的常用手法,实现反跟踪!
00401069 |. 8958 08 mov dword ptr ds:[eax+8],ebx //DR1
0040106C |. 8958 0C mov dword ptr ds:[eax+C],ebx //DR2
0040106F |. 8958 10 mov dword ptr ds:[eax+10],ebx//DR3
00401072 |. C740 18 55010>mov dword ptr ds:[eax+18],155 //DR7
00401079 |. B8 00000000 mov eax,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 pop ebx
0040107F |. C9 leave
00401080 \. C2 1000 retn 10
[总结]
//看学强调: 在此回调函数上设断点,可以轻易地对付一些加壳的反跟踪代码!!!!!
//看学强调: 要提前在err结构的handler地址上设断点,否则代码就可能跑飞跟踪seh的关键断点!!!!
//看学提示: 可修改CONTEXT结构成员,来实现反跟踪及改变程序流程(设置暗桩吗?)
**************************************************************************************************************
[附录] 跟踪到异常处理回调函数的过程:
注: windows xp-sp1平台.只要是同样平台,就可以按下面步骤,来到系统的异常处理回调函数.
熟悉一下这段代码,应该有好处,当发生异常时,可以快速找到那个call ecx异常处理回调函数,从而找到程序自己的异常处理代码。
00401000 >/$ 68 51104000 push seh2.00401051 // SE handler installation
//只有在这个401051上设断点,才能跟到异常处理代码(SEH代码)处.
//即要提前在err结构的handler地址上设断点,否则代码就可能跑飞!
//跟踪seh的关键断点!!!!
00401005 |. 64:FF35 00000>push dword ptr fs:[0]
0040100C |. 64:8925 00000>mov dword ptr fs:[0],esp
00401013 |. BE 00000000 mov esi,0
00401018 |. 8B06 mov eax,dword ptr ds:[esi] //产生异常,来到 代码[1]
0040101A |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
0040101C |. 68 00304000 push seh2.00403000 ; |Title = "SEH"
00401021 |. 68 0F304000 push seh2.0040300F ; |Text = "SEH程序没有运行"
00401026 |. 6A 00 push 0 ; |hOwner = NULL
00401028 |. E8 57000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
0040102D |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
0040102F |. 68 00304000 push seh2.00403000 ; |Title = "SEH"
00401034 |. 68 04304000 push seh2.00403004 ; |Text = "Hello,SEH!"
00401039 |. 6A 00 push 0 ; |hOwner = NULL
0040103B |. E8 44000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401040 |. 64:8F05 00000>pop dword ptr fs:[0]
00401047 |. 83C4 04 add esp,4
0040104A |. 6A 00 push 0 ; /ExitCode = 0
0040104C \. E8 39000000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
00401051 /$ 55 push ebp ; Structured exception handler
00401052 |. 8BEC mov ebp,esp
00401054 |. 53 push ebx
00401055 |. 8B45 10 mov eax,dword ptr ss:[ebp+10]
00401058 |. 8D1D 2D104000 lea ebx,dword ptr ds:[40102D]
0040105E 8998 B8000000 mov dword ptr ds:[eax+B8],ebx
00401064 |. 33DB xor ebx,ebx
00401066 |. 8958 04 mov dword ptr ds:[eax+4],ebx
00401069 |. 8958 08 mov dword ptr ds:[eax+8],ebx
0040106C |. 8958 0C mov dword ptr ds:[eax+C],ebx
0040106F |. 8958 10 mov dword ptr ds:[eax+10],ebx
00401072 |. C740 18 55010>mov dword ptr ds:[eax+18],155
00401079 |. B8 00000000 mov eax,0
0040107E |. 5B pop ebx
0040107F |. C9 leave
00401080 \. C2 1000 retn 10
代码[1]
77FB4DB3 8B1C24 mov ebx,dword ptr ss:[esp]
77FB4DB6 51 push ecx
77FB4DB7 53 push ebx
77FB4DB8 E8 ACBDFAFF call ntdll.77F60B69 //F7 进入,来到代码 [2]
77FB4DBD 0AC0 or al,al
77FB4DBF 74 0C je short ntdll.77FB4DCD
77FB4DC1 5B pop ebx
77FB4DC2 59 pop ecx
77FB4DC3 6A 00 push 0
77FB4DC5 51 push ecx
77FB4DC6 E8 480BFCFF call ntdll.ZwContinue //代码[5],F7进入,回到代码[6]
77FB4DCB EB 0B jmp short ntdll.77FB4DD8
77FB4DCD 5B pop ebx
77FB4DCE 59 pop ecx
77FB4DCF 6A 00 push 0
77FB4DD1 51 push ecx
77FB4DD2 53 push ebx
77FB4DD3 E8 F213FCFF call ntdll.ZwRaiseException
77FB4DD8 83C4 EC add esp,-14
77FB4DDB 890424 mov dword ptr ss:[esp],eax
77FB4DDE C74424 04 01000>mov dword ptr ss:[esp+4],1
77FB4DE6 895C24 08 mov dword ptr ss:[esp+8],ebx
77FB4DEA C74424 10 00000>mov dword ptr ss:[esp+10],0
77FB4DF2 54 push esp
77FB4DF3 E8 AFC2F9FF call ntdll.RtlRaiseException
77FB4DF8 C2 0800 retn 8
77FB4DFB >^ E9 7DBCFAFF jmp ntdll.77F60A7D
代码 [2]
77F60B69 55 push ebp
77F60B6A 8BEC mov ebp,esp
77F60B6C 83EC 60 sub esp,60
77F60B6F 56 push esi
77F60B70 FF75 0C push dword ptr ss:[ebp+C]
77F60B73 8B75 08 mov esi,dword ptr ss:[ebp+8]
77F60B76 56 push esi
77F60B77 E8 AA000000 call ntdll.77F60C26
77F60B7C 84C0 test al,al
77F60B7E 0F85 EB6F0200 jnz ntdll.77F87B6F
77F60B84 53 push ebx
77F60B85 57 push edi
77F60B86 8D45 F8 lea eax,dword ptr ss:[ebp-8]
77F60B89 50 push eax
77F60B8A 8D45 FC lea eax,dword ptr ss:[ebp-4]
77F60B8D 50 push eax
77F60B8E E8 3C910100 call ntdll.77F79CCF
77F60B93 E8 52910100 call ntdll.77F79CEA
77F60B98 8365 08 00 and dword ptr ss:[ebp+8],0
77F60B9C 8BD8 mov ebx,eax
77F60B9E 83FB FF cmp ebx,-1
77F60BA1 0F84 4A1C0100 je ntdll.77F727F1
77F60BA7 3B5D FC cmp ebx,dword ptr ss:[ebp-4]
77F60BAA 0F82 481C0100 jb ntdll.77F727F8
77F60BB0 8D43 08 lea eax,dword ptr ds:[ebx+8]
77F60BB3 3B45 F8 cmp eax,dword ptr ss:[ebp-8]
77F60BB6 0F87 3C1C0100 ja ntdll.77F727F8
77F60BBC F6C3 03 test bl,3
77F60BBF 0F85 331C0100 jnz ntdll.77F727F8
77F60BC5 8B43 04 mov eax,dword ptr ds:[ebx+4]
77F60BC8 3B45 FC cmp eax,dword ptr ss:[ebp-4]
77F60BCB 72 09 jb short ntdll.77F60BD6
77F60BCD 3B45 F8 cmp eax,dword ptr ss:[ebp-8]
77F60BD0 0F82 221C0100 jb ntdll.77F727F8
77F60BD6 F605 4A32FC77 8>test byte ptr ds:[77FC324A],80
77F60BDD 0F85 936F0200 jnz ntdll.77F87B76
77F60BE3 FF73 04 push dword ptr ds:[ebx+4]
77F60BE6 8D45 F0 lea eax,dword ptr ss:[ebp-10]
77F60BE9 50 push eax
77F60BEA FF75 0C push dword ptr ss:[ebp+C]
77F60BED 53 push ebx
77F60BEE 56 push esi
77F60BEF E8 528F0100 call ntdll.77F79B46 // F4下,F7进入,来到代码[3]
77F60BF4 F605 4A32FC77 8>test byte ptr ds:[77FC324A],80
77F60BFB 8BF8 mov edi,eax
77F60BFD 0F85 896F0200 jnz ntdll.77F87B8C
77F60C03 395D 08 cmp dword ptr ss:[ebp+8],ebx
77F60C06 0F84 8E6F0200 je ntdll.77F87B9A
77F60C0C 8BC7 mov eax,edi
77F60C0E 33C9 xor ecx,ecx
77F60C10 2BC1 sub eax,ecx
77F60C12 0F84 3E340100 je ntdll.77F74056
77F60C18 48 dec eax
77F60C19 0F85 886F0200 jnz ntdll.77F87BA7
77F60C1F 8B1B mov ebx,dword ptr ds:[ebx]
77F60C21 ^ E9 78FFFFFF jmp ntdll.77F60B9E
77F60C26 55 push ebp
77F60C27 8BEC mov ebp,esp
77F60C29 51 push ecx
77F60C2A 51 push ecx
77F60C2B 57 push edi
77F60C2C BF 1032FC77 mov edi,ntdll.77FC3210
77F60C31 393D 1032FC77 cmp dword ptr ds:[77FC3210],edi
77F60C37 0F85 48E80100 jnz ntdll.77F7F485
77F60C3D 32C0 xor al,al
77F60C3F 5F pop edi
77F60C40 C9 leave
77F60C41 C2 0800 retn 8
77F60C44 > 55 push ebp
代码[3]
77F79B46 BA B89BF777 mov edx,ntdll.77F79BB8
77F79B4B EB 07 jmp short ntdll.77F79B54
77F79B4D BA DF9BF777 mov edx,ntdll.77F79BDF
77F79B52 8D09 lea ecx,dword ptr ds:[ecx]
77F79B54 53 push ebx
77F79B55 56 push esi
77F79B56 57 push edi
77F79B57 33C0 xor eax,eax
77F79B59 33DB xor ebx,ebx
77F79B5B 33F6 xor esi,esi
77F79B5D 33FF xor edi,edi
77F79B5F FF7424 20 push dword ptr ss:[esp+20]
77F79B63 FF7424 20 push dword ptr ss:[esp+20]
77F79B67 FF7424 20 push dword ptr ss:[esp+20]
77F79B6B FF7424 20 push dword ptr ss:[esp+20]
77F79B6F FF7424 20 push dword ptr ss:[esp+20]
77F79B73 E8 06000000 call ntdll.77F79B7E //// F4下,F7进入,来到代码[4]
77F79B78 5F pop edi
77F79B79 5E pop esi
77F79B7A 5B pop ebx
77F79B7B C2 1400 retn 14
代码[4]
77F79B7E 55 push ebp
77F79B7F 8BEC mov ebp,esp
77F79B81 FF75 0C push dword ptr ss:[ebp+C]
77F79B84 52 push edx
77F79B85 64:FF35 0000000>push dword ptr fs:[0]
77F79B8C 64:8925 0000000>mov dword ptr fs:[0],esp
77F79B93 FF75 14 push dword ptr ss:[ebp+14]
77F79B96 FF75 10 push dword ptr ss:[ebp+10]
77F79B99 FF75 0C push dword ptr ss:[ebp+C]
77F79B9C FF75 08 push dword ptr ss:[ebp+8]
77F79B9F 8B4D 18 mov ecx,dword ptr ss:[ebp+18]
77F79BA2 FFD1 call ecx //这就是异常处理回调函数!
77F79BA4 64:8B25 0000000>mov esp,dword ptr fs:[0]
77F79BAB 64:8F05 0000000>pop dword ptr fs:[0]
77F79BB2 8BE5 mov esp,ebp
77F79BB4 5D pop ebp
77F79BB5 C2 1400 retn 14 //返回后继续跟,回到代码[5]处
代码[6]
77F75913 > B8 20000000 mov eax,20
77F75918 BA 0003FE7F mov edx,7FFE0300
77F7591D FFD2 call edx //f7,到代码[8]
77F7591F C2 0800 retn 8
代码[8]
7FFE0300 8BD4 mov edx,esp
7FFE0302 0F34 sysenter
7FFE0304 C3 retn //返回到 代码[9]
代码[9]
0040102F |. 68 00304000 push seh2.00403000 ; |Title = "SEH"
00401034 |. 68 04304000 push seh2.00403004 ; |Text = "Hello,SEH!"
00401039 |. 6A 00 push 0 ; |hOwner = NULL
0040103B |. E8 44000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401040 |. 64:8F05 00000>pop dword ptr fs:[0]
00401047 |. 83C4 04 add esp,4
0040104A |. 6A 00 push 0 ; /ExitCode = 0
0040104C \. E8 39000000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess //f7,进入,到代码[10]
代码[10]-----这段代码,任何程序只要执行了exitprocess都会看到!留个印象吧!
77E598FD > 55 push ebp
77E598FE 8BEC mov ebp,esp
77E59900 6A FF push -1
77E59902 68 B0F3E877 push kernel32.77E8F3B0
77E59907 FF75 08 push dword ptr ss:[ebp+8]
77E5990A E8 86FFFFFF call kernel32.77E59895 // 结束了应用程序的生命!
77E5990F ^ E9 A47DFEFF jmp kernel32.TerminateProcess
77E59914 - FF25 F413E477 jmp dword ptr ds:[<&ntdll.LdrShutdownProcess>] ; ntdll.LdrShutdownProcess
77E5991A 391D A470EB77 cmp dword ptr ds:[77EB70A4],ebx
77E59920 0F84 99150000 je kernel32.77E5AEBF
77E59926 53 push ebx
77E59927 53 push ebx
77E59928 53 push ebx
77E59929 E8 D2F4FEFF call kernel32.WriteProfileStringW
77E5992E E9 8C150000 jmp kernel32.77E5AEBF
77E59933 > 837C24 04 00 cmp dword ptr ss:[esp+4],0
77E59938 0F84 C4730200 je kernel32.77E80D02
77E5993E FF7424 08 push dword ptr ss:[esp+8]
77E59942 FF7424 08 push dword ptr ss:[esp+8]
77E59946 FF15 6814E477 call dword ptr ds:[<&ntdll.NtTerminateThread>] ; ntdll.ZwTerminateThread
77E5994C 85C0 test eax,eax
77E5994E 0F8C B7730200 jl kernel32.77E80D0B
77E59954 33C0 xor eax,eax
77E59956 40 inc eax
77E59957 C2 0800 retn 8
**************************************************************************************************************附件:SEH.rar
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)