Windows的PE加载器在启动程序的时候_第1页
Windows的PE加载器在启动程序的时候_第2页
Windows的PE加载器在启动程序的时候_第3页
Windows的PE加载器在启动程序的时候_第4页
Windows的PE加载器在启动程序的时候_第5页
已阅读5页,还剩53页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Windows的PE加载器在启动程序的时候,会将磁盘上的文件加载到内存,然后做很多操作,如函数导入表重定位,变量预处理之类的。这位仁兄等于是自己写了一个PE加载器。直接将内存中的程序启动。记得以前的“红色代码”病毒也有相同的特性。 直接启动内存中的程序相当于加了一个壳,可以把程序加密保存,运行时解密到内存,然后启动,不过对于增加破解难度还要稍微复杂点。否则人家把内存中的进程DUMP出来然后修复导入表就被拖出来了。 #includestdafx.htypedefIMAGE_SECTION_HEADER(*PIMAGE_SECTION_HEADERS)1;/计算对齐后的大小unsignedlong

2、GetAlignedSize(unsignedlongOrigin,unsignedlongAlignment)return(Origin+Alignment- 1)/Alignment*Alignment;/计算加载pe并对齐需要占用多少内存/未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0unsignedlongCalcTotalImageSize(PIMAGE_DOS_HEADERMzH,unsignedlongFileLen,PIMAGE_NT_HEADERSpeH,PIMAGE_SECTION_HEADERSpeSec

3、H)unsignedlongres;/计算pe头的大小res=GetAlignedSize(peH-OptionalHeader.SizeOfHeaders,peH-OptionalHeader.SectionAlignment);/计算所有节的大小for(inti= 0;iFileHeader.NumberOfSections;+i)/超出文件范围if(peSecHi-PointerToRawData+peSecHi-SizeOfRawDataFileLen)return 0;else if(peSecHi-VirtualAddress)/计算对齐后某节的大小if(peSecHi-Misc.

4、VirtualSize)res=GetAlignedSize(peSecHi-VirtualAddress+peSecHi-Misc.VirtualSize,peH-OptionalHeader.SectionAlignment);elseres=GetAlignedSize(peSecHi-VirtualAddress+peSecHi-SizeOfRawData,peH-OptionalHeader.SectionAlignment);else if(peSecHi-Misc.VirtualSizeSizeOfRawData)res+=GetAlignedSize(peSecHi-SizeO

5、fRawData,peH-OptionalHeader.SectionAlignment);elseres+=GetAlignedSize(peSecHi-Misc.VirtualSize,peH-OptionalHeader.SectionAlignment);/if_else/forreturnres;/加载pe到内存并对齐所有节BOOLAlignPEToMem(void *Buf,longLen,PIMAGE_NT_HEADERS&peH,PIMAGE_SECTION_HEADERS&peSecH,void *&Mem,unsignedlong &ImageSize)PIMAGE_DOS

