text:
{$region 'constants'}
const
// Max length of short section name.
  IMAGE_SIZEOF_SHORT_NAME = 8;

// 3.1 Section Flags
// The section flags in the Characteristics field of the section
// header indicate characteristics of the section.
const
                                 // = $00000000;  //	Reserved for future use.
                                 //	= $00000001;  //  Reserved for future use.
                                 //	= $00000002;  //  Reserved for future use.
                                 // = $00000004;  //  Reserved for future use.
  IMAGE_SCN_TYPE_NO_PAD	            = $00000008;  //	The section should not be padded to the next boundary.
                                                  //  This flag is obsolete and is replaced by
                                                  //  IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files.
                                 // = $00000010	  //  Reserved for future use.
  IMAGE_SCN_CNT_CODE	              = $00000020;  //	The section contains executable code.
  IMAGE_SCN_CNT_INITIALIZED_DATA	  = $00000040;  //	The section contains initialized data.
  IMAGE_SCN_CNT_UNINITIALIZED_DATA  = $00000080;  //	The section contains uninitialized data.
  IMAGE_SCN_LNK_OTHER	              = $00000100;  //	Reserved for future use.
  IMAGE_SCN_LNK_INFO	              = $00000200;  //	The section contains comments or other information.
                                                  //  The .drectve section has this type. This is valid for object files only.
                                //  = $00000400	  //  Reserved for future use.
  IMAGE_SCN_LNK_REMOVE	            = $00000800;  //	The section will not become part of the image. This is valid only for object files.
  IMAGE_SCN_LNK_COMDAT	            = $00001000;  //	The section contains COMDAT data.
  IMAGE_SCN_GPREL	                  = $00008000;  //	The section contains data referenced through the global pointer (GP).
  IMAGE_SCN_MEM_PURGEABLE	          = $00020000;  //	Reserved for future use.
  IMAGE_SCN_MEM_16BIT	              = $00020000;  //	For ARM machine types, the section contains Thumb code.
                                                  //  Reserved for future use with other machine types.
  IMAGE_SCN_MEM_LOCKED	            = $00040000;  //	Reserved for future use.
  IMAGE_SCN_MEM_PRELOAD	            = $00080000;  //	Reserved for future use.
  IMAGE_SCN_ALIGN_1BYTES	          = $00100000;  //	Align data on a 1-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_2BYTES	          = $00200000;  //	Align data on a 2-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_4BYTES	          = $00300000;  //	Align data on a 4-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_8BYTES	          = $00400000;  //	Align data on an 8-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_16BYTES	          = $00500000;  //	Align data on a 16-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_32BYTES	          = $00600000;  //	Align data on a 32-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_64BYTES	          = $00700000;  //	Align data on a 64-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_128BYTES	        = $00800000;  //	Align data on a 128-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_256BYTES	        = $00900000;  //	Align data on a 256-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_512BYTES	        = $00A00000;  //	Align data on a 512-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_1024BYTES	        = $00B00000;  //	Align data on a 1024-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_2048BYTES	        = $00C00000;  //	Align data on a 2048-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_4096BYTES	        = $00D00000;  //	Align data on a 4096-byte boundary. Valid only for object files.
  IMAGE_SCN_ALIGN_8192BYTES	        = $00E00000;  //	Align data on an 8192-byte boundary. Valid only for object files.
  IMAGE_SCN_LNK_NRELOC_OVFL	        = $01000000;  //	The section contains extended relocations.
  IMAGE_SCN_MEM_DISCARDABLE	        = $02000000;  //	The section can be discarded as needed.
  IMAGE_SCN_MEM_NOT_CACHED	        = $04000000;  //	The section cannot be cached.
  IMAGE_SCN_MEM_NOT_PAGED	          = $08000000;  //	The section is not pageable.
  IMAGE_SCN_MEM_SHARED	            = $10000000;  //	The section can be shared in memory.
  IMAGE_SCN_MEM_EXECUTE	            = $20000000;  //	The section can be executed as code.
  IMAGE_SCN_MEM_READ	              = $40000000;  //	The section can be read.
  IMAGE_SCN_MEM_WRITE	              = $80000000;  //	The section can be written to.
{$endregion 'constants'}


text:
unit PE.Types.FileHeader;

interface

// 2.3.1. Machine Types
const
  IMAGE_FILE_MACHINE_UNKNOWN          = $0;     // The contents of this field are assumed to be applicable to any machine type
  IMAGE_FILE_MACHINE_AM33             = $1D3;   // Matsushita AM33
  IMAGE_FILE_MACHINE_AMD64            = $8664;  // x64
  IMAGE_FILE_MACHINE_ARM              = $1C0;   // ARM little endian
  IMAGE_FILE_MACHINE_ARMV7            = $1C4;   // ARMv7 (or higher) Thumb mode only
  IMAGE_FILE_MACHINE_EBC              = $EBC;   // EFI byte code
  IMAGE_FILE_MACHINE_I386             = $14C;   // Intel 386 or later processors and compatible processors
  IMAGE_FILE_MACHINE_IA64             = $200;   // Intel Itanium processor family
  IMAGE_FILE_MACHINE_M32R             = $9041;  // Mitsubishi M32R little endian
  IMAGE_FILE_MACHINE_MIPS16           = $266;   // MIPS16
  IMAGE_FILE_MACHINE_MIPSFPU          = $366;   // MIPS with FPU
  IMAGE_FILE_MACHINE_MIPSFPU16        = $466;   // MIPS16 with FPU
  IMAGE_FILE_MACHINE_POWERPC          = $1F0;   // Power PC little endian
  IMAGE_FILE_MACHINE_POWERPCFP        = $1F1;   // Power PC with floating point support
  IMAGE_FILE_MACHINE_R4000            = $166;   // MIPS little endian
  IMAGE_FILE_MACHINE_SH3              = $1A2;   // Hitachi SH3
  IMAGE_FILE_MACHINE_SH3DSP           = $1A3;   // Hitachi SH3 DSP
  IMAGE_FILE_MACHINE_SH4              = $1A6;   // Hitachi SH4
  IMAGE_FILE_MACHINE_SH5              = $1A8;   // Hitachi SH5
  IMAGE_FILE_MACHINE_THUMB            = $1C2;   // ARM or Thumb (“interworking”)
  IMAGE_FILE_MACHINE_WCEMIPSV2        = $169;   // MIPS little-endian WCE v2

// 2.3.2. Characteristics
  IMAGE_FILE_RELOCS_STRIPPED	        = $0001;  // Image only, Windows CE, and Windows NT® and later. This indicates that the file does not contain base relocations and must therefore be loaded at its preferred base address. If the base address is not available, the loader reports an error. The default behavior of the linker is to strip base relocations from executable (EXE) files.
  IMAGE_FILE_EXECUTABLE_IMAGE	        = $0002;  // Image only. This indicates that the image file is valid and can be run. If this flag is not set, it indicates a linker error.
  IMAGE_FILE_LINE_NUMS_STRIPPED	      = $0004;	// COFF line numbers have been removed. This flag is deprecated and should be zero.
  IMAGE_FILE_LOCAL_SYMS_STRIPPED	    = $0008;	// COFF symbol table entries for local symbols have been removed. This flag is deprecated and should be zero.
  IMAGE_FILE_AGGRESSIVE_WS_TRIM	      = $0010;	// Obsolete. Aggressively trim working set. This flag is deprecated for Windows 2000 and later and must be zero.
  IMAGE_FILE_LARGE_ADDRESS_AWARE	    = $0020;	// Application can handle > 2 GB addresses.
//                                      $0040	  // This flag is reserved for future use.
  IMAGE_FILE_BYTES_REVERSED_LO	      = $0080;  // Little endian: the least significant bit (LSB) precedes the most significant bit (MSB) in memory. This flag is deprecated and should be zero.
  IMAGE_FILE_32BIT_MACHINE	          = $0100;  // Machine is based on a 32-bit-word architecture.
  IMAGE_FILE_DEBUG_STRIPPED	          = $0200;  // Debugging information is removed from the image file.
  IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP	= $0400;  // If the image is on removable media, fully load it and copy it to the swap file.
  IMAGE_FILE_NET_RUN_FROM_SWAP	      = $0800;  // If the image is on network media, fully load it and copy it to the swap file.
  IMAGE_FILE_SYSTEM	                  = $1000;  // The image file is a system file, not a user program.
  IMAGE_FILE_DLL	                    = $2000;  // The image file is a dynamic-link library (DLL). Such files are considered executable files for almost all purposes, although they cannot be directly run.
  IMAGE_FILE_UP_SYSTEM_ONLY	          = $4000;  // The file should be run only on a uniprocessor machine.
  IMAGE_FILE_BYTES_REVERSED_HI      	= $8000;  // Big endian: the MSB precedes the LSB in memory. This flag is deprecated and should be zero.

// 2.4. Optional Header (Image Only)
  PE_MAGIC_PE32     = $10b;
  PE_MAGIC_PE32PLUS = $20b;

// 2.4.2. Optional Header Windows-Specific Fields (Image Only)
// Windows Subsystem
  IMAGE_SUBSYSTEM_UNKNOWN	                = 0;	//  An unknown subsystem
  IMAGE_SUBSYSTEM_NATIVE	                = 1;	//  Device drivers and native Windows processes
  IMAGE_SUBSYSTEM_WINDOWS_GUI	            = 2;	//  The Windows graphical user interface (GUI) subsystem
  IMAGE_SUBSYSTEM_WINDOWS_CUI	            = 3;	//  The Windows character subsystem
  IMAGE_SUBSYSTEM_POSIX_CUI	              = 7;	//  The Posix character subsystem
  IMAGE_SUBSYSTEM_WINDOWS_CE_GUI	        = 9;  //	Windows CE
  IMAGE_SUBSYSTEM_EFI_APPLICATION	        = 10;	//  An Extensible Firmware Interface (EFI) application
  IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11; //	An EFI driver with boot services
  IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER      = 12; //	An EFI driver with run-time services
  IMAGE_SUBSYSTEM_EFI_ROM	                = 13; //	An EFI ROM image
  IMAGE_SUBSYSTEM_XBOX	                  = 14; //	XBOX

