对于0.8.43.5852版的软件MEDIACODER中存在的栈溢出漏洞的分析。
参考自:https://whereisk0shl.top/post/2018-06-23
POC出处:https://www.exploit-db.com/exploits/40148
1.背景知识
A.关于Windbg常用指令
指令 | 描述 |
---|---|
.detach |
结束调试会话,被调试进程仍可继续运行 |
k [n] [f] [L] [#Frames] |
显示调用栈信息 |
kn |
调用栈包含帧号 |
kf |
临近帧的距离 |
kL |
忽略源代码 |
kb |
最开始的 3 参数 |
kp |
所有的参数,包括参数类型、名称和值 |
kP |
所有的参数 |
kv |
FPO信息 |
kb 5 |
显示最开始的 5 个帧 |
.frame /r |
显示当前寄存器信息 |
B.关于覆盖SEH的漏洞利用方式
标准利用构造shellcode格式:
填充物+ "\xEB\x06\x90\x90" +pop pop retn 指令序列地址+shellcode
,这里需要确定的就是填充物的长度(即SEH的偏移地址),还有就是需要寻找到合适的ppr指令序列地址,最好是应用程序自身或自身dll的,不能找开启了safeSEH防护的(大部分系统dll都是开启了safeseh保护的),否则会利用失败。如果碰到后面的缓冲区太短不足以放下shellcode,或者指令序列地址中包含00容易造成shellcode截断的情况,则可以考虑将shellcode放在前面的缓冲区,然后将SEH处理指令填充成向前跳转的指令,对应的exp示例如下图所示。
2.漏洞复现
A.触发崩溃
运行POC生成evil.m3u
文件,用MediaCoder
打开,触发崩溃。
B.定位崩溃代码
用Windbg捕获崩溃信息如下图所示,可以看到产生崩溃的具体代码位置为004306b5
(也就是IMG_InvertAlpha+0x1bdb5
),可从此处入手进行后续的漏洞分析操作。由于漏洞分析操作是在IDA中进行代码阅读的,所以具体的定位方式如下——
- 定位到IDA中
004306b5
地址处的代码,和windbg中是一样的,但感觉可能并不是每次都会刚好是一样的。 - 利用
IMG_InvertAlpha+0x1bdb5
进行定位(比较准确),在IDA中找到IMG_InvertAlpha
函数,然后定位到其地址+0x1bdb5的地址处。
C.疑惑
参考教程中通过ollydbg的kb命令,回溯栈信息,还能看到入手点的上层调用函数,如下图。
但是我在win7上分析时,kb命令获取的信息却不太一样,应该是利用脚本需要根据利用环境进行调整的原因。
3.漏洞分析
关键在于搞清楚我们构造的输入数据,在程序中是怎样被处理的,并且是怎样造成程序的崩溃的。所以光有上述入手点并不够,我们还需要通过动态调试,从入手点回溯函数调用流程,从而分析清楚漏洞产生原因。
这里我通过IDA进行动态调试和分析。
从关键代码处进行分析,向上回溯如下图——
然后在关键语句处下断点,用ida动态调试,分析如下——
- 调用流程:0043cbc3——-0043cb90———-00430698(此时ecx中存放的就是从文件中读取的数据)
- 接下来一个一个读取其中的字符,并按顺序存放在起始地址为[edx+ecx-1](调试过程中是0018f300)的内存中(这里是有安全漏洞的,因为读取赋值的终止条件是取到的值为0,并没有对长度进行限制。)
- 一直读取就会报错如图所示(因为构造的文件太长,在尝试不断写入字符的过程中访问到了不可访问的位置(调试过程中是190000))————————————这里就触发了SEH异常处理,所以利用时就要想办法覆盖SEH指针达到任意代码执行的目的。
- 然后再强制运行就会报错如图,因为此时ebx已经被覆盖成了0x41414141,在接下来执行call ebx时程序就会报错终止。
这里也可以看出之前的poc利用失败了,需要根据具体的环境进行调整。
4.漏洞利用
由上述可知,最终ebx被覆盖成0x41414141,我们将POC进行修改,将重复字符“A”换成不一样的字符,以定位SEH的具体偏移,最终定位到如下图所示位置。
接下来的具体利用涉及到SEH结构的调试,换用工具Immunity Debugger
(该工具在64位的windows系统上均不能成功运行,于是需要在一台32位的windows7虚拟机上进行分析)进行分析和调试。
A.利用Immunity Debugger
进行调试分析(32位win7)
动态调试发现,在32位的win7上该poc就能成功覆盖到SEH结构,也成功的构造了整个利用栈,但最后在执行完ppr
后执行向下跳6个字节(以到达shellcode区域)的指令时却报错提示Access violation when executing [0012F618]
,如下图。
这就很神奇了,明明程序触发异常之后就会来执行这里的SEH处理代码啊,怎么就报访问错误了?这种情况下也暂时想不到什么可能有用的处理方式,心疼,还以为能利用成功,再接再厉吧~
B.还想再尝试一下。。。(64位win7)
在64位的win7上利用windbg进行调试和分析,将偏移进行调整后成功覆盖SEH并进行利用,依然是同样的问题,执行到我们覆盖后的SEH处理代码后,就报内存访问错误了。
使用Windbg进行调试分析SEH时的2条关键命令——
!analyze -v
!exchain
5.参考
A.关于SEH
SEH以链表的形式存储在栈中,每一条SEH记录大小为8字节,包含2个元素:
- 指向下一条记录地址的指针(4字节)
- 指向处理当前异常的代码地址的指针(4字节)
下图为一个简单的SEH链条结构:
通过栈溢出覆盖SEH结构实现漏洞利用的基本步骤如下——
- 通过溢出覆盖栈中SEH,将指向下一条记录的指针覆盖为shellcode地址,将指向当前SEH处理函数的指针指向一个带有“POP POP RET”操作的函数;
- 触发一个SEH;
- 应用程序处理SEH时调用了“POP POP RET”指令,将指向下一条记录的指针作为EIP内容;
- 跳到shellcode地址,执行shellcode。