From 8b016e4409d4408c74799beb87b5ae428ed130f9 Mon Sep 17 00:00:00 2001 From: boris Date: Sun, 2 Dec 2018 17:36:33 +1300 Subject: homo shit still need to do client injection and finish reloc/import shit on server before i can call my job done --- loader/server/manual_map.cpp | 74 ++++++++++++++++++++++--- loader/server/manual_map.hpp | 129 ++++++++++++++----------------------------- 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 make_code(shellcode_args_t *arg) { std::vector 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(data()); @@ -131,7 +127,7 @@ namespace inject { // check nt header nt_headers = reinterpret_cast(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 &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(m_pe.data()); + nt_headers = reinterpret_cast(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 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 + #include #include #include #include #include -// 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; + using memory_section_t = std::pair; + + // 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 m_exports; + std::vector 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 &exports); + + // handles reloc and fixing imports + bool process_pe_file(uint32_t remote_address); + // returns all sections + std::vector get_pe_sections(); }; } \ No newline at end of file -- cgit v1.2.3