// DLL Characteristics
//RESERVED_0x0001                                 = $0001;  // Reserved, must be zero.
//RESERVED_0x0002                                 = $0002;  // Reserved, must be zero.
//RESERVED_0x0004                                 = $0004;  // Reserved, must be zero.
//RESERVED_0x0008                                 = $0008;  // Reserved, must be zero.
  IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE          = $0040;  // DLL can be relocated at load time.
  IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY       = $0080;  // Code Integrity checks are enforced.
  IMAGE_DLL_CHARACTERISTICS_NX_COMPAT             = $0100;  // Image is NX compatible.
  IMAGE_DLLCHARACTERISTICS_NO_ISOLATION           = $0200;  // Isolation aware, but do not isolate the image.
  IMAGE_DLLCHARACTERISTICS_NO_SEH                 = $0400;  // Does not use structured exception (SE) handling. No SE handler may be called in this image.
  IMAGE_DLLCHARACTERISTICS_NO_BIND                = $0800;  // Do not bind the image.
//RESERVED_0x1000                                 = $1000;  // Reserved, must be zero.
  IMAGE_DLLCHARACTERISTICS_WDM_DRIVER             = $2000;  // A WDM driver.
  IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE  = $8000;  // Terminal Server aware.

type
  TImageFileHeader = packed record
    Machine: uint16;
    NumberOfSections: uint16;
    TimeDateStamp: uint32;
    PointerToSymbolTable: uint32;
    NumberOfSymbols: uint32;
    SizeOfOptionalHeader: uint16;
    Characteristics: uint16;
  end;

  PImageFileHeader = ^TImageFileHeader;

implementation

end.

repo_name: vdisasm/pe-image-for-delphi

repo_language: Pascal

mime_type: text/plain


text:
{
  Module to convert constants of PE.Types.FileHeader to string.
}
unit PE.FileHeaderToStr;

interface

uses
  PE.Image,
  PE.Types.FileHeader;

function MachineToStr(PE: TPEImage): string;

implementation

function MachineToStr(PE: TPEImage): string;
begin
  case PE.FileHeader^.Machine of
    IMAGE_FILE_MACHINE_UNKNOWN:
      Result := ''; // The contents of this field are assumed to be applicable to any machine type
    IMAGE_FILE_MACHINE_AM33:
      Result := 'Matsushita AM33';
    IMAGE_FILE_MACHINE_AMD64:
      Result := 'x64';
    IMAGE_FILE_MACHINE_ARM:
      Result := 'ARM little endian';
    IMAGE_FILE_MACHINE_ARMV7:
      Result := 'ARMv7 (or higher) Thumb mode only';
    IMAGE_FILE_MACHINE_EBC:
      Result := 'EFI byte code';
    IMAGE_FILE_MACHINE_I386:
      Result := 'Intel 386 and compatible processors';
    IMAGE_FILE_MACHINE_IA64:
      Result := 'Intel Itanium processor family';
    IMAGE_FILE_MACHINE_M32R:
      Result := 'Mitsubishi M32R little endian';
    IMAGE_FILE_MACHINE_MIPS16:
      Result := 'MIPS16';
    IMAGE_FILE_MACHINE_MIPSFPU:
      Result := 'MIPS with FPU';
    IMAGE_FILE_MACHINE_MIPSFPU16:
      Result := 'MIPS16 with FPU';
    IMAGE_FILE_MACHINE_POWERPC:
      Result := 'Power PC little endian';
    IMAGE_FILE_MACHINE_POWERPCFP:
      Result := 'Power PC with floating point support';
    IMAGE_FILE_MACHINE_R4000:
      Result := 'MIPS little endian';
    IMAGE_FILE_MACHINE_SH3:
      Result := 'Hitachi SH3';
    IMAGE_FILE_MACHINE_SH3DSP:
      Result := 'Hitachi SH3 DSP';
    IMAGE_FILE_MACHINE_SH4:
      Result := 'Hitachi SH4';
    IMAGE_FILE_MACHINE_SH5:
      Result := 'Hitachi SH5';
    IMAGE_FILE_MACHINE_THUMB:
      Result := 'ARM or Thumb (“interworking”)';
    IMAGE_FILE_MACHINE_WCEMIPSV2:
      Result := 'MIPS little-endian WCE v2';
    else
      Result := 'Unknown Machine';
  end;
end;

end.


text:
# pe-image-for-delphi

This is Delphi library to work with Portable Executable Image files.
The main purpose is to make parsing image structures of 32/64 bit image easy.
Now it can parse most used things, like: sections, imports, exports, resources and tls.

Also it can write image, but that was not primary goal.

ToDo:

- There must be introduced sparsed/paged virtual memory concept (just like Windows does)
  Currently all section data is loaded into memory.
  Some virus samples tested can crash loading because of using too big virtual address range.
  With normal compiler generated images you won't have such problem.


text:
unit WinHelper;

interface

uses
  System.Generics.Collections,
  System.SysUtils,

  WinApi.TlHelp32,
  WinApi.Windows;

type
  TProcessRec = record
    PID: DWORD;
    Name: string;
    constructor Create(PID: DWORD; const Name: string);
  end;

  TProcessRecList = TList<TProcessRec>;

  TModuleRec = TModuleEntry32;

  TModuleRecList = TList<TModuleRec>;

  // return True to continue enumeration or False to stop it.
  TEnumProcessesCallback = reference to function(const pe: TProcessEntry32): boolean;
  TEnumModulesCallback = reference to function(const me: TModuleEntry32): boolean;

  // Enumerate processes with callback. Result is False if there was error.
function EnumProcesses(cb: TEnumProcessesCallback): boolean;

// Enumerate processes to list. Result is False if there was error.
function EnumProcessesToList(List: TProcessRecList): boolean;

type
  // Used to compare strings.
  TStringMatchKind = (
    MATCH_STRING_WHOLE, // string equals to X
    MATCH_STRING_START, // string starts with X
    MATCH_STRING_END,   // string ends with X
    MATCH_STRING_PART   // string contains X
    );

function FindPIDByProcessName(
  const Name: string;
  out PID: DWORD;
  Match: TStringMatchKind = MATCH_STRING_WHOLE): boolean;

// Enumerate modules with callback. Result is False if there was error.
function EnumModules(PID: DWORD; cb: TEnumModulesCallback): boolean;

// Enumerate modules to list. Result is False if there was error.
function EnumModulesToList(PID: DWORD; List: TModuleRecList): boolean;

type
  // Used in FindModule to test if this is the module we search.
  // Return True on match.
  TFindModuleChecker = reference to function(const me: TModuleEntry32): boolean;

  // Find module by custom condition.
function FindModule(PID: DWORD; out value: TModuleEntry32; Checker: TFindModuleChecker): boolean;

// Find module by address that belongs to this module.
function FindModuleByAddress(PID: DWORD; Addr: NativeUInt; out me: TModuleEntry32): boolean;

// Find module by module name.
function FindModuleByName(PID: DWORD; const Name: string): boolean;

// Find main process module (exe).
function FindMainModule(PID: DWORD; out me: TModuleEntry32): boolean;

function SetPrivilegeByName(const Name: string; State: boolean): boolean;

function SetDebugPrivilege(State: boolean): boolean;

implementation

function EnumProcesses(cb: TEnumProcessesCallback): boolean;
var
  hShot, hShotMod: THandle;
  pe: TProcessEntry32;
begin
  // Create process snapshot.
  hShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if hShot = INVALID_HANDLE_VALUE then
    exit(false);

  // Traverse it.
  try
    ZeroMemory(@pe, SizeOf(pe));
    pe.dwSize := SizeOf(pe);

    if not Process32First(hShot, pe) then
      exit(false);

    repeat
      // Add process only if we can query its module list.
      hShotMod := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe.th32ProcessID);
      if hShotMod <> INVALID_HANDLE_VALUE then
      begin
        CloseHandle(hShotMod);
        if not cb(pe) then
          break;
      end;
    until not Process32Next(hShot, pe);

    exit(True);
  finally
    CloseHandle(hShot);
  end;
end;

function EnumProcessesToList(List: TProcessRecList): boolean;
begin
  List.Clear;
  result := EnumProcesses(
    function(const pe: TProcessEntry32): boolean
    begin
      List.Add(TProcessRec.Create(pe.th32ProcessID, pe.szExeFile));
      result := True;
    end);
end;

function CompareStringsWithMachKind(const s1, s2: string; kind: TStringMatchKind): boolean;
begin
  case kind of
    MATCH_STRING_WHOLE:
      result := s1.Equals(s2);
    MATCH_STRING_START:
      result := s1.StartsWith(s2);
    MATCH_STRING_END:
      result := s1.EndsWith(s2);
    MATCH_STRING_PART:
      result := s1.Contains(s2);
  else
    result := false;
  end;
end;

function FindPIDByProcessName(const Name: string; out PID: DWORD; Match: TStringMatchKind): boolean;
var
  tmpName: string;
  foundPID: DWORD;
begin
  tmpName := Name.ToUpper;
  foundPID := 0;

  EnumProcesses(
    function(const pe: TProcessEntry32): boolean
    begin
      if CompareStringsWithMachKind(string(pe.szExeFile).ToUpper, tmpName, Match) then
      begin
        foundPID := pe.th32ProcessID;
        exit(false); // don't continue search, already found
      end;
      exit(True); // continue search
    end);

  PID := foundPID;
  result := foundPID <> 0;
end;

function EnumModules(PID: DWORD; cb: TEnumModulesCallback): boolean;
var
  hShot: THandle;
  me: TModuleEntry32;
