#include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_dec_interceptor.h" #include "main/php_streams.h" #include #include static zend_op_array* (*original_compile_file)(zend_file_handle *file_handle, int type); static zend_op_array* custom_compile_file(zend_file_handle *file_handle, int type) { if (!file_handle || !file_handle->filename) { fprintf(stderr, "[dec_interceptor] invalid file_handle or filename\n"); return original_compile_file(file_handle, type); } const char *source_path = file_handle->filename; const char *basename = strrchr(source_path, '/'); basename = basename ? basename + 1 : source_path; if (strcmp(basename, "install.php") != 0) { return original_compile_file(file_handle, type); } fprintf(stderr, "[dec_interceptor] matched %s\n", source_path); char *buffer = NULL; size_t size = 0; if (file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp) { FILE *fp = file_handle->handle.fp; fseek(fp, 0, SEEK_END); size = ftell(fp); fseek(fp, 0, SEEK_SET); if (size > 0 && size < 100 * 1024 * 1024) { buffer = emalloc(size + 1); if (fread(buffer, 1, size, fp) == size) { buffer[size] = '\0'; } else { efree(buffer); buffer = NULL; } } } else if (file_handle->type == ZEND_HANDLE_STREAM && file_handle->handle.stream.handle) { php_stream *stream = (php_stream *)file_handle->handle.stream.handle; php_stream_seek(stream, 0, SEEK_END); size = php_stream_tell(stream); php_stream_seek(stream, 0, SEEK_SET); if (size > 0 && size < 100 * 1024 * 1024) { buffer = emalloc(size + 1); size_t read_bytes = php_stream_read(stream, buffer, size); if (read_bytes > 0) { buffer[read_bytes] = '\0'; size = read_bytes; } else { efree(buffer); buffer = NULL; } } } if (buffer && size > 0) { char output_path[PATH_MAX]; snprintf(output_path, sizeof(output_path), "/tmp/dump_install_%ld.dec.php", time(NULL)); FILE *out = fopen(output_path, "wb"); if (out) { fwrite(buffer, 1, size, out); fclose(out); fprintf(stderr, "[dec_interceptor] dumped to: %s (%zu bytes)\n", output_path, size); } else { fprintf(stderr, "[dec_interceptor] failed to open output: %s\n", output_path); } efree(buffer); } return original_compile_file(file_handle, type); } PHP_MINIT_FUNCTION(dec_interceptor) { original_compile_file = zend_compile_file; zend_compile_file = custom_compile_file; return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(dec_interceptor) { zend_compile_file = original_compile_file; return SUCCESS; } PHP_MINFO_FUNCTION(dec_interceptor) { php_info_print_table_start(); php_info_print_table_row(2, "dec_interceptor support", "enabled"); php_info_print_table_end(); } zend_module_entry dec_interceptor_module_entry = { STANDARD_MODULE_HEADER, "dec_interceptor", NULL, PHP_MINIT(dec_interceptor), PHP_MSHUTDOWN(dec_interceptor), NULL, NULL, PHP_MINFO(dec_interceptor), PHP_DEC_INTERCEPTOR_VERSION, STANDARD_MODULE_PROPERTIES }; ZEND_GET_MODULE(dec_interceptor)