从零开始学howtoheap:理解glibc分配机制和UAF漏洞利用

本文从glibc的分配机制入手,通过how2heap教程讲解了first_fit算法,展示了如何利用Use-After-Free(UAF)漏洞。通过调试程序,解释了在释放内存后,再次分配可能导致的内存重用问题,并提供了UAF漏洞的简单利用示例。
摘要由CSDN通过智能技术生成

how2heap是由shellphish团队制作的堆利用教程,介绍了多种堆利用技术,后续系列实验我们就通过这个教程来学习。环境可参见从零开始配置pwn环境:优化pwn虚拟机配置支持libc等指令-CSDN博客

1.理解glibc分配机制

pwndbg> r
Starting program: /ctf/work/how2heap/first_fit 
尽管这个例子没有演示攻击效果,但是它演示了 glibc 的分配机制
glibc 使用首次适应算法选择空闲的堆块
如果有一个空闲堆块且足够大,那么 malloc 将选择它
如果存在 use-after-free 的情况那可以利用这一特性
首先申请两个比较大的 chunk
第一个 a = malloc(0x512) 在: 0x603010
第二个 b = malloc(0x256) 在: 0x603530
我们可以继续分配
现在我们把 "AAAAAAAA" 这个字符串写到 a 那里 
第一次申请的 0x603010 指向 AAAAAAAA
接下来 free 掉第一个...
接下来只要我们申请一块小于 0x512 的 chunk,那就会分配到原本 a 那里: 0x603010
第三次 c = malloc(0x500) 在: 0x603010
我们这次往里写一串 "CCCCCCCC" 到刚申请的 c 中
第三次申请的 c 0x603010 指向 CCCCCCCC
第一次申请的 a 0x603010 指向 CCCCCCCC
可以看到,虽然我们刚刚看的是 a 的,但它的内容却是 "CCCCCCCC"
[Inferior 1 (process 60) exited normally]
pwndbg> 
 

2.first_fit程序

这个程序并不展示如何攻击,而是展示glibc的一种分配规则。glibc 使用一种first-fit算法去选择一个free-chunk。如果存在一个free-chunk并且足够大的话,malloc会优先选取这个chunk。这种机制就可以在被利用于use after free(简称 uaf) 的情形中.

使用命令gcc -g first_fit.c -o first_fit编译,-g参数会保留代码的文字信息,便于调试。以下为first_fit.c程序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    fprintf(stderr, "尽管这个例子没有演示攻击效果,但是它演示了 glibc 的分配机制\n");
    fprintf(stderr, "glibc 使用首次适应算法选择空闲的堆块\n");
    fprintf(stderr, "如果有一个空闲堆块且足够大,那么 malloc 将选择它\n");
    fprintf(stderr, "如果存在 use-after-free 的情况那可以利用这一特性\n");

    fprintf(stderr, "首先申请两个比较大的 chunk\n");
    char* a = malloc(0x512);
    char* b = malloc(0x256);
    char* c;

    fprintf(stderr, "第一个 a = malloc(0x512) 在: %p\n", a);
    fprintf(stderr, "第二个 b = malloc(0x256) 在: %p\n", b);
    fprintf(stderr, "我们可以继续分配\n");
    fprintf(stderr, "现在我们把 \"AAAAAAAA\" 这个字符串写到 a 那里 \n");
    strcpy(a, "AAAAAAAA");
    fprintf(stderr, "第一次申请的 %p 指向 %s\n", a, a);

    fprintf(stderr, "接下来 free 掉第一个...\n");
    free(a);

    fprintf(stderr, "接下来只要我们申请一块小于 0x512 的 chunk,那就会分配到原本 a 那里: %p\n", a);

    c = malloc(0x500);
    fprintf(stderr, "第三次 c = malloc(0x500) 在: %p\n", c);
    fprintf(stderr, "我们这次往里写一串 \"CCCCCCCC\" 到刚申请的 c 中\n");
    strcpy(c, "CCCCCCCC");
    fprintf(stderr, "第三次申请的 c %p 指向 %s\n", c, c);
    fprintf(stderr, "第一次申请的 a %p 指向 %s\n", a, a);
    fprintf(stderr, "可以看到,虽然我们刚刚看的是 a 的,但它的内容却是 \"CCCCCCCC\"\n");
}

3.调试程序 

root@pwn_test1604:/ctf/work/how2heap# gdb ./first_fit
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 171 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
Reading symbols from ./first_fit...done.
pwndbg> b 22
Breakpoint 1 at 0x40078b: file first_fit.c, line 22.
pwndbg> b 35
Breakpoint 2 at 0x400893: file first_fit.c, line 35.
pwndbg> r
Starting program: /ctf/work/how2heap/first_fit 
尽管这个例子没有演示攻击效果,但是它演示了 glibc 的分配机制
glibc 使用首次适应算法选择空闲的堆块
如果有一个空闲堆块且足够大,那么 malloc 将选择它
如果存在 use-after-free 的情况那可以利用这一特性
首先申请两个比较大的 chunk
第一个 a = malloc(0x512) 在: 0x603010
第二个 b = malloc(0x256) 在: 0x603530
我们可以继续分配
现在我们把 "AAAAAAAA" 这个字符串写到 a 那里 

Breakpoint 1, main () at first_fit.c:22
22          fprintf(stderr, "第一次申请的 %p 指向 %s\n", a, a);
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x603010 ◂— 'AAAAAAAA'
 RBX  0x0
 RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfff
 RDX  0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0
 RDI  0x2
 RSI  0x4141414141414141 ('AAAAAAAA')
 R8   0x3b
 R9   0x7ffff7dd2540 (_IO_2_1_stderr_) ◂— 0xfbad2887
 R10  0x1
 R11  0x246
 R12  0x400550 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6b0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5d0 —▸ 0x4008c0 (__libc_csu_init) ◂— push   r15
 RSP  0x7fffffffe5b0 —▸ 0x4008c0 (__libc_csu_init) ◂— push   r15
 RIP  0x40078b (main+325) ◂— mov    rax, qword ptr [rip + 0x2018ce]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────
 ► 0x40078b <main+325>    mov    rax, qword ptr [rip + 0x2018ce] <0x602060>
   0x400792 <main+332>    mov    rcx, qword ptr [rbp - 0x18]
   0x400796 <main+336>    mov    rdx, qword ptr [rbp - 0x18]
   0x40079a <main+340>    mov    esi, 0x400b38
   0x40079f <main+345>    mov    rdi, rax
   0x
  • 32
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值