Skip to content

Commit 13eebec

Browse files
First commit
1 parent 46752ea commit 13eebec

File tree

3 files changed

+242
-0
lines changed

3 files changed

+242
-0
lines changed

README.md

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# php-eval-hook
2+
3+
A PHP extension for hooking `eval`. Useful for dumping eval-obfuscated code.
4+
5+
## Compiling steps
6+
7+
The extension has only been tested on PHP 7.2.24 available on Ubuntu 18.04 repos. Expected to work with PHP 7.x in general. May work with PHP 5.x but is untested.
8+
9+
1. Install php and php-dev packages. Here we are using the packages available on the official Ubuntu 18.04 repos.
10+
11+
```
12+
$ sudo apt install php7.2 php7.2-dev
13+
```
14+
15+
2. Clone the repository
16+
17+
```
18+
git https://github.com/extremecoders-re/php-eval-hook
19+
```
20+
21+
3. Run `phpize`. This will generate the `Makefile` and other files needed for buidling the extension.
22+
23+
```
24+
$ cd php-eval-hook
25+
$ phpize
26+
```
27+
28+
4. Build the extension. `make install` copies the `.so` to the appropriate location.
29+
30+
```
31+
$ ./configure --enable-evalhook
32+
33+
$ make
34+
35+
$ make install
36+
Installing shared extensions: /usr/lib/php/20170718/
37+
```
38+
39+
## Registering the extension with PHP
40+
41+
1. Find the location of *php.ini*.
42+
43+
```
44+
$ php -r 'phpinfo();' | grep php.ini
45+
Configuration File (php.ini) Path => /etc/php/7.2/cli
46+
Loaded Configuration File => /etc/php/7.2/cli/php.ini
47+
```
48+
49+
2. Edit *php.ini* and add the line `extension=evalhook.so` at the end.
50+
```
51+
$ echo "extension=evalhook.so" >> /etc/php/7.2/cli/php.ini
52+
```
53+
54+
3. Ensure that the extension is properly loaded.
55+
```
56+
$ php -r 'print_r(get_loaded_extensions());' | grep evalhook
57+
[14] => evalhook
58+
```
59+
60+
```
61+
$ php -r 'phpinfo();' | grep eval
62+
evalhook
63+
eval() hooking => enabled
64+
callback function => __eval
65+
```
66+
67+
## Usage
68+
69+
You must define a callback function named `__eval` in your PHP code. The extension will call this function whenever it encounters an `eval`. Inside your callback you can print the code to stdout or dump to a file or whatever you want.
70+
71+
### Example
72+
73+
**Original Code**
74+
```php
75+
<?php
76+
function test_obfuscated()
77+
{
78+
echo("This is an obfuscated function\n");
79+
}
80+
81+
test_obfuscated();
82+
?>
83+
```
84+
**obfuscated.php** [Generated from [Simple online PHP obfuscator](https://www.mobilefish.com/services/php_obfuscator/php_obfuscator.php)]
85+
```
86+
<?php
87+
eval(str_rot13(gzinflate(str_rot13(base64_decode('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')))));
88+
?>
89+
```
90+
91+
**harness.php**
92+
```php
93+
<?php
94+
function __eval($code, $file) {
95+
echo "eval() @ {$file}:\n{$code}\n\n";
96+
97+
// return FALSE if you want to prevent the eval()
98+
// return false;
99+
100+
// return a string if you want to replace the eval-d code
101+
// return 'echo 2;';
102+
103+
// return nothing to continue execution normally
104+
}
105+
106+
include("obfuscated.php");
107+
?>
108+
```
109+
110+
```
111+
$ php obfuscated.php
112+
This is an obfuscated function
113+
```
114+
115+
```
116+
$ php harness.php | tail
117+
118+
eval() @ /workspace/php7/obfuscated.php(2) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'
119+
d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : ev
120+
al()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code:
121+
function test_obfuscated()
122+
{
123+
echo("This is an obfuscated function\n");
124+
}
125+
126+
test_obfuscated();
127+
128+
This is an obfuscated function
129+
```
130+
131+
## Credits
132+
133+
The extension is based on [php-eval](https://github.com/mfmans/php-eval).

config.m4

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
PHP_ARG_ENABLE(evalhook, whether to enable evalhook support,
2+
[ --enable-evalhook Enable PHP eval hook support])
3+
if test "$PHP_EVALHOOK" = "yes"; then
4+
AC_DEFINE(HAVE_EVALHOOK, 1, [Whether you have PHP EVALHOOK])
5+
PHP_NEW_EXTENSION(evalhook, evalhook.c, $ext_shared)
6+
fi

evalhook.c

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/* $Id$ */
2+
3+
#include "php.h"
4+
#include "ext/standard/info.h"
5+
6+
7+
#define EVAL_CALLBACK_FUNCTION "__eval"
8+
9+
10+
static zend_op_array* (*old_compile_string)(zval *source_string, char *filename TSRMLS_DC);
11+
12+
13+
static zend_op_array* evalhook_compile_string(zval *source_string, char *filename TSRMLS_DC)
14+
{
15+
zend_op_array *op_array = NULL;
16+
int op_compiled = 0;
17+
18+
if(strstr(filename, "eval()'d code")) {
19+
if(zend_hash_str_exists(CG(function_table), EVAL_CALLBACK_FUNCTION, strlen(EVAL_CALLBACK_FUNCTION) TSRMLS_CC)) {
20+
zval function;
21+
zval retval;
22+
zval parameter[2];
23+
24+
parameter[0] = *source_string;
25+
26+
ZVAL_STRING(&function, EVAL_CALLBACK_FUNCTION);
27+
ZVAL_STRING(&parameter[1], filename);
28+
29+
if(call_user_function(CG(function_table), NULL, &function, &retval, 2, parameter TSRMLS_CC) == SUCCESS) {
30+
switch(Z_TYPE(retval)) {
31+
case IS_STRING:
32+
op_array = old_compile_string(&retval, filename TSRMLS_CC);
33+
case IS_FALSE:
34+
op_compiled = 1;
35+
break;
36+
}
37+
}
38+
39+
zval_dtor(&function);
40+
zval_dtor(&retval);
41+
zval_dtor(&parameter[1]);
42+
}
43+
}
44+
45+
if(op_compiled) {
46+
return op_array;
47+
} else {
48+
return old_compile_string(source_string, filename TSRMLS_CC);
49+
}
50+
}
51+
52+
53+
PHP_MINIT_FUNCTION(evalhook)
54+
{
55+
return SUCCESS;
56+
}
57+
58+
PHP_MSHUTDOWN_FUNCTION(evalhook)
59+
{
60+
return SUCCESS;
61+
}
62+
63+
PHP_RINIT_FUNCTION(evalhook)
64+
{
65+
old_compile_string = zend_compile_string;
66+
zend_compile_string = evalhook_compile_string;
67+
return SUCCESS;
68+
}
69+
70+
PHP_RSHUTDOWN_FUNCTION(evalhook)
71+
{
72+
zend_compile_string = old_compile_string;
73+
return SUCCESS;
74+
}
75+
76+
PHP_MINFO_FUNCTION(evalhook)
77+
{
78+
php_info_print_table_start();
79+
php_info_print_table_row(2, "eval() hooking", "enabled");
80+
php_info_print_table_row(2, "callback function", EVAL_CALLBACK_FUNCTION);
81+
php_info_print_table_end();
82+
}
83+
84+
85+
zend_function_entry evalhook_functions[] = {
86+
ZEND_FE_END
87+
};
88+
89+
zend_module_entry evalhook_module_entry = {
90+
STANDARD_MODULE_HEADER,
91+
"evalhook",
92+
evalhook_functions,
93+
PHP_MINIT(evalhook),
94+
PHP_MSHUTDOWN(evalhook),
95+
PHP_RINIT(evalhook),
96+
PHP_RSHUTDOWN(evalhook),
97+
PHP_MINFO(evalhook),
98+
"0.0.1-dev",
99+
STANDARD_MODULE_PROPERTIES
100+
};
101+
102+
ZEND_GET_MODULE(evalhook)
103+

0 commit comments

Comments
 (0)