SEH学习笔记 0x00 博客地址:https://bbs.pediy.com/thread-249592.htm
SEH(Structured Exception Handling:结构化异常处理)是windows系统中的异常处理机制,还可用于反调试程序,源代码中SEH体现在try,except等关键字上。
OS异常处理的方法:
进程出现异常,首先看看进程中有没有存在异常处理的代码(try或except)之类的,如果没有OS就启动默认的异常处理机制,中止程序运行。
当进程处于调试状态时,出现异常后首先由调试器(x32dbg之类的)处理,这时候我们就:
直接修改异常(代码、寄存器与内存)。
将异常抛回被调试程序,F8直接运行。
OS默认的异常处理机制。
常见异常: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 EXCEPTION_ACCESS_VIOLATION 0xC0000005 程序企图读写一个不可访问的地址时引发的异常。例如企图读取0地址处的内存。 EXCEPTION_ARRAY_BOUNDS_EXCEEDED 0xC000008C 数组访问越界时引发的异常。 EXCEPTION_BREAKPOINT 0x80000003 触发断点时引发的异常。 EXCEPTION_DATATYPE_MISALIGNMENT 0x80000002 程序读取一个未经对齐的数据时引发的异常。 EXCEPTION_FLT_DENORMAL_OPERAND 0xC000008D 如果浮点数操作的操作数是非正常的,则引发该异常。所谓非正常,即它的值太小以至于不能用标准格式表示出来。 EXCEPTION_FLT_DIVIDE_BY_ZERO 0xC000008E 浮点数除法的除数是0时引发该异常。 EXCEPTION_FLT_INEXACT_RESULT 0xC000008F 浮点数操作的结果不能精确表示成小数时引发该异常。 EXCEPTION_FLT_INVALID_OPERATION 0xC0000090 该异常表示不包括在这个表内的其它浮点数异常。 EXCEPTION_FLT_OVERFLOW 0xC0000091 浮点数的指数超过所能表示的最大值时引发该异常。 EXCEPTION_FLT_STACK_CHECK 0xC0000092 进行浮点数运算时栈发生溢出或下溢时引发该异常。 EXCEPTION_FLT_UNDERFLOW 0xC0000093 浮点数的指数小于所能表示的最小值时引发该异常。 EXCEPTION_ILLEGAL_INSTRUCTION 0xC000001D 程序企图执行一个无效的指令时引发该异常。 EXCEPTION_IN_PAGE_ERROR 0xC0000006 程序要访问的内存页不在物理内存中时引发的异常。 EXCEPTION_INT_DIVIDE_BY_ZERO 0xC0000094 整数除法的除数是0时引发该异常。 EXCEPTION_INT_OVERFLOW 0xC0000095 整数操作的结果溢出时引发该异常。 EXCEPTION_INVALID_DISPOSITION 0xC0000026 异常处理器返回一个无效的处理的时引发该异常。 EXCEPTION_NONCONTINUABLE_EXCEPTION 0xC0000025 发生一个不可继续执行的异常时,如果程序继续执行,则会引发该异常。 EXCEPTION_PRIV_INSTRUCTION 0xC0000096 程序企图执行一条当前CPU模式不允许的指令时引发该异常。 EXCEPTION_SINGLE_STEP 0x80000004 标志寄存器的TF位为1时,每执行一条指令就会引发该异常。主要用于单步调试。 EXCEPTION_STACK_OVERFLOW 0xC00000FD 栈溢出时引发该异常。
直接copy过来的。
SEH链 SEH以链的形式存在,如果这个异常处理中没有发现相关异常,就直接传到下一个异常处理器。
SEH是由_EXCEPTION_REGISTRATION_RECORD结构体组成的链表。
1 2 3 4 ntdll!_EXCEPTION_REGISTRATION_RECORD +0x000 Next : Ptr32 _EXCEPTION_REGISTRATION_RECORD +0x004 Handler : Ptr32 _EXCEPTION_DISPOSITION }
Next指向下一个_EXCEPTION_REGISTRATION_RECORD结构,Handler表示异常处理函数 。若Next成员的值为FFFFFFFF,则表示它是链表最后一个结点。
异常处理函数的定义如下:
1 2 3 4 5 6 EXCEPTION_DISPOSITION __cdecl _except_handler ( EXCEPTION_RECORD *pRecord, EXCEPTION_REGISTRATION_RECORD *pFrame, CONTEXT *pContext, PVOID pValue );
其中第1个参数是EXCEPTION_RECORD(异常记录),其结构为:
1 2 3 4 5 6 7 8 typedef struct _EXCEPTION_RECORD { DWORD ExceptionCode; //异常代码 DWORD ExceptionFlags; struct _EXCEPTION_RECORD *ExceptionRecord; PVOID ExceptionAddress; //异常发生地址 DWORD NumberParameters; ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; } EXCEPTION_RECORD;
第3个参数是指向CONTEXT结构体的指针,用来备份CPU的值。
异常发生的时候,程序就会执行SEH,此时OS会将程序结构体的指针传递给异常处理函数,传递的内容中有eip,异常处理函数会将这个eip进行修改,这样之前暂停的线程会执行新的eip地址处的代码(反调试中经常使用这个技术)。
0x01 回调函数 简单解释 MDN的解释:被作为实参传入另一函数,并在该外部函数内被调用,用以来完成某些任务的函数,称为回调函数。把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,这就叫做回调。如果代码立即被执行就称为同步回调,如果在之后晚点的某个时间再执行,则称之为异步回调。
例如:
1 2 3 4 5 6 7 8 9 10 function greeting (name ) { alert ('Hello ' + name); } function processUserInput (callback ) { var name = prompt ('Please enter your name.' ); callback (name); } processUserInput (greeting);
其中greeting就是一个回调函数,这是同步执行的,然而回调函数大多数用于异步操作 。
为什么使用回调? 回调函数的好处是解耦 。(解耦的意思就是让程序积木化,程序模块化 )
如下图所示:
如下是一段程序来程序上图意思:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <stdio.h> #include <softwareLib.h> int Callback () { printf ("callback" ) return 0 ; } int main () { Library(Callback); return 0 ; }
我们能把我们自己写的函数作为参数传入到Library函数中,并且丝毫不需要修改库函数的实现。
当需要降低耦合度的时候,更应该使用回调函数。
回调函数实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <stdio.h> int Callback_1 (int x) { printf ("Hello, this is Callback_1: x = %d " , x); return 0 ; } int Callback_2 (int x) { printf ("Hello, this is Callback_2: x = %d " , x); return 0 ; } int Callback_3 (int x) { printf ("Hello, this is Callback_3: x = %d " , x); return 0 ; } int Handle (int y, int (*Callback)(int )) { printf ("Entering Handle Function. " ); Callback(y); printf ("Leaving Handle Function. " ); } int main () { int a = 2 ; int b = 4 ; int c = 6 ; printf ("Entering Main Function. " ); Handle(a, Callback_1); Handle(b, Callback_2); Handle(c, Callback_3); printf ("Leaving Main Function. " ); return 0 ; }