使用堆溢出来写入任意数据

amc*_*ack 22 c security heap exploit

我一直在努力学习堆溢出攻击的基础知识.我最感兴趣的是使用损坏或修改块元数据作为攻击的基础,但我也对其他建议持开放态度.我知道我的利用目标应该是用printf()函数指针覆盖challenge()函数指针,但我似乎无法弄清楚如何实现该写入.我有以下要利用的代码,它使用的mallocglibc 2.11.2:

void challenge()
{
        puts("you win\n");
}

int main(int argc, char **argv)
{
        char *inputA, *inputB, *inputC;

        inputA = malloc(32);
        inputB = malloc(32);
        inputC = malloc(32);

        strcpy(inputA, argv[1]);
        strcpy(inputB, argv[2]);
        strcpy(inputC, argv[3]);

        free(inputC);
        free(inputB);
        free(inputA);

        printf("execute challenge to win\n");
}
Run Code Online (Sandbox Code Playgroud)

显然,实现对分配的块的元数据的实际覆盖是微不足道的.但是,我还没有找到使用任何标准技术来利用此代码的方法.我已阅读并试图实施以下技术:

  • 论文:w00w00关于Heap Overflows
    • 尽管论文非常清楚,但该unlink技术已经过时了一段时间.
  • Malloc Maleficarum.txt
    • 本文扩展了w00w00天的漏洞利用技术,并解释了glibc的新版本.但是,我没有发现,鉴于本文详述的5种技术,上述代码与这些技术的任何先决条件相匹配.
  • 通过打破它来理解堆(pdf)
    • pdf非常好地回顾了堆的工作原理,但重点介绍了双重自由技术.

我最初试图通过操纵inputC的块的大小值来利用此代码,以便它指向inputC块的头部.当这不起作用时,我尝试进一步指向inputB的块.那时我意识到新的glibc会对大小值进行健全性检查.

如果用户能够将分配的块的元数据编辑为任意值,并使用它来覆盖GOT中的值或写入任何其他任意地址,那么用户如何利用免费利用漏洞利用?

注意:当我写"任意地址"据我所知,内存页面可能是只读或受保护的,我的意思是我可以假设我可以写一个地址.

Few*_*itz 11

注意:在我回答之前我会说这纯粹是一个学术答案,并不打算用于恶意目的.我知道OP正在进行的练习,它们是开源的,并不是为了鼓励任何用户在未经批准的情况下使用这些技术.

我将详细介绍下面的技术,但为了供您参考,我将看一下Vudo malloc技巧(在上面的一个链接中引用它),因为我的概述将是一个简短的概述:http://www.phrack.com /issues.html?issue=57&id=8

它详细说明了malloc如何处理创建内存块,从列表和其他东西中提取内存.特别是unlink攻击对于这次攻击很有意义(注意:你是正确的,glibc现在对这个特殊原因进行大小检查,但你应该使用较旧的libc进行此练习......遗留兄弟).

从论文中,分配的块和空闲块使用相同的数据结构,但数据的处理方式不同.看这里:

chunk -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         | prev_size: size of the previous chunk, in bytes (used   |
         | by dlmalloc only if this previous chunk is free)        |
         +---------------------------------------------------------+
         | size: size of the chunk (the number of bytes between    |
         | "chunk" and "nextchunk") and 2 bits status information  |
  mem -> +---------------------------------------------------------+
         | fd: not used by dlmalloc because "chunk" is allocated   |
         | (user data therefore starts here)                       |
         + - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
         | bk: not used by dlmalloc because "chunk" is allocated   |
         | (there may be user data here)                           |
         + - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
         |                                                         |
         |                                                         |
         | user data (may be 0 bytes long)                         |
         |                                                         |
         |                                                         |
 next -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         | prev_size: not used by dlmalloc because "chunk" is      |
         | allocated (may hold user data, to decrease wastage)     |
         +---------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

分配的块不使用fd或bk指针,但是免费的块会使用.这在以后会变得很重要.你应该知道足够的编程来理解Doug Lea的malloc中的"块"被组织成一个双向链表; 有一个用于空闲块的列表和另一个用于已分配的列表(技术上有几个免费列表,具体取决于大小,但由于代码分配了相同大小的块,因此它无关紧要).所以当你释放一个特定的块时,你必须修复指针以保持列表的顺利进行.

例如,假设您从下面的列表中释放块y:

x <-> y <-> z
Run Code Online (Sandbox Code Playgroud)

请注意,在上图中,bk和fd的点包含沿列表迭代的必要指针.当malloc想要从列表中取出一个块p时,它会调用一个宏来修复列表:

#define unlink( y, BK, FD ) {            
    BK = P->bk;                          
    FD = P->fd;                          
    FD->bk = BK;                         
    BK->fd = FD;                         
}
Run Code Online (Sandbox Code Playgroud)

宏本身并不难理解,但在旧版本的libc中需要注意的重要一点是它不会对大小或写入的指针执行完整性检查.在您的情况下,它意味着没有任何类型的地址随机化,您可以通过以特定方式溢出堆(通过此处的strncopy)可预测并可靠地确定堆的状态并将任意指针重定向到您选择的地址.

要使攻击有效,需要做一些事情:

  • 块的fd指针指向要覆盖的地址减去12个字节.偏移量与malloc在修改列表时清理对齐方式有关
  • 块的bk指针指向shellcode
  • 大小需要为-4.这完成了一些事情,即它设置块中的状态位

因此,您必须在特定示例中使用偏移量,但是您尝试使用strcpy传递的一般恶意格式的格式如下:

| 垃圾填满合法缓冲区| -4 | -4 | 你要覆盖的addr -12(0x0C)| 你要打电话的地址

请注意,负数将prev_size字段设置为-4,这使得空闲路由认为prev_size块实际上是在您控制/正在破坏的当前块中启动的.

是的,如果没有提到这种攻击对当前版本的glibc不起作用,那么正确的解释是不完整的.大小已完成完整性检查,unlink方法不起作用.与地址随机化等缓解措施相结合,使得这种攻击在遗留系统之外的任何事情上都不可行.但这里描述的方法是我如何做到这一挑战;)

  • 正如你所说,这种方法在很多方面已经过时了.如健全性检查和多个竞技场的引入(所以-4尺寸不起作用).如果您了解西班牙语,您可以阅读我开发的论文,解释所有这些内容以及如何使用现代glibc版本绕过它们:http://overflowedminds.net/Papers/Newlog/linux_heap_exploiting_revisited.pdf您可以在这里阅读一些英文幻灯片: http://prezi.com/wcnbbokuousb/linux-heap-exploiting-revisited-en/?kw=view-wcnbbokuousb&rc=ref-2251669 (2认同)