├── 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 ) );
--------------------------------------------------------------------------------