Skip to content

Commit bd934e4

Browse files
committed
[REFACT] Refactored the template main
1 parent b403f95 commit bd934e4

File tree

1 file changed

+67
-22
lines changed

1 file changed

+67
-22
lines changed

project_template/main.cpp

+67-22
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,89 @@
1+
/**
2+
A demo of a basic manual PE loader - you can use it as a starting point for your own project,
3+
or delete it and start from scratch
4+
*/
5+
16
#include <Windows.h>
27
#include <iostream>
38
#include <tchar.h>
49

510
#include <peconv.h> // include libPeConv header
611

7-
/**
8-
A demo of a basic manual PE loader - you can use it as a starting point for your own project,
9-
or delete it and start from the scratch
10-
*/
11-
int load_and_run(LPCTSTR pe_path)
12+
BYTE* g_Payload = nullptr;
13+
size_t g_PayloadSize = 0;
14+
15+
// manually load the PE file using libPeConv
16+
bool load_payload(LPCTSTR pe_path)
1217
{
1318
// manually load the PE file using libPeConv:
14-
size_t v_size = 0;
19+
size_t g_PayloadSize = 0;
1520
#ifdef LOAD_FROM_PATH
1621
//if the PE is dropped on the disk, you can load it from the file:
17-
BYTE* my_pe = peconv::load_pe_executable(pe_path, v_size);
18-
#else
22+
g_Payload = peconv::load_pe_executable(pe_path, g_PayloadSize);
23+
#else // load from memory buffer
24+
/*
25+
in this example the memory buffer is first loaded from the disk,
26+
but it can as well be fetch from resources, or a hardcoded buffer
27+
*/
1928
size_t bufsize = 0;
20-
BYTE *buffer = peconv::load_file(pe_path, bufsize);
29+
BYTE* buf = peconv::load_file(pe_path, bufsize);
30+
if (buf) {
31+
// if the file is NOT dropped on the disk, you can load it directly from a memory buffer:
32+
g_Payload = peconv::load_pe_executable(buf, bufsize, g_PayloadSize);
2133

22-
// if the file is NOT dropped on the disk, you can load it directly from a memory buffer:
23-
BYTE* my_pe = peconv::load_pe_executable(buffer, bufsize, v_size);
34+
// at this point we can free the buffer with the raw payload:
35+
peconv::free_file(buf); buf = nullptr;
36+
37+
if (!g_Payload) {
38+
return false;
39+
}
40+
}
2441
#endif
25-
if (!my_pe) {
42+
return true;
43+
}
44+
45+
int run_payload()
46+
{
47+
if (!g_Payload) {
48+
std::cerr << "[!] The payload is not loaded!\n";
2649
return -1;
2750
}
28-
2951
// if the loaded PE needs to access resources, you may need to connect it to the PEB:
30-
peconv::set_main_module_in_peb((HMODULE)my_pe);
52+
peconv::set_main_module_in_peb((HMODULE)g_Payload);
3153

3254
// if needed, you can run TLS callbacks before the Entry Point:
33-
peconv::run_tls_callbacks(my_pe, v_size);
55+
peconv::run_tls_callbacks(g_Payload, g_PayloadSize);
3456

3557
//calculate the Entry Point of the manually loaded module
36-
DWORD ep_rva = peconv::get_entry_point_rva(my_pe);
58+
DWORD ep_rva = peconv::get_entry_point_rva(g_Payload);
3759
if (!ep_rva) {
60+
std::cerr << "[!] Cannot fetch EP!\n";
3861
return -2;
3962
}
40-
ULONG_PTR ep_va = ep_rva + (ULONG_PTR)my_pe;
41-
//assuming that the payload is an EXE file (not DLL) this will be the simplest prototype of the main:
42-
int(*new_main)() = (int(*)())ep_va;
63+
const ULONG_PTR ep_va = ep_rva + (ULONG_PTR)g_Payload;
64+
65+
// run appropriate version of payload's main:
66+
int ret = 0;
67+
if (peconv::is_module_dll(g_Payload)) {
68+
//the prototype of the DllMain fuction:
69+
BOOL WINAPI _DllMain(
70+
HINSTANCE hinstDLL, // handle to DLL module
71+
DWORD fdwReason, // reason for calling function
72+
LPVOID lpvReserved); // reserved
73+
auto new_main = reinterpret_cast<decltype(&_DllMain)>(ep_va);
74+
75+
// call the Entry Point of the manually loaded PE :
76+
ret = new_main((HINSTANCE)g_Payload, DLL_PROCESS_ATTACH, 0);
77+
}
78+
else {
79+
//the simplest prototype of the main fuction:
80+
int basic_main(void);
81+
auto new_main = reinterpret_cast<decltype(&basic_main)>(ep_va);
4382

44-
//call the Entry Point of the manually loaded PE:
45-
return new_main();
83+
//call the Entry Point of the manually loaded PE:
84+
ret = new_main();
85+
}
86+
return ret;
4687
}
4788

4889
int _tmain(int argc, LPTSTR argv[])
@@ -52,5 +93,9 @@ int _tmain(int argc, LPTSTR argv[])
5293
return 0;
5394
}
5495
const LPTSTR pe_path = argv[1];
55-
return load_and_run(pe_path);
96+
if (!load_payload(pe_path)) {
97+
return -1;
98+
}
99+
std::cout << "Payload loaded!\n";
100+
return run_payload();
56101
}

0 commit comments

Comments
 (0)