├── Dockerfile ├── LICENSE.md ├── README.md ├── config ├── piof.ini └── rsyslog.conf ├── images ├── headerlogo.png ├── icon90.png ├── icon_black.png ├── icon_transparent.png ├── logo.html └── logo.png ├── run.sh └── src ├── .gitignore ├── config.m4 ├── hooks ├── include │ ├── hook.c │ └── hook.h ├── md5 │ ├── hook.c │ └── hook.h └── system │ ├── hook.c │ └── hook.h ├── hooks_disabled └── eval │ ├── hook.c │ └── hook.h ├── piof.c ├── piof_config.h ├── piof_globals.c ├── piof_globals.h └── scripts ├── buildall.sh ├── buildhooks.sh └── tests.sh /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.2-apache 2 | 3 | RUN apt update 4 | 5 | RUN docker-php-source extract 6 | 7 | RUN apt install nano -y 8 | 9 | RUN apt install rsyslog --fix-missing -y 10 | 11 | COPY config/piof.ini /usr/local/etc/php/conf.d 12 | 13 | COPY config/rsyslog.conf /etc/rsyslog.conf 14 | 15 | 16 | COPY src /opt/piof 17 | 18 | WORKDIR /opt/piof/ 19 | 20 | RUN ./scripts/buildall.sh 21 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | Copyright 2019 Martino Lessio - Alessandro Braccio 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) 2 | ![Twitter Follow](https://img.shields.io/twitter/follow/rhpco.svg?label=Twitter%20%40rhpco&style=social) 3 | ![Twitter Follow](https://img.shields.io/twitter/follow/martinolessio.svg?label=Twitter%20%40martinolessio&style=social) 4 | 5 | 6 | # PIOF - PHP Instrumentation Open Framework 7 | ![PIOF - PHP Instrumentation Open Framework](https://github.com/ingenuity-ninja/piof/raw/master/images/headerlogo.png) 8 | 9 | # What 10 | PIOF - Is a dynamic and modular instrumentation framework for PHP. 11 | 12 | # Why 13 | It is useful for Developers, Reverse Engineers, Malware Analyst and Vulnerability Researcher. 14 | With PIOF you can: 15 | 16 | - Perform debugging, tracing and performance analysis 17 | - Instrument PHP code on the interpreter layer 18 | - Instrument obfuscated PHP code 19 | - Virtual Patching 20 | - Prototype IAST and RASP technologies 21 | 22 | # Where 23 | Tested on: 24 | ``` 25 | PHP 7.2.10-0ubuntu0.18.04.1 (cli) (built: Sep 13 2018 13:45:02) ( NTS ) 26 | Copyright (c) 1997-2018 The PHP Group 27 | Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies 28 | with Zend OPcache v7.2.10-0ubuntu0.18.04.1, Copyright (c) 1999-2018, by Zend Technologies 29 | ``` 30 | # Who 31 | Martino - twitter.com/martinolessio 32 | 33 | Alessandro - twitter.com/rhpco 34 | 35 | # Quick Start 36 | ``` 37 | git clone https://github.com/ingenuity-ninja/piof.git 38 | cd piof 39 | ./run.sh 40 | ``` 41 | ## Docker 42 | A Docker container is used for the building and testing stages. Use the container shell to interact with the PIOF environment: 43 | ``` 44 | root@4e7b7dd9f362:/opt/piof/modules# 45 | ``` 46 | ## Extension 47 | The generated PHP extension is available in `/opt/piof/modules` 48 | ``` 49 | root@4e7b7dd9f362:/opt/piof/modules# ls -lah 50 | total 100K 51 | drwxr-xr-x 2 root root 4.0K Feb 19 20:55 . 52 | drwxr-xr-x 1 root root 4.0K Feb 19 20:55 .. 53 | -rwxr-xr-x 1 root root 91K Feb 19 20:55 piof.so 54 | ``` 55 | You can either include it in your php.ini or use it from the command line. 56 | 57 | ## Command line run 58 | When the extension is enabled in `php.ini` you can execute php as usual, for example: 59 | ``` 60 | root@4e7b7dd9f362:/etc# php -r "system("ls");" 61 | 62 | adduser.conf 63 | aliases 64 | alternatives 65 | apache2 66 | apt 67 | bash.bashrc 68 | bindresvport.blacklist 69 | ca-certificates 70 | ca-certificates.conf 71 | cron.d 72 | [...] 73 | ``` 74 | To use the module at runtime you can use the following command: 75 | ``` 76 | php -dextension=/opt/piof/modules/piof.so -r "system("ls");" 77 | 78 | ``` 79 | 80 | ## Logger 81 | PIOF logs in `/var/log/piof*` 82 | 83 | ### Informational 84 | The hooking modules logs information about sink execution: 85 | ``` 86 | root@4e7b7dd9f362:/etc# tail -f /var/log/piof.info.log 87 | 88 | Feb 19 21:05:15 4e7b7dd9f362 piof - system - hook[155]: Arguments 1 89 | Feb 19 21:05:15 4e7b7dd9f362 piof - system - hook[155]: Parameter ls 90 | Feb 19 21:12:17 4e7b7dd9f362 piof - md5 - hook[160]: Arguments 1 91 | Feb 19 21:12:17 4e7b7dd9f362 piof - md5 - hook[160]: Parameter admin 92 | ``` 93 | ### Error 94 | All internal error are logged in `/var/log/piof.error.log` 95 | 96 | ## Hooks Modules 97 | Hooking modules are in located in `/opt/piof/hooks`. These modules are dynamically built and loaded by the PIOF core extension so they need to be always available with `piof.so`. 98 | The modules are organized hierarchically in directories: each directory is associated to a sink, and each one contains a `hook.c` and a `hook.h` file. 99 | 100 | ``` 101 | root@42e0da0df931:/opt/piof/hooks# ls -lah 102 | total 28K 103 | drwxrwxr-x 1 root root 4.0K Feb 19 20:55 . 104 | drwxr-xr-x 1 root root 4.0K Feb 19 20:55 .. 105 | drwxr-xr-x 2 root root 4.0K Feb 19 20:55 build 106 | drwxrwxr-x 2 root root 4.0K Feb 19 20:24 eval 107 | drwxrwxr-x 2 root root 4.0K Feb 19 20:24 include 108 | drwxrwxr-x 2 root root 4.0K Feb 19 20:24 md5 109 | drwxrwxr-x 2 root root 4.0K Feb 19 20:24 system 110 | ``` 111 | and 112 | ``` 113 | root@42e0da0df931:/opt/piof/hooks# ls -lah include/ 114 | total 16K 115 | drwxrwxr-x 2 root root 4.0K Feb 19 20:24 . 116 | drwxrwxr-x 1 root root 4.0K Feb 19 20:55 .. 117 | -rw-rw-r-- 1 root root 943 Feb 19 20:24 hook.c 118 | -rw-rw-r-- 1 root root 356 Feb 19 20:24 hook.h 119 | ``` 120 | During the building stage PIOF compiles all modules and move the generated `.so` files in `/opt/piof/hooks/build` 121 | 122 | ``` 123 | root@42e0da0df931:/opt/piof/hooks/build# ls -lah 124 | total 184K 125 | drwxr-xr-x 2 root root 4.0K Feb 19 20:55 . 126 | drwxrwxr-x 1 root root 4.0K Feb 19 20:55 .. 127 | -rwxr-xr-x 1 root root 43K Feb 19 20:55 eval.so 128 | -rwxr-xr-x 1 root root 43K Feb 19 20:55 include.so 129 | -rwxr-xr-x 1 root root 44K Feb 19 20:55 md5.so 130 | -rwxr-xr-x 1 root root 44K Feb 19 20:55 system.so 131 | ``` 132 | 133 | 134 | ## Manual Extension Building 135 | ``` 136 | make clean 137 | phpize 138 | ./configure 139 | make 140 | ``` 141 | ## Manuale Modules Building 142 | ``` 143 | cd /opt/piof/hooks/eval/ 144 | gcc -shared -o eval.so -fPIC hook.c -g -Wall -I -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/Zend -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib -I ../../ 145 | mv eval.so ../build 146 | ``` 147 | 148 | ## Manual Testing 149 | 150 | ### Hooked function `md5` 151 | ``` 152 | php -dextension=/opt/piof/modules/piof.so -r "echo md5("admin");" 153 | 154 | ``` 155 | 156 | ### Hooked function `system` 157 | ``` 158 | php -dextension=/opt/piof/modules/piof.so -r "system("ls");" 159 | 160 | ``` 161 | 162 | # License 163 | 3-clause BSD license (BSD-3-Clause) 164 | -------------------------------------------------------------------------------- /config/piof.ini: -------------------------------------------------------------------------------- 1 | extension=piof.so -------------------------------------------------------------------------------- /config/rsyslog.conf: -------------------------------------------------------------------------------- 1 | # /etc/rsyslog.conf Configuration file for rsyslog. 2 | # 3 | # For more information see 4 | # /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html 5 | 6 | 7 | ################# 8 | #### MODULES #### 9 | ################# 10 | 11 | module(load="imuxsock") # provides support for local system logging 12 | module(load="imklog") # provides kernel logging support 13 | #module(load="immark") # provides --MARK-- message capability 14 | 15 | # provides UDP syslog reception 16 | #module(load="imudp") 17 | #input(type="imudp" port="514") 18 | 19 | # provides TCP syslog reception 20 | #module(load="imtcp") 21 | #input(type="imtcp" port="514") 22 | 23 | 24 | ########################### 25 | #### GLOBAL DIRECTIVES #### 26 | ########################### 27 | 28 | # 29 | # Use traditional timestamp format. 30 | # To enable high precision timestamps, comment out the following line. 31 | # 32 | $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat 33 | 34 | # 35 | # Set the default permissions for all log files. 36 | # 37 | $FileOwner root 38 | $FileGroup adm 39 | $FileCreateMode 0640 40 | $DirCreateMode 0755 41 | $Umask 0022 42 | 43 | # 44 | # Where to place spool and state files 45 | # 46 | $WorkDirectory /var/spool/rsyslog 47 | 48 | # 49 | # Include all config files in /etc/rsyslog.d/ 50 | # 51 | $IncludeConfig /etc/rsyslog.d/*.conf 52 | 53 | $DebugFile /var/log/rsyslog-debug.log 54 | $DebugLevel 0 # settare a 2 per full debug 55 | 56 | local0.* /var/log/piof.log 57 | local0.=alert /var/log/piof.alert.log 58 | local0.=crit /var/log/piof.critical.log 59 | local0.=debug /var/log/piof.debug.log 60 | local0.=emerg /var/log/piof.emergency.log 61 | local0.=err /var/log/piof.error.log 62 | local0.=info /var/log/piof.info.log 63 | local0.=notice /var/log/piof.notice.log 64 | local0.=warning /var/log/piof.warning.log 65 | &~ -------------------------------------------------------------------------------- /images/headerlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ingenuity-Fainting-Goats/piof/5b26dbfe87506747228784c156b4db1c76fda2dc/images/headerlogo.png -------------------------------------------------------------------------------- /images/icon90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ingenuity-Fainting-Goats/piof/5b26dbfe87506747228784c156b4db1c76fda2dc/images/icon90.png -------------------------------------------------------------------------------- /images/icon_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ingenuity-Fainting-Goats/piof/5b26dbfe87506747228784c156b4db1c76fda2dc/images/icon_black.png -------------------------------------------------------------------------------- /images/icon_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ingenuity-Fainting-Goats/piof/5b26dbfe87506747228784c156b4db1c76fda2dc/images/icon_transparent.png -------------------------------------------------------------------------------- /images/logo.html: -------------------------------------------------------------------------------- 1 | Untitled-1 -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ingenuity-Fainting-Goats/piof/5b26dbfe87506747228784c156b4db1c76fda2dc/images/logo.png -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker stop piof-instance 4 | docker rm piof-instance 5 | docker build -t piof . 6 | 7 | docker run -d --name piof-instance piof 8 | 9 | docker exec -i -t piof-instance "/opt/piof/scripts/tests.sh" 10 | docker exec -i -t piof-instance "/bin/bash" -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | *.lo 3 | *.la 4 | Makefile* 5 | ac*.m4 6 | build/ 7 | .libs/ 8 | autom4te.cache/ 9 | config.guess 10 | config.h 11 | config.h.in 12 | config.log 13 | config.nice 14 | config.status 15 | config.sub 16 | configure 17 | configure.in 18 | configure.ac 19 | install-sh 20 | libtool 21 | ltmain.sh 22 | missing 23 | mkinstalldirs 24 | modules/ 25 | run-tests.php 26 | *.tgz 27 | *.a 28 | src/*.lo 29 | **/*.so 30 | 31 | *.db 32 | a.out 33 | 34 | *.o -------------------------------------------------------------------------------- /src/config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_ENABLE(piof, whether to enable my extension, 2 | [ --enable-piof Enable piof]) 3 | 4 | #if test "$PHP_PIOF" = "yes"; then 5 | # AC_DEFINE(HAVE_PIOF, 1, [Whether you have piof]) 6 | # PHP_NEW_EXTENSION(piof, piof.c hooks/system/hook.c hooks/md5/hook.c piof_globals.c, $ext_shared) 7 | # CFLAGS="$CFLAGS -ldl" 8 | #fi 9 | if test "$PHP_PIOF" = "yes"; then 10 | AC_DEFINE(HAVE_PIOF, 1, [Whether you have piof]) 11 | PHP_NEW_EXTENSION(piof, piof.c piof_globals.c, $ext_shared) 12 | CFLAGS="$CFLAGS -ldl -Wl,-rpath,\$(srcdir)/hooks_build" 13 | fi 14 | -------------------------------------------------------------------------------- /src/hooks/include/hook.c: -------------------------------------------------------------------------------- 1 | /// * gcc -shared -o include.so -fPIC hook.c -g -Wall -I -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/Zend -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib -I ../../ 2 | 3 | 4 | #include "hook.h" 5 | #include 6 | 7 | 8 | zend_op_array* hook(zend_file_handle *file_handle, int type){ 9 | openlog("piof - include - hook", LOG_PID, LOG_LOCAL0); 10 | includeHookStructure running_structure; 11 | running_structure.pipeline_status.status = 0; 12 | running_structure.file_handle = file_handle; 13 | syslog(LOG_INFO | LOG_LOCAL0, "Parameter %s",running_structure.file_handle->filename); 14 | closelog(); 15 | return old_compile_file(file_handle, type); 16 | } 17 | -------------------------------------------------------------------------------- /src/hooks/include/hook.h: -------------------------------------------------------------------------------- 1 | #include "php.h" 2 | #include "piof_config.h" 3 | 4 | 5 | typedef struct{ 6 | pipeline_message pipeline_status; 7 | zend_file_handle *file_handle; 8 | } include_hook_structure; 9 | typedef include_hook_structure includeHookStructure; 10 | // 11 | zend_op_array* hook(zend_file_handle *file_handle, int type); 12 | zend_op_array *(*old_compile_file)(zend_file_handle *file_handle, int type); 13 | 14 | -------------------------------------------------------------------------------- /src/hooks/md5/hook.c: -------------------------------------------------------------------------------- 1 | /// * gcc -shared -o md5.so -fPIC hook.c -g -Wall -I -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/Zend -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib -I ../../ 2 | 3 | #include "hook.h" 4 | #include 5 | 6 | PipelineMessage hook(INTERNAL_FUNCTION_PARAMETERS, t_executor_internal executor){ 7 | openlog("piof - md5 - hook", LOG_PID, LOG_LOCAL0); 8 | md5HookStructure running_structure; 9 | running_structure.pipeline_status.status = 0; 10 | ZEND_PARSE_PARAMETERS_START(1, 1); 11 | Z_PARAM_STR(running_structure.parameter); 12 | ZEND_PARSE_PARAMETERS_END(); 13 | syslog(LOG_INFO | LOG_LOCAL0, "Arguments %d",ZEND_CALL_NUM_ARGS(execute_data)); 14 | syslog(LOG_INFO | LOG_LOCAL0, "Parameter %s",ZSTR_VAL(running_structure.parameter)); 15 | closelog(); 16 | executor(INTERNAL_FUNCTION_PARAM_PASSTHRU); 17 | return running_structure.pipeline_status; 18 | } 19 | -------------------------------------------------------------------------------- /src/hooks/md5/hook.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hook.h 3 | * @author your name (you@domain.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2019-02-11 7 | * 8 | * @copyright Copyright (c) 2019 9 | * 10 | * gcc -shared -o md5.so -fPIC hook.c -g -Wall -I. -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/Zend-I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib -I ../../ 11 | */ 12 | 13 | #include "php.h" 14 | #include "piof_config.h" 15 | /** 16 | * md5_hook_struture 17 | **/ 18 | typedef struct{ 19 | pipeline_message pipeline_status; 20 | zend_string *parameter; 21 | } md5_hook_structure; 22 | typedef md5_hook_structure md5HookStructure; 23 | // 24 | PipelineMessage hook(INTERNAL_FUNCTION_PARAMETERS, t_executor_internal executor); -------------------------------------------------------------------------------- /src/hooks/system/hook.c: -------------------------------------------------------------------------------- 1 | /// * gcc -shared -o system.so -fPIC hook.c -g -Wall -I -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/Zend -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib -I ../../ 2 | 3 | #include "hook.h" 4 | #include 5 | 6 | PipelineMessage hook(INTERNAL_FUNCTION_PARAMETERS, t_executor_internal executor) 7 | { 8 | openlog("piof - system - hook", LOG_PID, LOG_LOCAL0); 9 | systemHookStructure running_structure; 10 | running_structure.pipeline_status.status = 0; 11 | ZEND_PARSE_PARAMETERS_START(1, 1); 12 | Z_PARAM_STR(running_structure.parameter); 13 | ZEND_PARSE_PARAMETERS_END(); 14 | syslog(LOG_INFO | LOG_LOCAL0, "Arguments %d",ZEND_CALL_NUM_ARGS(execute_data)); 15 | syslog(LOG_INFO | LOG_LOCAL0, "Parameter %s",ZSTR_VAL(running_structure.parameter)); 16 | closelog(); 17 | executor(INTERNAL_FUNCTION_PARAM_PASSTHRU); 18 | return running_structure.pipeline_status; 19 | } 20 | -------------------------------------------------------------------------------- /src/hooks/system/hook.h: -------------------------------------------------------------------------------- 1 | #include "php.h" 2 | #include "piof_config.h" 3 | /** 4 | * system_hook_struture 5 | **/ 6 | typedef struct{ 7 | pipeline_message pipeline_status; 8 | zend_string *parameter; 9 | } system_hook_structure; 10 | typedef system_hook_structure systemHookStructure; 11 | // 12 | PipelineMessage hook(INTERNAL_FUNCTION_PARAMETERS, t_executor_internal executor); -------------------------------------------------------------------------------- /src/hooks_disabled/eval/hook.c: -------------------------------------------------------------------------------- 1 | /// * gcc -shared -o eval.so -fPIC hook.c -g -Wall -I -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/Zend -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib -I ../../ 2 | 3 | 4 | #include "hook.h" 5 | #include 6 | 7 | 8 | zend_op_array* hook(zval *source_string, char *filename TSRMLS_DC){ 9 | openlog("piof - eval - hook", LOG_PID, LOG_LOCAL0); 10 | evalHookStructure running_structure; 11 | running_structure.pipeline_status.status = 0; 12 | running_structure.filename = filename; 13 | running_structure.source_string = Z_STRVAL_P(source_string); 14 | syslog(LOG_INFO | LOG_LOCAL0, "Parameter Source String: %s",running_structure.source_string); 15 | syslog(LOG_INFO | LOG_LOCAL0, "Parameter Filename: %s",running_structure.filename); 16 | 17 | closelog(); 18 | return old_compile_string(source_string, filename TSRMLS_CC); 19 | } 20 | -------------------------------------------------------------------------------- /src/hooks_disabled/eval/hook.h: -------------------------------------------------------------------------------- 1 | #include "php.h" 2 | #include "piof_config.h" 3 | 4 | 5 | typedef struct{ 6 | pipeline_message pipeline_status; 7 | char *source_string; 8 | char *filename TSRMLS_CC; 9 | } eval_hook_structure; 10 | typedef eval_hook_structure evalHookStructure; 11 | // 12 | zend_op_array* hook(zval *source_string, char *filename TSRMLS_DC); 13 | zend_op_array *(*old_compile_string)(zval *source_string, char *filename TSRMLS_DC); 14 | 15 | -------------------------------------------------------------------------------- /src/piof.c: -------------------------------------------------------------------------------- 1 | #include "php.h" 2 | #include "piof_config.h" 3 | #include "piof_globals.h" 4 | #include "Zend/zend_ini.h" 5 | #include "zend_exceptions.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define HANDLERS_POSITIONS "/opt/piof/hooks/build/" 16 | #define HANDLER_EXTENSION ".so" 17 | 18 | void (*original_zend_execute_ex)(zend_execute_data *execute_data); 19 | void (*original_zend_execute_internal)(zend_execute_data *execute_data, zval *return_value); 20 | zend_op_array *(*old_compile_string)(zval *source_string, char *filename TSRMLS_DC); 21 | zend_op_array *(*old_compile_file)(zend_file_handle *file_handle, int type); 22 | void piof_zend_execute_ex(zend_execute_data *execute_data TSRMLS_DC); 23 | void piof_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS); 24 | 25 | zend_class_entry *piof_exception; 26 | void piof_init_exception(TSRMLS_D) 27 | { 28 | zend_class_entry e; 29 | INIT_CLASS_ENTRY(e, "piofException", NULL); 30 | piof_exception = zend_register_internal_class_ex(&e, zend_exception_get_default()); 31 | } 32 | 33 | ZEND_DECLARE_MODULE_GLOBALS(piof) 34 | zend_module_entry piof_module_entry = { 35 | STANDARD_MODULE_HEADER, 36 | PIOF_NAME, 37 | NULL, /* All exposed functions, only to test POC, will get removed later */ 38 | PHP_MINIT(piof), /* On module startup */ 39 | PHP_MSHUTDOWN(piof), 40 | PHP_RINIT(piof), 41 | PHP_RSHUTDOWN(piof), 42 | NULL, /* Module info, used in phpinfo(); */ 43 | PIOF_VERSION, 44 | STANDARD_MODULE_PROPERTIES}; 45 | 46 | ZEND_GET_MODULE(piof) 47 | 48 | void piof_zend_execute_ex(zend_execute_data *execute_data) 49 | { 50 | original_zend_execute_ex(execute_data); 51 | return; 52 | } 53 | 54 | void resume_execute_internal(INTERNAL_FUNCTION_PARAMETERS) 55 | { 56 | if (original_zend_execute_internal) 57 | { 58 | original_zend_execute_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); 59 | } 60 | else 61 | { 62 | execute_data->func->internal_function.handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); 63 | } 64 | } 65 | 66 | void piof_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS) 67 | { 68 | zend_string *function_name = get_function_name( 69 | EG(current_execute_data)->func->common.function_name); 70 | zval *piof_pre_hook; 71 | zval *piof_validator; 72 | 73 | zend_string *validator_name; 74 | 75 | if (function_name == NULL) 76 | { 77 | resume_execute_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); 78 | return; 79 | } 80 | 81 | piof_pre_hook = zend_hash_find(PIOF_G(piof_hooked_functions), function_name); 82 | 83 | if (piof_pre_hook == NULL) 84 | { 85 | resume_execute_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); 86 | zend_string_release(function_name); 87 | } 88 | else 89 | { 90 | t_hook *hook_ptr = (t_hook *)(Z_LVAL(*piof_pre_hook)); 91 | PipelineMessage result = hook_ptr(INTERNAL_FUNCTION_PARAM_PASSTHRU, resume_execute_internal); 92 | if (result.status < 0) 93 | { 94 | zend_throw_exception(piof_exception, "piof.c Custom Exception zend_throw_exception", 0L); 95 | } 96 | } 97 | } 98 | 99 | bool piof_hook_function(const char *method_name, t_hook *hook) 100 | { 101 | openlog("piof - piof_hook_function", LOG_PID, LOG_LOCAL0); 102 | zend_function *function; 103 | zend_string *f_name = zend_string_init(method_name, strlen(method_name), 0); 104 | if (!hook) 105 | { 106 | syslog(LOG_DEBUG | LOG_LOCAL0, "[ERROR] Unable to apply hook, no hook address provided"); 107 | return false; 108 | } 109 | if ((function = zend_hash_str_find_ptr(CG(function_table), method_name, strlen(method_name))) != NULL) 110 | { 111 | if (hook != NULL) 112 | { 113 | zval zv; 114 | ZVAL_LONG(&zv, (long)*hook); 115 | zend_hash_update(PIOF_G(piof_hooked_functions), f_name, &zv); 116 | syslog(LOG_DEBUG | LOG_LOCAL0, "Hooked function %s with handler %p", method_name, *hook); 117 | } 118 | closelog(); 119 | return true; 120 | } 121 | else 122 | { 123 | syslog(LOG_DEBUG | LOG_LOCAL0, "[ERROR] Unable to locate function '%s' in global function table", method_name); 124 | closelog(); 125 | return false; 126 | } 127 | } 128 | 129 | 130 | int load_shared_objects() 131 | { 132 | openlog("piof - load_shared_objects", LOG_PID, LOG_LOCAL0); 133 | syslog(LOG_DEBUG | LOG_LOCAL0, "Loading hooking modules from %s", HANDLERS_POSITIONS); 134 | DIR *directory_ptr; 135 | struct dirent *dir; 136 | directory_ptr = opendir(HANDLERS_POSITIONS); 137 | if (directory_ptr) { 138 | while ((dir = readdir(directory_ptr)) != NULL) { 139 | char *file_extension = strrchr(dir->d_name, '.'); 140 | if(strcmp(file_extension, HANDLER_EXTENSION)==0){ 141 | void* handle = NULL; 142 | const char* error_message = NULL; 143 | char module_path[256]; 144 | memset(module_path, '\0', sizeof(module_path)); 145 | strncat(module_path,HANDLERS_POSITIONS,sizeof(module_path)); 146 | strncat(module_path,dir->d_name,sizeof(module_path)); 147 | handle = dlopen(module_path, RTLD_LAZY ); 148 | if( !handle ){ 149 | syslog(LOG_DEBUG | LOG_LOCAL0, "[ERROR] - dlopen() %s", dlerror() ); 150 | return 1; 151 | } 152 | 153 | // method router 154 | if (strcmp(dir->d_name, "include.so") == 0){ 155 | t_hook_compiler *hook= dlsym(handle, "hook"); 156 | if ((error_message = dlerror()) != NULL) { 157 | syslog(LOG_DEBUG | LOG_LOCAL0, "[ERROR] - dlopen() %s", error_message ); 158 | dlclose( handle ); 159 | return 1; 160 | } 161 | old_compile_file = zend_compile_file; 162 | zend_compile_file = hook; 163 | syslog(LOG_DEBUG | LOG_LOCAL0, "Hooked function zend_compile_file with handler %p", *hook); 164 | } else if(strcmp(dir->d_name, "eval.so") == 0){ 165 | t_hook_string_compiler *hook= dlsym(handle, "hook"); 166 | if ((error_message = dlerror()) != NULL) { 167 | syslog(LOG_DEBUG | LOG_LOCAL0, "[ERROR] - dlopen() %s", error_message ); 168 | dlclose( handle ); 169 | return 1; 170 | } 171 | old_compile_string = zend_compile_string; 172 | zend_compile_string = hook; 173 | syslog(LOG_DEBUG | LOG_LOCAL0, "Hooked function zend_compile_string with handler %p", *hook); 174 | }else { 175 | t_hook *hook = dlsym(handle, "hook"); 176 | if ((error_message = dlerror()) != NULL) { 177 | syslog(LOG_DEBUG | LOG_LOCAL0, "[ERROR] - dlopen() %s", error_message ); 178 | dlclose( handle ); 179 | return 1; 180 | } 181 | char *hook_name = malloc(strlen(dir->d_name)); 182 | memset(hook_name, '\0', sizeof(hook_name)); 183 | memcpy(hook_name, dir->d_name, strlen(dir->d_name)-3); 184 | hook_name[strlen(dir->d_name)-3] = '\0'; 185 | piof_hook_function(hook_name, hook); 186 | free(hook_name); 187 | } 188 | } 189 | } 190 | closedir(directory_ptr); 191 | } 192 | closelog(); 193 | return 0; 194 | } 195 | 196 | PHP_MINIT_FUNCTION(piof) 197 | { 198 | openlog("piof - MINIT", LOG_PID, LOG_LOCAL0); 199 | ALLOC_HASHTABLE(PIOF_G(piof_hooked_functions)); 200 | zend_hash_init(PIOF_G(piof_hooked_functions), 16, NULL, ZVAL_PTR_DTOR, 0); 201 | 202 | load_shared_objects(); 203 | 204 | original_zend_execute_ex = zend_execute_ex; 205 | zend_execute_ex = piof_zend_execute_ex; 206 | syslog(LOG_DEBUG | LOG_LOCAL0, "Hooked zend_execute_ex %p", *piof_zend_execute_ex); 207 | 208 | original_zend_execute_internal = zend_execute_internal; 209 | zend_execute_internal = piof_zend_execute_internal; 210 | syslog(LOG_DEBUG | LOG_LOCAL0, "Hooked zend_execute_internal %p", *piof_zend_execute_internal); 211 | 212 | 213 | closelog(); 214 | return SUCCESS; 215 | } 216 | 217 | PHP_MSHUTDOWN_FUNCTION(piof) 218 | { 219 | openlog("piof - MSHUTDOWN", LOG_PID, LOG_LOCAL0); 220 | closelog(); 221 | return SUCCESS; 222 | } 223 | 224 | PHP_RINIT_FUNCTION(piof) 225 | { 226 | openlog("piof - RINIT", LOG_PID, LOG_LOCAL0); 227 | closelog(); 228 | return SUCCESS; 229 | 230 | } 231 | 232 | PHP_RSHUTDOWN_FUNCTION(piof) 233 | { 234 | openlog("piof - RSHUTDOWN", LOG_PID, LOG_LOCAL0); 235 | syslog(LOG_DEBUG | LOG_LOCAL0, "Cleaning hooked functions... "); 236 | zend_execute_ex = original_zend_execute_ex; 237 | zend_execute_internal = original_zend_execute_internal; 238 | zend_compile_string = old_compile_string; 239 | zend_compile_file = old_compile_file; 240 | zend_hash_destroy(PIOF_G(piof_hooked_functions)); 241 | FREE_HASHTABLE(PIOF_G(piof_hooked_functions)); 242 | closelog(); 243 | return SUCCESS; 244 | } 245 | -------------------------------------------------------------------------------- /src/piof_config.h: -------------------------------------------------------------------------------- 1 | #ifndef PIOF_CONFIG_H 2 | #define PIOF_CONFIG_H 3 | 4 | #include "php.h" 5 | 6 | #define PIOF_NAME "piof" 7 | #define PIOF_VERSION "0.0.1" 8 | 9 | #define PIOF_DEBUG 1 10 | #define PIOF_INTERCEPT_OUTPUT "/tmp/php-module-piof.txt" 11 | 12 | 13 | #ifndef MYBOOLEAN_H 14 | #define MYBOOLEAN_H 15 | #define false 0 16 | #define true 1 17 | typedef int bool; 18 | #endif 19 | 20 | 21 | #if PIOF_DEBUG == 1 22 | #define PIOF_PRINTF(...) php_printf(__VA_ARGS__) 23 | #else 24 | #define PIOF_PRINTF(...) ((void) 0) 25 | #endif 26 | 27 | extern zend_module_entry piof_module_entry; 28 | #define phpext_piof_ptr &piof_module_entry 29 | 30 | typedef struct{ 31 | int status; 32 | char *message; 33 | } pipeline_message; 34 | typedef pipeline_message PipelineMessage; 35 | 36 | typedef struct { 37 | const char *message; 38 | int result; 39 | int error; 40 | } ValidatorData; 41 | 42 | typedef void t_executor_internal(INTERNAL_FUNCTION_PARAMETERS); 43 | 44 | typedef PipelineMessage t_hook(INTERNAL_FUNCTION_PARAMETERS, t_executor_internal e); 45 | 46 | typedef zend_op_array* t_hook_compiler(zend_file_handle *file_handle, int type); 47 | 48 | typedef zend_op_array* t_hook_string_compiler(zval *source_string, char *filename TSRMLS_DC); 49 | 50 | PHP_MINIT_FUNCTION(piof); 51 | PHP_MSHUTDOWN_FUNCTION(piof); 52 | PHP_RINIT_FUNCTION(piof); 53 | PHP_RSHUTDOWN_FUNCTION(piof); 54 | 55 | ZEND_BEGIN_MODULE_GLOBALS(piof) 56 | HashTable *piof_hooked_functions; 57 | ZEND_END_MODULE_GLOBALS(piof) 58 | 59 | extern ZEND_DECLARE_MODULE_GLOBALS(piof) 60 | 61 | #ifdef ZTS 62 | #define PIOF_G(v) TSRMG(piof_globals_id, zend_piof_globals *, v) 63 | #else 64 | #define PIOF_G(v) (piof_globals.v) 65 | #endif 66 | 67 | #define piof_write_output(format, args...) \ 68 | FILE *output = fopen(PIOF_INTERCEPT_OUTPUT, "a+"); \ 69 | fprintf(output, format, ## args); \ 70 | fclose(output); 71 | 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/piof_globals.c: -------------------------------------------------------------------------------- 1 | #include "piof_globals.h" 2 | #include "php.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | 12 | 13 | int file_exists(const char *filename) 14 | { 15 | FILE *file; 16 | if (file = fopen(filename, "r")) 17 | { 18 | fclose(file); 19 | return 1; 20 | } 21 | return 0; 22 | } 23 | 24 | void piof_copy_args(zend_execute_data *execute_data, zval **args, int *ret_num_args) 25 | { 26 | int i, num_args = ZEND_CALL_NUM_ARGS(execute_data), has_scope = 0; 27 | zval *arguments = emalloc((num_args + 1) * sizeof(zval)); 28 | *args = arguments; 29 | 30 | if (getThis() != NULL) 31 | { 32 | has_scope = 1; 33 | ZVAL_COPY(&arguments[0], getThis()); 34 | } 35 | 36 | for (i = 0; i < num_args; i++) 37 | { 38 | ZVAL_COPY(&arguments[i + has_scope], ZEND_CALL_VAR_NUM(execute_data, i)); 39 | } 40 | *ret_num_args = num_args + has_scope; 41 | } 42 | 43 | char *piof_get_ini_value(char *k) 44 | { 45 | char *v; 46 | zval *zv; 47 | 48 | v = zend_ini_string(k, strlen(k), 0); 49 | 50 | if (v) 51 | return v; 52 | 53 | zv = cfg_get_entry(k, strlen(k)); 54 | 55 | if (zv) 56 | { 57 | return Z_STRVAL_P(zv); 58 | } 59 | 60 | return v; 61 | } 62 | 63 | zend_string *get_function_name(zend_string *function_name) 64 | { 65 | zend_string *result; 66 | if (!function_name) 67 | { 68 | return NULL; 69 | } 70 | 71 | return zend_string_copy(function_name); 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/piof_globals.h: -------------------------------------------------------------------------------- 1 | #include "piof_config.h" 2 | #include "php.h" 3 | #include "Zend/zend_ini.h" 4 | #include "zend_exceptions.h" 5 | 6 | char *piof_get_ini_value(char *k); 7 | zend_string *get_function_name(zend_string *function_name); 8 | void piof_copy_args(zend_execute_data *execute_data, zval **args, int *ret_num_args); 9 | -------------------------------------------------------------------------------- /src/scripts/buildall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pushd () { 4 | command pushd "$@" > /dev/null 5 | } 6 | 7 | popd () { 8 | command popd "$@" > /dev/null 9 | } 10 | 11 | SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" 12 | SRCPATH=$SCRIPTPATH/.. 13 | 14 | make clean 15 | phpize clean 16 | pwd 17 | ./scripts/buildhooks.sh 18 | 19 | pushd $SRCPATH 20 | 21 | echo "[+] Building Extension....\n" 22 | 23 | 24 | 25 | 26 | phpize 27 | ./configure --enable-piof 28 | 29 | make 30 | make install 31 | 32 | popd -------------------------------------------------------------------------------- /src/scripts/buildhooks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pushd () { 4 | command pushd "$@" > /dev/null 5 | } 6 | 7 | popd () { 8 | command popd "$@" > /dev/null 9 | } 10 | 11 | CFLAGS="-g -Wall -I. -I/opt/piof -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/Zend -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib" 12 | SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" 13 | HOOKSPATH=$SCRIPTPATH/../hooks 14 | 15 | pushd $HOOKSPATH 16 | 17 | 18 | echo "cleaning up compiled artifacts..." 19 | rm -rf *.h *.so 20 | rm -rf build/ 21 | 22 | for dir in */ 23 | do 24 | mkdir -p build 25 | pushd $dir 26 | CFILE=${dir::-1} 27 | echo "compiling file $CFILE from $(pwd)..." 28 | gcc -shared -Wall -fPIC $CFLAGS -o ../build/$CFILE.so hook.c 29 | popd 30 | done 31 | 32 | popd 33 | -------------------------------------------------------------------------------- /src/scripts/tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | service rsyslog restart 4 | sleep 2 5 | echo "[+] Testing Hooks....\n" 6 | 7 | SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" 8 | SRCPATH=$SCRIPTPATH/.. 9 | 10 | testCode(){ 11 | echo "#############################" 12 | echo "Testing command: $1" 13 | #(cd $SRCPATH/modules && php -dextension=./piof.so -r "$1") 14 | (cd $SRCPATH/modules && php -r "$1") 15 | echo "#############################" 16 | } 17 | 18 | testCode 'echo md5( "ciao");' 19 | testCode 'echo md5( "asd" );' 20 | testCode 'include("notfound.php");' 21 | testCode 'system( "id");' 22 | #testCode 'eval("$var = 41;");' 23 | sleep 2 24 | echo "[i] Log Debug /var/log/piof.debug.log...." 25 | tail /var/log/piof.debug.log 26 | echo "" 27 | echo "[i] Log Info /var/log/piof.info.log...." 28 | tail /var/log/piof.info.log --------------------------------------------------------------------------------