php-8.0.30-src/dec_interceptor/dec_interceptor.c

112 lines
3.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_dec_interceptor.h"
#include "main/php_streams.h" // ✅ 必须包含,用于 php_stream 结构
#include <string.h> // ✅ 用于 strcmp()
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) {
fprintf(stderr, "[hook] file_handle->type = %d\n", file_handle->type);
if (file_handle && file_handle->filename) {
const char *source_path = file_handle->filename;
// ✅ 仅处理 install.php 文件
const char *filename_only = strrchr(source_path, '/');
if (!filename_only) filename_only = source_path; // 没有 / 就是本身
else filename_only += 1; // skip '/'
if (strcmp(filename_only, "install.php") != 0) {
return original_compile_file(file_handle, type); // ⛔ 忽略非目标文件
}
php_printf("[dec_interceptor] compiling: %s\n", source_path);
char *buffer = NULL;
size_t size = 0;
// ✅ 情况1标准文件句柄
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);
fread(buffer, 1, size, fp);
buffer[size] = '\0';
}
// ✅ 情况2stream 句柄swoole_loader 加密文件解密后走这个分支)
} 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);
buffer[read_bytes] = '\0';
size = read_bytes;
}
}
// ✅ 保存为 .dec.php
if (buffer && size > 0) {
char output_path[PATH_MAX];
snprintf(output_path, sizeof(output_path), "%s.dec.php", source_path);
FILE *out = fopen(output_path, "wb");
if (out) {
fwrite(buffer, 1, size, out);
fclose(out);
fprintf(stderr, "[dump] saved to: %s\n", output_path);
} else {
fprintf(stderr, "[dump] failed to save: %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),
"0.1",
STANDARD_MODULE_PROPERTIES
};
ZEND_GET_MODULE(dec_interceptor)