Procedure TForm1.Button1Click( Sender: TObject ); Var a: TForm1; Begin a := Nil; Try a.Show; Except ShowMessage( '1111' ); End; End;
Unit1.pas.38: a := Nil; 00452702 33C0 xor eax,eax Unit1.pas.39: Try 00452704 33D2 xor edx,edx 00452706 55 push ebp 00452707 6821274500 push $00452721 0045270C 64FF32 push dword ptr fs:[edx] 0045270F 648922 mov fs:[edx],esp Unit1.pas.40: a.Show; 00452712 E811B3FFFF call TCustomForm.Show 00452717 33C0 xor eax,eax 00452719 5A pop edx 0045271A 59 pop ecx 0045271B 59 pop ecx 0045271C 648910 mov fs:[eax],edx 0045271F EB14 jmp +$14 00452721 E91E12FBFF jmp @HandleAnyException Unit1.pas.42: ShowMessage( '1111' ); 00452726 B844274500 mov eax,$00452744 0045272B E85C8DFDFF call ShowMessage 00452730 E87715FBFF call @DoneExcept Unit1.pas.44: End;
Procedure SetExceptionProc( Proc: Pointer ); Asm //将回调函数指针压入堆栈 push eax //保护 原来的处理函数 push fs:[0] mov fs:[0],esp End; 你看和Delphi代码里面Try反编译出来的一样吧. Function ExceptionProc( pExcept: PExceptionRecord;pError: Pointer;pContxt: PContext;pDispatch: Pointer ): Integer; Stdcall; Begin ShowMessage( '1111' ); Result:=0; End; 注意是stdcall调用方式,貌似有些资料上面是cdecl.这里我们先不管这么多了. Procedure TestException( ); Begin //try SetExceptionProc( @ExceptionProc ); //make a exception Asm xor edx,edx mov [edx],0 End; //恢复异常 Asm pop eax mov fs:[0],eax add esp,8 End; End; Procedure TForm1.Button2Click( Sender: TObject ); Begin TestException; End;
Program Project2; {$APPTYPE CONSOLE} Uses SysUtils, Windows; Type PExecption_Handler= ^Exception_Handler; PException_Registration= ^Exception_Registration; _ExceptionHandler= Record ExceptionRecord: PExceptionRecord; SEH: PException_Registration; Context: PContext; DispatcherContext: Pointer; End; Exception_Handler= _ExceptionHandler; _ExceptionRegistration= Record Prev: PException_Registration; Handler: PExecption_Handler; End; Exception_Registration= _ExceptionRegistration; Const EXCEPTION_CONTINUE_EXECUTION= 0; ///恢复CONTEXT里的寄存器环境,继续执行 EXCEPTION_CONTINUE_SEARCH= 1; ///拒绝处理这个异常,请调用下个异常处理函数 EXCEPTION_NESTED_EXCEPTION= 2; ///函数中出发了新的异常 EXCEPTION_COLLIDED_UNWIND= 3; ///发生了嵌套展开操作 EH_NONE= 0; EH_NONCONTINUABLE= 1; EH_UNWINDING= 2; EH_EXIT_UNWIND= 4; EH_STACK_INVALID= 8; EH_NESTED_CALL= 16; STATUS_ACCESS_VIOLATION= $C0000005; ///访问非法地址 STATUS_ARRAY_BOUNDS_EXCEEDED= $C000008C; STATUS_FLOAT_DENORMAL_OPERAND= $C000008D; STATUS_FLOAT_DIVIDE_BY_ZERO= $C000008E; STATUS_FLOAT_INEXACT_RESULT= $C000008F; STATUS_FLOAT_INVALID_OPERATION= $C0000090; STATUS_FLOAT_OVERFLOW= $C0000091; STATUS_FLOAT_STACK_CHECK= $C0000092; STATUS_FLOAT_UNDERFLOW= $C0000093; STATUS_INTEGER_DIVIDE_BY_ZERO= $C0000094; ///除0错误 STATUS_INTEGER_OVERFLOW= $C0000095; STATUS_PRIVILEGED_INSTRUCTION= $C0000096; STATUS_STACK_OVERFLOW= $C00000FD; STATUS_CONTROL_C_EXIT= $C000013A; Var G_TEST: DWORD; Procedure Log( LogMsg: String ); Begin Writeln( LogMsg ); End; //看这个回调函数,和我们那个有点儿区别,第二个参数的作用原来是ExceptionRegistration,原来秘密在它身上 Function ExceptionHandler( ExceptionHandler: EXCEPTION_HANDLER ): LongInt; Cdecl; Begin Result := EXCEPTION_CONTINUE_SEARCH; If ExceptionHandler.ExceptionRecord.ExceptionFlags= EH_NONE Then Begin Case ExceptionHandler.ExceptionRecord.ExceptionCode Of STATUS_ACCESS_VIOLATION: Begin Log( '发现异常为非法内存访问,尝试修复EBX,继续执行' ); ExceptionHandler.Context.Ebx := DWORD( @G_TEST ); Result := EXCEPTION_CONTINUE_EXECUTION; End; Else Log( '这个异常我无法处理,请让别人处理吧' ); End; End Else If ExceptionHandler.ExceptionRecord.ExceptionFlags= EH_UNWINDING Then Log( '异常展开操作' ); End; Begin Asm ///设置SEH XOR EAX, EAX PUSH OFFSET ExceptionHandler PUSH FS:[EAX] MOV FS:[EAX], ESP ///产生内存访问错误 XOR EBX, EBX MOV [EBX], 0 ///取消SEH XOR EAX, EAX //这里用的这个 而不是我们用的那个pop eax呀..哈哈.一切正常了 MOV ECX, [ESP] MOV FS:[EAX], ECX ADD ESP, 8 End; Readln; End. 牛人拜读了.大家可以去CSDN上面看下. 好了我是DH.大家想了解更多可以看看雪的加密解密 以及 那个 什么软件漏洞分析 书上面都有SEH的章节. |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论