begin
  hShot := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, PID);
  if hShot = INVALID_HANDLE_VALUE then
    exit(false);

  try
    ZeroMemory(@me, SizeOf(me));
    me.dwSize := SizeOf(me);

    if not Module32First(hShot, me) then
      exit(false);

    repeat
      if not cb(me) then
        break;
    until not Module32Next(hShot, me);

    exit(True);
  finally
    CloseHandle(hShot);
  end;
end;

function EnumModulesToList(PID: DWORD; List: TModuleRecList): boolean;
begin
  List.Clear;
  result := EnumModules(PID,
    function(const me: TModuleEntry32): boolean
    begin
      List.Add(me);
      exit(True);
    end);
end;

function FindModule(PID: DWORD; out value: TModuleEntry32; Checker: TFindModuleChecker): boolean;
var
  found: boolean;
  tmp: TModuleEntry32;
begin
  found := false;
  EnumModules(PID,
    function(const me: TModuleEntry32): boolean
    begin
      if Checker(me) then
      begin
        tmp := me;
        found := True;
        exit(false);
      end;
      exit(True);
    end);

  if found then
    value := tmp
  else
    fillchar(value, SizeOf(value), 0);

  exit(found);
end;

function FindModuleByAddress(PID: DWORD; Addr: NativeUInt; out me: TModuleEntry32): boolean;
begin
  result := FindModule(PID, me,
    function(const me: TModuleEntry32): boolean
    begin
      result :=
        (Addr >= NativeUInt(me.modBaseAddr)) and
        (Addr < NativeUInt(me.modBaseAddr + me.modBaseSize));
    end);
end;

function FindModuleByName(PID: DWORD; const Name: string): boolean;
var
  tmpName: string;
  me: TModuleEntry32;
begin
  tmpName := name.ToUpper;
  result := FindModule(PID, me,
    function(const me: TModuleEntry32): boolean
    begin
      result := string(me.szModule).ToUpper.Equals(tmpName);
    end);
end;

function FindMainModule(PID: DWORD; out me: TModuleEntry32): boolean;
begin
  result := FindModule(PID, me,
    function(const me: TModuleEntry32): boolean
    begin
      result := True; // first module is main one
    end);
end;

// http://msdn.microsoft.com/en-us/library/windows/desktop/aa446619(v=vs.85).aspx
function SetPrivilege(
  hToken: THandle;      // access token handle
lpszPrivilege: LPCTSTR; // name of privilege to enable/disable
bEnablePrivilege: BOOL  // to enable or disable privilege
  ): boolean;
var
  tp: TOKEN_PRIVILEGES;
  luid: int64;
  Status: DWORD;
  ReturnLength: DWORD;
begin
  if LookupPrivilegeValue(
    nil,         // lookup privilege on local system
  lpszPrivilege, // privilege to lookup
  luid)          // receives LUID of privilege
  then
  begin
    tp.PrivilegeCount := 1;
    tp.Privileges[0].luid := luid;
    if bEnablePrivilege then
      tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
    else
      tp.Privileges[0].Attributes := 0;

    // Enable the privilege or disable all privileges.
    if AdjustTokenPrivileges(hToken, false, tp, SizeOf(TOKEN_PRIVILEGES), nil, ReturnLength) then
    begin
      Status := GetLastError();
      if Status = ERROR_SUCCESS then
        exit(True);
    end;
  end;

  exit(false);
end;

function SetPrivilegeByName(const Name: string; State: boolean): boolean;
var
  hToken: THandle;
begin
  if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES, hToken) then
    exit(false);
  result := SetPrivilege(hToken, LPCTSTR(Name), State);
  CloseHandle(hToken);
end;

function SetDebugPrivilege(State: boolean): boolean;
begin
  result := SetPrivilegeByName('SeDebugPrivilege', State);
end;

{ TProcessRec }

constructor TProcessRec.Create(PID: DWORD; const Name: string);
begin
  self.PID := PID;
  self.Name := Name;
end;

end.


text:
unit PE.DataDirectories;

interface

uses
  System.Classes,
  System.SysUtils,

  PE.Common,
  PE.Msg,
  PE.Section,
  PE.Sections,
  PE.Types.Directories,
  PE.Utils;

type
  TDataDirectories = class
  private
    FPE: TObject; // TPEImage
    FItems: array of TImageDataDirectory;
    function GetCount: integer; inline;
    procedure SetCount(const Value: integer);
  public
    constructor Create(APE: TObject);

    procedure Clear;

    procedure NullInvalid(const Msg: TMsgMgr);

    // Load array of TImageDataDirectory (va,size) from stream.
    procedure LoadDirectoriesFromStream(
      Stream: TStream;
      const Msg: TMsgMgr;
      DeclaredCount: uint32; // # of rva and sizes
      MaxBytes: uint16
      );

    // Save array of TImageDataDirectory (va,size) to stream.
    // Return saved size.
    function SaveDirectoriesToStream(Stream: TStream): integer;

    // Check if index is in item range.
    function IsGoodIndex(Index: integer): boolean; inline;

    // Get TImageDataDirectory by Index.
    // Result is True if Index exists.
    // OutDir is optional and can be nil.
    function Get(Index: integer; OutDir: PImageDataDirectory): boolean;

    // Get directory name.
    function GetName(Index: integer): string;

    // Put directory safely. If Index > than current item count, empty items
    // will be added.
    procedure Put(Index: integer; const Dir: TImageDataDirectory); overload;

    procedure Put(Index: integer; RVA, Size: uint32); overload;

    // If Index exists set RVA and Size to 0.
    procedure Null(Index: integer);

    // Check if directory by Index occuppies whole section. If it's true,
    // result is section. Otherwise result is nil.
    function GetSectionDedicatedToDir(Index: integer;
      AlignSize: boolean = False): TPESection;

    // Get index of directory, which occupies whole Section. Result is -1 if
    // not found.
    function GetDirDedicatedToSection(Section: TPESection; AlignSize: boolean = False): integer;

    // Save data pointed by directory RVA and Size to file.
    // Index is directory index.
    function SaveToStream(Index: integer; Stream: TStream): boolean;
    function SaveToFile(Index: integer; const FileName: string): boolean;

    // Load data into memory pointed by directory RVA and Size.
    // Index is directory index.
    // Offset is file offset where to start reading from.
    // Result is True if complete size was read.
    function LoadFromStream(Index: integer; Stream: TStream; Offset: uint64): boolean;
    function LoadFromFile(Index: integer; const FileName: string; Offset: uint64): boolean;

    property Count: integer read GetCount write SetCount;
  end;

implementation

uses
  // Expand
  PE.Headers,
  PE.Image;

{ TDataDirectories }

procedure TDataDirectories.Clear;
begin
  FItems := nil;
  self.Count := 0;
end;

constructor TDataDirectories.Create(APE: TObject);
begin
  self.FPE := APE;
end;

function TDataDirectories.GetSectionDedicatedToDir(Index: integer;
  AlignSize: boolean): TPESection;
var
  Dir: TImageDataDirectory;
  sec: TPESection;
  ExpectedSize, VSize: uint32;
  img: TPEImage;
begin
  Result := nil;
  if not Get(Index, @Dir) then
    exit;
  if Dir.IsEmpty then
    exit;
  img := TPEImage(FPE);
  if not img.Sections.RVAToSec(Dir.VirtualAddress, @sec) then
    exit;
  if (sec.RVA <> Dir.VirtualAddress) then
    exit;
  if AlignSize then
  begin
    ExpectedSize := AlignUp(Dir.Size, img.SectionAlignment);
    VSize := AlignUp(sec.VirtualSize, img.SectionAlignment);
  end
  else
  begin
    ExpectedSize := Dir.Size;
    VSize := sec.VirtualSize;
  end;
  if (VSize = ExpectedSize) then
    Result := sec;
end;

function TDataDirectories.IsGoodIndex(Index: integer): boolean;
begin
  Result := (Index >= 0) and (Index < Length(FItems));
end;

function TDataDirectories.Get(Index: integer; OutDir: PImageDataDirectory): boolean;
begin
  Result := IsGoodIndex(Index);
  if Result and Assigned(OutDir) then
    OutDir^ := FItems[Index];
end;

procedure TDataDirectories.Put(Index: integer; const Dir: TImageDataDirectory);
begin
  if Index >= Length(FItems) then
    SetLength(FItems, Index + 1)
  else if Index < 0 then
    Index := 0;
  FItems[Index] := Dir;
end;

procedure TDataDirectories.Put(Index: integer; RVA, Size: uint32);
var
  d: TImageDataDirectory;
begin
  d.RVA := RVA;
  d.Size := Size;
  Put(Index, d);
end;

procedure TDataDirectories.Null(Index: integer);
begin
  if (Index >= 0) and (Index < Length(FItems)) then
    FItems[Index] := NULL_IMAGE_DATA_DIRECTORY;
end;

function TDataDirectories.GetCount: integer;
begin
  Result := Length(FItems);
end;

function TDataDirectories.GetDirDedicatedToSection(Section: TPESection; AlignSize: boolean = False): integer;
var
  i: integer;
begin
  for i := 0 to Length(FItems) - 1 do
  begin
    if GetSectionDedicatedToDir(i, AlignSize) = Section then
      exit(i);
  end;
  exit(-1);
end;

function TDataDirectories.GetName(Index: integer): string;
begin
  if IsGoodIndex(Index) then
    Result := GetDirectoryName(index)
  else
    Result := '';
end;

procedure TDataDirectories.NullInvalid(const Msg: TMsgMgr);
var
  i: integer;
  needToNullDir: boolean;
