C++&系统 异常
来源:互联网 发布:嵌入式 linux 忘记密码 编辑:程序博客网 时间:2024/04/30 09:50
User Mode
C++ Demo(Debug)
int wmain( int argc, WCHAR * argv[]){00DF13C0 push ebp00DF13C1 mov ebp,esp00DF13C3 push 0FFFFFFFEh00DF13C5 push 0DF6EB8h00DF13CA push 0DF107Dh00DF13CF mov eax,dword ptr fs:[00000000h]00DF13D5 push eax00DF13D6 add esp,0FFFFFF38h :分配局部变量。Q:没有局部变量,只需esp-8,分配EXCEPTION_REGISTRATION_RECORD剩余的8字节,但为什么这里还有这么大空间?求解答00DF13DC push ebx00DF13DD push esi00DF13DE push edi00DF13DF lea edi,[ebp-0D8h]00DF13E5 mov ecx,30h00DF13EA mov eax,0CCCCCCCCh00DF13EF rep stos dword ptr es:[edi] :对栈上的(局部变量)进行0xcccccccc赋值。每个局部变量的两端都会被增加0xcccccccc,也就是说一个DWORD实际会占用3个DWORD。使用0xcccccccc的原因:1.数值较大,且为负,容易被察觉 2.int 3的机器码为0xcc,可以探测到栈被执行00DF13F1 mov eax,dword ptr ds:[00DF8000h]00DF13F6 xor dword ptr [ebp-8],eax00DF13F9 xor eax,ebp00DF13FB push eax :计算cookie00DF13FC lea eax,[ebp-10h]00DF13FF mov dword ptr fs:[00000000h],eax00DF1405 mov dword ptr [ebp-18h],esp :存入esp __try{ :至此,异常帧构建完毕,并且插入了fs:[0],开始生效00DF1408 mov dword ptr [ebp-4],0 getchar();00DF140F mov esi,esp00DF1411 call dword ptr ds:[0DF92B8h]00DF1417 cmp esi,esp00DF1419 call __RTC_CheckEsp (0DF1145h) }__except(EXCEPTION_EXECUTE_HANDLER){00DF141E mov dword ptr [ebp-4],0FFFFFFFEh00DF1425 jmp $LN6+0Ah (0DF1437h)$LN10:00DF1427 mov eax,1$LN9:00DF142C ret$LN6:00DF142D mov esp,dword ptr [ebp-18h] GetExceptionCode(); }00DF1430 mov dword ptr [ebp-4],0FFFFFFFEh return 0;00DF1437 xor eax,eax}00DF1439 mov ecx,dword ptr [ebp-10h]00DF143C mov dword ptr fs:[0],ecx :撤销之前插入的异常链节点00DF1443 pop ecx :拿到cookie00DF1444 pop edi00DF1445 pop esi00DF1446 pop ebx}00DF1447 add esp,0D8h00DF144D cmp ebp,esp00DF144F call __RTC_CheckEsp (0DF1145h)00DF1454 mov esp,ebp00DF1456 pop ebp00DF1457 ret
堆栈图:
ntdll!__RtlUserThreadStart
.text:778337CE ; __stdcall __RtlUserThreadStart(x, x).text:778337CE ___RtlUserThreadStart@8 proc near ; CODE XREF: _RtlUserThreadStart(x,x)+16p.text:778337CE.text:778337CE ExitStatus = dword ptr -24h.text:778337CE var_20 = dword ptr -20h.text:778337CE var_1C = dword ptr -1Ch.text:778337CE ms_exc = CPPEH_RECORD ptr -18h.text:778337CE arg_0 = dword ptr 8.text:778337CE arg_4 = dword ptr 0Ch.text:778337CE.text:778337CE ; FUNCTION CHUNK AT .text:777D5E77 SIZE 00000009 BYTES.text:778337CE ; FUNCTION CHUNK AT .text:77847EEB SIZE 00000030 BYTES.text:778337CE ; FUNCTION CHUNK AT .text:77848260 SIZE 0000001E BYTES.text:778337CE.text:778337CE 000 push 14h.text:778337D0 004 push offset off_77821278.text:778337D5 008 call __SEH_prolog4.text:778337DA 038 and [ebp+ms_exc.registration.TryLevel], 0 ... ...---------------------------------------------------------------------------------------------------.text:77822C0C __SEH_prolog4 proc near ; CODE XREF: LdrFlushAlternateResourceModules()+7p.text:77822C0C ; RtlpCopyMappedMemoryEx(x,x,x,x,x,x)+7p ....text:77822C0C.text:77822C0C arg_4 = dword ptr 8.text:77822C0C.text:77822C0C 000 push offset __except_handler4.text:77822C11 004 push large dword ptr fs:0.text:77822C18 008 mov eax, [esp+8+arg_4].text:77822C1C 008 mov [esp+8+arg_4], ebp.text:77822C20 008 lea ebp, [esp+8+arg_4].text:77822C24 008 sub esp, eax.text:77822C26 008 push ebx.text:77822C27 00C push esi.text:77822C28 010 push edi.text:77822C29 014 mov eax, ___security_cookie.text:77822C2E 014 xor [ebp-4], eax.text:77822C31 014 xor eax, ebp.text:77822C33 014 push eax.text:77822C34 018 mov [ebp-18h], esp.text:77822C37 018 push dword ptr [ebp-8] :这块和上面的例子不一样,因为要把__SEH_prolog4函数下一条指令的地址重新压栈,为了后面的retn能正常返回.text:77822C3A 01C mov eax, [ebp-4].text:77822C3D 01C mov dword ptr [ebp-4], 0FFFFFFFEh.text:77822C44 01C mov [ebp-8], eax.text:77822C47 01C lea eax, [ebp-10h].text:77822C4A 01C mov large fs:0, eax.text:77822C50 01C retn.text:77822C50 __SEH_prolog4 endp
- 只要发生异常第一就是进入内核,然后构造EXCEPTION_RECORD和CONTEXT,并且进行处理逻辑,然后返回UserMode,在某个时机调用异常链上的Handler。
mouseOS《SEH stack 结构探索(1)— 从 SEH 链的最底层(线程第1个SEH结构)说起》:
http://www.mouseos.com/windows/SEH3.html
Kernel Mode
Tarp00(divide error)
- 发生异常之后,陷入内核,执行Trap00函数
ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING ENTER_DR_ASSIST kit0_a, kit0_t,NoAbiosAssistalign dword public _KiTrap00_KiTrap00 proc push 0 ; push dummy error code ENTER_TRAP kit0_a, kit0_t :构建TrapFrame.errnz (EFLAGS_V86_MASK AND 0FF00FFFFh) test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h jnz Kt0040 ; trap occured in V86 mode :如果是虚拟86模式 test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is previous mode = USER jz short Kt0000 :如果是用户模式 cmp word ptr [ebp]+TsSegCs,KGDT_R3_CODE OR RPL_MASK jne Kt0020 :如果是vdm;; Set up exception record for raising Integer_Divided_by_zero exception; and call _KiDispatchException;Kt0000:if DBG test [ebp]+TsEFlags, EFLAGS_INTERRUPT_MASK ; faulted with jnz short @f ; interrupts disabled? xor eax, eax mov esi, [ebp]+TsEip ; [esi] = faulting instruction stdCall _KeBugCheck2,<IRQL_NOT_LESS_OR_EQUAL,eax,-1,eax,esi,ebp>@@:endif sti;; Flat mode;; The intel processor raises a divide by zero exception on DIV instructions; which overflow. To be compatible with other processors we want to; return overflows as such and not as divide by zero's. The operand; on the div instruction is tested to see if it's zero or not.; stdCall _Ki386CheckDivideByZeroTrap,<ebp> mov ebx, [ebp]+TsEip ; (ebx)-> faulting instruction jmp CommonDispatchException0Args ; Won't return :跳到异常处理过程Kt0010:;; 16:16 mode; sti mov ebx, [ebp]+TsEip ; (ebx)-> faulting instruction mov eax, STATUS_INTEGER_DIVIDE_BY_ZERO jmp CommonDispatchException0Args ; never returnKt0020:; Check to see if this process is a vdm mov ebx,PCR[PcPrcbData+PbCurrentThread] mov ebx,[ebx]+ThApcState+AsProcess cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process? je Kt0010Kt0040: stdCall _Ki386VdmReflectException_A, <0> or al,al jz short Kt0010 ; couldn't reflect, gen exception jmp _KiExceptionExit_KiTrap00 endp
- 准备数据结构,然后真正的去处理异常
CommonDispatchException0Args: xor ecx, ecx ; zero arguments call CommonDispatchExceptionCommonDispatchException1Arg0d: xor edx, edx ; zero edxCommonDispatchException1Arg: mov ecx, 1 ; one argument call CommonDispatchException ; there is no returnCommonDispatchException2Args0d: xor edx, edx ; zero edxCommonDispatchException2Args: mov ecx, 2 ; two arguments call CommonDispatchException ; there is no return------------------------------------------------------------------------------------------------- public CommonDispatchExceptionalign dwordCommonDispatchException proccPublicFpo 0, ExceptionRecordLength/4;; Set up exception record for raising exception; sub esp, ExceptionRecordLength ; allocate exception record mov dword ptr [esp]+ErExceptionCode, eax ; set up exception code xor eax, eax mov dword ptr [esp]+ErExceptionFlags, eax ; set exception flags mov dword ptr [esp]+ErExceptionRecord, eax ; set associated exception record mov dword ptr [esp]+ErExceptionAddress, ebx mov dword ptr [esp]+ErNumberParameters, ecx ; set number of parameters cmp ecx, 0 je short de00 lea ebx, [esp + ErExceptionInformation] mov [ebx], edx mov [ebx+4], esi mov [ebx+8], edi :整个这一段都是在栈上准备EXCEPTION_RECORDde00:;; set up arguments and call _KiDispatchException; mov ecx, esp ; (ecx)->exception record.errnz (EFLAGS_V86_MASK AND 0FF00FFFFh) test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h jz short de10 mov eax,0FFFFh jmp short de20de10: mov eax,[ebp]+TsSegCsde20: and eax,MODE_MASK; 1 - first chance TRUE; eax - PreviousMode; ebp - trap frame addr; 0 - Null exception frame; ecx - exception record addr stdCall _KiDispatchException,<ecx, 0, ebp, eax, 1> :正儿八经去处理异常了 mov esp, ebp ; (esp) -> trap frame jmp _KiExceptionExitCommonDispatchException endp
- 调用KiDispatchException
VOIDKiDispatchException ( IN PEXCEPTION_RECORD ExceptionRecord, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN FirstChance );
- 注意最后一个参数,FirstChance,我们陷入内核是第一次。如果是UserMode Exception,主要是构建CONTEXT结构,并且返到ntdll!KiUserExceptionDispatcher,给用户态机会,来调用异常链,如果异常链没有处理OK,则会在ntdll!KiUserExceptionDispatcher中调用ZwRaiseException,进行第二次机会的处理
阅读全文
0 0
- C++&系统 异常
- C#.Net开发基于Oracle数据库系统常见异常处理
- 系统异常关机后,Eclipse启动报错c
- More Effective C++----(15)了解异常处理的系统开销
- 系统异常
- C异常
- 【c++】异常
- 【C/C++】异常机制
- 【swing】在做c/s的图书管理系统时遇到的异常及解决办法
- C语言的setjmp:异常处理与构建协作式多任务系统
- C语言的setjmp:异常处理与构建协作式多任务系统
- 设计异常管理系统
- 设计异常管理系统
- Windows系统异常处理
- 设计异常管理系统
- Oracle 系统异常名称
- 防火墙造成系统异常
- 【中断异常】系统调用
- set in Python
- mysql动态扩容调研
- python中的装包与拆包
- 自己定义CNN网络模型并使用caffe训练
- 设计模式之pimpl惯用法C语言版(城门失火 殃及池鱼)
- C++&系统 异常
- c++ 宏
- Cpp.Study.Note.初识 Cpp中的类
- MyEclipse导入 Java Web工程
- 基于JQ 根据输入内容自适应输入框高度 支持输入增高 渲染时设置高度和内容一致
- 网络安全知识之对称加密与base64
- hadoop2.x概览
- Spring整合Ehcache管理缓存
- 突出重点马原!2018考研政治暑期复习完整计划