├── README.md ├── api.php ├── c_mem.php ├── c_pe_mapper.php ├── client ├── pe_mapper_premium_clientside.sln └── pe_mapper_premium_clientside │ ├── json.hpp │ ├── pe_mapper_premium_clientside.vcxproj │ ├── pe_mapper_premium_clientside.vcxproj.filters │ ├── remote.hpp │ ├── requests.cpp │ ├── requests.hpp │ ├── src.cpp │ └── str_transformer.hpp └── index.php /README.md: -------------------------------------------------------------------------------- 1 | # php_server_mapper 2 | Win32 PE server mapper written on PHP. 3 |

4 | ## System requirements: 5 | - Win32 PE to load (dll, sys) 6 | - PHP 5.0+- 7 | - Web Server (nginx/apache) 8 |

9 | ## Features: 10 | - Complete premapper, no unnecessary data is sent to client 11 | - Optimized PE parser 12 | - API set fix 13 | - Themida and Code Virtualizer support 14 | - Win32 PE support 15 | - Reloc table is being stripped 16 | - Doesn't require VDS to run (only webhosting is required) 17 | - Popular data serialization used - (json) 18 | - No POST or PUT requests (very good for optimization and times to load) 19 | - Can be easily integrated with xenforo or any other web engine written on php 20 | - Requires LITERALLY any version of php 21 | - Project includes client written on C++ 22 | - Even ordinal imports can be resolved (untested) 23 |

24 | ## Improvements: 25 | - Add caching system to store the bin after initialization (not required) 26 |