begin
  // Check RVAs.
  for i := 0 to self.Count - 1 do
  begin
    // Empty dir is ok.
    if FItems[i].IsEmpty then
      continue;

    needToNullDir := False;

    if (FItems[i].Size = 0) and (FItems[i].RVA <> 0) then
    begin
      Msg.Write(SCategoryDataDirecory, 'Directory # %d has size = 0.', [i]);
      needToNullDir := true;
    end
    else if not TPEImage(FPE).RVAExists(FItems[i].RVA) then
    begin
      Msg.Write(SCategoryDataDirecory, 'Directory # %d RVA is not in image.', [i]);
      needToNullDir := true;
    end;

    if needToNullDir and (PO_NULL_INVALID_DIRECTORY in TPEImage(FPE).Options) then
    begin
      FItems[i] := NULL_IMAGE_DATA_DIRECTORY;
      Msg.Write(SCategoryDataDirecory, 'Directory # %d nulled.', [i]);
    end;
  end;
end;

procedure TDataDirectories.LoadDirectoriesFromStream;
var
  MaxCountPossible: integer;
  CountToRead: integer;
  SizeToFileEnd: uint64;
  Size: uint32;
  MaxSizePossible: uint16;
begin
  Clear;

  if DeclaredCount = 0 then
  begin
    Msg.Write(SCategoryDataDirecory, 'No data directories.');
    exit;
  end;

  SizeToFileEnd := (Stream.Size - Stream.Position);

  // Max size available for dirs.
  if SizeToFileEnd > MaxBytes then
    MaxSizePossible := MaxBytes
  else
    MaxSizePossible := SizeToFileEnd;

  MaxCountPossible := MaxSizePossible div SizeOf(TImageDataDirectory);

  // File can have part of dword stored. It must be extended with zeros.
  if (MaxSizePossible mod SizeOf(TImageDataDirectory)) <> 0 then
    inc(MaxCountPossible);

  if DeclaredCount <> TYPICAL_NUMBER_OF_DIRECTORIES then
    Msg.Write(SCategoryDataDirecory, 'Non-usual count of directories declared (0x%x).', [DeclaredCount]);

  if DeclaredCount > MaxCountPossible then
  begin
    CountToRead := MaxCountPossible;

    Msg.Write(SCategoryDataDirecory,
      'Declared count of directories is greater than file can contain (0x%x > 0x%x).',
      [DeclaredCount, MaxCountPossible]);
    Msg.Write(SCategoryDataDirecory, 'Fall back to 0x%x.', [MaxCountPossible]);
  end
  else
  begin
    CountToRead := DeclaredCount;
  end;

  // Read data directories.

  Size := CountToRead * SizeOf(TImageDataDirectory);
  SetLength(FItems, CountToRead);

  // Must clear buffer, cause it can have partial values (filled with zeros).
  FillChar(FItems[0], Size, 0);

  // Not all readed size/rva can be valid. You must check rvas before use.
  Stream.Read(FItems[0], Size);

  // Set final count.
  self.Count := CountToRead;

  NullInvalid(Msg);
end;

function TDataDirectories.SaveToStream(Index: integer; Stream: TStream): boolean;
var
  Dir: TImageDataDirectory;
begin
  if Get(Index, @Dir) then
  begin
    TPEImage(FPE).SaveRegionToStream(Stream, Dir.VirtualAddress, Dir.Size);
    exit(true);
  end;
  exit(False);
end;

function TDataDirectories.SaveToFile(Index: integer; const FileName: string): boolean;
var
  fs: TFileStream;
begin
  fs := TFileStream.Create(FileName, fmCreate);
  try
    Result := SaveToStream(Index, fs);
  finally
    fs.Free;
  end;
end;

function TDataDirectories.LoadFromStream(Index: integer; Stream: TStream; Offset: uint64): boolean;
var
  Dir: TImageDataDirectory;
  ReadCount: uint32;
begin
  if Get(Index, @Dir) then
  begin
    TPEImage(FPE).LoadRegionFromStream(Stream, Offset, Dir.VirtualAddress, Dir.Size, @ReadCount);
    exit(ReadCount = Dir.Size);
  end;
  exit(False);
end;

function TDataDirectories.LoadFromFile(Index: integer; const FileName: string; Offset: uint64): boolean;
var
  fs: TFileStream;
begin
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    Result := LoadFromStream(Index, fs, Offset);
  finally
    fs.Free;
  end;
end;

function TDataDirectories.SaveDirectoriesToStream(Stream: TStream): integer;
begin
  Result := Stream.Write(FItems[0], Length(FItems) * SizeOf(TImageDataDirectory))
end;

procedure TDataDirectories.SetCount(const Value: integer);
begin
  SetLength(FItems, Value);
  TPEImage(FPE).OptionalHeader.NumberOfRvaAndSizes := Value;
end;

end.


text:
{
  Load and map module into current process.
  Module MUST have relocations or be RIP-addressed to be loaded normally.
}
unit PE.ExecutableLoader;

interface

uses
  System.Classes,
  System.Generics.Collections,

  WinApi.Windows,

  PE.Common,
  PE.Image;

type
  TMapStatus = (
    msOK,
    msImageAlreadyMapped,
    msError,
    msImageSizeError,
    msMapSectionsError,
    msSectionAllocError,
    msProtectSectionsError,
    msImportLibraryNotFound,
    msImportNameNotFound,
    msImportOrdinalNotFound,
    msEntryPointFailure
    );

  TMapStatusHelper = record helper for TMapStatus
    function ToString: string;
  end;

  TExecutableLoadingOption = (
    // Write PE header into start of allocated image.
    elo_MapHeader,

    // Apply fixups after image mapping.
    elo_FixRelocations,

    // Resolve imported functions after image mapping.
    elo_FixImports,

    // Apply protection defined in section header to mapped sections.
    elo_ProtectSections,

    // Call EXE or DLL entry point when image mapped.
    elo_CallEntryPoint
    );

  TExecutableLoadingOptions = set of TExecutableLoadingOption;

const
  DEFAULT_OPTIONS = [
    elo_MapHeader,
    elo_FixRelocations,
    elo_FixImports,
    elo_ProtectSections,
    elo_CallEntryPoint
    ];

type
  TEXEEntry = procedure(); stdcall;
  TDLLEntry = function(hInstDLL: HINST; fdwReason: DWORD; lpvReserved: LPVOID): BOOL; stdcall;

  TLoadedModules = TDictionary<string, HMODULE>;

  TExecutableModule = class
  private
    FPE: TPEImage;
    FOptions: TExecutableLoadingOptions;
    FInstance: NativeUInt;
    FEntry: Pointer;
    FSizeOfImage: UInt32;
    FLoadedImports: TLoadedModules;
    function Check(const Desc: string; var rslt: TMapStatus; ms: TMapStatus): boolean;

    function MapSections(PrefferedVa: UInt64): TMapStatus;
    function MapHeader: TMapStatus;
    function ProtectSections: TMapStatus;
    function Relocate: TMapStatus;
    function LoadImports: TMapStatus;

    procedure UnloadImports;
  public
    constructor Create(PE: TPEImage);
    destructor Destroy; override;

    function IsImageMapped: boolean; inline;

    function Load(
      PrefferedVa: UInt64 = 0;
      Options: TExecutableLoadingOptions = DEFAULT_OPTIONS): TMapStatus;

    function Unload: boolean;

    property Instance: NativeUInt read FInstance;
  end;

implementation

uses
  System.SysUtils,

  PE.Types.FileHeader,
  PE.Utils,
  PE.Sections,
  PE.Image.Saving,

  PE.Imports,
  PE.Imports.Func,
  PE.Imports.Lib,

  PE.MemoryStream,
  PE.Section,
  PE.Types.Relocations;

function HasBits(Value, mask: DWORD): boolean; inline;
begin
  Result := (Value and mask) <> 0;
end;

function CharacteristicsToProtect(CH: DWORD): DWORD;
var
  X, R, W, C: boolean;
begin
  Result := 0;

  X := HasBits(CH, IMAGE_SCN_MEM_EXECUTE);
  R := HasBits(CH, IMAGE_SCN_MEM_READ);
  W := HasBits(CH, IMAGE_SCN_MEM_WRITE);
  C := HasBits(CH, IMAGE_SCN_MEM_NOT_CACHED);

  if X then
  begin
    if R then
    begin
      if W then
        Result := Result or PAGE_EXECUTE_READWRITE
      else
        Result := Result or PAGE_EXECUTE_READ;
    end
    else if W then
      Result := Result or PAGE_EXECUTE_WRITECOPY
    else
      Result := Result or PAGE_EXECUTE;
  end
  else if R then
  begin
    if W then
      Result := Result or PAGE_READWRITE
    else
      Result := Result or PAGE_READONLY;
  end
  else if W then
    Result := Result or PAGE_WRITECOPY
  else
  begin
    Result := Result or PAGE_NOACCESS;
  end;

  if C then
    Result := Result or PAGE_NOCACHE;
end;

function min(d1, d2: DWORD): DWORD;
begin
  if d1 < d2 then
    Result := d1
  else
    Result := d2;
end;

{ TExecutableModule }

function TExecutableModule.Check(const Desc: string; var rslt: TMapStatus;
  ms: TMapStatus): boolean;
begin
  rslt := ms;
  Result := ms = msOK;

  if Result then
    FPE.Msg.Write(Desc + ' .. OK.')
  else
    FPE.Msg.Write(Desc + ' .. failed.')
end;

constructor TExecutableModule.Create(PE: TPEImage);
begin
  FPE := PE;
  FLoadedImports := TLoadedModules.Create;
end;

destructor TExecutableModule.Destroy;
begin
  Unload;
  FLoadedImports.Free;
  inherited;
end;

function TExecutableModule.IsImageMapped: boolean;
begin
  Result := FInstance <> 0;
end;

function TExecutableModule.MapSections(PrefferedVa: UInt64): TMapStatus;
var
  i: integer;
  sec: TPESection;
  size: DWORD;
  va: pbyte;
