技术交流,DH讲解.

前几天一个朋友在弄游戏外挂想带NP调试,就像自己来捕获游戏的异常.
好像就要用到SEH这方面的知识.
一起研究了一下,这里看下研究 和 在网上找的资料吧.
SEH就是Structure Exception Handling.结构化异常处理,具体可以看下MSDN.
MSDN在手,走遍天下无敌手.哈哈.
当时先自己看下Delphi 怎么实现try..except..end的吧.我们写段程序然后调试就知道了.

Procedure TForm1.Button1Click( Sender: TObject );
Vara: TForm1;
Begina := Nil;Trya.Show;ExceptShowMessage( '1111' );End;
End;

这样是会发生异常的吧,我们下断点,然后调试的时候ctrl + alt + c进入CPU窗口.

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;

我们看见了try模块的代码了吧.好的自己来写个函数.

Procedure SetExceptionProc( Proc: Pointer );
Asm//将回调函数指针压入堆栈push eax//保护 原来的处理函数push fs:[0]mov fs:[0],esp
End;

你看和Delphi代码里面Try反编译出来的一样吧.
至于为什么要这样写?我也不知道,所以我们现在需要去找资料了.
发生异常时系统的处理顺序(by Jeremy Gordon):
   1.系统首先判断异常是否应发送给目标程序的异常处理例程,如果决定应该发送,并且目标程序正在被调试,则系统
   挂起程序并向调试器发送EXCEPTION_DEBUG_EVENT消息.呵呵,这不是正好可以用来探测调试器的存在吗?
   2.如果你的程序没有被调试或者调试器未能处理异常,系统就会继续查找你是否安装了线程相关的异常处理例程,如果
   你安装了线程相关的异常处理例程,系统就把异常发送给你的程序seh处理例程,交由其处理.
   3.每个线程相关的异常处理例程可以处理或者不处理这个异常,如果他不处理并且安装了多个线程相关的异常处理例程,
可交由链起来的其他例程处理.
   4.如果这些例程均选择不处理异常,如果程序处于被调试状态,操作系统仍会再次挂起程序通知debugger.
   5.如果程序未处于被调试状态或者debugger没有能够处理,并且你调用SetUnhandledExceptionFilter安装了最后异
   常处理例程的话,系统转向对它的调用.
   6.如果你没有安装最后异常处理例程或者他没有处理这个异常,系统会调用默认的系统处理程序,通常显示一个对话框,
   你可以选择关闭或者最后将其附加到调试器上的调试按钮.如果没有调试器能被附加于其上或者调试器也处理不了,系统
   就调用ExitProcess终结程序.
   7.不过在终结之前,系统仍然对发生异常的线程异常处理句柄来一次展开,这是线程异常处理例程最后清理的机会.
事实上,当异常发生时,系统给了我们一个处理异常的机会,他首先会调用我们自定义的seh处理例程,当然也包括
了相关信息,在调用之前,系统把包含这些信息结构的指针压入stack,供我们的异常处理例程调用,
传递给例程的参数通常是四个,其中只有三个有明确意义,另一个到现在为止还没有发现有什么作用,
这些参数是:pExcept:DWORD,pErr:DWORD,pContext:DWORD,pDispatch意义如下:
pExcept: --- EXCEPTION_RECORD结构的指针
pErr: --- 前面ERR结构的指针
pContext: --- CONTEXT结构的指针 ,里面都是我们寄存器的值.
pDispatch:---没有发现有啥意义
Delphi里面已经定义好了这些结构体指针了,我就不多说了.
我们来把回调函数写出来吧.

Function ExceptionProc( pExcept: PExceptionRecord;pError: Pointer;pContxt: PContext;pDispatch: Pointer ): Integer; Stdcall;
BeginShowMessage( '1111' );Result:=0;
End;

注意是stdcall调用方式,貌似有些资料上面是cdecl.这里我们先不管这么多了.
现在我们看看系统是怎么调用我们回调函数的.
关键的 Win32 数据结构——线程信息块(即 TEB 和 TIB)。
该数据结构的某些域在 Windows NT、Windows 95、Win32s 和 OS/2 平台上是一样的。
TIB 中的第一个 DWORD 是指向线程 EXCEPTION_REGISTRATION 结构的指针。
在 Intel Win32 平台上,FS 寄存器总是指向当前的 TIB。
因此,在 FS:[0]位置,你能找到 EXCEPTION_REGISTRATION 结构的指针。
这里也就解释了 我们SetExceptionProc函数了.
好的我们自己写段代码来测试一下了:

Procedure TestException( );
Begin//trySetExceptionProc( @ExceptionProc );//make a exceptionAsmxor edx,edxmov [edx],0End;//恢复异常Asmpop eaxmov fs:[0],eaxadd esp,8End;
End;
Procedure TForm1.Button2Click( Sender: TObject );
BeginTestException;
End;

测试中恢复异常还是有问题.

终于在CSDN的书呆子的博客上面找到了答案.

