简介:
异常分为俩种,CPU产生的异常(除0,缺页)和软件模拟产生的异常
来自《加密与解密》
SEH:
SEH是Windows操作系统提供的异常处理机制,在程序源代码中使用_try、__except、_finally关键字来具体实现。
TEB/T:
typedef struct _NT_TIB {
struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; //异常的链表
PVOID StackBase;
PVOID StackLimit;
PVOID SubSystemTib;
union {
PVOID FiberData;
DWORD Version;
};
PVOID ArbitraryUserPointer;
struct _NT_TIB *Self;
} NT_TIB;
通过TEB结构体的NtTib成员可以很容易的访问进程的SEH链,TEB。
NtTib.ExceptionList=FS:[0]
SEH链:
SEH以链的形式存在。第一个异常处理中未处理相关异常,它就会被传递到下一个异常处理器,直到得到处理。SEH是由_EXCEPTION_REGISTRATION_RECORD结构体组成的链表
typedef struct_EXCEPTION_REGISTRATION RECORD
{
PEXCEPTION_REGISTRATION_RECORD Next;
PEXCEPTION_DISPOSITION Handler;
EXCEPTION_REGISTRATION_RECORD,*PEXCEPTION_REGISTRATION_RECORD;
}
Next成员指向下一个_EXCEPTION_REGISTRATION_RECORD结构体指针,handler成员是异常处理函数(异常处理器)。若Next成员的值为FFFFFFFF,则表示它是链表最后一个结点
发生异常的时候会按照(A)->(B)->(C)的顺序依次传递,直到由异常处理器处理
可以通过在堆栈看seh结构体,链接下一个seh 同时储存函数处理地址,seh不一定是try except,可能会事先注册。
异常处理函数:
EXCEPTION_DISPOSITION __cdecl _except_handler (
EXCEPTION_RECORD *pRecord,
EXCEPTION_REGISTRATION_RECORD *pFrame,
CONTEXT *pContext,
PVOID pValue
);
由系统调用,是一个回调函数,第一个参数是一个指向EXCEPTION_RECORD结构体的指针
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode; //异常代码
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD *ExceptionRecord;
PVOID ExceptionAddress; //异常发生地址
DWORD NumberParameters;
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD;
异常发生的时候,执行异常代码的线程就会发生中断,转而运行SEH,此时OS会把线程 CONTEXT结构体的指针传递给异常处理函数的相应参数。里面有个eip成员,在异常处理函数中将参数传递过来的CONTEXT.eip设置为其他地址,然后返回处理函数。这样之前暂停的线程会执行新的EIP地址处的代码(反调试中经常使用这个技术)
SEH安装/删除方法
汇编中安装使用
push @MyHandler ;异常处理程序
push FS:[0] ;SEH Linked List头
mov dword ptr fs:[0],esp ;添加链表
汇编中的删除SEH代码
POP DWORD PRT FS:[0] ;读取栈值并将其放入FS:[0],这里的栈值存放的下一个SEH的起始地址,执行该命令之后,就可以从栈中删除对应的SEH。
ADD ESP,4
Fs:[0]总是指向当前线程的TIB,其中0偏移的指向线程的异常链表,即ExceptionList是指向异常处理链表(EXCEPTION_REGISTRATION结构)的一个指针。
OD选项
od中选择options-debugging options-.exception
合理配置可以在不暂停调试器的情况下基于规避SEH实现的反调试招数。
默认选中。也就是说,碰到软件模拟产生的异常 的时候不会暂停。
忽略其它异常
这里添加的异常会 发送给被调试者。
反调试
异常(Exception )常用于反调试技术。正常运行的进程发生异常时,在SEH机制的作用下,OS会接收异常,然后调用进程中注册的SEH处理。但是,若进程(被调试者)在调试运行中发生异常,调试器就会接收处理。利用该特征可判断进程是正常运行还是调试运行,然后根据不同结果执行不同操作,这就是反调试技术的原理。
Windows操作系统中最具代表性的异常是断点异常。BreakPoint指令触发异常时,若程序处于正常运行状态,则自动调用已经注册过的SEH;若程序处于调试运行状态,则系统会立刻停止运行程序,并将控制权转给调试器。一般而言,异常处理器中都含有修改EIP值的代码。修改调试器选项可以把处在调试中的进程产生的相关异常转给操作系统,自动调用SEH处理。但即便如此,在异常处理器中适当应用静态反调试技术,也能够轻松判断进程是否处于调试状态。此外,EIP值在异常处理器内部如何变化也不得而知,这意味着,必须跟踪进入异常处理器才能继续调试。
处理:
用OD在Debugging options对话框的Exceptions选项卡中,复选“相应的异常类型”后,调试器就会忽略被调试进程中发生的异常,而由自身的SEH处理。