1.简介
PE文件插入程序经常用于恶意代码感染其他程序.本文介绍3种方式:空闲空间, 新增节,在最后一个节中插入程序.
2.空闲空间插入程序
大部分PE文件的节因为文件对齐而产生一些空闲空间,所以可以将程序插入到这些空间中,然后修改入口点,或者修改入口点代码跳到该处执行,执行完后跳回
OEP.
程序1:获取PE文件中节的空间可用情况
.386 .model flat, stdcall ;32 bit memory model option casemap :none ;case sensitive include msvcrt.inc include windows.inc include kernel32.inc includelib msvcrt.lib includelib kernel32.lib .data format db '%-10s%-15p',0ah,0dh,0 titleinfo db '名称 可用空间',0ah,0dh,0 titlehead db 'head',0 sectionname dword 0 buffer db 100 dup (0) filename db MAX_PATH dup(0) scanff db '%s',0 imagebase dword 0 psection dword 0 .code loadpe proc @FileName:dword LOCAL hFile LOCAL hMap LOCAL @imagebase pushad invoke CreateFile,@FileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 mov hFile,eax invoke CreateFileMapping,hFile,0,PAGE_READONLY,0,0,0 mov hMap,eax invoke MapViewOfFile,hMap,FILE_MAP_READ,0,0,0 mov @imagebase,eax invoke CloseHandle,hFile invoke CloseHandle,hMap popad mov eax,@imagebase ret loadpe endp unloadpe proc imageBase invoke UnmapViewOfFile,imageBase ret unloadpe endp _RVAToOffset proc _lpFileHead,_dwRVA local @dwReturn pushad mov esi,_lpFileHead assume esi:ptr IMAGE_DOS_HEADER add esi,[esi].e_lfanew assume esi:ptr IMAGE_NT_HEADERS mov edi,_dwRVA mov edx,esi add edx,sizeof IMAGE_NT_HEADERS assume edx:ptr IMAGE_SECTION_HEADER movzx ecx,[esi].FileHeader.NumberOfSections ;遍历节表 .repeat mov eax,[edx].VirtualAddress ;计算该节结束RVA,不用Misc的主要原因是有些段的Misc值是错误的! add eax,[edx].SizeOfRawData .if (edi>=[edx].VirtualAddress)&&(edi<eax) mov eax,[edx].VirtualAddress ;计算RVA在节中的偏移 sub edi,eax mov eax,[edx].PointerToRawData ;加上节在文件中的的起始位置 add eax,edi jmp @F .endif add edx,sizeof IMAGE_SECTION_HEADER .untilcxz assume edx:nothing assume esi:nothing mov eax,-1 @@: mov @dwReturn,eax popad mov eax,@dwReturn ret _RVAToOffset endp start: invoke crt_scanf,offset scanff,offset filename invoke crt_printf,offset titleinfo invoke loadpe,offset filename mov imagebase,eax assume esi:NOTHING assume esi:ptr IMAGE_SECTION_HEADER mov ebx,imagebase assume ebx:ptr IMAGE_DOS_HEADER mov eax,[ebx].e_lfanew add eax,imagebase add eax,4 assume eax:ptr IMAGE_FILE_HEADER movzx edi,[eax].NumberOfSections ; mov edx,eax ; add edx,sizeof IMAGE_FILE_HEADER ; assume edx:ptr IMAGE_OPTIONAL_HEADER32 ; mov edx,[edx].FileAlignment sub eax,4 add eax,sizeof IMAGE_NT_HEADERS32 mov psection,eax assume eax:ptr IMAGE_SECTION_HEADER invoke _RVAToOffset,imagebase,[eax].VirtualAddress mov esi,eax add esi,imagebase ;指向第一个节 ;assume psection:ptr IMAGE_SECTION_HEADER mov ebx,imagebase assume ebx:ptr IMAGE_DOS_HEADER mov eax,[ebx].e_lfanew add eax,sizeof IMAGE_NT_HEADERS32 mov ebx,eax mov ax,di mov ecx,sizeof IMAGE_SECTION_HEADER mul ecx xchg ebx,eax;执行完后,ebx是节表头大小,eax是dos头+nt头大小 add ebx,eax add ebx,imagebase mov eax,esi sub eax,ebx invoke crt_sprintf,offset buffer,offset format,offset titlehead,eax invoke crt_printf,offset buffer ;edi作为计数器,psection指向节表头 .while 1 .break .if edi==0 ;mov ebx,psection ;assume ebx:ptr IMAGE_SECTION_HEADER ; invoke _RVAToOffset,imagebase, ; mov sectionname,eax ; mov eax,imagebase ; add sectionname,eax mov ebx,psection assume ebx:ptr IMAGE_SECTION_HEADER mov eax,[ebx].Misc.VirtualSize;对齐前尺寸 mov ebx,[ebx].SizeOfRawData;对齐后尺寸 sub ebx,eax invoke RtlZeroMemory,offset buffer,100 invoke crt_sprintf, offset buffer,offset format,psection,ebx invoke crt_printf,offset buffer dec edi add psection,sizeof IMAGE_SECTION_HEADER .endw invoke unloadpe,imagebase invoke ExitProcess,0 ;######################################################################## end start
3.新增节中插入程序
(1).将新增节放在文件尾部,而且将该节的节区头增加到节区头部分的最后.
(2).需要做:文件头部修改节数量字段, 在文件头部节区头增加一个IMAGE_SECTION_DESCRIPTOR
实例代码:
4.在最后一节插入程序
(1).在最后一节的空闲空间中插入程序是最简单有效的
(2).思路:
将附加代码附加到最后一节中->修正最后一个节表的字段:SizeOfRawData,PointerToRawData,Characteristics->修正PE文件头字段:
SizeOfImage,AddressEntryPoint