begin
  Result := msMapSectionsError;

  FSizeOfImage := FPE.CalcVirtualSizeOfImage;

  if FSizeOfImage = 0 then
    exit(msImageSizeError);

  // Reserve and commit memory for image.
  FInstance := NativeUInt(VirtualAlloc(
    Pointer(PrefferedVa),
    FSizeOfImage,
    MEM_RESERVE or MEM_COMMIT,
    PAGE_READWRITE
    ));

  if FInstance = 0 then
    exit(msSectionAllocError);

  // copy sections and header
  // todo: header

  for i := 0 to FPE.Sections.Count - 1 do
  begin
    sec := FPE.Sections[i];
    if sec.VirtualSize <> 0 then
    begin
      va := pbyte(FInstance) + sec.RVA;
      size := min(sec.VirtualSize, sec.RawSize);
      if not FPE.SeekRVA(sec.RVA) then
        exit;
      FPE.Read(va, size);
    end;
  end;

  Result := msOK;
end;

function TExecutableModule.MapHeader: TMapStatus;
var
  ms: TPECustomMemoryStream;
begin
  if not(elo_MapHeader in FOptions) then
    exit(msOK);

  ms := TPECustomMemoryStream.CreateFromPointer(Pointer(FInstance), FSizeOfImage);
  try
    // Write header as-is without recalcualtions.
    if not SaveHeaders(FPE, ms, False) then
      exit(msError);
  finally
    ms.Free;
  end;

  exit(msOK);
end;

function TExecutableModule.LoadImports: TMapStatus;
var
  ImpLib: TPEImportLibrary;
  Fn: TPEImportFunction;
  ImpLibName: String;
  hmod: HMODULE;
  proc: Pointer;
  RVA: TRVA;
  va: TVA;
  ModuleMustBeFreed: boolean;
begin
  if not(elo_FixImports in FOptions) then
    exit(msOK);

  for ImpLib in FPE.Imports.Libs do
  begin
    ImpLibName := ImpLib.Name;

    FPE.Msg.Write('Processing import module: "%s"', [ImpLibName]);

    // Check if module already in address space.
    hmod := GetModuleHandle(PChar(ImpLibName));
    ModuleMustBeFreed := hmod = 0;

    // Try make system load lib from default paths.
    if hmod = 0 then
      hmod := LoadLibrary(PChar(ImpLibName));
    // Try load from dir, where image located.
    if (hmod = 0) and (FPE.FileName <> '') then
    begin
      hmod := LoadLibrary(PChar(ExtractFilePath(FPE.FileName) + ImpLibName));
    end;
    // If lib not found, raise.
    if hmod = 0 then
    begin
      FPE.Msg.Write('Imported module "%s" not loaded.', [ImpLibName]);
      // It's either not found, or its dependencies not found.
      exit(msImportLibraryNotFound);
    end;

    // Module found.
    if ModuleMustBeFreed then
      FLoadedImports.Add(ImpLibName, hmod);

    // Process import functions.
    RVA := ImpLib.IatRva;

    for Fn in ImpLib.Functions do
    begin
      // Find imported function.

      // By Name.
      if Fn.Name <> '' then
      begin
        proc := GetProcAddress(hmod, PChar(Fn.Name));
        if proc = nil then
        begin
          FPE.Msg.Write('Imported name "%s" not found.', [Fn.Name]);
          exit(msImportNameNotFound);
        end;
      end
      else
      // By Ordinal.
      begin
        proc := GetProcAddress(hmod, PAnsiChar(Fn.Ordinal));
        if proc = nil then
        begin
          FPE.Msg.Write('Imported ordinal "%d" not found.', [Fn.Ordinal]);
          exit(msImportOrdinalNotFound);
        end;
      end;

      // Patch.
      va := FInstance + RVA;
      if FPE.Is32bit then
        PUINT(va)^ := UInt32(proc)
      else if FPE.Is64bit then
        PUInt64(va)^ := UInt64(proc);

      inc(RVA, FPE.ImageWordSize);
    end;

    // inc(RVA, FPE.ImageWordSize); // null
  end;
  Result := msOK;
end;

function TExecutableModule.ProtectSections: TMapStatus;
var
  i: integer;
  sec: TPESection;
  prot: cardinal;
  va: pbyte;
  dw: DWORD;
begin
  if not(elo_ProtectSections in FOptions) then
    exit(msOK);

  for i := 0 to FPE.Sections.Count - 1 do
  begin
    Result := msProtectSectionsError;
    sec := FPE.Sections[i];
    if sec.VirtualSize <> 0 then
    begin
      va := Pointer(FInstance);
      inc(va, sec.RVA);
      prot := CharacteristicsToProtect(sec.Flags);
      if not VirtualProtect(va, sec.VirtualSize, prot, dw) then
        exit;
    end;
  end;
  Result := msOK;
end;

function TExecutableModule.Relocate: TMapStatus;
var
  Reloc: TReloc;
  Delta: UInt32;
  pDst: PCardinal;
begin
  if not(elo_FixRelocations in FOptions) then
    exit(msOK);

  Delta := FInstance - FPE.ImageBase;

  if Delta = 0 then
    exit(msOK); // no relocation needed

  for Reloc in FPE.Relocs.Items do
  begin
    case Reloc.&Type of
      IMAGE_REL_BASED_HIGHLOW:
        begin
          pDst := PCardinal(FInstance + Reloc.RVA);
          inc(pDst^, Delta);
        end;
    else
      raise Exception.CreateFmt('Unsupported relocation type: %d', [Reloc.&Type]);
    end;
  end;
  Result := msOK;
end;

function TExecutableModule.Load(
  PrefferedVa: UInt64;
  Options: TExecutableLoadingOptions): TMapStatus;
var
  EntryOK: boolean;
begin
  if IsImageMapped then
    exit(msImageAlreadyMapped);

  Result := msError;

  FOptions := Options;

  if
    Check('Map Sections', Result, MapSections(PrefferedVa)) and
    Check('Map Header', Result, MapHeader()) and
    Check('Fix Relocation', Result, Relocate()) and
    Check('Fix Imports', Result, LoadImports()) and
    Check('Protect Sections', Result, ProtectSections()) then
  begin
    if FPE.EntryPointRVA = 0 then
      FEntry := nil
    else
      FEntry := Pointer(FInstance + FPE.EntryPointRVA);

    // If don't need to call entry or there is no entry just skip this part
    if (not Assigned(FEntry)) or (not(elo_CallEntryPoint in FOptions)) then
      EntryOK := True
      // Call Entry Point.
    else if FPE.IsDLL then
    begin
      FPE.Msg.Write('Calling DLL Entry with DLL_PROCESS_ATTACH.');
      EntryOK := TDLLEntry(FEntry)(FInstance, DLL_PROCESS_ATTACH, nil);
      if not EntryOK then
        FPE.Msg.Write('DLL returned FALSE.');
    end
    else
    begin
      FPE.Msg.Write('Calling EXE Entry.');
      TEXEEntry(FEntry)();
      EntryOK := True;
    end;

    if EntryOK then
      exit(msOK)
    else
      Result := msEntryPointFailure;
  end;

  // If something failed.
  Unload;
end;

function TExecutableModule.Unload: boolean;
begin
  if not IsImageMapped then
    exit(True);

  if (elo_CallEntryPoint in FOptions) and Assigned(FEntry) then
  begin
    // DLL finalization.
    if FPE.IsDLL then
    begin
      FPE.Msg.Write('Calling DLL Entry with DLL_PROCESS_DETACH.');
      TDLLEntry(FEntry)(FInstance, DLL_PROCESS_DETACH, nil);
    end;
  end;

  // Unload imported libraries.
  UnloadImports;

  // Free image memory
  VirtualFree(Pointer(FInstance), FSizeOfImage, MEM_RELEASE);
  FInstance := 0;

  Result := True;
end;

procedure TExecutableModule.UnloadImports;
var
  Pair: TPair<string, HMODULE>;
begin
  for Pair in FLoadedImports do
  begin
    FPE.Msg.Write('Unloading import "%s"', [Pair.Key]);
    FreeLibrary(Pair.Value);
  end;
  FLoadedImports.Clear;
end;

{ TMapStatusHelper }

const
  MapStatusText: array [TMapStatus] of string = (
    'OK',
    'Image already mapped',
    'Error',
    'Image size error',
    'Map sections error',
    'Section allocation error',
    'Protect sections error',
    'Import library not found',
    'Import name not found',
    'Import ordinal not found',
    'Entry point failure'
    );

function TMapStatusHelper.ToString: string;
begin
  if self in [low(TMapStatus) .. high(TMapStatus)] then
    Result := MapStatusText[self]
  else
    Result := '???';
end;

end.


text:
program test;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Windows,
  SysUtils,
  PE.Common,
  PE.Image,
  PE.Imports.Lib,
  PE.Imports.Func,
  PE.Build,
  PE.Section;

const
  NORMAL_EXIT_CODE = $C0DE;
  SRC_FILENAME = 'test.exe';
  DST_FILENAME = 'test.out.exe';

procedure Log(text: string);
begin
  WriteLn(Format('[%4x] %s', [GetCurrentProcessId(), text]));
end;

function RunWithParam(exe: string; param: string = ''): boolean;
var
  cmdLine: string;
  si: TStartupInfo;
  pi: TProcessInformation;
  code: dword;
begin
  cmdLine := param;

  ZeroMemory(@si, sizeof(si));
  si.cb := sizeof(si);

  ZeroMemory(@pi, sizeof(pi));

  if (CreateProcess(Pointer(exe), Pointer(cmdLine), nil, nil, false, 0, nil, nil, si, pi)) then
  begin
    WaitForSingleObject(pi.hProcess, INFINITE);
    if (GetExitCodeProcess(pi.hProcess, code)) then
    begin
      CloseHandle(pi.hThread);
      CloseHandle(pi.hProcess);
      exit(code = NORMAL_EXIT_CODE);
    end;
  end;

  exit(false);
end;

procedure WritePushDword(img: TPEImage; value: dword);
var
  rec: packed record
    op: byte;
    value: dword;
  end;
begin
  rec.op := $68;
  rec.value := value;
  img.Write(rec, sizeof(rec));
