漏洞分析——MEDIACODER 0.8.43.5852 - .M3U缓冲区溢出漏洞

对于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 显示当前寄存器信息

WinDbg 命令三部曲:(一)WinDbg 命令手册

B.关于覆盖SEH的漏洞利用方式

  1. 标准利用构造shellcode格式:填充物+ "\xEB\x06\x90\x90" +pop pop retn 指令序列地址+shellcode,这里需要确定的就是填充物的长度(即SEH的偏移地址),还有就是需要寻找到合适的ppr指令序列地址,最好是应用程序自身或自身dll的,不能找开启了safeSEH防护的(大部分系统dll都是开启了safeseh保护的),否则会利用失败。

  2. 如果碰到后面的缓冲区太短不足以放下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结构实现漏洞利用的基本步骤如下——

  1. 通过溢出覆盖栈中SEH,将指向下一条记录的指针覆盖为shellcode地址,将指向当前SEH处理函数的指针指向一个带有“POP POP RET”操作的函数;
  2. 触发一个SEH;
  3. 应用程序处理SEH时调用了“POP POP RET”指令,将指向下一条记录的指针作为EIP内容;
  4. 跳到shellcode地址,执行shellcode。

Windows SEH学习 x86
SEH分析笔记(X64篇)
栈溢出中利用SEH
【干货分享】看教程学溢出之SEH利用

B.关于Access Violation(非法访问)

Access Violation(非法访问)错误的解决方法