summaryrefslogtreecommitdiff
path: root/loader
diff options
context:
space:
mode:
Diffstat (limited to 'loader')
-rw-r--r--loader/server/manual_map.cpp74
-rw-r--r--loader/server/manual_map.hpp129
2 files changed, 107 insertions, 96 deletions
diff --git a/loader/server/manual_map.cpp b/loader/server/manual_map.cpp
index d8cf57d..1c6fa12 100644
--- a/loader/server/manual_map.cpp
+++ b/loader/server/manual_map.cpp
@@ -68,6 +68,7 @@ namespace remote_code {
std::memset(&code[offset], value, sizeof uint32_t);
}
+ // turbo chad shellcode maker (c) bowis
std::vector<uint8_t> make_code(shellcode_args_t *arg) {
std::vector<uint8_t> code;
code.insert(code.begin(), shellcode_code, shellcode_code + shellcode_size);
@@ -81,10 +82,6 @@ namespace remote_code {
// nave i hope ur happy
for(int n = 0; n < 3; ++n)
patch_code(code, find_byte_pattern(code, { 0x69, 0x69, 0x69, 0x69 }), arg->m_endscene);
-
- //for (auto &c : code) {
- // printf("%02x ", c);
- //}
return code;
}
@@ -107,9 +104,8 @@ namespace inject {
pe_file.seekg(0, pe_file.beg);
- // HOMOSEXUAL CAST FUCKERY PLEASE SKIP THIS LINE
// AAAAAAAAAAAA BAD
- pe_file.read((char*)&m_file[0], pe_size);
+ pe_file.read((char*)m_file.data(), pe_size);
pe_file.close();
@@ -119,8 +115,8 @@ namespace inject {
}
bool c_pe_file::valid() {
- nt::dos_header_t *dos_header;
- nt::nt_headers_t *nt_headers;
+ IMAGE_DOS_HEADER *dos_header;
+ IMAGE_NT_HEADERS *nt_headers;
// check dos header
dos_header = reinterpret_cast<decltype(dos_header)>(data());
@@ -131,7 +127,7 @@ namespace inject {
// check nt header
nt_headers = reinterpret_cast<decltype(nt_headers)>(data() + dos_header->e_lfanew);
- if (nt_headers->signature != 0x50450000)
+ if (nt_headers->Signature != 0x50450000)
return false;
return true;
@@ -145,4 +141,64 @@ namespace inject {
size_t c_pe_file::size() const {
return m_file.size();
}
+
+ // implementation of mapper
+ c_mapper::c_mapper(c_pe_file &pe_file) {
+ if (!pe_file.valid()) {
+ printf("pe file error, check nt/dos headers\n");
+ }
+
+ m_pe = std::move(pe_file);
+ }
+
+ // returns size of module to allocate on client
+ size_t c_mapper::initialise(std::vector<process_export_t> &exports) {
+ if (exports.empty()) {
+ printf("no process exports received, invalid input\n");
+ return 0;
+ }
+
+ m_exports = std::move(exports);
+
+ return m_pe.size();
+ }
+
+ bool c_mapper::process_imports(uint32_t /*remote_address*/) {
+ return true;
+ }
+
+ bool c_mapper::process_reloc(uint32_t /*remote_address*/) {
+ IMAGE_DOS_HEADER *dos_header;
+ IMAGE_NT_HEADERS *nt_headers;
+
+ dos_header = reinterpret_cast<decltype(dos_header)>(m_pe.data());
+ nt_headers = reinterpret_cast<decltype(nt_headers)>(m_pe.data() + dos_header->e_lfanew);
+
+ if (nt_headers->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) {
+ printf("no reloc necessary\n");
+ return true;
+ }
+
+ return true;
+ }
+
+ // handles reloc and fixing imports
+ bool c_mapper::process_pe_file(uint32_t remote_address) {
+ if (remote_address < 0x10000000 || remote_address > 0x7FF00000) {
+ printf("invalid base address received, fail\n");
+ return false;
+ }
+
+ if (!process_reloc(remote_address))
+ return false;
+
+ if (!process_imports(remote_address))
+ return false;
+
+ return true;
+ }
+
+ std::vector<memory_section_t> c_mapper::get_pe_sections() {
+ return m_sections;
+ }
} \ No newline at end of file
diff --git a/loader/server/manual_map.hpp b/loader/server/manual_map.hpp
index c23ac90..7431353 100644
--- a/loader/server/manual_map.hpp
+++ b/loader/server/manual_map.hpp
@@ -1,92 +1,14 @@
#pragma once
+// TODO: get stripped down version of what we need and shove it in here
+#include <windows.h>
+
#include <cstdint>
#include <cstdio>
#include <fstream>
#include <iterator>
#include <vector>
-// if we compile on linux, we won't have access to windows.h (?)
-// i'll put there here just so we can access them anyway
-namespace nt {
- struct data_directory_t {
- uint32_t virtual_address;
- uint32_t size;
- };
-
- struct optional_header_t {
- uint16_t magic;
- uint8_t major_link_version;
- uint8_t minor_link_version;
- uint32_t size_of_code;
- uint32_t size_of_init_data;
- uint32_t size_of_uninit_data;
- uint32_t entry_point;
- uint32_t base_of_code;
- uint32_t base_of_data;
- uint32_t image_base;
- uint32_t section_align;
- uint32_t file_align;
- uint16_t major_os_version;
- uint16_t minor_os_version;
- uint16_t major_img_version;
- uint16_t minor_img_version;
- uint16_t major_sub_version;
- uint16_t minor_sub_version;
- uint32_t win32_version;
- uint32_t size_image;
- uint32_t size_headers;
- uint32_t checksum;
- uint16_t subsystem;
- uint16_t dll_characteristics;
- uint32_t size_of_stack_reserve;
- uint32_t size_of_stack_commit;
- uint32_t size_of_heap_reserve;
- uint32_t size_of_heap_commit;
- uint32_t ldr_flags;
- uint32_t number_of_rva_and_sizes;
- data_directory_t data_directory[16];
- };
-
- struct file_header_t {
- uint16_t machine;
- uint16_t number_of_sections;
- uint32_t time_stamp;
- uint32_t ptr_symbol_table;
- uint32_t sym_number;
- uint16_t opt_header_size;
- uint16_t characteristics;
- };
-
- struct dos_header_t {
- uint16_t e_magic;
- uint16_t e_cblp;
- uint16_t e_cp;
- uint16_t e_crlc;
- uint16_t e_cparhdr;
- uint16_t e_minalloc;
- uint16_t e_maxalloc;
- uint16_t e_ss;
- uint16_t e_sp;
- uint16_t e_csum;
- uint16_t e_ip;
- uint16_t e_cs;
- uint16_t e_lfarlc;
- uint16_t e_ovno;
- uint16_t e_res[4];
- uint16_t e_oemid;
- uint16_t e_oeminfo;
- uint16_t e_res2[10];
- int32_t e_lfanew;
- };
-
- struct nt_headers_t {
- uint32_t signature;
- file_header_t file_header;
- optional_header_t opt_header;
- };
-}
-
// here's the game plan:
// - client runs, waits for game to start and whatnot
// - we wait for serverbrowser.dll to load (if source game, we should have an option in the game struct to wait for module)
@@ -98,24 +20,57 @@ namespace nt {
// - server packs shellcode with data from client, sends to client
// - client runs shellcode, we're injected
namespace inject {
+ // used as generic wrapper for pe, tells client how much to allocate, etc.
class c_pe_file {
protected:
std::vector< uint8_t > m_file;
public:
+ c_pe_file() = default;
c_pe_file(const char *file);
bool valid();
uint8_t *data();
size_t size() const;
};
- // server part of the manual mapper
- class c_map_server {
+ // used for fixing imports
+ struct process_export_t {
+ uint32_t m_hash;
+ uint32_t m_address;
+ };
+
+ // used for writing memory in client
+ struct memory_page_t {
+ uint32_t m_address;
+ uint32_t m_protection;
+ };
+
+ // container for sections
+ using byte_array_t = std::vector<uint8_t>;
+ using memory_section_t = std::pair<memory_page_t, byte_array_t>;
+
+ // used as server wrapper for the manual mapper
+ class c_mapper {
protected:
- using section_data_t = std::vector< uint8_t >;
- using section_t = std::pair< uint32_t /* address */, section_data_t >;
-
- std::vector< section_t > m_sections;
+ std::vector<process_export_t> m_exports;
+ std::vector<memory_section_t> m_sections;
+
+ c_pe_file m_pe;
+
+ private:
+ bool process_reloc(uint32_t remote_address);
+ bool process_imports(uint32_t remote_address);
+
public:
+ c_mapper() = default;
+ c_mapper(c_pe_file &pe_file);
+
+ // returns size of module to allocate on client
+ size_t initialise(std::vector<process_export_t> &exports);
+
+ // handles reloc and fixing imports
+ bool process_pe_file(uint32_t remote_address);
+ // returns all sections
+ std::vector<memory_section_t> get_pe_sections();
};
} \ No newline at end of file