之前的笔记搬运
0x1 异常的处理流程
一般异常是由硬件产生中断 -> 系统改写中断拿到异常 -> 处理并包装信息 ->
再发给应用程序
0x2 接收异常处理
接收异常处理就是在最后一步时, 使得操作系统派发的异常信息先一步给我们处理;
用到的函数原形:
1 | LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter( |
SetUnhandledExceptionFilter这个函数只有一个参数,
就是处理异常信息的回调函数指针, 在操作系统接受到异常时候就会调用设置的回调函数
回调函数原形:
1 | LONG UnhandledExceptionFilter( |
UnhandledExceptionFilter 的返回值决定如何进行下一步系统动作
1.EXCEPTION_EXECUTE_HANDLER(1)——-无法处理异常, 进程退出
2.EXCEPTION_CONTINUE_SEARCH(0)——-不做处理, 把异常向上抛出,有其他或者系统接收
3.EXCEPTION_CONTINUE_EXECUTION(-1)—异常已修复,系统将CONTEXT设置回去并继续执行程序(正常情况下异常处理不可能返回-1,当返回值为-1时, 那么这个异常一定是有意造成的)
UnhandledExceptionFilter这个函数也只有一个参数, 是一个异常信息的结构体,
在看看结构体:
1 | typedef struct _EXCEPTION_POINTERS { |
ExceptionRecord, 这个结构体是具体的异常信息
ContextRecord 记录了发生异常的寄存器环境
在具体看看这两个结构体:
EXCEPTION_RECORD:
1 | typedef struct _EXCEPTION_RECORD { |
CONTEXT :
1 | ContextFlags DWORD ? ;设置需要操作的寄存器范围 |
标志代表的部分
ExtendedRegisters db MAXIMUM_SUPPORTED_EXTENSION dup(?)
;表示扩展寄存器的内容,如MMX…
这个结构体可以保存CPU线程运行时寄存器环境,
而CPU在进行线程切换时也是需要利用这个结构体来保存和还原环境的,
说到这里就需要提到俩个函数
SetThreadContext 和 GetThreadContext
1 | BOOL SetThreadContext( |
利用这两个函数可以来获取和设置当前线程的寄存器环境, 也可以做一些特殊操作哦,
比如先获取环境, 再修改一下EIP设置回去就可以达到修改代码流程的目的,
不过在获取和设置时需要记得SuspendThread挂起线程,
设置完成后才ResumeThread激活线程
0x3 中断和子程序的区别
中断: 类似于回调函数, 在一定情况下会触发, 也可以主动调用
子程序: 只可以主动调用, 不会被动调用