-
Notifications
You must be signed in to change notification settings - Fork 2
/
bootfuzz.asm
426 lines (328 loc) · 7.83 KB
/
bootfuzz.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
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
; BOOTFUZZ
;
; Copyright (c) 2024 Nicholas Starke
; https://github.com/nstarke/bootfuzz
;
; assemble with `nasm -f bin -o bootfuzz.img bootfuzz.asm`
; run in qemu: `qemu-system-i386 -fda bootfuzz.img -nographic -accel kvm`
[bits 16]
; MBR boot sector address
org 0x7c00
start:
; vga video mode bios settings
mov ah, 0x0
mov al, 0x2 ; mov al, 0x2 for 'text mode'
; mov al, 0x12 for 'vga mode'
int 0x10
; vga video memory map
mov ax, 0xb000 ; mov al, 0xb000 (or 0xb800) for 'text mode'
; mov al, 0xa000 for 'vga mode'
mov ds, ax
mov es, ax
; set up code segment
push cs
; set up stack
pop ds
; print banner / options
mov bx, banner_str
call print_string
; read user selection
call read_keyboard
; check if user entered "1" (ASCII - 0x31)
cmp al, 0x31
je fuzz_in
; check if user entered "2" (ASCII - 0x32)
cmp al, 0x32
je fuzz_out
; check if user entered "3" (ASCII - 0x33)
cmp al, 0x33
je fuzz_read
fuzz_read:
; set INT13 operation mode to disk read (0x2)
mov bx, 0x2
push bx
je fuzz_int13
; check if user entered "4" (ASCII - 0x34)
cmp al, 0x34
jne reboot
fuzz_write:
; set INT13 operation mode to disk write
mov bx, 0x3
push bx
je fuzz_int13
; if the user enters anything else, reboot
reboot:
int 0x19
fuzz_in:
; print '\r'
mov al, 0xd
call print_letter
; print '\n'
mov al, 0xa
call print_letter
; print "IN"
mov bx, in_str
call print_string
; put random value in ax
call get_random
; copy first random value into dx so it can be
; supplied to IN later as the 'src' operand.
; also so it can be printed to console
mov dx, ax
call print_hex
; save dx for later to be used with 'in'
push dx
; create second random value
call get_random
; move second random value into cx
mov cx, ax
; put third random value in ax. This will be used as
; the 'dest' operand for IN later, after multiplying by cx.
call get_random
; multiply ax and cx. This is to 'spread' the operand values
; for 'in'. since the BIOS service timer is deterministic,
; it will always produce values that are proximate.
; multiplying helps redistribute the operand values.
mul cx
; take multiplied value and save it on the stack for later
push ax
; move random value into dx so it can be hex
; printed out to console.
mov dx, ax
; print out '-' (dash) character
mov al, 0x2d
call print_letter
; prints out second random value
call print_hex
; restore ax so we can pass it to 'in'
pop ax
; restore dx so we can pass it to 'in'
pop dx
; perform the test by executing 'in'
in ax, dx
; loop forever
jmp fuzz_in
fuzz_out:
; print to console '\r'
mov al, 0xd
call print_letter
; print to console '\n'
mov al, 0xa
call print_letter
; print to console "OUT"
mov bx, out_str
call print_string
; get first random value that will eventually
; be used as the 'dest' operand to 'out'
call get_random
; move first random value into dx so it will be
; the 'dest operand to 'out'
mov dx, ax
; print first random value
call print_hex
; save first random value for later. will be
; pop'd into dx before executing 'in'
push dx
; get second random value
call get_random
; move second random value into cx.
mov cx, ax
; get third random value
call get_random
; multiply second and third random values to
; redistribute operand ranges.
mul cx
; save multiplied random value for later
push ax
; move muliplied random value into dx for printing
mov dx, ax
; print '-' (dash) character to delimit two random
; values
mov al, 0x2d
call print_letter
; print second random value currently stored in dx
call print_hex
; restore ax so it can be used as 'src' operand to
; 'out' instruction.
pop ax
; restore dx so it can be used as the 'dest' operand
; to the 'out' instruction
pop dx
; execute 'out' instruction
out dx, ax
; loop forever
jmp fuzz_out
fuzz_int13:
; print '\r'
mov al, 0xd
call print_letter
; print '\n'
mov al, 0xa
call print_letter
; pop the read/write type into bh.
pop bx
cmp bx, 0x2
; check if we are 'reading' or 'writing'
; and print out the proper string.
je print_read
print_write:
push bx
; print 'write' string
mov bx, write_str
call print_string
; skip 'print_read' logic
jmp continue_disk_fuzz
print_read:
push bx
; print 'read'
mov bx, read_str
call print_string
continue_disk_fuzz:
; get first random value
call get_random
mov dx, ax
; save first random value for later
push dx
; print first random value.
call print_hex
; get second random value
call get_random
; move second random value into cx.
mov cx, ax
; get third random value
call get_random
; multiply second and third random values to
; redistribute operand ranges.
mul cx
; save second random value for later
push ax
; move second random value into dx for printing
mov dx, ax
; print '-' (dash) character to console
mov al, 0x2d
call print_letter
; print second random hex value
call print_hex
; restore second random value
pop ax
; copy second random value into cx as arguments
; for int13 invocation
mov cx, ax
; restoring dx to first random value
pop dx
; copy read/write arg into ah
pop bx
; moving BIOS Service type (read/write) to 'ah'
; which is a parameter to the BIOS Service.
mov ah, bl
; save bx for next iteration
push bx
; invoke the BIOS service (int13)
int 0x13
; loop forever
jmp fuzz_int13
; relies on BIOS Services timer to create
; 'random' values returned in ax.
get_random:
push bx
push cx
push dx
push si
push di
xor ax, ax
in al, (0x40)
mov cl, 2
mov ah, al
in al, (0x40)
pop di
pop si
pop dx
pop cx
pop bx
ret
; Utility functions that aren't very interesting
; Collected from:
; * https://stackoverflow.com/questions/27636985/printing-hex-from-dx-with-nasm
; * https://github.com/nanochess/book8088
print_letter:
pusha
mov ah, 0xe
mov bx, 0xf
int 0x10
popa
ret
print_string:
pusha
print_string_begin:
mov al, [bx]
test al, al
je print_string_end
push bx
call print_letter
pop bx
inc bx
jmp print_string_begin
print_string_end:
popa
ret
print_hex:
pusha
mov si, hex_str + 2
mov cx, 0
next_character:
inc cx
mov bx, dx
and bx, 0xf000
shr bx, 4
add bh, 0x30
cmp bh, 0x39
jg add_7
add_character_hex:
mov [si], bh
inc si
shl dx, 4
cmp cx, 4
jnz next_character
jmp _done
_done:
mov bx, hex_str
call print_string
popa
ret
add_7:
add bh, 0x7
jmp add_character_hex
read_keyboard:
push bx
push cx
push dx
push si
push di
mov ah, 0x0
int 0x16
pop di
pop si
pop dx
pop cx
pop bx
ret
hex_str:
db '0x0000', 0x0
banner_str:
db "Bootfuzz By Nick Starke (https://github.com/nstarke)", 0xa, 0xd, 0xa
db "Select Target:", 0xa, 0xd
db "1) IN", 0xa, 0xd
db "2) OUT", 0xa, 0xd
db "3) Read", 0xa, 0xd
db "4) Write", 0xa, 0xd, 0xa
db "Enter 1-4", 0xa, 0xd, 0x0
in_str:
db "In:", 0x0
out_str:
db "Out:", 0x0
read_str:
db "Read:", 0x0
write_str:
db "Write:", 0x0
times 510-($-$$) db 0
db 0x55,0xaa