6、_HEADERSrcMz;/DOS头PIMAGE_NT_HEADERSSrcPeH;/PE头PIMAGE_SECTION_HEADERSSrcPeSecH;/节表SrcMz=(PIMAGE_DOS_HEADER)Buf;if(Lene_magic!=IMAGE_DOS_SIGNATURE)returnFALSE;if(Lene_lfanew+(long)sizeof(IMAGE_NT_HEADERS)returnFALSE;SrcPeH=(PIMAGE_NT_HEADERS)(int)SrcMz+SrcMz-e_lfanew);if(SrcPeH-Signature!=IMAGE_NT_SIG

7、NATURE)returnFALSE;if(SrcPeH-FileHeader.Characteristics&IMAGE_FILE_DLL)|(SrcPeH-FileHeader.Characteristics&IMAGE_FILE_EXECUTABLE_IMAGE= 0)|(SrcPeH-FileHeader.SizeOfOptionalHeader!=sizeof(IMAGE_OPTIONAL_HEADER)returnFALSE;SrcPeSecH=(PIMAGE_SECTION_HEADERS)(int)SrcPeH+sizeof(IMAGE_NT_HEADERS);ImageSiz

8、e=CalcTotalImageSize(SrcMz,Len,SrcPeH,SrcPeSecH);if(ImageSize= 0)returnFALSE;Mem=VirtualAlloc(NULL,ImageSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);/分配内存if(Mem!=NULL)/计算需要复制的PE头字节数unsignedlongl=SrcPeH-OptionalHeader.SizeOfHeaders;for(inti= 0;iFileHeader.NumberOfSections;+i)if(SrcPeSecHi-PointerToRawData

9、)&(SrcPeSecHi-PointerToRawDataPointerToRawData;memmove(Mem,SrcMz,l);peH=(PIMAGE_NT_HEADERS)(int)Mem+(PIMAGE_DOS_HEADER)Mem)-e_lfanew);peSecH=(PIMAGE_SECTION_HEADERS)(int)peH+sizeof(IMAGE_NT_HEADERS);void *Pt=(void *)(unsignedlong)Mem+GetAlignedSize(peH-OptionalHeader.SizeOfHeaders,peH-OptionalHeader

10、.SectionAlignment);for(i= 0;iFileHeader.NumberOfSections;+i)/定位该节在内存中的位置if(peSecHi-VirtualAddress)Pt=(void *)(unsignedlong)Mem+peSecHi-VirtualAddress);if(peSecHi-SizeOfRawData)/复制数据到内存memmove(Pt,(constvoid *)(unsignedlong)(SrcMz)+peSecHi-PointerToRawData),peSecHi-SizeOfRawData);if(peSecHi-Misc.Virtu

11、alSizeSizeOfRawData)Pt=(void *)(unsignedlong)Pt+GetAlignedSize(peSecHi-SizeOfRawData,peH-OptionalHeader.SectionAlignment);else /pt定位到下一节开始位置Pt=(void *)(unsignedlong)Pt+GetAlignedSize(peSecHi-Misc.VirtualSize,peH-OptionalHeader.SectionAlignment);elsePt=(void *)(unsignedlong)Pt+GetAlignedSize(peSecHi-

12、Misc.VirtualSize,peH-OptionalHeader.SectionAlignment);returnTRUE;typedefvoid *(_stdcall*pfVirtualAllocEx)(unsignedlong,void *,unsignedlong,unsignedlong,unsignedlong);pfVirtualAllocExMyVirtualAllocEx=NULL;BOOLIsNT()returnMyVirtualAllocEx!=NULL;/生成外壳程序命令行char *PrepareShellExe(char *CmdParam,unsignedlo

13、ngBaseAddr,unsignedlongImageSize)if(IsNT()char *Buf= new char256;memset(Buf,0,256);GetModuleFileName(0,Buf,256);strcat(Buf,CmdParam);returnBuf;/请记得释放内存;-)else/Win98下的处理请参考原文;-)/ :/ *PImageBaseRelocation;#pragmapack(pop)/重定向PE用到的地址voidDoRelocation(PIMAGE_NT_HEADERSpeH,void *OldBase,void *NewBase)unsi

14、gnedlongDelta=(unsignedlong)NewBase-peH-OptionalHeader.ImageBase;PImageBaseRelocationp=(PImageBaseRelocation)(unsignedlong)OldBase+peH-OptionalHeader.DataDirectoryIMAGE_DIRECTORY_ENTRY_BASERELOC.VirtualAddress);while(p-VirtualAddress+p-SizeOfBlock)unsignedshort *pw=(unsignedshort *)(int)p+sizeof(*p)

