Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

分析杀毒软件BitDefender中的整数溢出漏洞(第二部分)――漏洞利用

0
0

分析杀毒软件BitDefender中的整数溢出漏洞(第二部分)――漏洞利用

如果你还没有阅读本系列的第一部分,请在 此处查看 。

我们的上一篇文章回顾了来自 Pagefault 提交 的内容,详细介绍了 Bitdefender 杀毒软件产品中的整数溢出问题。虽然仅依靠这些内容就足以向供应商提交一份漏洞报告,但 Pagefault 还通过提供一个概念验证( PoC )漏洞利用来进一步支持该报告。以下是实际中的利用:

Youtube 视频连接: https://youtu.be/fPK8UjAogWg

Pagefault 提供了关于漏洞如何工作的以下细节。

漏洞利用 由于终止条件是一个虚拟的越界读取,以及 Bitdefender 代码仿真器实现 SEH 的事实,我们可以多次重写覆盖。我们还可以通过修改执行的代码来调整被覆盖的长度和内容。
分析杀毒软件BitDefender中的整数溢出漏洞(第二部分)――漏洞利用

该 vsserve.exe 可执行文件的确会唤醒 ASLR 和 DEP ,然而通过在 JIT 页面内利用与位置无关的 shellcode ,漏洞利用绕过了这些缓解措施。实现代码执行需要操纵任意的内存地址。

Bitdefender 仿真器为仿真程序提供虚拟地址空间。一个 0x1000 字节的仿真器页面具有一个 0x1048 字节的相应实际页面,其中包含几个帮助仿真在页面上操作的字段:
分析杀毒软件BitDefender中的整数溢出漏洞(第二部分)――漏洞利用

在仿真程序内部遇到的多个 VirtualAlloc 调用和相关的内存访问将导致创建多个 0x1048 结构,随后在遇到相应的 VirtualFree 调用,这些结构将被释放。

在内部, 0x1048 分配通过 msvcrt 的 malloc() 执行,并落在低碎片堆( LFH )中。对于 windows 7 及以下版本,继续利用的方法是分配多个虚拟页面,释放至少一个虚拟页面,触发分配并溢出 0x1048 缓冲区的脆弱功能,然后破坏这个虚拟页面。

对于 Windows 8 及以上版本, LFH 增加了随机性,使得堆不那么确定。漏洞利用通过将 LFH 随机表位置重新设置为在重新分配尝试之间的 0xFF 分配,从而绕过了随机化。为了实现所需数量的内存分配并避免额外分配,必须为仿真代码创建 JIT 代码。这是通过执行一段代码至少 34 次来实现的。

在 Windows 8 及以上版本上实现漏洞利用的步骤示例:

l NUMPAGES (例如 60 个)虚拟页面被分配;

l 在 LFH 库中有一个随机的位置,最后一页被释放;

l 随后是 0xFF 分配( JIT 被触发以精确地针对这个数字);

l 脆弱的功能被触发,脆弱的缓冲区被分配来代替最后一页;

l 触发 8 个字节的有限覆盖,并检查其他 NUMPAGES-1 虚拟页面,以查看其内容是否被修改;

l 如果检测到修改:

n 0xFF 分配总数必须发生在脆弱缓冲区和下一个缓冲区之间的最后分配之间;

n 0x1048 字节的另一个缓冲区被分配到与最后一个字节相同的位置,并且这一次覆盖了足够多的字节( 0x1024 ),允许漏洞利用。

l 如果未检测到修改,漏洞利用则将分配另一组虚拟页面并重复这个过程。

重复这个过程直至检测到修改或达到重试限制。有限的覆盖是必需的,以避免碰到攻击保护页面。

一旦虚拟页面被修改,任何访问它的尝试都会受到影响。偏移量 0x1020 处的 dword 决定了用于计算被访问内存的真实地址所需要使用的目标读 / 写地址:

real_address = real_address_base + requested_virtual_address dword[0x1020]

这使我们可以写入任意的偏移量。在这种情况下,可以修改位于已损坏缓冲区之前的第二个虚拟缓冲区的偏移量 0x1020 ,从而允许对第二个虚拟缓冲区的写入偏移量进行重复控制。换句话来说,我们将损坏的缓冲区指向先前的缓冲区:


分析杀毒软件BitDefender中的整数溢出漏洞(第二部分)――漏洞利用

到目前为止所描述的所有技术都可以通过任意偏移量实现可靠的读 / 写原语。然而,这对于代码执行来说是不够的。

如果一段代码被仿真器解释至少 34 次,那么 JIT 编译就会启动,然后仿真器解释给定的操作码并构造相应的动态代码,以便对仿真代码执行以下调用。构造的代码被放置在一个可写和可执行的内存页面中。

对于每个 JIT 段, malloc() 分析重复代码时都会创建一个内存结构。该内容结构的大小可以通过在仿真代码中放置计算指令来控制。通过多次调用具有多个 push ecx/pop ecx 对的函数,可以实现 0x1048 字节的大小。

重复调用的函数数组由相同的内容构成,并且只有在实现了任意读写功能后才会对每个函数执行第 34 次调用,并释放最后一个脆弱的缓冲区。

其中一个虚拟缓冲区占用的空间将被其中一个 JIT 结构占用,因此我们可以使用读 / 写偏移量来访问它。相对于控制的虚拟页面, JIT 缓冲区被放置为 0x1108*x 字节( 0x1108 = 0x1048 ,四舍五入到最近的 LFH 大小,为块标头添加了 8 个字节)。

JIT 结构从几个有用的字段开始:


分析杀毒软件BitDefender中的整数溢出漏洞(第二部分)――漏洞利用

通过在偏移量 0x2C 处读取 dword ,我们可以提取损坏的虚拟页面的实际地址,从而可以进一步对任意地址进行读写,而不仅仅是对任意偏移量进行读写。新获得的能力接下来用于修改放置在 JIT 结构中第一个 dword 所指向的地址处的字节。

一个自定义的 shellcode 将包含的可执行文件转储到文件中并执行,它被放置在编译后的 JIT 代码中,,该代码在下一个调用对应的 JIT 编译函数的调用中执行。 shellcode 以一个 TerminateProcess() 结尾,避免了由于损坏的堆而导致的潜在崩溃。

结论

如果你想自己测试一下, PoC 就在 这里 。它应该在 73447 之前的 BitDefender 版本上工作。

这个漏洞还表明,即使启用诸如 ASLR 和 DEP 这样的缓解措施,熟练的攻击者仍然可以找到执行代码的方法。如果你是一位开发人员,希望避免软件中出现整数溢出问题, CERT 提供了一些关于如何避免在各种操作中出现带符号整数的溢出的优秀 指南 ,这是绝对值得回顾。最后,感谢 Pagefault 的报告和 Bitdefender 对问题的及时解决。


Viewing all articles
Browse latest Browse all 12749

Latest Images

Trending Articles





Latest Images