Rick教你写shellcode系列之邪恶的pdf

2020-04-30 约 354 字 预计阅读 2 分钟

声明:本文 【Rick教你写shellcode系列之邪恶的pdf】 由作者 snappyjack 于 2020-04-30 09:24:23 首发 先知社区 曾经 浏览数 19 次

感谢 snappyjack 的辛苦付出!

起因

exploit-db中一篇关于PDFResurrect的溢出引起了我的注意:

PDFResurrect 0.15 has a buffer overflow via a crafted PDF file because data associated with startxref and %%EOF is mishandled.(https://www.exploit-db.com/exploits/47178)

该软件在解析pdf的时候对于startxref错误的控制导致了栈溢出(CVE-2019-14267).

既然都栈溢出了,理论上我们是可以在pdf中写入构造好的payload,实现getshell的,然而在type一栏中作者确只写了DoS,pyaload样本也只是一个导致DoS的crash样本.那么我们来试一下在pdf中写入payload

下载和编译

安装的过程比较简单,./configure之后,修改MakeFile中的CFLAGS如下

CFLAGS = -O0 -g -Wall -fno-stack-protector $(EXTRA_CFLAGS)

-O0关掉优化方便gdb调试,而单一的stack overflow,让我们-fno-stack-protector

make之后查看下保护状态

开始尝试

根据漏洞的类型和文件的保护措施,第一想到的就是使用ROP绕过NX,从而实现getshell.然而在pdfresurrect不存在system()这种功能,在里面找rop链是基本没戏了,只能从动态链接库中找找看

所以是时候祭出我们的神器了,one_gadget:一键查找可用的rop链 https://github.com/david942j/one_gadget


找到了4条rop链,具体用哪条,到最后的一步再看.

offset的计算

根据作者提供的信息,溢出出现的位置如下

...
...
char x, *c, buf[256];
...
...
    for (i=0; i<pdf->n_xrefs; i++)
    {
        /* Seek to %%EOF */
        if ((pos = get_next_eof(fp)) < 0)
          break;

        /* Set and increment the version */
        pdf->xrefs[i].version = ver++;

        /* Rewind until we find end of "startxref" */
        pos_count = 0;
        while (SAFE_F(fp, ((x = fgetc(fp)) != 'f'))) <== The loop will continue incrementing pos_count until find a 'f' char
          fseek(fp, pos - (++pos_count), SEEK_SET);

        /* Suck in end of "startxref" to start of %%EOF */
        memset(buf, 0, sizeof(buf));
        SAFE_E(fread(buf, 1, pos_count, fp), pos_count, <== If pos_count > 256 then a buffer overflow occur
               "Failed to read startxref.\n");
        c = buf;
        while (*c == ' ' || *c == '\n' || *c == '\r')
          ++c;

        /* xref start position */
        pdf->xrefs[i].start = atol(c);
...
...

我们在pdf.c:237处打一个断点,并分别查找buf和rbp的位置,从而计算payload需要的偏移

如图所示,buf位置0x7fffffffe460,rbp位置0x7fffffffe5a0,所以我们的offset为

offset=0x5a0-0x460 = 320

我们使用notepad打开pdf,添加在xref%%EOF中添加offset如下

然后我们使用gdb调试,运行完fread函数之后栈空间情况如下

正如我们所愿,刚好覆盖到rbp前一个位置

遇见第一个坑

继续往下走,在0x40217b出现了问题,指令对比rdxrax,若不等,程序退出,幸好我们的rax可控,此处修改至相等即可绕过.

遇见第二个坑

运行到0x4021db出现了第二个问题

stack上的覆盖影响到了pdf->xrefs[i]中i的值,出现了报错,导致程序crash,仔细查看i的值,发现同样可控,在没有仔细研究源码的情况下,同样的无脑修改使其绕过.

风雨之后并没有见彩虹

绕过了前两个,迎来了第三个

此处是一个正常退出,这就需要研究一下源码

程序退出的位置在is_valid_xref函数的587行,巨大的xref->start使文件指针指向了一个非常靠后的位置,结果可想而知,文件内容读取失败.

而奇怪的0x2bdc528094fb87数值让人摸不到头脑,貌似是一个不可控的数值,从哪里来的不知道.就在我准备放弃的时候,条件反射查了一下数值

damn!又是可控!只好继续无脑修改

黎明的曙光就在眼前

通过proc查看libc基地址然后计算出rop实际地址

终于见到了大boss,即将ret到rop地址

可现实却给了我当头一棒

没有one_gadget符合的条件!what else can I do?

没有条件创造条件

没有符合的条件,只好硬着头皮查找其他gadget

ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6

终于找到你,还好我没放弃

利用两个sub rax, 1 ; ret让rax置零,再接那个rax == NULL的one_gadget,winhex中修改

测试

boom!!成功拿到shell,大功告成!

附件

完整的payload见 https://github.com/snappyJack/pdfresurrect_CVE-2019-14267
其中rop位置可能需要自行修改

本人gcc和系统版本如下

root@c7c87f16a29d:/home/pdfresurrect-0.15# /lib/x86_64-linux-gnu/libc.so.6 -V
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu11) stable release version 2.23, by Roland McGrath et al.
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 5.4.0 20160609.
Available extensions:
    crypt add-on version 2.1 by Michael Glad and others
    GNU Libidn by Simon Josefsson
    Native POSIX Threads Library by Ulrich Drepper et al
    BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
root@c7c87f16a29d:/home/pdfresurrect-0.15# uname -a
Linux c7c87f16a29d 3.10.0-1062.4.1.el7.x86_64 #1 SMP Fri Oct 18 17:15:30 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
root@c7c87f16a29d:/home/pdfresurrect-0.15#

参考

https://www.exploit-db.com/exploits/47178

关键词:[‘安全技术’, ‘漏洞分析’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now