27 | ## Credits: 28 | - [@es3n1n](https://github.com/es3n1n) 29 | - [@violanes](https://github.com/violanes) 30 | - Mr. Nursultan Probirkeen (contact: og@mail.ru) 31 | - [@cpz](https://github.com/cpz) 32 | -------------------------------------------------------------------------------- /api.php: -------------------------------------------------------------------------------- 1 | initialize( ); 6 | 7 | if ( $status != 0 ) { 8 | echo json_encode( array( "status" => $status ), JSON_UNESCAPED_SLASHES ); 9 | exit( ); 10 | } 11 | 12 | if ( isset( $_GET[ "data" ] ) ) { 13 | echo json_encode( $mapper->get_loader_data( ), JSON_UNESCAPED_SLASHES ); 14 | } elseif ( isset( $_GET[ "image" ] ) ) { 15 | if ( !isset( $_GET[ "base" ] ) || !isset( $_GET[ "imports" ] ) ) { 16 | echo json_encode( array( "success" => false ), JSON_UNESCAPED_SLASHES ); 17 | exit( ); 18 | } 19 | 20 | $mapped_bin = $mapper->map( intval( $_GET[ "base" ] ), json_decode( $_GET[ "imports" ], 1 ) ); 21 | if ( count( $mapped_bin ) < 0x1000 ) { 22 | echo json_encode( array( "success" => false ), JSON_UNESCAPED_SLASHES ); 23 | exit( ); 24 | } 25 | 26 | echo json_encode( $mapped_bin, JSON_UNESCAPED_SLASHES ); 27 | } -------------------------------------------------------------------------------- /c_mem.php: -------------------------------------------------------------------------------- 1 | read_mem( $source, $offset, $size ); 13 | for ( $i = $dest_offset; $i < $dest_offset + $size; $i++ ) 14 | $dest[ $i ] = $mem[ $i - $dest_offset ]; 15 | 16 | return $dest; 17 | } 18 | 19 | public function set_dword( array $dest, int $offset, int $delta ) : array { 20 | $replacement = unpack( "C*", pack( "L", $delta ) ); 21 | for ( $i = $offset; $i < $offset + 4; $i++ ) 22 | $dest[ $i ] = $replacement[ $i - $offset + 1 ]; 23 | 24 | return $dest; 25 | } 26 | 27 | public function read_dword( array $source, int $offset ) : int { 28 | $arr = $this->read_mem($source, $offset, 4); 29 | return (($arr[3] & 0xFF) << 24) | (($arr[2] & 0xFF) << 16) | (($arr[1] & 0xFF) << 8) | ($arr[0] & 0xFF); 30 | } 31 | 32 | public function read_qword( array $source, int $offset ) : array { 33 | return $this->read_mem($source, $offset, 8); 34 | } 35 | 36 | public function read_word( array $source, int $offset ) : int { 37 | $arr = $this->read_mem($source, $offset, 2); 38 | return (($arr[1] & 0xFF) << 8) | ($arr[0] & 0xFF); 39 | } 40 | 41 | public function read_string( array $source, int $offset ) : string { 42 | $result = ""; 43 | while ( $source[ $offset ] != 0 ) 44 | $result .= chr( $source[ $offset++ ] ); 45 | 46 | return $result; 47 | } 48 | } -------------------------------------------------------------------------------- /c_pe_mapper.php: -------------------------------------------------------------------------------- 1 | bin = unpack( "C*", $contents ); 19 | fclose( $handle ); 20 | 21 | $this->mem_mgr = new c_mem( ); 22 | } 23 | 24 | public function initialize( ) : int { 25 | $dos_nt_offset = $this->mem_mgr->read_dword( $this->bin, 0x3C + 0x1 ); 26 | $nt_sig = $this->mem_mgr->read_dword( $this->bin, $dos_nt_offset + 0x1 ); 27 | 28 | if ( $nt_sig != 0x4550 ) 29 | return 1; // invalid nt signature 30 | 31 | $size_of_image = $this->mem_mgr->read_dword( $this->bin, $dos_nt_offset + 0x50 + 0x1 ); 32 | $size_of_header = $this->mem_mgr->read_word( $this->bin, $dos_nt_offset + 0x54 + 0x1 ); 33 | 34 | $this->base = $this->mem_mgr->read_dword( $this->bin, $dos_nt_offset + 0x34 + 0x1 ); 35 | $this->size_of_image = $size_of_image; 36 | 37 | $mapped_bin = array_fill( 0, $size_of_image, 0 ); 38 | $mapped_bin = $this->mem_mgr->mem_copy( $this->bin, $mapped_bin, 0, 1, $size_of_header ); 39 | 40 | $num_of_sections = $this->mem_mgr->read_word( $mapped_bin, $dos_nt_offset + 0x6 ); 41 | $section_header = array_fill( 0, 0x28 * $num_of_sections, 0 ); 42 | $section_header = $this->mem_mgr->mem_copy( $mapped_bin, $section_header, 0, 43 | $dos_nt_offset + 0xF8, 0x28 * $num_of_sections ); 44 | 45 | $this->entry = $this->mem_mgr->read_dword( $mapped_bin, $dos_nt_offset + 0x28 ); 46 | 47 | for ( $i = 0; $i < $num_of_sections; $i++ ) { 48 | $name = ""; 49 | foreach ( $this->mem_mgr->read_qword( $section_header, $i * 0x28 ) as $char ) 50 | $name .= chr( $char ); 51 | 52 | $va = $this->mem_mgr->read_dword( $section_header, $i * 0x28 + 0xC ); 53 | $ptr = $this->mem_mgr->read_dword( $section_header, $i * 0x28 + 0x14 ); 54 | $size = $this->mem_mgr->read_dword( $section_header, $i * 0x28 + 0x10 ); 55 | 56 | $this->sections[ $name ] = array( 57 | "virtual_address" => $va, 58 | "ptr_to_raw" => $ptr, 59 | "size" => $size 60 | ); 61 | 62 | if ( $name == ".reloc" ) { 63 | for ( $j = 0; $j < $size; $j++ ) 64 | $this->bin[ $ptr + $j + 1 ] = 0; 65 | } 66 | 67 | $mapped_bin = $this->mem_mgr->mem_copy( $this->bin, $mapped_bin, $va, $ptr + 1, $size ); 68 | } 69 | 70 | $directories = array_fill( 0, 0x8 * 16, 0 ); 71 | $directories = $this->mem_mgr->mem_copy( $mapped_bin, $directories, 0, 72 | $dos_nt_offset + 0x78, 0x8 * 16 ); 73 | 74 | $imp_dir_offset = $this->mem_mgr->read_dword( $directories, 0x8 ); 75 | 76 | $imports = array_fill( 0, $this->mem_mgr->read_dword( $directories, 0x8 + 4 ), 0 ); 77 | $imports = $this->mem_mgr->read_mem( $mapped_bin, $imp_dir_offset, count( $imports ) ); 78 | 79 | while ( $this->mem_mgr->read_dword( $imports, 0 ) > 0 ) { 80 | $module_name = $this->mem_mgr->read_string( $mapped_bin, 81 | $this->mem_mgr->read_dword( $imports, 0xC ) ); 82 | 83 | $thunk_offset = 0; 84 | $orig_thunk = $this->mem_mgr->read_mem( $mapped_bin, 85 | $this->mem_mgr->read_dword( $imports, 0x0 ), 4 ); 86 | 87 | if ( mb_substr( $module_name, 0, 7 ) == "api-ms-" ) 88 | $module_name = "ucrtbase.dll"; 89 | 90 | while ( $this->mem_mgr->read_dword( $orig_thunk, 0 ) > 0 ) { 91 | $thunk_data = $this->mem_mgr->read_dword( $orig_thunk, 0 ); 92 | if ( $thunk_data & 0x80000000 ) { 93 | $function = $thunk_data & 0xFFFF; 94 | } else { 95 | $function = $this->mem_mgr->read_string( $mapped_bin, 96 | $this->mem_mgr->read_dword( $orig_thunk, 0 ) + 2 ); 97 | } 98 | 99 | $this->imports[ $module_name ][ $function ] = $this->mem_mgr->read_dword( $imports, 0x10 ) 100 | + $thunk_offset; 101 | 102 | $thunk_offset += 4; 103 | $orig_thunk = $this->mem_mgr->read_mem( $mapped_bin, 104 | $this->mem_mgr->read_dword( $imports, 0x0 ) + $thunk_offset, 4 ); 105 | } 106 | 107 | $imp_dir_offset += 0x14; 108 | $imports = $this->mem_mgr->read_mem( $mapped_bin, $imp_dir_offset, count( $imports ) ); 109 | } 110 | 111 | $reloc_dir_offset = $this->mem_mgr->read_dword( $directories, 0x8 * 5 ); 112 | 113 | $relocs = array_fill( 0, $this->mem_mgr->read_dword( $directories, 0x8 * 5 + 4 ), 0 ); 114 | $relocs = $this->mem_mgr->read_mem( $mapped_bin, $reloc_dir_offset, count( $relocs ) ); 115 | 116 | while ( $this->mem_mgr->read_dword( $relocs, 0 ) > 0 ) { 117 | // CODE VIRTUALIZER AND THEMIDA SUPPORT! NEVER SEEN BEFORE 118 | if ( $this->mem_mgr->read_dword( $relocs, 0 ) >= $size_of_image ) 119 | break; 120 | // END OF CODE VIRTUALIZER AND THEMIDA SUPPORT! NEVER SEEN BEFORE 121 | 122 | $num_of_relocs = ( $this->mem_mgr->read_dword( $relocs, 4 ) - 8 ) / 2; 123 | $block = $this->mem_mgr->read_mem( $mapped_bin, $reloc_dir_offset + 8, $num_of_relocs * 2 ); 124 | 125 | for ( $i = 0; $i < $num_of_relocs; $i++ ) { 126 | $block_offset = $this->mem_mgr->read_word( $block, $i * 2 ); 127 | if ( $block_offset >> 0xC != 3 ) 128 | continue; 129 | 130 | $this->relocs[ ] = $this->mem_mgr->read_dword( $relocs, 0 ) + ( $block_offset & 0xFFF ); 131 | } 132 | 133 | $reloc_dir_offset += $this->mem_mgr->read_dword( $relocs, 4 ); 134 | $relocs = $this->mem_mgr->read_mem( $mapped_bin, $reloc_dir_offset, count( $relocs ) ); 135 | } 136 | 137 | $this->mapped_bin = $mapped_bin; 138 | return 0; 139 | } 140 | 141 | public function map( int $base, array $imports ) : array { 142 | $mapped_bin = array_fill( 0, $this->size_of_image, 0 ); 143 | foreach ( $this->sections as $section ) { 144 | $mapped_bin = $this->mem_mgr->mem_copy( $this->mapped_bin, $mapped_bin, 145 | $section[ "virtual_address" ], $section[ "virtual_address" ], $section[ "size" ] ); 146 | } 147 | 148 | foreach ( $this->relocs as $reloc ) { 149 | $mapped_bin = $this->mem_mgr->set_dword( $mapped_bin, $reloc, 150 | $this->mem_mgr->read_dword( $mapped_bin, $reloc ) + $base - $this->base ); 151 | } 152 | 153 | foreach ( $this->imports as $module => $functions ) { 154 | if ( empty( $imports[ $module ] ) || !is_array( $imports[ $module ] ) ) 155 | return array( ); 156 | 157 | foreach ( $functions as $function => $rva ) { 158 | if ( empty( $imports[ $module ][ $function ] ) ) 159 | return array( ); 160 | 161 | $mapped_bin = $this->mem_mgr->set_dword( $mapped_bin, $rva, $imports[ $module ][ $function ] ); 162 | } 163 | } 164 | 165 | return $mapped_bin; 166 | } 167 | 168 | public function get_loader_data( ) : array { 169 | $imports = array( ); 170 | foreach ( $this->imports as $module => $functions ) { 171 | foreach ( $functions as $function => $rva ) 172 | $imports[ $module ][ ] = $function; 173 | } 174 | 175 | return ( 176 | array( 177 | "imports" => $imports, 178 | "size" => $this->size_of_image, 179 | "entry" => $this->entry 180 | ) 181 | ); 182 | } 183 | } -------------------------------------------------------------------------------- /client/pe_mapper_premium_clientside.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33205.214 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pe_mapper_premium_clientside", "pe_mapper_premium_clientside\pe_mapper_premium_clientside.vcxproj", "{C3FD91EB-8335-4177-8ED8-72E1B9CB5BEC}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {C3FD91EB-8335-4177-8ED8-72E1B9CB5BEC}.Debug|x64.ActiveCfg = Debug|x64 17 | {C3FD91EB-8335-4177-8ED8-72E1B9CB5BEC}.Debug|x64.Build.0 = Debug|x64 18 | {C3FD91EB-8335-4177-8ED8-72E1B9CB5BEC}.Debug|x86.ActiveCfg = Debug|Win32 19 | {C3FD91EB-8335-4177-8ED8-72E1B9CB5BEC}.Debug|x86.Build.0 = Debug|Win32 20 | {C3FD91EB-8335-4177-8ED8-72E1B9CB5BEC}.Release|x64.ActiveCfg = Release|x64 21 | {C3FD91EB-8335-4177-8ED8-72E1B9CB5BEC}.Release|x64.Build.0 = Release|x64 22 | {C3FD91EB-8335-4177-8ED8-72E1B9CB5BEC}.Release|x86.ActiveCfg = Release|Win32 23 | {C3FD91EB-8335-4177-8ED8-72E1B9CB5BEC}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {22B6EDB0-9C8E-40DB-B35F-A12D6A98D792} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /client/pe_mapper_premium_clientside/pe_mapper_premium_clientside.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {c3fd91eb-8335-4177-8ed8-72e1b9cb5bec} 25 | pemapperpremiumclientside 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | true 79 | stdcpplatest 80 | stdc17 81 | 82 | 83 | Console 84 | true 85 | 86 | 87 | 88 | 89 | Level3 90 | true 91 | true 92 | true 93 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | true 95 | stdcpplatest 96 | stdc17 97 | 98 | 99 | Console 100 | true 101 | true 102 | true 103 | 104 | 105 | 106 | 107 | Level3 108 | true 109 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 110 | true 111 | 112 | 113 | Console 114 | true 115 | 116 | 117 | 118 | 119 | Level3 120 | true 121 | true 122 | true 123 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 124 | true 125 | 126 | 127 | Console 128 | true 129 | true 130 | true 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /client/pe_mapper_premium_clientside/pe_mapper_premium_clientside.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /client/pe_mapper_premium_clientside/remote.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "str_transformer.hpp" 8 | 9 | 10 | namespace remote { 11 | inline std::uintptr_t get_module_base(::HANDLE proc, const std::string& module_name) noexcept { 12 | auto snaphsot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, GetProcessId(proc)); 13 | 14 | if (!snaphsot || snaphsot == INVALID_HANDLE_VALUE) { 15 | return 0; 16 | } 17 | 18 | ::MODULEENTRY32W entry = { .dwSize = sizeof(entry) }; 19 | if (!Module32FirstW(snaphsot, &entry)) { 20 | CloseHandle(snaphsot); 21 | return 0; 22 | } 23 | 24 | auto w_s_module = ::str_transformer::str_to_wstr(module_name); 25 | ::str_transformer::stolower(w_s_module); 26 | 27 | do { 28 | auto module_name = std::wstring(entry.szModule); 29 | ::str_transformer::stolower(module_name); 30 | ::str_transformer::truncate(module_name); 31 | 32 | if (!wcscmp(module_name.c_str(), w_s_module.c_str())) { 33 | CloseHandle(snaphsot); 34 | return reinterpret_cast(entry.modBaseAddr); 35 | } 36 | } while (Module32Next(snaphsot, &entry)); 37 | 38 | CloseHandle(snaphsot); 39 | return 0; 40 | } 41 | 42 | inline bool write_raw(::HANDLE proc, std::uint64_t addr, const void* buffer, std::size_t size, std::size_t* size_written) noexcept { 43 | return 44 | WriteProcessMemory(proc, 45 | reinterpret_cast(addr), 46 | buffer, 47 | size, 48 | (SIZE_T*)size_written); 49 | } 50 | 51 | inline bool read_raw(::HANDLE proc, std::uint64_t addr, void* buffer, std::size_t size, std::size_t* size_read) noexcept { 52 | return 53 | ReadProcessMemory( 54 | proc, 55 | reinterpret_cast(addr), 56 | buffer, 57 | size, 58 | (SIZE_T*)size_read); 59 | } 60 | 61 | inline std::uintptr_t alloc_raw(::HANDLE proc, std::size_t size, std::uint32_t protect = PAGE_EXECUTE_READWRITE, std::uint32_t type = MEM_COMMIT) noexcept { 62 | return reinterpret_cast(VirtualAllocEx(proc, 63 | 0, 64 | size, 65 | type, 66 | protect)); 67 | } 68 | 69 | inline bool free_raw(::HANDLE proc, std::uint64_t addr) noexcept { 70 | return 71 | VirtualFreeEx( 72 | proc, 73 | reinterpret_cast<::LPVOID>(addr), 74 | 0, 75 | MEM_RELEASE); 76 | } 77 | 78 | inline std::uintptr_t get_proc_address(::HANDLE proc, std::uintptr_t mod_base, const std::string& func_name) { 79 | static std::uintptr_t region = 0; 80 | static std::uintptr_t p_mod_base = 0; 81 | static std::uintptr_t p_func_name = 0; 82 | static std::uintptr_t p_result = 0; 83 | 84 | if (!region) { 85 | std::vector shellcode = { 86 | 0x68, 0x88, 0x14, 0x88, 0x14, // push 0x14881488 87 | 0xFF, 0x35, 0x37, 0x13, 0x37, 0x13, // push dword ptr [0x13371337] 88 | 0xB8, 0x37, 0x13, 0x37, 0x13, // mov eax, 0x1337 89 | 0xFF, 0xD0, // call eax 90 | 0xA3, 0x37, 0x13, 0x37, 0x13, // mov dword ptr [0x1337], eax 91 | 0xC3, // ret 92 | }; 93 | 94 | region = alloc_raw(proc, 0x1000, PAGE_EXECUTE_READWRITE, MEM_COMMIT); 95 | p_mod_base = region + shellcode.size(); 96 | p_result = p_mod_base + sizeof(std::uintptr_t); 97 | p_func_name = p_result + sizeof(std::uintptr_t); 98 | 99 | *reinterpret_cast(&shellcode[1]) = p_func_name; 100 | *reinterpret_cast(&shellcode[7]) = p_mod_base; 101 | *reinterpret_cast(&shellcode[12]) = reinterpret_cast(GetProcAddress); 102 | *reinterpret_cast(&shellcode[19]) = p_result; 103 | 104 | if (!write_raw(proc, region, shellcode.data(), shellcode.size(), nullptr)) 105 | throw std::runtime_error("unable to write shellcode"); 106 | } 107 | 108 | std::uintptr_t result = 0; 109 | if (!write_raw(proc, p_result, &result, sizeof(result), nullptr)) 110 | throw std::runtime_error("unable to reset shellcode"); 111 | 112 | if (!write_raw(proc, p_mod_base, &mod_base, sizeof(mod_base), nullptr)) 113 | throw std::runtime_error("unable to write shellcode [0]"); 114 | 115 | std::vector func_name_raw(func_name.length() + 1); 116 | std::memcpy(func_name_raw.data(), func_name.data(), func_name.length()); 117 | func_name_raw[func_name.length()] = '\0'; 118 | 119 | if (!write_raw(proc, p_func_name, func_name_raw.data(), func_name_raw.size(), nullptr)) 120 | throw std::runtime_error("unable to write shellcode [1]"); 121 | 122 | WaitForSingleObject(CreateRemoteThread(proc, nullptr, 0, reinterpret_cast(region), nullptr, 0, nullptr), -1); 123 | 124 | if (!read_raw(proc, p_result, &result, sizeof(result), nullptr)) 125 | throw std::runtime_error("unable to read result [2]"); 126 | 127 | return result; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /client/pe_mapper_premium_clientside/requests.cpp: -------------------------------------------------------------------------------- 1 | #include "requests.hpp" 2 | 3 | namespace networking { 4 | errorable_json_result get(const char* domain, const char* url) { 5 | std::string response_data = err_json_data; 6 | 7 | auto internet_session = InternetOpenA("Autism/1.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); 8 | 9 | if (!internet_session) 10 | return { nlohmann::json::parse(response_data), true }; 11 | 12 | auto http_session = InternetConnectA(internet_session, domain, 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL); 13 | 14 | if (!http_session) 15 | return { nlohmann::json::parse(response_data), true }; 16 | 17 | HINTERNET http_req = HttpOpenRequestA(http_session, "GET", url, 0, 0, 0, INTERNET_FLAG_RELOAD, 0); 18 | 19 | if (!http_session) 20 | return nlohmann::json::parse(response_data); 21 | 22 | const char* szHeaders = "Content-Type: application/json\r\nUser-Agent: Autism/1.0"; 23 | 24 | if (!HttpSendRequestA(http_req, szHeaders, strlen(szHeaders), NULL, NULL)) 25 | return { response_data, true }; 26 | 27 | response_data.clear(); 28 | 29 | CHAR temp_buffer[1024] = { 0 }; 30 | DWORD read_ret = 0; 31 | 32 | while (InternetReadFile(http_req, temp_buffer, sizeof(temp_buffer) - 1, &read_ret) && read_ret) 33 | response_data.append(temp_buffer, read_ret); 34 | 35 | InternetCloseHandle(http_req); 36 | InternetCloseHandle(http_session); 37 | InternetCloseHandle(internet_session); 38 | 39 | try { 40 | return { nlohmann::json::parse(response_data), false }; 41 | } 42 | catch (const nlohmann::json::parse_error& err [[maybe_unused]] ) { 43 | return { nlohmann::json::parse(err_json_data), true }; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /client/pe_mapper_premium_clientside/requests.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // clang-format off 3 | #include 4 | #include 5 | #include 6 | // clang-format on 7 | #include 8 | 9 | #include "json.hpp" 10 | 11 | #pragma comment(lib, "urlmon.lib") 12 | #pragma comment(lib, "wininet.lib") 13 | 14 | namespace networking { 15 | using errorable_json_result = std::pair; 16 | constexpr const char* err_json_data = "{\"error\": \"Unable to connect to server\"}"; 17 | 18 | errorable_json_result get(const char* domain, const char* url); 19 | } // namespace networking 20 | -------------------------------------------------------------------------------- /client/pe_mapper_premium_clientside/src.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "requests.hpp" 6 | #include "remote.hpp" 7 | 8 | #define DOMAIN "yougametest.com" 9 | #define SCRIPT_PATH "/debil/api.php" 10 | 11 | 12 | namespace api { 13 | struct initial_data_t { 14 | public: 15 | struct import_t { 16 | public: 17 | std::string m_module; 18 | std::unordered_map m_functions; 19 | }; 20 | 21 | std::vector m_imports; 22 | std::size_t m_size; 23 | std::uintptr_t m_entry; 24 | }; 25 | 26 | initial_data_t get_initial_data() { 27 | auto [resp, err] = networking::get(DOMAIN, SCRIPT_PATH "?data"); 28 | if (err) 29 | throw std::runtime_error("unable to get initial data"); 30 | 31 | initial_data_t data; 32 | 33 | const auto import_data = resp["imports"].get(); 34 | for (auto [module_name, functions] : import_data) { 35 | auto& imported_module = data.m_imports.emplace_back(); 36 | 37 | imported_module.m_module = module_name; 38 | for (auto&& func_name : functions) 39 | imported_module.m_functions.emplace(func_name, 0); 40 | } 41 | 42 | data.m_size = resp.at("size").get(); 43 | data.m_entry = resp.at("entry").get(); 44 | 45 | return data; 46 | } 47 | 48 | std::vector get_binary(std::uintptr_t base, initial_data_t& initial_data) { 49 | nlohmann::json imports_data; 50 | 51 | for (auto& import_data : initial_data.m_imports) 52 | imports_data[import_data.m_module] = import_data.m_functions; 53 | 54 | auto [resp, err] = networking::get(DOMAIN, (std::string(SCRIPT_PATH"?image=1&base=") + std::to_string(base) + "&imports=" + imports_data.dump()).c_str()); 55 | if (err) 56 | throw std::runtime_error("unable to get binary"); 57 | 58 | return resp.get>(); 59 | } 60 | } 61 | 62 | 63 | namespace detail { 64 | void* get_process_by_name(const wchar_t* name) { 65 | void* thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 66 | if (thSnapShot == INVALID_HANDLE_VALUE) 67 | return nullptr; 68 | 69 | PROCESSENTRY32W pe; 70 | pe.dwSize = sizeof(PROCESSENTRY32W); 71 | 72 | unsigned long ret = 0; 73 | for (bool proc = Process32FirstW(thSnapShot, &pe); proc; proc = Process32NextW(thSnapShot, &pe)) { 74 | if (wcscmp(pe.szExeFile, name)) 75 | continue; 76 | ret = pe.th32ProcessID; 77 | break; 78 | } 79 | 80 | CloseHandle(thSnapShot); 81 | 82 | return ret ? OpenProcess(PROCESS_ALL_ACCESS, false, ret) : nullptr; 83 | } 84 | } 85 | 86 | 87 | int main() try { 88 | void* proc = detail::get_process_by_name(L"steam.exe"); 89 | if (!proc) { 90 | std::cerr << "process not found" << std::endl; 91 | return EXIT_FAILURE; 92 | } 93 | 94 | auto initial_data = api::get_initial_data(); 95 | std::cout << "got initial_data | size: " << initial_data.m_size << std::endl; 96 | 97 | for (auto& import : initial_data.m_imports) { 98 | auto mod_base = remote::get_module_base(proc, import.m_module); 99 | 100 | for (auto [function_name, _] : import.m_functions) { 101 | auto exp = remote::get_proc_address(proc, mod_base, function_name); 102 | if (!exp) 103 | throw std::runtime_error("unable to get export " + function_name); 104 | 105 | import.m_functions[function_name] = exp; 106 | std::cout << "[~] " << function_name << " @ " << std::hex << std::showbase << exp << std::endl; 107 | } 108 | } 109 | 110 | const auto base = remote::alloc_raw(proc, initial_data.m_size, PAGE_EXECUTE_READWRITE, MEM_COMMIT); 111 | if (!base) 112 | throw std::runtime_error("no base?"); 113 | 114 | const auto bin = api::get_binary(base, initial_data); 115 | if (!remote::write_raw(proc, base, bin.data(), bin.size(), nullptr)) 116 | throw std::runtime_error("unable to write final binary"); 117 | 118 | std::vector invoke_ep_shell = { 119 | 0x83, 0xEC, 0x28, // sub esp, 0x28 120 | 0x68, 0x00, 0x00, 0x00, 0x00, // push reserved 121 | 0x68, 0x01, 0x00, 0x00, 0x00, // push DLL_PROCESS_ATTACH 122 | 0x68, 0x00, 0x00, 0x00, 0x00, // push base 123 | 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, entrypoint 124 | 0xFF, 0xD0, // call eax 125 | 0x83, 0xC4, 0x28, // add esp, 0x28 126 | 0xC3 // ret 127 | }; 128 | 129 | *reinterpret_cast(&invoke_ep_shell[4]) = 0x1337; // reserved value 130 | *reinterpret_cast(&invoke_ep_shell[14]) = base; 131 | *reinterpret_cast(&invoke_ep_shell[19]) = base + initial_data.m_entry; 132 | 133 | if (!remote::write_raw(proc, base, invoke_ep_shell.data(), invoke_ep_shell.size(), nullptr)) 134 | throw std::runtime_error("unable to write shellcode"); 135 | 136 | CreateRemoteThread(proc, nullptr, 0, LPTHREAD_START_ROUTINE(base), nullptr, 0, nullptr); 137 | 138 | std::cout << "[~] done" << std::endl; 139 | return EXIT_SUCCESS; 140 | } 141 | catch (std::runtime_error& err) { 142 | std::cerr << "EXCEPTION: " << err.what() << std::endl; 143 | return EXIT_FAILURE; 144 | } 145 | 146 | static_assert(sizeof(void*) == 4, "go fuck yourself"); 147 | -------------------------------------------------------------------------------- /client/pe_mapper_premium_clientside/str_transformer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | namespace str_transformer { 8 | inline void stolower(std::string& data) noexcept { 9 | std::transform(data.begin(), data.end(), data.begin(), tolower); 10 | } 11 | 12 | inline void stolower(std::wstring& data) noexcept { 13 | std::transform(data.begin(), data.end(), data.begin(), towlower); 14 | } 15 | 16 | inline void stolower(std::wstring& data, std::size_t size) noexcept { 17 | std::transform(data.begin(), data.begin() + size, data.begin(), towlower); 18 | } 19 | 20 | inline void truncate(std::string& data) noexcept { 21 | data.erase(std::find(data.begin(), data.end(), '\0'), data.end()); 22 | } 23 | 24 | inline void truncate(std::wstring& data) noexcept { 25 | data.erase(std::find(data.begin(), data.end(), '\0'), data.end()); 26 | } 27 | 28 | inline std::string wstr_to_str(const std::wstring& data) noexcept { 29 | 30 | if (data.empty()) { 31 | return {}; 32 | } 33 | 34 | const int str_len = 35 | WideCharToMultiByte( 36 | CP_UTF8, 37 | 0, 38 | data.data(), static_cast(data.size()), 39 | nullptr, 0, nullptr, nullptr 40 | ); 41 | 42 | std::string out; 43 | out.resize(str_len); 44 | 45 | WideCharToMultiByte( 46 | CP_UTF8, 47 | 0, 48 | data.data(), static_cast(data.size()), 49 | &out[0], str_len, 50 | nullptr, nullptr 51 | ); 52 | 53 | return out; 54 | } 55 | 56 | inline std::string wstr_to_str(const std::wstring_view data) noexcept { 57 | 58 | if (data.empty()) { 59 | return {}; 60 | } 61 | 62 | const int str_len = 63 | WideCharToMultiByte( 64 | CP_UTF8, 65 | 0, 66 | data.data(), static_cast(data.size()), 67 | nullptr, 0, nullptr, nullptr 68 | ); 69 | 70 | std::string out; 71 | out.resize(str_len); 72 | 73 | WideCharToMultiByte( 74 | CP_UTF8, 75 | 0, 76 | data.data(), static_cast(data.size()), 77 | &out[0], str_len, 78 | nullptr, nullptr 79 | ); 80 | 81 | return out; 82 | } 83 | 84 | inline std::wstring str_to_wstr(const std::string& data) noexcept { 85 | if (data.empty()) { 86 | return {}; 87 | } 88 | 89 | const int str_len = 90 | MultiByteToWideChar( 91 | CP_UTF8, 92 | 0, 93 | data.data(), static_cast(data.size()), 94 | nullptr, 0 95 | ); 96 | 97 | std::wstring out; 98 | out.resize(str_len); 99 | 100 | MultiByteToWideChar( 101 | CP_UTF8, 102 | 0, 103 | data.data(), static_cast(data.size()), 104 | &out[0], str_len 105 | ); 106 | 107 | return out; 108 | } 109 | 110 | inline std::wstring str_to_wstr(const std::string_view data) noexcept { 111 | if (data.empty()) { 112 | return {}; 113 | } 114 | 115 | const int str_len = 116 | MultiByteToWideChar( 117 | CP_UTF8, 118 | 0, 119 | data.data(), static_cast(data.size()), 120 | nullptr, 0 121 | ); 122 | 123 | std::wstring out; 124 | out.resize(str_len); 125 | 126 | MultiByteToWideChar( 127 | CP_UTF8, 128 | 0, 129 | data.data(), static_cast(data.size()), 130 | &out[0], str_len 131 | ); 132 | 133 | return out; 134 | } 135 | } -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | initialize( ); 6 | if ( $status != 0 ) 7 | echo "failed cause of " . $status; 8 | 9 | //echo "init passed successfully!"; 10 | 11 | $mapper_data = json_decode( $mapper->get_loader_data( ), 1 ); 12 | $imports = array( ); 13 | foreach ( $mapper_data[ "imports" ] as $import => $functions ) { 14 | foreach ( $functions as $function ) 15 | $imports[ $import ][ $function ] = 0x14881488; 16 | } 17 | 18 | print_r( $mapper->map( 0x30000000, $imports ) ); --------------------------------------------------------------------------------