Program Project2;
{$APPTYPE CONSOLE}
UsesSysUtils,Windows;
TypePExecption_Handler= ^Exception_Handler;PException_Registration= ^Exception_Registration;_ExceptionHandler= RecordExceptionRecord: PExceptionRecord;SEH: PException_Registration;Context: PContext;DispatcherContext: Pointer;End;Exception_Handler= _ExceptionHandler;_ExceptionRegistration= RecordPrev: PException_Registration;Handler: PExecption_Handler;End;Exception_Registration= _ExceptionRegistration;
ConstEXCEPTION_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;
VarG_TEST: DWORD;
Procedure Log( LogMsg: String );
BeginWriteln( LogMsg );
End;
//看这个回调函数,和我们那个有点儿区别,第二个参数的作用原来是ExceptionRegistration,原来秘密在它身上
Function ExceptionHandler( ExceptionHandler: EXCEPTION_HANDLER ): LongInt; Cdecl;
BeginResult := EXCEPTION_CONTINUE_SEARCH;If ExceptionHandler.ExceptionRecord.ExceptionFlags= EH_NONE ThenBeginCase ExceptionHandler.ExceptionRecord.ExceptionCode OfSTATUS_ACCESS_VIOLATION:BeginLog( '发现异常为非法内存访问,尝试修复EBX,继续执行' );ExceptionHandler.Context.Ebx := DWORD( @G_TEST );Result := EXCEPTION_CONTINUE_EXECUTION;End;ElseLog( '这个异常我无法处理,请让别人处理吧' );End;EndElseIf ExceptionHandler.ExceptionRecord.ExceptionFlags= EH_UNWINDING ThenLog( '异常展开操作' );End;BeginAsm///设置SEHXOR EAX, EAXPUSH OFFSET ExceptionHandlerPUSH FS:[EAX]MOV FS:[EAX], ESP///产生内存访问错误XOR EBX, EBXMOV [EBX], 0///取消SEHXOR EAX, EAX//这里用的这个 而不是我们用的那个pop eax呀..哈哈.一切正常了MOV ECX, [ESP]MOV FS:[EAX], ECXADD ESP, 8End;Readln;
End.

牛人拜读了.大家可以去CSDN上面看下.

好了我是DH.大家想了解更多可以看看雪的加密解密 以及 那个 什么软件漏洞分析 书上面都有SEH的章节.

Delphi - SEH研究相关推荐

  1. delphi VCL研究之消息分发机制(转)

    原文来源,http://blog.csdn.net/sushengmiyan/article/details/8635550 1.VCL 概貌 先看一下VCL类图的主要分支,如图4.1所示. 在图中可 ...

  2. 打造日活超260万链游,Axie Infinity 创始人 Trung Nguyen 是如何做到的?

    对于喜欢玩手机链游的玩家来将Axie Infinit这款游戏可以说是非常的熟悉的,今天小编和大家分享以下关于其创始人的一些相关的故事. Trung Nguyen 对 CryptoKitties 很感兴 ...

  3. 用Delphi开发OPC客户端工具的方法研究

    用Delphi开发OPC客户端工具的方法研究[1]<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:o ...

  4. SEH in ASM 研究(一)

    SEH  in ASM 研究(一)                                             By Hume/冷雨飘心 为什么老调重弹:     SEH出现已绝非一日,但 ...

  5. 关于Delphi XE2的FMX的一点点研究之消息篇

    Delphi XE2出来了一阵子了,里面比较抢眼的东西,除了VCLStyle这个换肤的东西之外,另外最让人眼亮的应该是FMX这个东西了.万一的博客上都连载了一票的关于FMX的使用心得了.我还是没咋去关 ...

  6. Delphi Open Tools Api实例研究(二)

    Delphi  Open  Tools  Api实例研究(二) 先行知识: Delphi /接口 / DLL / COM(了解) 来自: http://dev.csdn.net/develop/art ...

  7. Delphi Open Tools Api实例研究(一)

    Delphi Open Tools Api实例研究(一) 先行知识:Delphi/接口/VCL组件包/COM(了解) 来自:http://dev.csdn.net/develop/article/21 ...

  8. 《Delphi传奇》研究系列文章1:服务端控制中心(服务器网关启动器)

    提示:所有的研究心得直接写在源码注释中,对照源码看注释即可学习了解传奇的流程架构.<Delphi传奇>全部源码获取可加入Delphi开发局QQ群:32422310 <Delphi传奇 ...

  9. 万一的delphi博客写得太好了,真是有专门研究delphi的高手

    ====================================================== 注:本文源代码点此下载 ================================= ...

最新文章

  1. 《麻省理工科技评论》:2018年18大科技趋势,2017年7大失败技术
  2. python 并行计算 并行方法总结 concurrent.futures pp pathos multiprocessing multiprocess模块 总结对比
  3. 跟alex学python_跟着Alex学习python
  4. suList() 和 asList()
  5. NodeJs系列二:你好,世界
  6. 某些您可以编辑的区域交叠在一起 可能不能同时显示_DX200操作要领—修改与编辑程序(三十九)...
  7. RedmiK40系列首销5分钟破30万台 旗舰焊门员实至名归
  8. 董付国老师6本Python系列图书阅读指南
  9. PAC自动代理文件格式,教你如何写PAC文件
  10. Jersey学习笔记
  11. 慢性病管理系统/案列/APP/小程序/网站
  12. 博途v14电脑要求_Win10运行不了博途V14怎么办?
  13. canvas基础学习笔记
  14. C内存分配方式与C++内存分配方式
  15. 漫威系列电影、电视剧的推荐观看顺序是怎样的?
  16. 怎么知道当前计算机用户名和密码,怎么查看电脑当前所设置的密码
  17. 先进事迹计算机维护与维修,汽车维修工先进事迹
  18. 艾伟_转载:[一步一步MVC]第四回:漫谈ActionLink,有时“胡搅蛮缠”
  19. java兔子繁殖总数_Java 兔子繁殖迭代问题
  20. 大数据在高校的应用场景_大数据技术在高校教育中的应用

热门文章

  1. CORS 跨域-哪些操作受到同源限制
  2. 什么是认证、授权、会话
  3. SpringSecurity分布式整合之认证模块搭建
  4. Eureka-eureka原理分析
  5. 分布式ID-美团(Leaf)
  6. 为什么使用mq?具体的使用场景是什么?
  7. Spring如何将事件分配给专门的监听器?
  8. 一致性hash算法原理
  9. BaseExecutor.query()-从数据库查询
  10. 什么时候清理物理消息文件?