1

Hope this isn't too silly a question to ask. I'm fairly new to C and PHP internals but looking to learn more about them.

I've recently began looking into development of PHP extensions. I'm trying to overwrite an internal function to perform some action, before it executes the original function.

I found an example on http://www.phpinternalsbook.com/php7/extensions_design/hooks.html where they overwrite the var_dump() function. Though I tried to build on this and compile it but can't seem to get it working properly.

Here's the code I currently have:

php_hook.c:

// include the PHP API itself
#include <php.h>
// then include the header of your extension
#include "php_hook.h"

// register our function to the PHP API 
// so that PHP knows, which functions are in this module
zend_function_entry hook_php_functions[] = {
    ZEND_NAMED_FE(my_overwrite_var_dump, my_overwrite_var_dump, NULL)
    {NULL, NULL, NULL}
};

// some pieces of information about our module
zend_module_entry hook_php_module_entry = {
    STANDARD_MODULE_HEADER,
    PHP_HOOK_EXTNAME,
    hook_php_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    PHP_HOOK_VERSION,
    STANDARD_MODULE_PROPERTIES
};

// use a macro to output additional C code, to make ext dynamically loadable
ZEND_GET_MODULE(hook_php)

#if PHP_VERSION_ID < 70200
typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS);
#endif
zif_handler original_handler_var_dump;

ZEND_NAMED_FUNCTION(my_overwrite_var_dump)
{
    php_printf("hooked (var_dump))\n");
    // if we want to call the original function
    original_handler_var_dump(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}

PHP_MINIT_FUNCTION(hook_php)
{
    zend_function *original;

    original = zend_hash_str_find_ptr(EG(function_table), "var_dump", sizeof("var_dump")-1);

    if (original != NULL) {
        original_handler_var_dump = original->internal_function.handler;
        original->internal_function.handler = my_overwrite_var_dump;
    }
}

config.m4:

PHP_ARG_ENABLE(php_hook, Whether to enable the HelloWorldPHP extension, [ --enable-hook-php Enable HelloWorldPHP])

if test "$PHP_HOOK" != "no"; then
    PHP_NEW_EXTENSION(php_hook, php_hook.c, $ext_shared)
fi

php_hook.h:

// we define Module constants
#define PHP_HOOK_EXTNAME "php_hook"
#define PHP_HOOK_VERSION "0.0.1"

// then we declare the function to be exported
ZEND_NAMED_FUNCTION(my_overwrite_var_dump);

When I call var_dump(1) it just returns int(1) still. I'm on PHP 7.3 currently.

fufyayokku
  • 11
  • 1

1 Answers1

0

I haven“t tested it but I think something like this should work:

...

PHP_FUNCTION(my_overwrite_var_dump)
{
    php_printf("hooked (var_dump))\n");
    // if we want to call the original function
    original_handler_var_dump(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}


PHP_MINIT_FUNCTION(hook_php)
{
    zend_function *original;

    original = zend_hash_str_find_ptr(CG(function_table), "var_dump", sizeof("var_dump")-1);

    if (original != NULL) {
        original_handler_var_dump = original->internal_function.handler;
        original->internal_function.handler = PHP_FN(my_overwrite_var_dump);
    }
}

Things I changed:

  • Instead of ZEND_NAMED_FUNCTION I used PHP_FUNCTION
  • Instead of EG() I used CG()
  • The last thing is that in order to overwrite the handler you have to use PHP_FN(my_overwrite_var_dump)

Let me know how it goes!