初探php扩展层面(一)
字数 1090 2025-08-26 22:11:22
PHP扩展开发与HOOK技术深入解析
一、环境搭建与基础扩展开发
1.1 开发环境准备
推荐使用Docker环境进行PHP扩展开发,避免本地环境配置问题:
docker run -i -d --security-opt seccomp=unconfined -v /path/to/code:/home php5-debug
1.2 创建基础扩展
- 在PHP源码ext目录下执行:
./ext_skel --extname=extension_name
- 修改config.m4文件,取消注释:
PHP_ARG_ENABLE(extension_name, whether to enable extension_name support,
[ --enable-extension_name Enable extension_name support])
- 在头文件php_extension_name.h中添加函数声明:
PHP_FUNCTION(confirm_extension_name_compiled);
PHP_FUNCTION(extension_name);
- 在扩展源文件extension_name.c中添加函数映射:
const zend_function_entry extension_name_functions[] = {
PHP_FE(extension_name, NULL)
PHP_FE(confirm_extension_name_compiled, NULL)
PHP_FE_END
};
- 实现基础函数:
PHP_FUNCTION(extension_name) {
php_printf("hello world");
}
- 编译安装扩展:
phpize
./configure --enable-extension_name --enable-debug
make
二、PHP代码执行流程
PHP代码执行分为四个主要阶段:
- Scanning - 将PHP代码转换为语言片段(Tokens)
- Parsing - 将Tokens转化为简单而有意义的表达式
- Compilation - 将表达式编译成opcode
- Execution - 顺次执行opcodes,实现脚本功能
三、Opcode HOOK技术
3.1 基础HOOK实现
使用zend_set_user_opcode_handler函数HOOK特定操作码:
zend_set_user_opcode_handler(ZEND_ECHO, custom_handler);
自定义处理函数:
int custom_handler(ZEND_OPCODE_HANDLER_ARGS) {
php_printf("hook success");
return ZEND_USER_OPCODE_RETURN; // 不继续执行原操作
// return ZEND_USER_OPCODE_DISPATCH; // 继续执行原操作
}
3.2 重要宏定义
-
执行环境宏:
EG()- 访问符号表、函数、资源信息和常量CG()- 访问核心全局变量PG()- 访问PHP全局变量(php.ini映射)FG()- 文件全局变量
-
函数类型定义:
#define ZEND_INTERNAL_FUNCTION 1 // 内部函数 #define ZEND_USER_FUNCTION 2 // 用户定义函数 #define ZEND_OVERLOADED_FUNCTION 3 // 重载函数 #define ZEND_EVAL_CODE 4 // eval代码 #define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5 -
执行数据结构:
struct _zend_execute_data { const zend_op *opline; // 当前执行的opline zend_execute_data *call; // 当前调用 zval *return_value; // 返回值 zend_function *func; // 执行的函数 zval This; // this + call_info + num_args zend_execute_data *prev_execute_data; zend_array *symbol_table; // ...其他成员 };
四、Webshell防御实践
4.1 Eval HOOK实现
HOOK ZEND_INCLUDE_OR_EVAL操作码防御危险函数:
static int HOOK_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS) {
zend_op *opline = execute_data->opline;
zval *operands = opline->op1.zv;
char *cmd = Z_STRVAL_P(operands);
if(cmd) {
if((strstr(cmd, "system")==NULL) &&
(strstr(cmd, "exec")==NULL) &&
(strstr(cmd, "shell_exec")==NULL) &&
(strstr(cmd, "passthru")==NULL) &&
(strstr(cmd, "popen")==NULL)) {
return ZEND_USER_OPCODE_DISPATCH;
} else {
return ZEND_USER_OPCODE_RETURN;
}
}
return ZEND_USER_OPCODE_DISPATCH;
}
4.2 字符串变量处理
字符串变量特殊处理:
Z_STRVAL/Z_STRVAL_P/Z_STRVAL_PP- 获取字符串值Z_STRLEN/Z_STRLEN_P/Z_STRLEN_PP- 获取字符串长度
4.3 防御局限性
仅HOOK ZEND_INCLUDE_OR_EVAL不足以防所有攻击,例如:
eval('echo `whoami`;');
需要额外HOOK DO_FCALL等操作码实现更全面的防御。
五、扩展开发进阶
-
变量操作:
- 使用
zval结构处理PHP变量 - 注意引用计数和内存管理
- 使用
-
函数注册:
- 支持参数解析和返回值处理
- 实现面向对象接口
-
资源管理:
- 注册自定义资源类型
- 实现资源析构函数
-
线程安全:
- 考虑多线程环境下的安全性
- 使用TSRM机制
六、参考资源
通过深入理解PHP扩展开发和HOOK技术,可以实现强大的功能扩展和安全防护能力。开发过程中需要注意PHP版本兼容性、内存管理和线程安全等问题。