<Oday安全 11.6利用加载模块之外的地址绕过SafeSEH>一节注记---jmp [ebp+N] (下)
来源:互联网 发布:前端dns优化 编辑:程序博客网 时间:2024/06/05 13:17
接上回,还剩几条跳转的指令还没分析到,这些指令将在本篇中完成。
先来看看call/jmp [ebp-0x4]这条指令。这是在当前函数_except_handler4栈的局部变量,因此需要查看反汇编代码:
0:000> uf ntdll!ExecuteHandler2ntdll!ExecuteHandler2:7c923282 55 push ebp7c923283 8bec mov ebp,esp7c923285 ff750c push dword ptr [ebp+0Ch]7c923288 52 push edx7c923289 64ff3500000000 push dword ptr fs:[0]7c923290 64892500000000 mov dword ptr fs:[0],esp7c923297 ff7514 push dword ptr [ebp+14h]7c92329a ff7510 push dword ptr [ebp+10h]7c92329d ff750c push dword ptr [ebp+0Ch]7c9232a0 ff7508 push dword ptr [ebp+8]7c9232a3 8b4d18 mov ecx,dword ptr [ebp+18h]7c9232a6 ffd1 call ecx ;调用异常处理程序_except_handler
先前提到,由于栈溢出,异常处理结构已经被覆盖,因此执行call ecx时并不会去执行_except_handler而是执行call/jmp [ebp+N]指令。由于这条指令并没有操作ebp,因此ebp的值依然是ntdll!ExecuteHandler2的函数栈桢。[ebp-4]就顺理成章的变成了ntdll!ExecuteHandler2中的第一个入栈局部变量。而第一个入栈的局部变量正是[ebp+0xc]。这个值是什么?正好和另一个call/jmp [ebp+N]相同----call/jmp [ebp+0x0c]。
上面提到了[ebp+0xc],现在我们来看下call/jmp [ebp+0x0c]这个指令。这个指令分析起来比较简单ebp+0x0c传入函数的第二个参数的地址(广义Esp定理:[ebp+0]:orig ebp;[ebp+4]:retAddr;[ebp+8]:arg1;[ebp+0xc]:arg2).被调用的函数不用说就是异常处理函数_except_handler4了,那么,是谁调用并传参数给它的?
0:000> kbChildEBP RetAddr Args to Child 0012f9b4 7c9232a8 0012faa0 0012fe80(<-参数2) 0012fab4 offset!_except_handler40012f9d8 7c92327a 0012faa0 0012fe80 0012fab4 ntdll!ExecuteHandler2+0x260012fa88 7c92e46a 00000000 0012fab4 0012faa0 ntdll!ExecuteHandler+0x240:000> dd 0012fe80 L2 ;第二个参数的地址值为0x12fe800012fe80 0012ffa8 00411078 ;12fe80包含了一个异常处理节点0:000> ln 00411078(00411078) offset!ILT+115(__except_handler4) | (0041107d) offset!ILT+120(__lock)Exact matches:从堆栈回溯结果来看Arg2是ntdll!ExecuteHandler2调用_except_handler4时传入的;而_except_handler4接口的第二个参数正是PEXCEPTION_REGISTRATION结构。这样异常处理时还是会跳转到被溢出后的栈中,进而执行shellcode。
再看第4条指令call [ebp-0x18]又指向哪?同样,当前ebp指向的是ntdll!ExecuteHandler2的栈桢,[ebp-0x18]还是ntdll!ExecuteHandler2中的局部变量。
0:000> ?? @ebp-0x18unsigned int 0x12f9c00:000> dd 0x12f9c0 L1 0012f9c0 0012fe80 ;同样是当前异常处理节点在栈中的地址ntdll!ExecuteHandler2:7c92329d ff750c push dword ptr [ebp+0Ch] <----这条指令执行后,正好形成局部变量[ebp-0x18]。而这条指令压入的正是前面分析过的[ebp+0xc]7c9232a0 ff7508 push dword ptr [ebp+8]7c9232a3 8b4d18 mov ecx,dword ptr [ebp+18h]7c9232a6 ffd1 call ecx最后两条指令,偏移实在是太远了:[ebp+0x24]/[ebp+0x30]一种冲出地球的感觉...
[ebp+0x0c]是函数ntdll!ExecuteHandler2的第二个参数,[ebp+0x24]比[ebp+0x0c]更早入栈,这十有八九和ntdll!ExecuteHandler2的调用者有关了,查看函数调用栈:
0:000> kbChildEBP RetAddr Args to Child 0012f9b4 7c9232a8 0012faa0 0012fe80 0012fab4 offset!_except_handler40012f9d8 7c92327a 0012faa0 0012fe80 0012fab4 ntdll!ExecuteHandler2+0x260012fa88 7c92e46a 00000000 0012fab4 0012faa0 ntdll!ExecuteHandler+0x24ntdll!ExecuteHandler2的调用者是ntdll!ExecuteHandler,反汇编代码,可以看到[ebp+0x24]的由来:
0:000> uf ExecuteHandlerntdll!ExecuteHandler:7c923256 53 push ebx <----------------压栈后形成[ebp+0x24]7c923257 56 push esi7c923258 57 push edi7c923259 33c0 xor eax,eax7c92325b 33db xor ebx,ebx7c92325d 33f6 xor esi,esi7c92325f 33ff xor edi,edi7c923261 ff742420 push dword ptr [esp+20h]7c923265 ff742420 push dword ptr [esp+20h]7c923269 ff742420 push dword ptr [esp+20h]7c92326d ff742420 push dword ptr [esp+20h] <---------这条指令形成[ebp+0x0c],从这倒着数上去就能找到[ebp+0x24]的由来,那就是函数的第一条指令7c923271 ff742420 push dword ptr [esp+20h]7c923275 e808000000 call ntdll!ExecuteHandler2 (7c923282)push ebx和异常处理的关系比较隐晦。张银奎的<软件调试>P723写到过ntdll!RtlpExecuteHandlerForException在调用ExecuteHandler前会将合适的值存放到ebx中然后再跳转到ExecuteHandler中执行。
ntdll!RtlpExecuteHandlerForException:7c923247 babc32927c mov edx,offset ntdll!ExecuteHandler2+0x3a (7c9232bc)7c92324c eb08 jmp ntdll!ExecuteHandler (7c923256)0:000> ?? @ebp+0x24unsigned int 0x12f9fc0:000> dd 0x12f9fc L20012f9fc 0012fe80 7c94a9efntdll!RtlpExecuteHandlerForException其实也不算什么函数,仅仅是做了个跳转,不会对栈造成影响。但是ebx中的值为什么会是当前异常处理结构呢?这又和ntdll!RtlpExecuteHandlerForException的调用者ntdll!RtlDispatchException有关。
ntdll!RtlDispatchException+0xa0:7c94a9de ff7304 push dword ptr [ebx+4]7c94a9e1 8d45ec lea eax,[ebp-14h]7c94a9e4 50 push eax7c94a9e5 ff750c push dword ptr [ebp+0Ch]7c94a9e8 53 push ebx7c94a9e9 56 push esi7c94a9ea e85888fdff call ntdll!RtlpExecuteHandlerForException
<软件调试>P718上给出了调用RtlpExecuteHandlerForException的接口形式:RtlpExecuteHandlerForException(pExcptRec,pRegistration,pContext,&DispatcherContext,pRegistration->Handler);结合接口形式和反汇编代码可以知道ebx中存储的值是pRegistration---异常处理节点;当进入到ntdll!RtlpExecuteHandlerForException后,ebx的值不变,还是pRegistration,因此[ebp+0x24]处存放的也是异常处理节点。知道了[ebp+0x24]的来历,再来反推[ebp+0x30]的来历就显得相对简单很多:进入ntdll!RtlpExecuteHandlerForException后的第一次push ebx与进行异常处理调用call _except_handler4之间差[0x24],在这个偏差上再反推找到3次压栈操作即为[ebp+0x30],凑巧这发生在ntdll!RtlDispatchException函数调用RtlpExecuteHandlerForException之际
ntdll!RtlDispatchException+0xa0:7c94a9e8 53 push ebx ;第一次压栈 [ebp+0x30]7c94a9e9 56 push esi ;第二次压栈 [ebp+0x2c]7c94a9ea e85888fdff call ntdll!RtlpExecuteHandlerForException ;函数调用 又一次压栈 [ebp+0x28]--->进入RtlpExecuteHandlerForException,执行push ebx;终于把所有指令分析结束 阿门
0 0
- <Oday安全 11.6利用加载模块之外的地址绕过SafeSEH>一节注记---jmp [ebp+N] (下)
- <Oday安全 11.6利用加载模块之外的地址绕过SafeSEH>一节注记---jmp [ebp+N] (上)
- <Oday安全 11.5利用未启用SafeSEH模块绕过SafeSEH>一节注记
- 利用加载模块之外的地址绕过SafeSEH
- 突破SafeSEH机制之三——利用加载模块之外的地址绕过SafeSEH
- <Oday安全 12.3.1Ret2Libc实战之利用ZwSetInformationProcess>一节注记(下)
- <Oday安全 12.3.1Ret2Libc实战之利用ZwSetInformationProcess>一节注记(上)
- 利用未启用SafeSEH模块绕过SafeSEH
- 突破SafeSEH机制之二——利用未启用SafeSEH模块绕过SafeSEH
- <Oday安全 12.3.1Ret2Libc实战之利用ZwSetInformationProcess>一节补充
- 突破SafeSEH机制之一——利用堆绕过SafeSEH
- 利用Adobe Flash Player ActiveX 控件绕过SafeSEH
- 利用Adobe Flash Player ActiveX控件绕过SafeSEH
- SafeSEH Exploit——利用未启用SafeSEH的DLL
- 模块对于 safeseh 映像是不安全的
- 模块对于 SAFESEH 映像是不安全的。
- 利用 Adobe Flash Player ActiveX 控件绕过 SafeSEH(问题及解决方法)
- 转移地址在寄存器的JMP指令
- 2个链表是否相交
- 中软的第一天
- 详细解读权限控制中的ER关系(新手入门必备知识)
- sdut acm 整理音乐
- 使用kettle将csv存为txt转入sql
- <Oday安全 11.6利用加载模块之外的地址绕过SafeSEH>一节注记---jmp [ebp+N] (下)
- Android 动画深入分析(Android开发艺术探索读书笔记)
- Android WebView Video完全详解(第一篇)-Android开发人员
- gcc的-ffunction-sections和-fdata-sections选项与ld的--gc-sections选项
- caffe 依赖的作用
- 逆序输出链表
- jdbc连接mysql数据库
- 知识库--Concurrency+ThreadPool+Executors(79)
- 矩阵第二章总结笔记