-
-
Save hasherezade/97b032e2e3eb6864a48c63ab69cedd4c to your computer and use it in GitHub Desktop.
libpPeConv-based loader for PEs using RtlPcToFileHeader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
#include <iostream> | |
#include <tchar.h> | |
#include <peconv.h> // include libPeConv header | |
BYTE* g_Payload = nullptr; | |
size_t g_PayloadSize = 0; | |
PVOID my_RtlPcToFileHeader( | |
PVOID PcValue, | |
PVOID* BaseOfImage | |
) | |
{ | |
PVOID ret = RtlPcToFileHeader(PcValue, BaseOfImage); | |
if (*BaseOfImage != NULL) { | |
return ret; | |
} | |
std::cout << "Cannot find image base for: " << std::hex << PcValue << std::endl; | |
if ((ULONG_PTR)PcValue >= (ULONG_PTR)g_Payload && (ULONG_PTR)PcValue <= ((ULONG_PTR)g_Payload + g_PayloadSize)) { | |
std::cout << "Overwriting base!\n"; | |
*BaseOfImage = g_Payload; | |
return g_Payload; | |
} | |
return ret; | |
} | |
// manually load the PE file using libPeConv | |
bool load_payload(LPCTSTR pe_path) | |
{ | |
// manually load the PE file using libPeConv: | |
g_PayloadSize = 0; | |
peconv::hooking_func_resolver my_res; | |
my_res.add_hook("RtlPcToFileHeader", (FARPROC)&my_RtlPcToFileHeader); | |
//if the PE is dropped on the disk, you can load it from the file: | |
g_Payload = peconv::load_pe_executable(pe_path, g_PayloadSize, (peconv::t_function_resolver*)&my_res); | |
if (!g_Payload) { | |
return false; | |
} | |
// if the loaded PE needs to access resources, you may need to connect it to the PEB: | |
//peconv::set_main_module_in_peb((HMODULE)g_Payload); | |
std::cout << "Loaded at base: " << std::hex << (ULONG_PTR)g_Payload << std::endl; | |
return true; | |
} | |
int run_payload() | |
{ | |
if (!g_Payload) { | |
std::cerr << "[!] The payload is not loaded!\n"; | |
return -1; | |
} | |
//calculate the Entry Point of the manually loaded module | |
DWORD ep_rva = peconv::get_entry_point_rva(g_Payload); | |
if (!ep_rva) { | |
std::cerr << "[!] Cannot fetch EP!\n"; | |
return -2; | |
} | |
std::cout << "Running the payload:\n"; | |
int ret = 0; | |
const ULONG_PTR ep_va = ep_rva + (ULONG_PTR)g_Payload; | |
if (peconv::is_module_dll(g_Payload)) { | |
//the prototype of the DllMain fuction: | |
BOOL WINAPI _DllMain( | |
HINSTANCE hinstDLL, // handle to DLL module | |
DWORD fdwReason, // reason for calling function | |
LPVOID lpvReserved); // reserved | |
auto new_main = reinterpret_cast<decltype(&_DllMain)>(ep_va); | |
// call the Entry Point of the manually loaded PE : | |
ret = new_main((HINSTANCE)g_Payload, DLL_PROCESS_ATTACH, 0); | |
} | |
else { | |
//the simplest prototype of the main fuction: | |
int basic_main(void); | |
auto new_main = reinterpret_cast<decltype(&basic_main)>(ep_va); | |
//call the Entry Point of the manually loaded PE: | |
ret = new_main(); | |
} | |
return ret; | |
} | |
int _tmain(int argc, LPTSTR argv[]) | |
{ | |
if (argc < 2) { | |
std::cout << "Args: <path to the exe>" << std::endl; | |
return 0; | |
} | |
const LPTSTR pe_path = argv[1]; | |
if (!load_payload(pe_path)) { | |
return -1; | |
} | |
return run_payload(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can copy it into the template: https://github.com/hasherezade/libpeconv_tpl