#include "manual_map.hpp" namespace remote_code { //i really hope you do this the turbochad way and sigscan your own shellcode for 69696969 // u rite constexpr size_t shellcode_size = 83; constexpr uint8_t shellcode_code[] = { 0x55, // push ebp 0x8B, 0xEC, // mov ebp, esp 0x51, // push ecx 0x56, // push esi 0x8D, 0x45, 0xFC, // lea eax, dword ptr[ ebp-4 ] 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, // mov dword ptr[ ebp-4 ], 0 // ; remove memory protection so we can write 0x50, // push eax 0x6A, 0x40, // push 40h 0x6A, 0x04, // push 4h 0x68, 0x69, 0x69, 0x69, 0x69, // push dword ptr[ vmt_endscene ] 0xBE, 0xEF, 0xBE, 0xAD, 0xDE, // mov esi, dword ptr[ virtual_protect ] 0xFF, 0xD6, // call esi 0x84, 0xC0, // test al, al 0x74, 0x2A, // jz clean_up 0x8D, 0x45, 0xFC, // lea eax, dword ptr[ ebp-4 ] // ; restore endscene ptr 0xC7, 0x05, 0x69, 0x69, 0x69, 0x69, 0x0F, 0xD0, 0x0F, 0xD0, // mov [ vmt_endscene ], [ vmt_endscene_o ] // ; restore memory protection 0x50, // push eax 0xFF, 0x75, 0xFC, // push dword ptr[ ebp-4 ] 0x6A, 0x04, // push 4h 0x68, 0x69, 0x69, 0x69, 0x69, // push dword ptr[ vmt_endscene ] 0xFF, 0xD6, // call esi // ; call cheat entrypoint 0x6A, 0x00, // push 0h 0x6A, 0x01, // push 1h 0x68, 0xDE, 0xC0, 0xAD, 0xDE, // push dword ptr[ cheat_header ] 0xB8, 0x0D, 0xF0, 0xAD, 0xDE, // mov eax, dword ptr[ cheat_entry ] 0xFF, 0xD0, // call eax // clean_up: 0x5E, // pop esi 0x8B, 0xE5, // mov esp, ebp 0x5D, // pop ebp 0xC3 // retn }; struct shellcode_args_t { uint32_t m_virtual_protect; // 0xDEADBEEF uint32_t m_cheat_entrypoint; // 0xDEADF00D uint32_t m_cheat_header; // 0xDEADC0DE uint32_t m_endscene; // 0x69696969 uint32_t m_endscene_o; // 0xD00FD00F }; // turbo chad sig scanner (c) bowis int32_t find_byte_pattern(std::vector &code, std::vector pattern) { for (int32_t n = 0; n < code.size(); ++n) { // check if code matches if ((code.size() - n) >= pattern.size()) { if (!memcmp(&code[n], pattern.data(), pattern.size())) return n; } } return -1; } // turbo chad code patcher (c) bowis void patch_code(std::vector &code, int32_t offset, uint32_t value) { 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); patch_code(code, find_byte_pattern(code, { 0xEF, 0xBE, 0xAD, 0xDE }), arg->m_virtual_protect); patch_code(code, find_byte_pattern(code, { 0x0D, 0xF0, 0xAD, 0xDE }), arg->m_cheat_entrypoint); patch_code(code, find_byte_pattern(code, { 0xDE, 0xC0, 0xAD, 0xDE }), arg->m_cheat_header); patch_code(code, find_byte_pattern(code, { 0x0F, 0xD0, 0x0F, 0xD0 }), arg->m_endscene_o); // there are three occurences of endscene // 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); return code; } } namespace inject { // pe file implementation c_pe_file::c_pe_file(const char *file) { std::ifstream pe_file(file, std::ifstream::in | std::ifstream::binary); if (!pe_file.is_open()) { printf("file (%s) does not exist\n", file); return; } pe_file.seekg(0, pe_file.end); auto pe_size = pe_file.tellg(); m_file.resize(pe_size); pe_file.seekg(0, pe_file.beg); // AAAAAAAAAAAA BAD pe_file.read((char*)m_file.data(), pe_size); pe_file.close(); //remote_code::shellcode_args_t args; //args = { 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555 }; //remote_code::make_code(&args); } bool c_pe_file::valid() { IMAGE_DOS_HEADER *dos_header; IMAGE_NT_HEADERS *nt_headers; // check dos header dos_header = reinterpret_cast(data()); if (dos_header->e_magic != 0x45DA) return false; // check nt header nt_headers = reinterpret_cast(data() + dos_header->e_lfanew); if (nt_headers->Signature != 0x50450000) return false; return true; } uint8_t *c_pe_file::data() { // go to the beginning of the file return m_file.data(); } 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; } IMAGE_BASE_RELOCATION *reloc; uintptr_t address = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; uintptr_t delta = (uintptr_t)m_pe.data() - nt_headers->OptionalHeader.ImageBase; reloc = reinterpret_cast(m_pe.data() + address); while (reloc->VirtualAddress) { if (reloc->SizeOfBlock >= sizeof IMAGE_BASE_RELOCATION) { size_t count = (reloc->SizeOfBlock - sizeof IMAGE_BASE_RELOCATION) / sizeof uint16_t; uint16_t *list = (uint16_t *)reloc + 1; uintptr_t* ptr{ }; for (size_t i{ }; i < count; ++i) { if (list[i]) { ptr = (uintptr_t*)((uintptr_t)(m_pe.data()) + (reloc->VirtualAddress + (list[i] & 0xfff))); *ptr += delta; } } } // advance reloc = (IMAGE_BASE_RELOCATION *)((uintptr_t)reloc + reloc->SizeOfBlock); } 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; } }