博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
delphi 给EXE文件增加区段
阅读量:5047 次
发布时间:2019-06-12

本文共 8401 字,大约阅读时间需要 28 分钟。

学习 PE 可执行文件格式,用 delphi 实现给 EXE 文件增加区段
unit uStudyPE;interfaceuses  Classes, SysUtils, Windows, uPERec;type  TImage_Section_headerList = class;  TStudyPE = class  private    FFileStream: TFileStream;    FNewStream: TMemoryStream;    FImage_Dos_Header: PImage_DOS_Header;    FImage_NT_Headers: PImage_NT_Headers;    FImage_Section_HeaderList: TImage_Section_headerList;  public    constructor Create;    destructor Destroy; override;  public    procedure LoadPE(AFileName: string);    property Image_Dos_Header: PImage_DOS_Header read FImage_Dos_Header;    property Image_NT_Headers: PImage_NT_Headers read FImage_NT_Headers;    property Image_Section_HeaderList: TImage_Section_headerList read FImage_Section_HeaderList;  end;  TImage_Section_headerList = class(TList)  public    procedure FreeAllItems();    destructor Destroy; override;  end;implementation{
TStudyPE }const Image_Dos_Header_len = SizeOf(TImage_dos_header); Image_NT_Headers_len = SizeOf(TImage_NT_Headers); Image_Section_Header_len = SizeOf(TImage_Section_Header);constructor TStudyPE.Create;begin inherited Create; New(FImage_Dos_Header); New(FImage_NT_Headers); FImage_Section_HeaderList := TImage_Section_headerList.Create; FNewStream := TMemoryStream.Create;end;destructor TStudyPE.Destroy;begin Dispose(FImage_Dos_Header); Dispose(FImage_NT_Headers); FImage_Section_HeaderList.Free; FNewStream.Free; inherited;end;procedure TStudyPE.LoadPE(AFileName: string);var e_lfanew: DWORD; pSecHeader: PImage_Section_header; nNumberOfSections: word; i: integer; nDosStubLen: integer; nSizeOfImage: DWORD; LImage_Section_header: TImage_Section_Header; Rva: DWORD; vaSize: DWORD; SizeOfHeaders: DWORD; // 一般是 $400 NewSectionSize: DWORD; // 新增区段大小begin if Assigned(FFileStream) then begin FFileStream.Free; end; NewSectionSize := $200; FFileStream := TFileStream.Create(AFileName, fmOpenRead); FFileStream.Read(FImage_Dos_Header^, Image_Dos_Header_len); // 读 DOS 头,64字节 FNewStream.Size := FFileStream.Size + NewSectionSize; // 新文件大小 FNewStream.Write(FImage_Dos_Header^, Image_Dos_Header_len); // 将 DOS 头写入新文件 e_lfanew := FImage_Dos_Header.e_lfanew; // 获取 Image_NT_Headers 的位置 nDosStubLen := e_lfanew - Image_Dos_Header_len; // DOS 汇编代码区域长度 // 将 DOS 汇编代码写入新文件,写完后 FFileStream.Position 正好在 Image_NT_Header 的位置上 FFileStream.Read((Pbyte(FNewStream.Memory) + Image_Dos_Header_len)^, nDosStubLen); FNewStream.Position := Image_Dos_Header_len + nDosStubLen; FFileStream.Read(FImage_NT_Headers^, Image_NT_Headers_len); // 获取 Image_NT_Headers SizeOfHeaders := FImage_NT_Headers.Image_Optional_Header32.SizeOfHeaders; nNumberOfSections := FImage_NT_Headers.Image_File_Header.NumberOfSections; // 区段数量 FImage_NT_Headers.Image_File_Header.NumberOfSections := nNumberOfSections + 1; // 增加区段数量 nSizeOfImage := FImage_NT_Headers.Image_Optional_Header32.SizeOfImage; FImage_NT_Headers.Image_Optional_Header32.SizeOfImage := nSizeOfImage + NewSectionSize; // 修改 EXE 所占内存大小 FNewStream.Write(FImage_NT_Headers^, Image_NT_Headers_len); // 将 Image_NT_Headers 写入新文件 FImage_Section_HeaderList.FreeAllItems; for i := 0 to nNumberOfSections - 1 do begin New(pSecHeader); FImage_Section_HeaderList.Add(pSecHeader); FFileStream.Read(pSecHeader^, Image_Section_Header_len); FNewStream.Write(pSecHeader^, Image_Section_Header_len); // 将各个 Image_Section_Header 写入新文件 end; LImage_Section_header := pSecHeader^; // 给新区段命名 LImage_Section_header.Name[0] := ord('.'); LImage_Section_header.Name[1] := ord('N'); LImage_Section_header.Name[2] := ord('E'); LImage_Section_header.Name[3] := ord('W'); LImage_Section_header.Name[4] := ord('T'); LImage_Section_header.Name[5] := ord('E'); LImage_Section_header.Name[6] := ord('S'); LImage_Section_header.Name[7] := ord('T'); // 用最后一个区段作参考计算新增区段的 VirtualAddress,PointerToRawData 的值 // VirtualAddress 是在EXE中虚拟地址 // PointerToRawData 新区段在文件中的位置 Rva := pSecHeader.VirtualAddress; vaSize := ((pSecHeader.Misc.VirtualSize + $FFF) div $1000) * $1000; LImage_Section_header.VirtualAddress := Rva + vaSize; // 新区段的虚拟地址 Rva := pSecHeader.PointerToRawData; vaSize := ((pSecHeader.Misc.VirtualSize + $1FF) div $200) * $200; LImage_Section_header.PointerToRawData := Rva + vaSize; // 新区段的文件中的位置 LImage_Section_header.Misc.VirtualSize := NewSectionSize; LImage_Section_header.SizeOfRawData := NewSectionSize; LImage_Section_header.Characteristics := $50000040; // 区段的属性(读,写,执行) // 要计算位置是否够放新 Section, 未完成,本例所改的 exe 是可以的。 if ((SizeOfHeaders - FFileStream.Position) < Image_Section_Header_len) then begin raise Exception.Create('区段位置不够,本Demo无法操作!'); // 为了简单,所以这样操作了。实际上是可以的,只是每个区段都得重新计算虚拟地址与在文件中的地址 end; FNewStream.Write(LImage_Section_header, Image_Section_Header_len); // 将新增 Image_Section_Header 写入新文件 // 将源文件剩下的数据写入新文件 FFileStream.Seek(SizeOfHeaders, soBeginning); FFileStream.Read((Pbyte(FNewStream.Memory) + SizeOfHeaders)^, FFileStream.Size - SizeOfHeaders); FNewStream.SaveToFile('new.exe');end;{
TImage_Section_headerList }destructor TImage_Section_headerList.Destroy;begin FreeAllItems; inherited;end;procedure TImage_Section_headerList.FreeAllItems;var p: PImage_Section_header;begin for p in self do Dispose(p); Clear;end;end.
uStudyPE.pas
unit uPERec;interfaceuses  Classes, SysUtils, Windows;type // Windows 单元中有这些结构,而我为了学习,从书上重新操作了一遍  PImage_DOS_Header = ^TImage_DOS_Header;  TImage_DOS_Header = packed record    e_magic: WORD; // DOS signature:4D5A ('MZ')    e_cblp: WORD;    e_cp: WORD;    e_crlc: WORD;    e_cparhdr: WORD;    e_minalloc: WORD;    e_maxalloc: WORD;    e_ss: WORD;    e_sp: WORD;    e_csum: WORD;    e_ip: WORD;    e_cs: WORD;    e_lfarlc: WORD;    e_ovno: WORD;    e_res: array [0 .. 3] of WORD;    e_oemid: WORD;    e_oeminfo: WORD;    e_res2: array [0 .. 9] of WORD;    e_lfanew: DWORD; // offset to NT hearder  end;  TImage_Optional_Header32 = _Image_Optional_Header32;  TImage_File_Header = _Image_File_Header;  PImage_NT_Headers = ^TImage_NT_Headers;  TImage_NT_Headers = packed record    Signature: DWORD; // PE Signature: 50450000 ('PE'00)    Image_File_Header: TImage_File_Header;    Image_Optional_Header32: TImage_Optional_Header32;  end;  PImage_File_Header = ^TImage_File_Header;  _Image_File_Header = packed record    Machine: WORD;    NumberOfSections: WORD;    TimeDateStamp: DWORD;    PointerToSymbolTable: DWORD;    NumberOfSymbols: DWORD;    SizeOfOptionalHeader: WORD;    Characteristics: WORD;  end;const  Image_NumberOf_Directory_Entries = 16;type  TImage_Data_Directory = _Image_Data_Directory;  PImage_Optional_Header32 = ^TImage_Optional_Header32;  _Image_Optional_Header32 = packed record    Magic: WORD;    MajorLinkerVersion: BYTE;    MinorLinkerVersion: BYTE;    SizeOfCode: DWORD;    SizeOfInitializedData: DWORD;    SizeOfUninitializedData: DWORD;    AddressOfEntryPoint: DWORD;    BaseOfCode: DWORD;    BaseOfData: DWORD;    ImageBase: DWORD;    SectionAlignment: DWORD;    fileAlignment: DWORD;    MajorOperatingSystemVersion: WORD;    MinorOperatingSystemVersion: WORD;    MajorImageVersion: WORD;    minorImageVersion: WORD;    MajorSubsystemVersion: WORD;    MinorSubsystemVersion: WORD;    Win32VersionValue: DWORD;    SizeOfImage: DWORD;    SizeOfHeaders: DWORD;    checkSum: DWORD;    Subsystem: WORD;    DllCharacteristics: WORD;    SizeOfStackReserve: DWORD;    SizeOfStackCommit: DWORD;    sizeOfHeapReserve: DWORD;    sizeofHeapcommit: DWORD;    LoaderFlags: DWORD;    NumberOfRvaAndSizes: DWORD;    Image_Data_Directory: array [0 .. Image_NumberOf_Directory_Entries - 1] of TImage_Data_Directory;  end;  _Image_Data_Directory = packed record    VirtualAddress: DWORD;    Size: DWORD;  end;const  Image_SizeOf_Short_Name = 8;type  TMisc = packed record    case integer of      0:(PhysicalAddress: DWORD);      1:(VirtualSize: DWORD);  end;  // 此为 C 语言 union 格式 改写而成  //  //  union {
// DWORD PhysicalAddress; // DWORD VirtualSize; // } Misc; // // PImage_Section_Header = ^TImage_Section_Header; TImage_Section_Header = packed record Name: array [0 .. Image_SizeOf_Short_Name - 1] of BYTE; Misc: TMisc; VirtualAddress: DWORD; SizeOfRawData: DWORD; PointerToRawData: DWORD; PointerToRelocations: DWORD; PointerToLineNumbers: DWORD; NumberOfRelocations: WORD; NumberofLineNumbers: WORD; Characteristics: DWORD; end;implementationend.
uPERec.pas

 

转载于:https://www.cnblogs.com/lackey/p/8240988.html

你可能感兴趣的文章
玩转storm
查看>>
浅谈 @RequestParam 和@PathVariable
查看>>
NSEnumerator用法小结
查看>>
Feign使用Hystrix无效原因及解决方法
查看>>
Sam做题记录
查看>>
C++的引用
查看>>
python itertools
查看>>
http://lorempixel.com/ 可以快速产生假图
查看>>
编写一个函数isMerge,判断一个字符串str是否可以由其他两个字符串part1和part2“组合”而成...
查看>>
文件操作
查看>>
NYOJ-613//HDU-1176-免费馅饼,数字三角形的兄弟~~
查看>>
graphite custom functions
查看>>
ssh无密码登陆屌丝指南
查看>>
一个自己写的判断2个相同对象的属性值差异的工具类
查看>>
oracle连接的三个配置文件(转)
查看>>
Java 8 中如何优雅的处理集合
查看>>
[HNOI2012]永无乡 线段树合并
查看>>
Centos下源码安装git
查看>>
控件发布:div2dropdownlist(div模拟dropdownlist控件)
查看>>
[置顶] 细说Cookies
查看>>