15、;for(unsignedinti=1;iSizeOfBlock-sizeof(*p)/ 2;+i)if(*pw)& 0 xF000 = 0 x3000)unsignedlong *t=(unsignedlong *)(unsignedlong)(OldBase)+p-VirtualAddress+(*pw)& 0 x0FFF);*t+=Delta;+pw;p=(PImageBaseRelocation)pw;/卸载原外壳占用内存BOOLUnloadShell(HANDLEProcHnd,unsignedlongBaseAddr)typedefunsignedlong(_stdcall*pfZ

16、wUnmapViewOfSection)(unsignedlong,unsignedlong);pfZwUnmapViewOfSectionZwUnmapViewOfSection=NULL;BOOLres=FALSE;HMODULEm=LoadLibrary(ntdll.dll);if(m)ZwUnmapViewOfSection=(pfZwUnmapViewOfSection)GetProcAddress(m,ZwUnmapViewOfSection);if(ZwUnmapViewOfSection)res=(ZwUnmapViewOfSection(unsignedlong)ProcHn

17、d,BaseAddr)= 0);FreeLibrary(m);returnres;/创建外壳进程并获取其基址、大小和当前运行状态BOOLCreateChild(char *Cmd,CONTEXT&Ctx,HANDLE&ProcHnd,HANDLE&ThrdHnd,unsignedlong &ProcId,unsignedlong &BaseAddr,unsignedlong &ImageSize)STARTUPINFOAsi;PROCESS_INFORMATIONpi;unsignedlongold;MEMORY_BASIC_INFORMATIONMemInfo;memset(&si,0,si

18、zeof(si);memset(&pi,0,sizeof(pi);si.cb=sizeof(si);BOOLres=CreateProcess(NULL,Cmd,NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&si,&pi);/以挂起方式运行进程;if(res)ProcHnd=pi.hProcess;ThrdHnd=pi.hThread;ProcId=pi.dwProcessId;/获取外壳进程运行状态,ctx.Ebx+8内存处存的是外壳进程的加载基址,ctx.Eax存放有外壳进程的入口地址Ctx.ContextFlags=CONTEXT_FULL;Ge

19、tThreadContext(ThrdHnd,&Ctx);ReadProcessMemory(ProcHnd,(void *)(Ctx.Ebx+8),&BaseAddr,sizeof(unsignedlong),&old);/读取加载基址void *p=(void *)BaseAddr;/计算外壳进程占有的内存while(VirtualQueryEx(ProcHnd,p,&MemInfo,sizeof(MemInfo)if(MemInfo.State=MEM_FREE)break;p=(void *)(unsignedlong)p+MemInfo.RegionSize);ImageSize=(

20、unsignedlong)p-(unsignedlong)BaseAddr;returnres;/创建外壳进程并用目标进程替换它然后执行HANDLEAttachPE(char *CmdParam,PIMAGE_NT_HEADERSpeH,PIMAGE_SECTION_HEADERSpeSecH,void *Ptr,unsignedlongImageSize,unsignedlong &ProcId)HANDLEres=INVALID_HANDLE_VALUE;CONTEXTCtx;HANDLEThrd;unsignedlongAddr,Size;char *s=PrepareShellExe(

21、CmdParam,peH-OptionalHeader.ImageBase,ImageSize);if(s=NULL)returnres;if(CreateChild(s,Ctx,res,Thrd,ProcId,Addr,Size)void *p=NULL;unsignedlongold;if(peH-OptionalHeader.ImageBase=Addr)&(Size=ImageSize)/外壳进程可以容纳目标进程并且加载地址一致p=(void *)Addr;VirtualProtectEx(res,p,Size,PAGE_EXECUTE_READWRITE,&old);else if(

22、IsNT()if(UnloadShell(res,Addr)/卸载外壳进程占有内存p=MyVirtualAllocEx(unsignedlong)res,(void *)peH-OptionalHeader.ImageBase,ImageSize,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE);if(p=NULL)&HasRelocationTable(peH)/分配内存失败并且目标进程支持重定向p=MyVirtualAllocEx(unsignedlong)res,NULL,ImageSize,MEM_RESERVE|MEM_COMMIT,PAG

23、E_EXECUTE_READWRITE);if(p)DoRelocation(peH,Ptr,p);/重定向if(p)WriteProcessMemory(res,(void *)(Ctx.Ebx+8),&p,sizeof(DWORD),&old);/重置目标进程运行环境中的基址peH-OptionalHeader.ImageBase=(unsignedlong)p;if(WriteProcessMemory(res,p,Ptr,ImageSize,&old)/复制PE数据到目标进程Ctx.ContextFlags=CONTEXT_FULL;if(unsignedlong)p=Addr)Ctx

24、.Eax=peH-OptionalHeader.ImageBase+peH-OptionalHeader.AddressOfEntryPoint;/重置运行环境中的入口地址elseCtx.Eax=(unsignedlong)p+peH-OptionalHeader.AddressOfEntryPoint;SetThreadContext(Thrd,&Ctx);/更新运行环境ResumeThread(Thrd);/执行CloseHandle(Thrd);else/加载失败,杀掉外壳进程TerminateProcess(res,0);CloseHandle(Thrd);CloseHandle(re

25、s);res=INVALID_HANDLE_VALUE;else/加载失败,杀掉外壳进程TerminateProcess(res,0);CloseHandle(Thrd);CloseHandle(res);res=INVALID_HANDLE_VALUE;deletes;returnres;/*/*从内存中加载并运行exe*参数:*Buffer:内存中的exe地址*Len:内存中exe占用长度*CmdParam:命令行参数(不包含exe文件名的剩余命令行参数)*ProcessId:返回的进程Id*返回值:如果成功则返回进程的Handle(ProcessHandle),如果失败则返回INVALI

26、D_HANDLE_VALUE*/HANDLEMemExecute(void *ABuffer,longLen,char *CmdParam,unsignedlong *ProcessId)HANDLEres=INVALID_HANDLE_VALUE;PIMAGE_NT_HEADERSpeH;PIMAGE_SECTION_HEADERSpeSecH;void *Ptr;unsignedlongpeSz;if(AlignPEToMem(ABuffer,Len,peH,peSecH,Ptr,peSz)res=AttachPE(CmdParam,peH,peSecH,Ptr,peSz,*Process

27、Id);VirtualFree(Ptr,peSz,MEM_DECOMMIT);returnres;/初始化classCInitpublic:CInit()MyVirtualAllocEx=(pfVirtualAllocEx)GetProcAddress(GetModuleHandle(Kernel32.dll),VirtualAllocEx);Init;intAPIENTRYWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnCmdShow)HANDLEhFile=NULL;hFile=:CreateFile

28、(f:SourceFromCsdn2.exe,FILE_ALL_ACCESS,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if(hFile=INVALID_HANDLE_VALUE)return -1;:SetFilePointer(hFile,0,NULL,FILE_BEGIN);DWORDdwFileSize=:GetFileSize(hFile,NULL);LPBYTEpBuf= newBYTEdwFileSize;memset(pBuf,0,dwFileSize);DWORDdwNumberOfBytesRead= 0;:ReadF

29、ile(hFile,pBuf,dwFileSize,&dwNumberOfBytesRead,NULL);:CloseHandle(hFile);unsignedlongulProcessId= 0;MemExecute(pBuf,dwFileSize,&ulProcessId);deletepBuf;return 0;=DELPHI版本=windows似乎只提供了一种启动进程的方法:即必须从一个可执行文件中加载并启动。而下面这段代码就是提供一种可以直接从内存中启动一个exe的变通办法。用途嘛, 也许可以用来保护你的exe,你可以对要保护的 exe 进行任意切分、加密、存储,只要运行时能将ex

30、e的内容正确拼接到一块内存中,就可以直接从内存中启动,而不必不安全地去生成一个临时文件再从临时文件启动进程。另外这段代码也提供了一种自己写exe外壳的简单途径,如果能配合其它各种外壳技术就更好地保护你的exe文件。原理很简单:就是“借尸还魂”,启动一个僵尸进程(NT下可以是自身程序启动的另一个进程),然后在它运行前将其整个替换成内存中的exe内容,待正式运行后执行的就是你的目标代码了。不过代码中还有一些不尽人意的地方,比如在98下运行会留一个僵尸程序的壳在硬盘上(其实那个僵尸程序本身就是一个完整的可执行程序,直接运行的话只显示一条错误信息然后就退出了)。另外由于客观条件限制,代码没有经过充分测

31、试,只在XP下进行了一些初步测试:普通exe都能正常运行,upx压缩过的exe绝大多数情况下都能运行,只有在不能卸载僵尸外壳时才有问题(upx压缩过的exe没有重定向表,无法加载到其它地址运行)。如果有bug望告之,如果有更好的方法特别是能解决98下的遗留尾巴的话希望不吝赐教。 Idle_ (阿呆) * * 从内存中加载并运行exe * * * 参数: * Buffer: 内存中的exe地址 * Len: 内存中exe占用长度 * CmdParam: 命令行参数(不包含exe文件名的剩余命令行参数) * ProcessId: 返回的进程Id * 返回值: 如果成功则返回进程的Handle(Pr

32、ocessHandle), 如果失败则返回INVALID_HANDLE_VALUE * unit PEUnit;interfaceuses windows;function MemExecute(const ABuffer; Len: Integer; CmdParam: string; varProcessId: Cardinal): Cardinal;implementation$R ExeShell.res / 外壳程序模板(98下使用)typeTImageSectionHeaders = array 0.0 of TImageSectionHeader;PImageSectionHea

33、ders = TImageSectionHeaders; 计算对齐后的大小 function GetAlignedSize(Origin, Alignment: Cardinal): Cardinal;beginresult := (Origin + Alignment - 1) div Alignment * Alignment;end; 计算加载pe并对齐需要占用多少内存,未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0 function CalcTotalImageSize(MzH: PImageDosHeader; Fi

34、leLen: Cardinal; peH:PImageNtHeaders;peSecH: PImageSectionHeaders): Cardinal;vari: Integer;begin计算pe头的大小result := GetAlignedSize(PeH.OptionalHeader.SizeOfHeaders,PeH.OptionalHeader.SectionAlignment);计算所有节的大小for i := 0 to peH.FileHeader.NumberOfSections - 1 doif peSecHi.PointerToRawData + peSecHi.Siz

35、eOfRawData FileLen then / 超出文件范围beginresult := 0;exit;endelse if peSecHi.VirtualAddress 0 then /计算对齐后某节的大小if peSecHi.Misc.VirtualSize 0 thenresult := GetAlignedSize(peSecHi.VirtualAddress +peSecHi.Misc.VirtualSize, PeH.OptionalHeader.SectionAlignment)elseresult := GetAlignedSize(peSecHi.VirtualAddre

36、ss + peSecHi.SizeOfRawData,PeH.OptionalHeader.SectionAlignment)else if peSecHi.Misc.VirtualSize peSecHi.SizeOfRawData thenresult := result + GetAlignedSize(peSecHi.SizeOfRawData,peH.OptionalHeader.SectionAlignment)elseresult := result + GetAlignedSize(peSecHi.Misc.VirtualSize,PeH.OptionalHeader.Sect

37、ionAlignment);end; 加载pe到内存并对齐所有节 function AlignPEToMem(const Buf; Len: Integer; var PeH: PImageNtHeaders;var PeSecH: PImageSectionHeaders; var Mem: Pointer; var ImageSize:Cardinal): Boolean;varSrcMz: PImageDosHeader; / DOS头SrcPeH: PImageNtHeaders; / PE头SrcPeSecH: PImageSectionHeaders; / 节表i: Integer

38、;l: Cardinal;Pt: Pointer;beginresult := false;SrcMz := Buf;if Len sizeof(TImageDosHeader) then exit;if SrcMz.e_magic IMAGE_DOS_SIGNATURE then exit;if Len SrcMz._lfanew+Sizeof(TImageNtHeaders) then exit;SrcPeH := pointer(Integer(SrcMz)+SrcMz._lfanew);if (SrcPeH.Signature IMAGE_NT_SIGNATURE) then exit

39、;if (SrcPeH.FileHeader.Characteristics and IMAGE_FILE_DLL 0) or(SrcPeH.FileHeader.Characteristics and IMAGE_FILE_EXECUTABLE_IMAGE = 0)or (SrcPeH.FileHeader.SizeOfOptionalHeader SizeOf(TImageOptionalHeader) then exit;SrcPeSecH := Pointer(Integer(SrcPeH)+SizeOf(TImageNtHeaders);ImageSize := CalcTotalI

40、mageSize(SrcMz, Len, SrcPeH, SrcPeSecH);if ImageSize = 0 thenexit;Mem := VirtualAlloc(nil, ImageSize, MEM_COMMIT,PAGE_EXECUTE_READWRITE); / 分配内存if Mem nil thenbegin/ 计算需要复制的PE头字节数l := SrcPeH.OptionalHeader.SizeOfHeaders;for i := 0 to SrcPeH.FileHeader.NumberOfSections - 1 doif (SrcPeSecHi.PointerToR

41、awData 0) and (SrcPeSecHi.PointerToRawData l) thenl := SrcPeSecHi.PointerToRawData;Move(SrcMz, Mem, l);PeH := Pointer(Integer(Mem) + PImageDosHeader(Mem)._lfanew);PeSecH := Pointer(Integer(PeH) + sizeof(TImageNtHeaders);Pt := Pointer(Cardinal(Mem) +GetAlignedSize(PeH.OptionalHeader.SizeOfHeaders,PeH

42、.OptionalHeader.SectionAlignment);for i := 0 to PeH.FileHeader.NumberOfSections - 1 dobegin/ 定位该节在内存中的位置if PeSecHi.VirtualAddress 0 thenPt := Pointer(Cardinal(Mem) + PeSecHi.VirtualAddress);if PeSecHi.SizeOfRawData 0 thenbegin/ 复制数据到内存Move(Pointer(Cardinal(SrcMz) + PeSecHi.PointerToRawData), pt,PeSe

43、cHi.SizeOfRawData);if peSecHi.Misc.VirtualSize peSecHi.SizeOfRawData thenpt := pointer(Cardinal(pt) + GetAlignedSize(PeSecHi.SizeOfRawData,PeH.OptionalHeader.SectionAlignment)elsept := pointer(Cardinal(pt) + GetAlignedSize(peSecHi.Misc.VirtualSize,peH.OptionalHeader.SectionAlignment);/ pt 定位到下一节开始位置

44、endelsept := pointer(Cardinal(pt) + GetAlignedSize(PeSecHi.Misc.VirtualSize,PeH.OptionalHeader.SectionAlignment);end;result := True;end;end;typeTVirtualAllocEx = function (hProcess: THandle; lpAddress: Pointer;dwSize, flAllocationType: DWORD; flProtect: DWORD): Pointer; stdcall;varMyVirtualAllocEx:

45、TVirtualAllocEx = nil;function IsNT: Boolean;beginresult := Assigned(MyVirtualAllocEx);end; 生成外壳程序命令行 function PrepareShellExe(CmdParam: string; BaseAddr, ImageSize: Cardinal):string;varr, h, sz: Cardinal;p: Pointer;fid, l: Integer;buf: Pointer;peH: PImageNtHeaders;peSecH: PImageSectionHeaders;begin

46、if IsNT then NT 系统下直接使用自身程序作为外壳进程 result := ParamStr(0)+CmdParamelse begin/ 由于98系统下无法重新分配外壳进程占用内存,所以必须保证运行的外壳程序能容纳目标进程并且加载地址一致/ 此处使用的方法是从资源中释放出一个事先建立好的外壳程序,然后通过修改其PE头使其运行时能加载到指定地址并至少能容纳目标进程r := FindResource(HInstance, SHELL_EXE, RT_RCDATA);h := LoadResource(HInstance, r);p := LockResource(h);l := Si

47、zeOfResource(HInstance, r);GetMem(Buf, l);Move(p, Buf, l); / 读到内存FreeResource(h);peH := Pointer(Integer(Buf) + PImageDosHeader(Buf)._lfanew);peSecH := Pointer(Integer(peH) + sizeof(TImageNtHeaders);peH.OptionalHeader.ImageBase := BaseAddr; / 修改PE头重的加载基址if peH.OptionalHeader.SizeOfImage ImageSize the

48、n / 目标比外壳大,修改外壳程序运行时占用的内存beginsz := Imagesize - peH.OptionalHeader.SizeOfImage;Inc(peH.OptionalHeader.SizeOfImage, sz); / 调整总占用内存数Inc(peSecHpeH.FileHeader.NumberOfSections-1.Misc.VirtualSize, sz); / 调整最后一节占用内存数end;/ 生成外壳程序文件名, 为本程序改后缀名得到的/ 由于不想 uses SysUtils (一旦 use 了程序将增大80K左右), 而且偷懒,所以只支持最多运行11个进程

49、,后缀名为.dat, .da0.da9result := ParamStr(0);result := copy(result, 1, length(result) - 4) + .dat;r := 0;while r 10 dobeginfid := CreateFile(pchar(result), GENERIC_READ or GENERIC_WRITE, 0, nil,Create_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);if fid 0 thenbeginresult := copy(result, 1, length(result)-3)+da+Char

50、(r+Byte(0);inc(r);endelse begin/SetFilePointer(fid, Imagesize, nil, 0);/SetEndOfFile(fid);/SetFilePointer(fid, 0, nil, 0);WriteFile(fid, Buf, l, h, nil); / 写入文件CloseHandle(fid);break;end;end;result := result + CmdParam; / 生成命令行FreeMem(Buf);end;end; 是否包含可重定向列表 function HasRelocationTable(peH: PImageN

51、tHeaders): Boolean;beginresult := (peH.OptionalHeader.DataDirectoryIMAGE_DIRECTORY_ENTRY_BASERELOC.VirtualAddress 0)and(peH.OptionalHeader.DataDirectoryIMAGE_DIRECTORY_ENTRY_BASERELOC.Size 0);end;typePImageBaseRelocation= TImageBaseRelocation;TImageBaseRelocation = packed recordVirtualAddress: cardi

52、nal;SizeOfBlock: cardinal;end; 重定向PE用到的地址 procedure DoRelocation(peH: PImageNtHeaders; OldBase, NewBase: Pointer);varDelta: Cardinal;p: PImageBaseRelocation;pw: PWord;i: Integer;beginDelta := Cardinal(NewBase) - peH.OptionalHeader.ImageBase;p := pointer(cardinal(OldBase) +peH.OptionalHeader.DataDire

53、ctoryIMAGE_DIRECTORY_ENTRY_BASERELOC.VirtualAddress);while (p.VirtualAddress + p.SizeOfBlock 0) dobeginpw := pointer(Integer(p) + Sizeof(p);for i := 1 to (p.SizeOfBlock - Sizeof(p) div 2 dobeginif pw and $F000 = $3000 thenInc(PCardinal(Cardinal(OldBase) + p.VirtualAddress + (pw and $0FFF), Delta);in

54、c(pw);end;p := Pointer(pw);end;end;typeTZwUnmapViewOfSection = function (Handle, BaseAdr: Cardinal): Cardinal;stdcall; 卸载原外壳占用内存 function UnloadShell(ProcHnd, BaseAddr: Cardinal): Boolean;varM: HModule;ZwUnmapViewOfSection: TZwUnmapViewOfSection;beginresult := False;m := LoadLibrary(ntdll.dll);if m

55、0 thenbeginZwUnmapViewOfSection := GetProcAddress(m, ZwUnmapViewOfSection);if assigned(ZwUnmapViewOfSection) thenresult := (ZwUnmapViewOfSection(ProcHnd, BaseAddr) = 0);FreeLibrary(m);end;end; 创建外壳进程并获取其基址、大小和当前运行状态 function CreateChild(Cmd: string; var Ctx: TContext; var ProcHnd, ThrdHnd,ProcId, Ba

56、seAddr, ImageSize: Cardinal): Boolean;varsi: TStartUpInfo;pi: TProcessInformation;Old: Cardinal;MemInfo: TMemoryBasicInformation;p: Pointer;beginFillChar(si, Sizeof(si), 0);FillChar(pi, SizeOf(pi), 0);si.cb := sizeof(si);result := CreateProcess(nil, PChar(Cmd), nil, nil, False, Create_SUSPENDED, nil

57、,nil, si, pi); / 以挂起方式运行进程if result thenbeginProcHnd := pi.hProcess;ThrdHnd := pi.hThread;ProcId := pi.dwProcessId; 获取外壳进程运行状态,ctx.Ebx+8内存处存的是外壳进程的加载基址,ctx.Eax存放有外壳进程的入口地址 ctx.ContextFlags := CONTEXT_FULL;GetThreadContext(ThrdHnd, ctx);ReadProcessMemory(ProcHnd, Pointer(ctx.Ebx+8), BaseAddr,SizeOf(C

58、ardinal), Old); / 读取加载基址p := Pointer(BaseAddr); 计算外壳进程占有的内存 while VirtualQueryEx(ProcHnd, p, MemInfo, Sizeof(MemInfo) 0 dobeginif MemInfo.State = MEM_FREE thenbreak;p := Pointer(Cardinal(p) + MemInfo.RegionSize);end;ImageSize := Cardinal(p) - Cardinal(BaseAddr);end;end; 创建外壳进程并用目标进程替换它然后执行 function

59、AttachPE(CmdParam: string; peH: PImageNtHeaders; peSecH:PImageSectionHeaders;Ptr: Pointer; ImageSize: Cardinal; var ProcId: Cardinal): Cardinal;vars: string;Addr, Size: Cardinal;ctx: TContext;Old: Cardinal;p: Pointer;Thrd: Cardinal;beginresult := INVALID_HANDLE_VALUE;s := PrepareShellExe(CmdParam, p

60、eH.OptionalHeader.ImageBase, ImageSize);if CreateChild(s, ctx, result, Thrd, ProcId, Addr, Size) thenbeginp := nil;if (peH.OptionalHeader.ImageBase = Addr) and (Size = ImageSize) then / 外壳进程可以容纳目标进程并且加载地址一致beginp := Pointer(Addr);VirtualProtectEx(result, p, Size, PAGE_EXECUTE_READWRITE, Old);endelse

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论