end;

function GetIatEntryAddr(img: TPEImage; lib: TPEImportLibrary; fn: TPEImportFunction): NativeUInt;
var
  i: integer;
begin
  for i := 0 to lib.Functions.Count - 1 do
    if (lib.Functions[i] = fn) then
      exit(lib.IatRva + i * img.ImageWordSize);

  raise Exception.Create('Function not found');
end;

procedure WriteCall(img: TPEImage; lib: TPEImportLibrary; fn: TPEImportFunction);
var
  rec: packed record
    op1, op2: byte;
    addr: NativeUInt;
  end;
begin
  rec.op1 := $FF;
  rec.op2 := $15;
  rec.addr := img.RVAToVA(GetIatEntryAddr(img, lib, fn));
  img.Write(rec, sizeof(rec));
end;

procedure WriteJmpRel(img: TPEImage; dst: TRVA);
var
  rec: packed record
    op: byte;
    delta: dword;
  end;
begin
  rec.op := $E9;
  rec.delta := dst - (img.PositionRVA + sizeof(rec));
  img.Write(rec, sizeof(rec));
end;

procedure TestImportRebuilding();
var
  img: TPEImage;
  oep: TRVA;
  sec: TPESection;
  lib: TPEImportLibrary;
  fn: TPEImportFunction;
begin
  img := TPEImage.Create();
  try
    if (img.LoadFromFile(SRC_FILENAME)) then
    begin
      lib :=  img.Imports.NewLib(kernel32);
      fn := lib.NewFunction('Beep');

      if (ReBuildDirData(img, DDIR_IMPORT, true) <> nil) then
      begin
        // Make some code to call beep at new entry point (in new section).
        // Then jump to original entry point.
        // Without relocations to make it simpler.
        oep := img.EntryPointRVA;
        sec := img.Sections.AddNew('.my', 32, $60000020, nil);
        img.EntryPointRVA := sec.RVA;

        img.SeekRVA(sec.RVA);
        WritePushDword(img, 1000); // dwDuration
        WritePushDword(img, 5000); // dwFreq
        WriteCall(img, lib, fn);
        WriteJmpRel(img, oep);

        // Save to file and try to run.
        img.SaveToFile(DST_FILENAME);

        if (RunWithParam(DST_FILENAME)) then
        begin
          Log('Import rebuilt OK');
        end
        else
        begin
          Log('Rebuilt image failed');
        end;
      end
      else
      begin
        Log('Failed to rebuld imports');
      end;
    end
    else
    begin
      Log('Failed to parse image');
    end;
  finally
    img.Free();
  end;

  RunWithParam(SRC_FILENAME);
end;

begin
  if (ParamStr(1) = 'test') then
  begin
    Log('Test call');
    TestImportRebuilding();
  end
  else
  begin
    Log('Normal call');
    Halt(NORMAL_EXIT_CODE);
  end;
end.


text:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <ProjectGuid>{23EDE4FD-3EED-4768-8648-7FDA314EC334}</ProjectGuid>
        <ProjectVersion>18.2</ProjectVersion>
        <FrameworkType>None</FrameworkType>
        <MainSource>test.dpr</MainSource>
        <Base>True</Base>
        <Config Condition="'$(Config)'==''">Debug</Config>
        <Platform Condition="'$(Platform)'==''">Win32</Platform>
        <TargetedPlatforms>1</TargetedPlatforms>
        <AppType>Console</AppType>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
        <Base_Win32>true</Base_Win32>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
        <Base_Win64>true</Base_Win64>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
        <Cfg_1>true</Cfg_1>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
        <Cfg_1_Win32>true</Cfg_1_Win32>
        <CfgParent>Cfg_1</CfgParent>
        <Cfg_1>true</Cfg_1>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
        <Cfg_2>true</Cfg_2>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Base)'!=''">
        <DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
        <DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
        <DCC_E>false</DCC_E>
        <DCC_N>false</DCC_N>
        <DCC_S>false</DCC_S>
        <DCC_F>false</DCC_F>
        <DCC_K>false</DCC_K>
        <DCC_UsePackage>RESTComponents;emsclientfiredac;FireDACIBDriver;emsclient;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;$(DCC_UsePackage)</DCC_UsePackage>
        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
        <SanitizedProjectName>test</SanitizedProjectName>
        <VerInfo_Locale>1033</VerInfo_Locale>
        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Base_Win32)'!=''">
        <DCC_UsePackage>DBXSqliteDriver;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;DataSnapFireDAC;tethering;svnui;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;svn;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;TeeDB;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;rtl;vclwinx;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
        <BT_BuildType>Debug</BT_BuildType>
        <DCC_ConsoleTarget>true</DCC_ConsoleTarget>
        <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
        <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
        <Manifest_File>(None)</Manifest_File>
        <Debugger_RunParams>test</Debugger_RunParams>
        <DCC_UnitSearchPath>..;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Base_Win64)'!=''">
        <DCC_UsePackage>DBXSqliteDriver;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;TeeDB;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;rtl;vclwinx;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
        <DCC_ConsoleTarget>true</DCC_ConsoleTarget>
        <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
        <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_1)'!=''">
        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
        <DCC_DebugDCUs>true</DCC_DebugDCUs>
        <DCC_Optimize>false</DCC_Optimize>
        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
        <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
        <DCC_RemoteDebug>true</DCC_RemoteDebug>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
        <DCC_RemoteDebug>false</DCC_RemoteDebug>
        <VerInfo_Locale>1033</VerInfo_Locale>
        <Manifest_File>(None)</Manifest_File>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_2)'!=''">
        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
        <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
        <DCC_DebugInformation>0</DCC_DebugInformation>
    </PropertyGroup>
    <ItemGroup>
        <DelphiCompile Include="$(MainSource)">
            <MainSource>MainSource</MainSource>
        </DelphiCompile>
        <BuildConfiguration Include="Release">
            <Key>Cfg_2</Key>
            <CfgParent>Base</CfgParent>
        </BuildConfiguration>
        <BuildConfiguration Include="Base">
            <Key>Base</Key>
        </BuildConfiguration>
        <BuildConfiguration Include="Debug">
            <Key>Cfg_1</Key>
            <CfgParent>Base</CfgParent>
        </BuildConfiguration>
    </ItemGroup>
    <ProjectExtensions>
        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
        <Borland.ProjectType>Application</Borland.ProjectType>
        <BorlandProject>
            <Delphi.Personality>
                <Source>
                    <Source Name="MainSource">test.dpr</Source>
                </Source>
                <Excluded_Packages>
                    <Excluded_Packages Name="$(BDSBIN)\dcloffice2k250.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
                    <Excluded_Packages Name="$(BDSBIN)\dclofficexp250.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
                </Excluded_Packages>
            </Delphi.Personality>
            <Deployment Version="3">
                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
                    <Platform Name="OSX32">
                        <Overwrite>true</Overwrite>
                    </Platform>
                </DeployFile>
                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
                    <Platform Name="iOSSimulator">
                        <Overwrite>true</Overwrite>
                    </Platform>
                </DeployFile>
                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule">
                    <Platform Name="iOSSimulator">
                        <Overwrite>true</Overwrite>
                    </Platform>
                </DeployFile>
                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule">
                    <Platform Name="OSX32">
                        <Overwrite>true</Overwrite>
                    </Platform>
                </DeployFile>
                <DeployFile LocalName="Win32\Debug\test.exe" Configuration="Debug" Class="ProjectOutput">
                    <Platform Name="Win32">
                        <RemoteName>test.exe</RemoteName>
                        <Overwrite>true</Overwrite>
                    </Platform>
                </DeployFile>
                <DeployClass Name="AdditionalDebugSymbols">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="Win32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>0</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidClassesDexFile">
                    <Platform Name="Android">
                        <RemoteDir>classes</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidGDBServer">
                    <Platform Name="Android">
                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidLibnativeArmeabiFile">
                    <Platform Name="Android">
                        <RemoteDir>library\lib\armeabi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidLibnativeMipsFile">
                    <Platform Name="Android">
                        <RemoteDir>library\lib\mips</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidServiceOutput">
                    <Platform Name="Android">
                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidSplashImageDef">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidSplashStyles">
                    <Platform Name="Android">
                        <RemoteDir>res\values</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_DefaultAppIcon">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_LauncherIcon144">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-xxhdpi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_LauncherIcon36">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-ldpi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_LauncherIcon48">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-mdpi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_LauncherIcon72">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-hdpi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_LauncherIcon96">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-xhdpi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_SplashImage426">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-small</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_SplashImage470">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-normal</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_SplashImage640">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-large</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_SplashImage960">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-xlarge</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="DebugSymbols">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="DependencyFramework">
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                        <Extensions>.framework</Extensions>
                    </Platform>
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="DependencyModule">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                        <Extensions>.dll;.bpl</Extensions>
                    </Platform>
                </DeployClass>
                <DeployClass Required="true" Name="DependencyPackage">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                        <Extensions>.bpl</Extensions>
                    </Platform>
                </DeployClass>
                <DeployClass Name="File">
                    <Platform Name="Android">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPad_Launch1024">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPad_Launch1536">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPad_Launch2048">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPad_Launch768">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPhone_Launch320">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPhone_Launch640">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPhone_Launch640x1136">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectAndroidManifest">
                    <Platform Name="Android">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectiOSDeviceDebug">
                    <Platform Name="iOSDevice32">
                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectiOSDeviceResourceRules">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectiOSEntitlements">
                    <Platform Name="iOSDevice32">
                        <RemoteDir>..\</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <RemoteDir>..\</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectiOSInfoPList">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectiOSResource">
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectOSXEntitlements">
                    <Platform Name="OSX32">
                        <RemoteDir>..\</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectOSXInfoPList">
                    <Platform Name="OSX32">
                        <RemoteDir>Contents</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectOSXResource">
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\Resources</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Required="true" Name="ProjectOutput">
                    <Platform Name="Android">
                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="Linux64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectUWPManifest">
                    <Platform Name="Win32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="Win64">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="UWP_DelphiLogo150">
                    <Platform Name="Win32">
                        <RemoteDir>Assets</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="Win64">
                        <RemoteDir>Assets</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="UWP_DelphiLogo44">
                    <Platform Name="Win32">
                        <RemoteDir>Assets</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="Win64">
                        <RemoteDir>Assets</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
                <ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
                <ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
                <ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
                <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
                <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
                <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
                <ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
            </Deployment>
            <Platforms>
                <Platform value="Win32">True</Platform>
                <Platform value="Win64">False</Platform>
            </Platforms>
        </BorlandProject>
        <ProjectFileVersion>12</ProjectFileVersion>
    </ProjectExtensions>
    <Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
    <Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
    <Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
