点击上方蓝字关注我们
Foxit Reader(旧名:Foxit PDF Reader),是一套用来阅读PDF格式文件的软件,由福建福昕软件所研发。 在 Adobe Reader 以及旧版本的 Foxit Reader 中,通常会利用 JS 的 ArrayBuffer 来布局内存并最终实现任意代码执行。然而,最新版本 Foxit Reader 中的 ArrayBuffer 已经被禁用,这导致漏洞利用的难度很大,目前还未见到网上有公开的漏洞利用方案。 这篇文章主要总结我在研究 Foxit Reader 漏洞利用的过程中积累的一些经验,从 Foxit Reader 的一套内存管理机制的角度出发,探索潜在的漏洞利用方式,为大家提供一些可能的思路。
|内存管理
+--------+
| 0x8 |--------> +--------+ +--------+
+--------+ | head | <====> | head | <====> ...
| 0x10 |------+ +--------+ +--------+
+--------+ | | chunk | | chunk |
| 0x18 |----+ | +--------+ +--------+
+--------+ | | | chunk | | chunk |
| ... | | | +--------+ +--------+
| | | ... | | ... |
| |
| +-> +--------+ +--------+
| | head | <====> | head | <====> ...
| +--------+ +--------+
| | chunk | | chunk |
| +--------+ +--------+
| | chunk | | chunk |
| +--------+ +--------+
| | ... | | ... |
|
+---> +--------+ +--------+
| head | <====> | head | <====> ...
+--------+ +--------+
| chunk | | chunk |
+--------+ +--------+
| chunk | | chunk |
+--------+ +--------+
| ... | | ... |
poolheadarray
中取得对应 size 的池,然后取得它的 nextfreechunk
返回。若 nextfreechunk
不存在,则分配一个新的 chunk。//...
if ( size > 0x400 )
return sub_1D92C70(a1, size);
idx = (size - 1) >> 3;
pool = poolheadarray[2 * idx];
if ( pool == pool->nextpool )
return sub_1D92D60(a1, (size - 1) >> 3);
v5 = pool->nextfreechunk;
++pool->ref;
v6 = *v5;
pool->nextfreechunk = *v5;
if ( !v6 )
{
sub_1D93260(pool, idx);
return v5;
}
//...
nextfreechunk
下。 v4 = *((a2 & 0xFFFFF000) + 4);
*a2 = v4;
v5 = pool->ref - 1;
*((a2 & 0xFFFFF000) + 4) = a2;
pool->ref = v5;
池的结构
base +--------+---------------+----------+-----------+
| | nextfreechunk | prevpool | nextpool |
+--------+---------------+----------+-----------+
| | sizeidx | offset | maxoffset |
+--------+---------------+----------+-----------+
| | | | |
-
nextfreechunk
:
nextfreechunk
指向链表头。分配内存时总是从 nextfreechunk
首先获取。nextfreechunk
为空,则存在两种情况:所有 chunk 已经全部分配或者还有从未分配过的 chunk。-
prevpool
和nextpool
:
-
sizeidx
:
-
offset
和maxoffset
:
nextfreechunk
并不会指向他们,只有所有已分配的 chunk 经历过 free 之后才能通过 nextfreechunk
进行之后的分配。而第一次的分配就需要 offset
和 maxoffset
来判断下一个应该分配的 chunk。offset
指向下一个尚未分配过的 chunk,maxoffset
指向池的末尾。当 offset < maxoffset
时,说明仍有尚未进行过分配的 chunk,若此时 nextfreechunk
为空,则返回 offset
处指向的 chunk。free chunk 的结构
nextfreechunk
将指向该 chunk,而 nextfreechunk
原来所指向的 chunk 将放入该 chunk 中,其结构图如下。+---------------+--------+--------+--------+
| nextfreechunk | | | |
+---------------+--------+--------+--------+
| | | | |
|漏洞利用
nextfreechunk
指针,我们将有机会操纵任意的内存块。nextfreechunk
为我们想要的地址,然后进行后续利用。nextfreechunk
通常与 C++ 对象的虚表指针处在同一位置,所以当存在一个 UAF 漏洞,并且在释放后调用虚函数时,我们还有机会直接劫持控制流。| | | | |
+----------+----------+----------+----------+ <- free chunk
| 0 | AAAAAAAA | AAAAAAAA | AAAAAAAA |
+----------+----------+----------+----------+ <- victim obj
| vtb | | | |
+----------+----------+----------+----------+
| | | | |
| | | | |
+-> +----------+----------+----------+----------+ <- free chunk
| | 0 | AAAAAAAA | AAAAAAAA | AAAAAAAA |
| +----------+----------+----------+----------+ <- victim obj
+-- | nextfree | | | |
+----------+----------+----------+----------+
| | | | |
obj.vtb->field_4()
时,就会执行到我们提前在内存中布局的地址 0x41414141
处。|总结
-End-
原文始发于微信公众号(360漏洞研究院):技术前瞻|一种 Foxit Reader 漏洞利用思路探索
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论