Shows how to embed the code of another executable in a binary and execute it at runtime directly from memory (without extracting to disk etc). Deinitely a classic, guaranteed to work on amd64. The generic name for this kind of technique is called RunPE (run portable executable).
It should generate runpe64.exe.
Licensed under MIT.
/*
RunPE for x64 - classic RunPE for 64-bit executables
Copyright (C) 2020 Valentin-Gabriel Radu
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-----
Compile using (make sure to use x64 cl):
cl runpe64.cpp
It should generate runpe64.exe.
*/
#undef UNICODE
#define UNICODE
#include <Windows.h>
/*
Based on examples from:
* https://github.com/Zer0Mem0ry/RunPE
* https://github.com/TRIKbranch/RunPE-X86--X64-
* https://gist.github.com/andreafortuna/d7fb92fb29e4ade27c0c6ce4401c99fa
This example compiles and runs standalone, just as a proof of concept.
*/
int runPE64 (
LPPROCESS_INFORMATION lpPI ,
LPSTARTUPINFO lpSI ,
LPVOID lpImage ,
LPWSTR wszArgs ,
SIZE_T szArgs
)
{
WCHAR wszFilePath [ MAX_PATH ];
if ( ! GetModuleFileName (
NULL ,
wszFilePath ,
sizeof wszFilePath
))
{
return - 1 ;
}
WCHAR wszArgsBuffer [ MAX_PATH + 2048 ];
ZeroMemory ( wszArgsBuffer , sizeof wszArgsBuffer );
SIZE_T length = wcslen ( wszFilePath );
memcpy (
wszArgsBuffer ,
wszFilePath ,
length * sizeof ( WCHAR )
);
wszArgsBuffer [ length ] = ' ' ;
memcpy (
wszArgsBuffer + length + 1 ,
wszArgs ,
szArgs
);
PIMAGE_DOS_HEADER lpDOSHeader =
reinterpret_cast < PIMAGE_DOS_HEADER > ( lpImage );
PIMAGE_NT_HEADERS lpNTHeader =
reinterpret_cast < PIMAGE_NT_HEADERS > (
reinterpret_cast < DWORD64 > ( lpImage ) + lpDOSHeader -> e_lfanew
);
if ( lpNTHeader -> Signature != IMAGE_NT_SIGNATURE )
{
return - 2 ;
}
if ( ! CreateProcess (
NULL ,
wszArgsBuffer ,
NULL ,
NULL ,
TRUE ,
CREATE_SUSPENDED ,
NULL ,
NULL ,
lpSI ,
lpPI
))
{
return - 3 ;
}
CONTEXT stCtx ;
ZeroMemory ( & stCtx , sizeof stCtx );
stCtx . ContextFlags = CONTEXT_FULL ;
if ( ! GetThreadContext ( lpPI -> hThread , & stCtx ))
{
TerminateProcess (
lpPI -> hProcess ,
- 4
);
return - 4 ;
}
LPVOID lpImageBase = VirtualAllocEx (
lpPI -> hProcess ,
reinterpret_cast < LPVOID > ( lpNTHeader -> OptionalHeader . ImageBase ),
lpNTHeader -> OptionalHeader . SizeOfImage ,
MEM_COMMIT | MEM_RESERVE ,
PAGE_EXECUTE_READWRITE
);
if ( lpImageBase == NULL )
{
TerminateProcess (
lpPI -> hProcess ,
- 5
);
return - 5 ;
}
if ( ! WriteProcessMemory (
lpPI -> hProcess ,
lpImageBase ,
lpImage ,
lpNTHeader -> OptionalHeader . SizeOfHeaders ,
NULL
))
{
TerminateProcess (
lpPI -> hProcess ,
- 6
);
return - 6 ;
}
for (
SIZE_T iSection = 0 ;
iSection < lpNTHeader -> FileHeader . NumberOfSections ;
++ iSection
)
{
PIMAGE_SECTION_HEADER stSectionHeader =
reinterpret_cast < PIMAGE_SECTION_HEADER > (
reinterpret_cast < DWORD64 > ( lpImage ) +
lpDOSHeader -> e_lfanew +
sizeof ( IMAGE_NT_HEADERS64 ) +
sizeof ( IMAGE_SECTION_HEADER ) * iSection
);
if ( ! WriteProcessMemory (
lpPI -> hProcess ,
reinterpret_cast < LPVOID > (
reinterpret_cast < DWORD64 > ( lpImageBase ) +
stSectionHeader -> VirtualAddress
),
reinterpret_cast < LPVOID > (
reinterpret_cast < DWORD64 > ( lpImage ) +
stSectionHeader -> PointerToRawData
),
stSectionHeader -> SizeOfRawData ,
NULL
))
{
TerminateProcess (
lpPI -> hProcess ,
- 7
);
return - 7 ;
}
}
if ( ! WriteProcessMemory (
lpPI -> hProcess ,
reinterpret_cast < LPVOID > (
stCtx . Rdx + sizeof ( LPVOID ) * 2
),
& lpImageBase ,
sizeof ( LPVOID ),
NULL
))
{
TerminateProcess (
lpPI -> hProcess ,
- 8
);
return - 8 ;
}
stCtx . Rcx = reinterpret_cast < DWORD64 > ( lpImageBase ) +
lpNTHeader -> OptionalHeader . AddressOfEntryPoint ;
if ( ! SetThreadContext (
lpPI -> hThread ,
& stCtx
))
{
TerminateProcess (
lpPI -> hProcess ,
- 9
);
return - 9 ;
}
if ( ! ResumeThread ( lpPI -> hThread ))
{
TerminateProcess (
lpPI -> hProcess ,
- 10
);
return - 10 ;
}
return 0 ;
}
/*
Tiny executable example from:
https://stackoverflow.com/questions/11886036/c-win32-smallest-possible-messageboxhello-app-exe
Generate the tiny exe from this code:
#undef UNICODE
#define UNICODE
#include <Windows.h>
void startup()
{
MessageBox(0, L"Hello, world", L"", MB_SETFOREGROUND);
ExitProcess(42);
}
Compile using (make sure to compile for x64):
cl tiny.c kernel32.lib user32.lib /O2 /link /entry:startup /subsystem:windows /align:16
Convert to hex using something like:
https://tomeko.net/online_tools/file_to_hex.php?lang=en
*/
unsigned char hello_world [] = {
0x4D , 0x5A , 0x90 , 0x00 , 0x03 , 0x00 , 0x00 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0xFF , 0xFF , 0x00 , 0x00 ,
0xB8 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xC0 , 0x00 , 0x00 , 0x00 ,
0x0E , 0x1F , 0xBA , 0x0E , 0x00 , 0xB4 , 0x09 , 0xCD , 0x21 , 0xB8 , 0x01 , 0x4C , 0xCD , 0x21 , 0x54 , 0x68 ,
0x69 , 0x73 , 0x20 , 0x70 , 0x72 , 0x6F , 0x67 , 0x72 , 0x61 , 0x6D , 0x20 , 0x63 , 0x61 , 0x6E , 0x6E , 0x6F ,
0x74 , 0x20 , 0x62 , 0x65 , 0x20 , 0x72 , 0x75 , 0x6E , 0x20 , 0x69 , 0x6E , 0x20 , 0x44 , 0x4F , 0x53 , 0x20 ,
0x6D , 0x6F , 0x64 , 0x65 , 0x2E , 0x0D , 0x0D , 0x0A , 0x24 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0xD1 , 0x60 , 0xE0 , 0xFF , 0x95 , 0x01 , 0x8E , 0xAC , 0x95 , 0x01 , 0x8E , 0xAC , 0x95 , 0x01 , 0x8E , 0xAC ,
0xCE , 0x69 , 0x8F , 0xAD , 0x90 , 0x01 , 0x8E , 0xAC , 0x95 , 0x01 , 0x8F , 0xAC , 0x97 , 0x01 , 0x8E , 0xAC ,
0x10 , 0x71 , 0x8A , 0xAD , 0x94 , 0x01 , 0x8E , 0xAC , 0x10 , 0x71 , 0x8C , 0xAD , 0x94 , 0x01 , 0x8E , 0xAC ,
0x52 , 0x69 , 0x63 , 0x68 , 0x95 , 0x01 , 0x8E , 0xAC , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x50 , 0x45 , 0x00 , 0x00 , 0x64 , 0x86 , 0x03 , 0x00 , 0xCA , 0xA3 , 0xDB , 0x5E , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0xF0 , 0x00 , 0x22 , 0x00 , 0x0B , 0x02 , 0x0E , 0x1A , 0x30 , 0x00 , 0x00 , 0x00 ,
0xD0 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x02 , 0x00 , 0x00 , 0x40 , 0x02 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x40 , 0x01 , 0x00 , 0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 ,
0x06 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x06 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x40 , 0x04 , 0x00 , 0x00 , 0x40 , 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x02 , 0x00 , 0x60 , 0x81 ,
0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x9C , 0x03 , 0x00 , 0x00 , 0x3C , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x30 , 0x04 , 0x00 , 0x00 , 0x0C , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xB4 , 0x02 , 0x00 , 0x00 , 0x1C , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x70 , 0x02 , 0x00 , 0x00 , 0x20 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x2E , 0x74 , 0x65 , 0x78 , 0x74 , 0x00 , 0x00 , 0x00 ,
0x2C , 0x00 , 0x00 , 0x00 , 0x40 , 0x02 , 0x00 , 0x00 , 0x30 , 0x00 , 0x00 , 0x00 , 0x40 , 0x02 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x20 , 0x00 , 0x00 , 0x60 ,
0x2E , 0x72 , 0x64 , 0x61 , 0x74 , 0x61 , 0x00 , 0x00 , 0xBE , 0x01 , 0x00 , 0x00 , 0x70 , 0x02 , 0x00 , 0x00 ,
0xC0 , 0x01 , 0x00 , 0x00 , 0x70 , 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x00 , 0x00 , 0x40 , 0x2E , 0x70 , 0x64 , 0x61 , 0x74 , 0x61 , 0x00 , 0x00 ,
0x0C , 0x00 , 0x00 , 0x00 , 0x30 , 0x04 , 0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x30 , 0x04 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x00 , 0x00 , 0x40 ,
0x48 , 0x83 , 0xEC , 0x28 , 0x41 , 0xB9 , 0x00 , 0x00 , 0x01 , 0x00 , 0x4C , 0x8D , 0x05 , 0x3F , 0x00 , 0x00 ,
0x00 , 0x48 , 0x8D , 0x15 , 0x40 , 0x00 , 0x00 , 0x00 , 0x33 , 0xC9 , 0xFF , 0x15 , 0x20 , 0x00 , 0x00 , 0x00 ,
0xB9 , 0x2A , 0x00 , 0x00 , 0x00 , 0xFF , 0x15 , 0x05 , 0x00 , 0x00 , 0x00 , 0xCC , 0x00 , 0x00 , 0x00 , 0x00 ,
0xF8 , 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x14 , 0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x48 , 0x00 , 0x65 , 0x00 , 0x6C , 0x00 , 0x6C , 0x00 ,
0x6F , 0x00 , 0x2C , 0x00 , 0x20 , 0x00 , 0x77 , 0x00 , 0x6F , 0x00 , 0x72 , 0x00 , 0x6C , 0x00 , 0x64 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xCA , 0xA3 , 0xDB , 0x5E , 0x00 , 0x00 , 0x00 , 0x00 ,
0x0D , 0x00 , 0x00 , 0x00 , 0xC4 , 0x00 , 0x00 , 0x00 , 0xD0 , 0x02 , 0x00 , 0x00 , 0xD0 , 0x02 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x02 , 0x00 , 0x00 , 0x2C , 0x00 , 0x00 , 0x00 , 0x2E , 0x74 , 0x65 , 0x78 ,
0x74 , 0x24 , 0x6D , 0x6E , 0x00 , 0x00 , 0x00 , 0x00 , 0x70 , 0x02 , 0x00 , 0x00 , 0x20 , 0x00 , 0x00 , 0x00 ,
0x2E , 0x69 , 0x64 , 0x61 , 0x74 , 0x61 , 0x24 , 0x35 , 0x00 , 0x00 , 0x00 , 0x00 , 0x90 , 0x02 , 0x00 , 0x00 ,
0x40 , 0x00 , 0x00 , 0x00 , 0x2E , 0x72 , 0x64 , 0x61 , 0x74 , 0x61 , 0x00 , 0x00 , 0xD0 , 0x02 , 0x00 , 0x00 ,
0xC4 , 0x00 , 0x00 , 0x00 , 0x2E , 0x72 , 0x64 , 0x61 , 0x74 , 0x61 , 0x24 , 0x7A , 0x7A , 0x7A , 0x64 , 0x62 ,
0x67 , 0x00 , 0x00 , 0x00 , 0x94 , 0x03 , 0x00 , 0x00 , 0x08 , 0x00 , 0x00 , 0x00 , 0x2E , 0x78 , 0x64 , 0x61 ,
0x74 , 0x61 , 0x00 , 0x00 , 0x9C , 0x03 , 0x00 , 0x00 , 0x28 , 0x00 , 0x00 , 0x00 , 0x2E , 0x69 , 0x64 , 0x61 ,
0x74 , 0x61 , 0x24 , 0x32 , 0x00 , 0x00 , 0x00 , 0x00 , 0xC4 , 0x03 , 0x00 , 0x00 , 0x14 , 0x00 , 0x00 , 0x00 ,
0x2E , 0x69 , 0x64 , 0x61 , 0x74 , 0x61 , 0x24 , 0x33 , 0x00 , 0x00 , 0x00 , 0x00 , 0xD8 , 0x03 , 0x00 , 0x00 ,
0x20 , 0x00 , 0x00 , 0x00 , 0x2E , 0x69 , 0x64 , 0x61 , 0x74 , 0x61 , 0x24 , 0x34 , 0x00 , 0x00 , 0x00 , 0x00 ,
0xF8 , 0x03 , 0x00 , 0x00 , 0x36 , 0x00 , 0x00 , 0x00 , 0x2E , 0x69 , 0x64 , 0x61 , 0x74 , 0x61 , 0x24 , 0x36 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x30 , 0x04 , 0x00 , 0x00 , 0x0C , 0x00 , 0x00 , 0x00 , 0x2E , 0x70 , 0x64 , 0x61 ,
0x74 , 0x61 , 0x00 , 0x00 , 0x01 , 0x04 , 0x01 , 0x00 , 0x04 , 0x42 , 0x00 , 0x00 , 0xD8 , 0x03 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x06 , 0x04 , 0x00 , 0x00 , 0x70 , 0x02 , 0x00 , 0x00 ,
0xE8 , 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x22 , 0x04 , 0x00 , 0x00 ,
0x80 , 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xF8 , 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x14 , 0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x64 , 0x01 , 0x45 , 0x78 , 0x69 , 0x74 , 0x50 , 0x72 ,
0x6F , 0x63 , 0x65 , 0x73 , 0x73 , 0x00 , 0x4B , 0x45 , 0x52 , 0x4E , 0x45 , 0x4C , 0x33 , 0x32 , 0x2E , 0x64 ,
0x6C , 0x6C , 0x00 , 0x00 , 0x8A , 0x02 , 0x4D , 0x65 , 0x73 , 0x73 , 0x61 , 0x67 , 0x65 , 0x42 , 0x6F , 0x78 ,
0x57 , 0x00 , 0x55 , 0x53 , 0x45 , 0x52 , 0x33 , 0x32 , 0x2E , 0x64 , 0x6C , 0x6C , 0x00 , 0x00 , 0x00 , 0x00 ,
0x40 , 0x02 , 0x00 , 0x00 , 0x6C , 0x02 , 0x00 , 0x00 , 0x94 , 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
};
int main (
int argc ,
char * argv []
)
{
DWORD dwRet = 0 ;
PROCESS_INFORMATION stPI ;
ZeroMemory ( & stPI , sizeof stPI );
STARTUPINFO stSI ;
ZeroMemory ( & stSI , sizeof stSI );
WCHAR szArgs [] = L"" ;
if ( ! runPE64 (
& stPI ,
& stSI ,
reinterpret_cast < LPVOID > ( hello_world ),
szArgs ,
sizeof szArgs
))
{
WaitForSingleObject (
stPI . hProcess ,
INFINITE
);
GetExitCodeProcess (
stPI . hProcess ,
& dwRet
);
CloseHandle ( stPI . hThread );
CloseHandle ( stPI . hProcess );
}
return dwRet ;
}