</Project>


text:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <ProjectGuid>{AF087879-1975-4DCF-9B3C-3EAEF3EDE92D}</ProjectGuid>
    </PropertyGroup>
    <ItemGroup>
        <Projects Include="00 Sample\SampleLib.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="01 Exports\ExportsAdd.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="01 Exports\ExportsRead.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="02 Imports\ImportsAdd.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="02 Imports\ImportsEnumeration.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="02 Imports\ImportsDelayed.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="03 Resources\ResourceExtract.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="03 Resources\ResourceBuild.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="03 Resources\ResourceStats.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="03 Resources\ResourceVersionInfo.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="05 FillMem\FillMem.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="06 Relocs\BuildRelocs.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="04 Module Loader\ModuleLoader.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="09 PEID Signatures\PeidSignatures.dproj">
            <Dependencies/>
        </Projects>
        <Projects Include="10 Load From Process\ProcessTest.dproj">
            <Dependencies/>
        </Projects>
    </ItemGroup>
    <ProjectExtensions>
        <Borland.Personality>Default.Personality.12</Borland.Personality>
        <Borland.ProjectType/>
        <BorlandProject>
            <Default.Personality/>
        </BorlandProject>
    </ProjectExtensions>
    <Target Name="SampleLib">
        <MSBuild Projects="00 Sample\SampleLib.dproj"/>
    </Target>
    <Target Name="SampleLib:Clean">
        <MSBuild Projects="00 Sample\SampleLib.dproj" Targets="Clean"/>
    </Target>
    <Target Name="SampleLib:Make">
        <MSBuild Projects="00 Sample\SampleLib.dproj" Targets="Make"/>
    </Target>
    <Target Name="ExportsAdd">
        <MSBuild Projects="01 Exports\ExportsAdd.dproj"/>
    </Target>
    <Target Name="ExportsAdd:Clean">
        <MSBuild Projects="01 Exports\ExportsAdd.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ExportsAdd:Make">
        <MSBuild Projects="01 Exports\ExportsAdd.dproj" Targets="Make"/>
    </Target>
    <Target Name="ExportsRead">
        <MSBuild Projects="01 Exports\ExportsRead.dproj"/>
    </Target>
    <Target Name="ExportsRead:Clean">
        <MSBuild Projects="01 Exports\ExportsRead.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ExportsRead:Make">
        <MSBuild Projects="01 Exports\ExportsRead.dproj" Targets="Make"/>
    </Target>
    <Target Name="ImportsAdd">
        <MSBuild Projects="02 Imports\ImportsAdd.dproj"/>
    </Target>
    <Target Name="ImportsAdd:Clean">
        <MSBuild Projects="02 Imports\ImportsAdd.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ImportsAdd:Make">
        <MSBuild Projects="02 Imports\ImportsAdd.dproj" Targets="Make"/>
    </Target>
    <Target Name="ImportsEnumeration">
        <MSBuild Projects="02 Imports\ImportsEnumeration.dproj"/>
    </Target>
    <Target Name="ImportsEnumeration:Clean">
        <MSBuild Projects="02 Imports\ImportsEnumeration.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ImportsEnumeration:Make">
        <MSBuild Projects="02 Imports\ImportsEnumeration.dproj" Targets="Make"/>
    </Target>
    <Target Name="ImportsDelayed">
        <MSBuild Projects="02 Imports\ImportsDelayed.dproj"/>
    </Target>
    <Target Name="ImportsDelayed:Clean">
        <MSBuild Projects="02 Imports\ImportsDelayed.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ImportsDelayed:Make">
        <MSBuild Projects="02 Imports\ImportsDelayed.dproj" Targets="Make"/>
    </Target>
    <Target Name="ResourceExtract">
        <MSBuild Projects="03 Resources\ResourceExtract.dproj"/>
    </Target>
    <Target Name="ResourceExtract:Clean">
        <MSBuild Projects="03 Resources\ResourceExtract.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ResourceExtract:Make">
        <MSBuild Projects="03 Resources\ResourceExtract.dproj" Targets="Make"/>
    </Target>
    <Target Name="ResourceBuild">
        <MSBuild Projects="03 Resources\ResourceBuild.dproj"/>
    </Target>
    <Target Name="ResourceBuild:Clean">
        <MSBuild Projects="03 Resources\ResourceBuild.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ResourceBuild:Make">
        <MSBuild Projects="03 Resources\ResourceBuild.dproj" Targets="Make"/>
    </Target>
    <Target Name="ResourceStats">
        <MSBuild Projects="03 Resources\ResourceStats.dproj"/>
    </Target>
    <Target Name="ResourceStats:Clean">
        <MSBuild Projects="03 Resources\ResourceStats.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ResourceStats:Make">
        <MSBuild Projects="03 Resources\ResourceStats.dproj" Targets="Make"/>
    </Target>
    <Target Name="ResourceVersionInfo">
        <MSBuild Projects="03 Resources\ResourceVersionInfo.dproj"/>
    </Target>
    <Target Name="ResourceVersionInfo:Clean">
        <MSBuild Projects="03 Resources\ResourceVersionInfo.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ResourceVersionInfo:Make">
        <MSBuild Projects="03 Resources\ResourceVersionInfo.dproj" Targets="Make"/>
    </Target>
    <Target Name="FillMem">
        <MSBuild Projects="05 FillMem\FillMem.dproj"/>
    </Target>
    <Target Name="FillMem:Clean">
        <MSBuild Projects="05 FillMem\FillMem.dproj" Targets="Clean"/>
    </Target>
    <Target Name="FillMem:Make">
        <MSBuild Projects="05 FillMem\FillMem.dproj" Targets="Make"/>
    </Target>
    <Target Name="BuildRelocs">
        <MSBuild Projects="06 Relocs\BuildRelocs.dproj"/>
    </Target>
    <Target Name="BuildRelocs:Clean">
        <MSBuild Projects="06 Relocs\BuildRelocs.dproj" Targets="Clean"/>
    </Target>
    <Target Name="BuildRelocs:Make">
        <MSBuild Projects="06 Relocs\BuildRelocs.dproj" Targets="Make"/>
    </Target>
    <Target Name="ModuleLoader">
        <MSBuild Projects="04 Module Loader\ModuleLoader.dproj"/>
    </Target>
    <Target Name="ModuleLoader:Clean">
        <MSBuild Projects="04 Module Loader\ModuleLoader.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ModuleLoader:Make">
        <MSBuild Projects="04 Module Loader\ModuleLoader.dproj" Targets="Make"/>
    </Target>
    <Target Name="PeidSignatures">
        <MSBuild Projects="09 PEID Signatures\PeidSignatures.dproj"/>
    </Target>
    <Target Name="PeidSignatures:Clean">
        <MSBuild Projects="09 PEID Signatures\PeidSignatures.dproj" Targets="Clean"/>
    </Target>
    <Target Name="PeidSignatures:Make">
        <MSBuild Projects="09 PEID Signatures\PeidSignatures.dproj" Targets="Make"/>
    </Target>
    <Target Name="ProcessTest">
        <MSBuild Projects="10 Load From Process\ProcessTest.dproj"/>
    </Target>
    <Target Name="ProcessTest:Clean">
        <MSBuild Projects="10 Load From Process\ProcessTest.dproj" Targets="Clean"/>
    </Target>
    <Target Name="ProcessTest:Make">
        <MSBuild Projects="10 Load From Process\ProcessTest.dproj" Targets="Make"/>
    </Target>
    <Target Name="Build">
        <CallTarget Targets="SampleLib;ExportsAdd;ExportsRead;ImportsAdd;ImportsEnumeration;ImportsDelayed;ResourceExtract;ResourceBuild;ResourceStats;ResourceVersionInfo;FillMem;BuildRelocs;ModuleLoader;PeidSignatures;ProcessTest"/>
    </Target>
    <Target Name="Clean">
        <CallTarget Targets="SampleLib:Clean;ExportsAdd:Clean;ExportsRead:Clean;ImportsAdd:Clean;ImportsEnumeration:Clean;ImportsDelayed:Clean;ResourceExtract:Clean;ResourceBuild:Clean;ResourceStats:Clean;ResourceVersionInfo:Clean;FillMem:Clean;BuildRelocs:Clean;ModuleLoader:Clean;PeidSignatures:Clean;ProcessTest:Clean"/>
    </Target>
    <Target Name="Make">
        <CallTarget Targets="SampleLib:Make;ExportsAdd:Make;ExportsRead:Make;ImportsAdd:Make;ImportsEnumeration:Make;ImportsDelayed:Make;ResourceExtract:Make;ResourceBuild:Make;ResourceStats:Make;ResourceVersionInfo:Make;FillMem:Make;BuildRelocs:Make;ModuleLoader:Make;PeidSignatures:Make;ProcessTest:Make"/>
    </Target>
    <Import Project="$(BDS)\Bin\CodeGear.Group.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Group.Targets')"/>
</Project>


text:
program ModuleLoader;

uses
  PE.Image,
  PE.ExecutableLoader;

var
  Img: TPEImage;
  Module: TExecutableModule;

