Skip to content

Commit 5238c4f

Browse files
author
violanes
committed
Initial commit
0 parents  commit 5238c4f

File tree

8 files changed

+320
-0
lines changed

8 files changed

+320
-0
lines changed

.idea/.gitignore

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/pe_mapper_premium.iml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/php.xml

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
require_once "c_pe_mapper.php";
3+
4+
$mapper = new c_pe_mapper( "Project1.dll" );
5+
$status = $mapper->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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
class c_mem {
3+
public function read_mem( array $source, int $offset, int $size ) : array {
4+
$result = array( );
5+
for ( $i = $offset; $i < $offset + $size; $i++ )
6+
$result[ ] = $source[ $i ];
7+
8+
return $result;
9+
}
10+
11+
public function mem_copy( array $source, array $dest, int $dest_offset, int $offset, int $size ) : array {
12+
$mem = $this->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

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<?php
2+
require_once "c_mem.php";
3+
class c_pe_mapper
4+
{
5+
private $bin;
6+
private $mem_mgr;
7+
private $size_of_image, $base;
8+
private $sections = array( );
9+
private $imports = array( );
10+
private $relocs = array( );
11+
private $mapped_bin = array( );
12+
private $entry = 0;
13+
14+
public function __construct( string $path ) {
15+
$handle = fopen( $path, "rb" );
16+
$file_size = filesize( $path );
17+
$contents = fread( $handle, $file_size );
18+
$this->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+
}

index.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
require_once "c_pe_mapper.php";
3+
4+
$mapper = new c_pe_mapper( "Project1.dll" );
5+
$status = $mapper->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 ) );

0 commit comments

Comments
 (0)