内核前置——异常处理技术
异常处理分两种:C++的try catch和C的__try __except
程序分两种:32位-x86,64位-x64
区别
(不绝对)
| 程序\类型 | try catch(C++) | __try __except(C) |
|---|---|---|
| x86(32) | 无__unwind块 无try catch块 有流程图 |
有__unwind 有__try块提示 有流程图 |
| x64(64) | 有__unwind 甚至我都没找到catch块中要打印的的字符串”yes” 无流程图 |
有__unwind 无__try块提示 有流程图 |
try catch+x86
32位程序
1 |
|
反汇编代码

可以看出,没有__unwind,也没有块提示,只有流程图提示
try catch+x64
1 |
|

有__unwind,无流程图,甚至我都没找到catch块中要打印的的字符串”yes”
__try __except+x86
1 |
|

有__unwind,有__try块提示,有流程图
__try __except+x64
1 |
|

有__unwind,无__try块提示,有流程图
题目练习
moe–unwind(32)
1 | int __cdecl main_0(int argc, const char **argv, const char **envp) |
ida打开源码,看到` MEMORY[0] = 0;`这是异常的表现,往0位置中写0,也就是说在这里的流程图会有对这个异常的解决

可以看到,try块可以进入下面的except解决部分,也可以进入后续程序,但是我们刚刚分析了
1 | mov [ebp+ms_exc.registration.TryLevel], 0 |
这个是会异常的,也就是一定会进except,所以直接分析这个块,再看后面

try块的内容是调用函数,看看函数

问题在这里,int 3,这个是断点异常,并且观察到,fs:[0],欸?这个不是SEH机制里的异常回调函数结构吗,这里会不会是在安装异常处理结构,所以说
1 | .text:0006183B mov eax, dword ptr ___security_cookie |
这里的作用便是,安装SEH,安装的回调函数就是sub_612FD,在发生异常的时候,会先遍历当前函数的SEH机制,通过将fs:[0]压入栈,进行处理,这个时候前面安装的回调函数就会被调用
但是需要注意,_except_handler 没有处理异常,然后返回给更高级上层函数处理,但是这个时候栈没清除,且没栈展开,所以系统又一次使用栈中的fs:[0] ,导致这个SEH解决方式进行了两遍
然后如果这个回调函数没有对着个断点异常处理,就会栈展开并且回到该函数的调用者函数,进行二次捕获,这个时候就被_except块捕获到,进行相关操作了
ACTF–dropper(64)
这个是64位的异常,64位异常好像没有看到有人说怎么找异常处理函数,应该是机制的问题,不过可以看看做了什么比如:

这里有一个idiv,那么就有可能发生除零异常,同时这个函数是没有对着个函数异常有处理的(这里可以下不同的断点来测验,是处理成功还是将解决权交给更高层的函数
这里有一种通过import来定位异常的方法,待会吃完饭回来学,然后把这段删掉
先说一下另一种细心的方法

看流程图会发现,多了一个小板块,这个板块在代码页面是没有的,并且断点也是可以断住异常处理的
所以这里是异常处理之后启用的代码

作用如上
自己练习的缝合
1 |
|