调试与异常--手工注册SEH

SEH (Structed Exception Handler,结构化异常处理)

手工注册SEH的前提是知道SEH异常处理函数的原型。

配置好双机调试环境,在WINDBG中输入 dt _TEB -b ,就可以查看TEB(Thread Environment Block 线程环境块)结构。

kd> dt _TEB -b
ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
      +0x000 ExceptionList    : Ptr32 
      +0x004 StackBase        : Ptr32 
      +0x008 StackLimit       : Ptr32 
      +0x00c SubSystemTib     : Ptr32 
      +0x010 FiberData        : Ptr32 
      +0x010 Version          : Uint4B
      +0x014 ArbitraryUserPointer : Ptr32 
      +0x018 Self             : Ptr32 
   +0x01c EnvironmentPointer : Ptr32 
   +0x020 ClientId         : _CLIENT_ID
      +0x000 UniqueProcess    : Ptr32 
      +0x004 UniqueThread     : Ptr32 
   +0x028 ActiveRpcHandle  : Ptr32 
   +0x02c ThreadLocalStoragePointer : Ptr32 
   +0x030 ProcessEnvironmentBlock : Ptr32 
   +0x034 LastErrorValue   : Uint4B

上面是TEB结构的一部分,这里主要介绍_NT_TIB这个结构体,因为需要从这里去寻找异常处理函数的原型。这个结构体的偏移量为0,可以通过FS寄存器来定位,系统通过FS:[0]找到这个结构体,也就是偏移量为0的成员,在TEB结构中表示ExceptionList这个字段,这是一个链表。当产生异常时,系统会依次调用其中的成员去处理异常。

现在在VS中查看_NT_TIB结构体中的成员,F12:

typedef struct _NT_TIB {
    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;    //继续从这里跟进去
    PVOID StackBase;
    PVOID StackLimit;
    PVOID SubSystemTib;
#if defined(_MSC_EXTENSIONS)
    union {
        PVOID FiberData;
        DWORD Version;
    };
#else
    PVOID FiberData;
#endif
    PVOID ArbitraryUserPointer;
    struct _NT_TIB *Self;
} NT_TIB;

处理异常的时候主要用到的是 _EXCEPTION_REGISTRATION_RECORD这个结构体,继续F12跟进去:

typedef struct _EXCEPTION_REGISTRATION_RECORD {
    struct _EXCEPTION_REGISTRATION_RECORD *Next;    //指向下一个SEH 的指针
    PEXCEPTION_ROUTINE Handler;                     //异常处理函数
} EXCEPTION_REGISTRATION_RECORD;

这里就能比较清楚的看到这是个链表结构了,再继续跟着PEXCEPTION_ROUTINE这个结构体进去,就可以得到SEH异常处理函数的原型了:

NTAPI EXCEPTION_ROUTINE (
    _Inout_ struct _EXCEPTION_RECORD *ExceptionRecord,
    _In_ PVOID EstablisherFrame,
    _Inout_ struct _CONTEXT *ContextRecord,
    _In_ PVOID DispatcherContext
    );

在自己写处理函数的时候,函数名是可以自己取的,只要符合命名规范都可以,但是参数的要保持一致,函数还需要一个返回值类型,在函数体中可以自己实现需要的功能。

使用示例:

//假定返回值为LONG
LONG NTAPI ExceptionHandler(
	_Inout_ struct _EXCEPTION_RECORD * ExceptionRecord,
	_In_ PVOID EstablishFrame,
	_Inout_ struct _CONTEXT * ContextRecord,
	_In_ PVOID DispatchContext)
{
	//自己实现函数体
	return 0;
}

 

搜索关注公众号[逆向小生],不定期更新逆向工程师需要掌握的技能,包括Windows和Android方面的逆向,还有作为一个逆向工程师的思维模式。

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值