begin
  Img := TPEImage.Create;
  Module := TExecutableModule.Create(Img);
  try
    if Img.LoadFromFile('SampleLib.dll') then
    begin
      if Module.Load() <> msOK then
          ; // error
    end;
  finally
    Module.Free; // free it before Img.
    Img.Free;
  end;

end.


text:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <ProjectGuid>{1E844CBC-CCF9-4791-9D14-3CF4F8C7E3EE}</ProjectGuid>
        <ProjectVersion>16.0</ProjectVersion>
        <FrameworkType>None</FrameworkType>
        <MainSource>ModuleLoader.dpr</MainSource>
        <Base>True</Base>
        <Config Condition="'$(Config)'==''">Debug</Config>
        <Platform Condition="'$(Platform)'==''">Win32</Platform>
        <TargetedPlatforms>1</TargetedPlatforms>
        <AppType>Console</AppType>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='OSX32' and '$(Base)'=='true') or '$(Base_OSX32)'!=''">
        <Base_OSX32>true</Base_OSX32>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
        <Base_Win32>true</Base_Win32>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
        <Base_Win64>true</Base_Win64>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
        <Cfg_1>true</Cfg_1>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
        <Cfg_1_Win32>true</Cfg_1_Win32>
        <CfgParent>Cfg_1</CfgParent>
        <Cfg_1>true</Cfg_1>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
        <Cfg_2>true</Cfg_2>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
        <Cfg_2_Win32>true</Cfg_2_Win32>
        <CfgParent>Cfg_2</CfgParent>
        <Cfg_2>true</Cfg_2>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Base)'!=''">
        <SanitizedProjectName>ModuleLoader</SanitizedProjectName>
        <DCC_UnitSearchPath>..\..;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
        <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
        <VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
        <VerInfo_Locale>1033</VerInfo_Locale>
        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
        <DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
        <DCC_ExeOutput>..\..\bin\examples</DCC_ExeOutput>
        <DCC_E>false</DCC_E>
        <DCC_N>false</DCC_N>
        <DCC_S>false</DCC_S>
        <DCC_F>false</DCC_F>
        <DCC_K>false</DCC_K>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Base_OSX32)'!=''">
        <DCC_UsePackage>bindcompfmx;DBXSqliteDriver;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;bindcomp;inetdb;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;xmlrtl;DbxCommonDriver;IndyProtocols;DBXMySQLDriver;dbxcds;bindengine;bindcompdbx;soaprtl;DBXOracleDriver;CustomIPTransport;dsnap;DBXInformixDriver;IndyIPServer;fmxase;IndyCore;IndyIPCommon;DBXFirebirdDriver;inet;fmxobj;inetdbxpress;DBXSybaseASADriver;fmxdae;dbexpress;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)</DCC_UsePackage>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Base_Win32)'!=''">
        <DCC_UsePackage>CrossFPC_XE3;bindcompfmx;DBXSqliteDriver;vcldbx;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;TeeDB;bindcomp;inetdb;inetdbbde;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DBXOdbcDriver;DataSnapServer;Tee;DataSnapProviderClient;xmlrtl;DBXSybaseASEDriver;ibxpress;DbxCommonDriver;svnui;vclimg;IndyProtocols;DBXMySQLDriver;dbxcds;MetropolisUILiveTile;bindengine;vclactnband;vcldb;bindcompdbx;FMXTee;vcldsnap;bindcompvcl;soaprtl;TeeUI;vclie;DBXDb2Driver;vcltouch;websnap;DBXOracleDriver;CustomIPTransport;vclribbon;VclSmp;dsnap;DBXInformixDriver;IndyIPServer;Intraweb;fmxase;vcl;DataSnapConnectors;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;DBXFirebirdDriver;FmxTeeUI;dsnapcon;inet;fmxobj;vclx;inetdbxpress;webdsnap;svn;DBXSybaseASADriver;fmxdae;bdertl;dbexpress;DataSnapIndy10ServerTransport;adortl;IndyIPClient;$(DCC_UsePackage)</DCC_UsePackage>
        <VerInfo_Locale>1033</VerInfo_Locale>
        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Base_Win64)'!=''">
        <DCC_UsePackage>bindcompfmx;DBXSqliteDriver;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;bindcomp;inetdb;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DBXOdbcDriver;DataSnapServer;DataSnapProviderClient;xmlrtl;DBXSybaseASEDriver;DbxCommonDriver;vclimg;IndyProtocols;DBXMySQLDriver;dbxcds;bindengine;vclactnband;vcldb;bindcompdbx;vcldsnap;bindcompvcl;soaprtl;vclie;DBXDb2Driver;vcltouch;websnap;DBXOracleDriver;CustomIPTransport;VclSmp;dsnap;DBXInformixDriver;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;IndyIPCommon;DBXFirebirdDriver;dsnapcon;inet;fmxobj;vclx;inetdbxpress;webdsnap;DBXSybaseASADriver;fmxdae;dbexpress;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)</DCC_UsePackage>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_1)'!=''">
        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
        <DCC_DebugDCUs>true</DCC_DebugDCUs>
        <DCC_Optimize>false</DCC_Optimize>
        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
        <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
        <DCC_RemoteDebug>true</DCC_RemoteDebug>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
        <DCC_RemoteDebug>false</DCC_RemoteDebug>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_2)'!=''">
        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
        <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
        <DCC_DebugInformation>0</DCC_DebugInformation>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
    </PropertyGroup>
    <ItemGroup>
        <DelphiCompile Include="$(MainSource)">
            <MainSource>MainSource</MainSource>
        </DelphiCompile>
        <BuildConfiguration Include="Release">
            <Key>Cfg_2</Key>
            <CfgParent>Base</CfgParent>
        </BuildConfiguration>
        <BuildConfiguration Include="Base">
            <Key>Base</Key>
        </BuildConfiguration>
        <BuildConfiguration Include="Debug">
            <Key>Cfg_1</Key>
            <CfgParent>Base</CfgParent>
        </BuildConfiguration>
    </ItemGroup>
    <ProjectExtensions>
        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
        <Borland.ProjectType/>
        <BorlandProject>
            <Delphi.Personality>
                <VersionInfo>
                    <VersionInfo Name="IncludeVerInfo">False</VersionInfo>
                    <VersionInfo Name="AutoIncBuild">False</VersionInfo>
                    <VersionInfo Name="MajorVer">1</VersionInfo>
                    <VersionInfo Name="MinorVer">0</VersionInfo>
                    <VersionInfo Name="Release">0</VersionInfo>
                    <VersionInfo Name="Build">0</VersionInfo>
                    <VersionInfo Name="Debug">False</VersionInfo>
                    <VersionInfo Name="PreRelease">False</VersionInfo>
                    <VersionInfo Name="Special">False</VersionInfo>
                    <VersionInfo Name="Private">False</VersionInfo>
                    <VersionInfo Name="DLL">False</VersionInfo>
                    <VersionInfo Name="Locale">1033</VersionInfo>
                    <VersionInfo Name="CodePage">1252</VersionInfo>
                </VersionInfo>
                <VersionInfoKeys>
                    <VersionInfoKeys Name="CompanyName"/>
                    <VersionInfoKeys Name="FileDescription"/>
                    <VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
                    <VersionInfoKeys Name="InternalName"/>
                    <VersionInfoKeys Name="LegalCopyright"/>
                    <VersionInfoKeys Name="LegalTrademarks"/>
                    <VersionInfoKeys Name="OriginalFilename"/>
                    <VersionInfoKeys Name="ProductName"/>
                    <VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
                    <VersionInfoKeys Name="Comments"/>
                    <VersionInfoKeys Name="CFBundleName"/>
                    <VersionInfoKeys Name="CFBundleDisplayName"/>
                    <VersionInfoKeys Name="CFBundleIdentifier"/>
                    <VersionInfoKeys Name="CFBundleVersion"/>
                    <VersionInfoKeys Name="CFBundlePackageType"/>
                    <VersionInfoKeys Name="CFBundleSignature"/>
                    <VersionInfoKeys Name="CFBundleAllowMixedLocalizations"/>
                    <VersionInfoKeys Name="CFBundleExecutable"/>
                </VersionInfoKeys>
                <Source>
                    <Source Name="MainSource">ModuleLoader.dpr</Source>
                </Source>
                <Excluded_Packages>
                    <Excluded_Packages Name="$(BDSBIN)\dcloffice2k200.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
                    <Excluded_Packages Name="$(BDSBIN)\dclofficexp200.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
                </Excluded_Packages>
            </Delphi.Personality>
            <Deployment/>
            <Platforms>
                <Platform value="OSX32">False</Platform>
                <Platform value="Win32">True</Platform>
                <Platform value="Win64">False</Platform>
            </Platforms>
        </BorlandProject>
        <ProjectFileVersion>12</ProjectFileVersion>
    </ProjectExtensions>
    <Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
    <Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
</Project>


text:
program BuildRelocs;

uses
  PE.Common,
  PE.Image,
  PE.Section,
  PE.Build;

var
  img: TPEImage;
  sec: TPESection;

begin
  img := TPEImage.Create;
  try
    sec := img.Sections.AddNew('.code', 32, $60000020, nil);

    // Create "code".
    sec.Mem[0] := $A1;
    PCardinal(@sec.Mem[1])^ := img.ImageBase + sec.RVA + 6;
    sec.Mem[5] := $C3;
    PCardinal(@sec.Mem[6])^ := $12345678;

    img.EntryPointRVA := sec.RVA;

    // Create reloc and export.
    img.Relocs.Put(sec.RVA + 1, 3);
    img.ExportSyms.AddByName(sec.RVA + 6, 'MyVariable');

    // Rebuild.
    ReBuildDirData(img, DDIR_RELOCATION, False);
    ReBuildDirData(img, DDIR_EXPORT, False);

    // Save.
    img.SaveToFile('myreloc.exe');
  finally
    img.Free;
  end;
end.