<?php
error_reporting(0);
highlight_file(__FILE__);
$a = "isctf2024";
$b = $_GET["b"];
@parse_str($b);
if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')) {
$num = $_POST["num"];
if($num == 2024){
die("QAQ");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");
}
if(intval($num,0) == 2024){
if (isset($_GET['which'])){
$which = $_GET['which'];
switch ($which){
case 0:
print('QAQ');
case 1:
case 2:
require_once $which.'.php';
echo $flag;
break;
default:
echo GWF_HTML::error('PHP-0817', 'Hacker NoNoNo!', false);
break;
}
}
}
}
直接分析代码
<?php
error_reporting(0);
highlight_file(__FILE__);
$a = "isctf2024";
$b = $_GET["b"]; // 从GET请求获取参数b的值
@parse_str($b); // 解析b的查询字符串到变量(@抑制错误,用于覆盖已有变量)
// 条件1:$a[0] != 'QNKCDZO'
// 条件2:md5($a[0])与md5('QNKCDZO')进行弱类型比较(0e开头的哈希碰撞)
if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')) {
$num = $_POST["num"]; // 从POST请求获取参数num的值
if($num == 2024){ // 直接比较num是否等于2024
die("QAQ"); // 相等则终止程序
}
if(preg_match("/[a-z]/i", $num)){ // 检查num是否包含字母
die("no no no!"); // 包含字母则终止程序
}
// 将num按进制0转换为整数(自动判断进制,如0x/0开头为十六/八进制)
// 要求转换结果等于2024,但原始值不能等于2024
if(intval($num,0) == 2024){
if (isset($_GET['which'])){ // 检查GET参数which是否存在
$which = $_GET['which']; // 获取which参数值
switch ($which){
case 0: // which=0时执行
print('QAQ'); // 输出QAQ(未break,继续执行case1/case2)
case 1: // which=1时加载1.php
case 2: // which=2时加载2.php
require_once $which.'.php'; // 动态包含文件
echo $flag; // 输出文件中的$flag变量
break;
default: // which为其他值时
echo GWF_HTML::error('PHP-0817', 'Hacker NoNoNo!', false);
break;
}
}
}
}
题目存在三个参数,b,num,which,
从b来说:
if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO'))
QNKCDZO的md5值为0e830400451993494058024219903391
以0e
开头的数字字符串在科学计数法中表示0乘以10的幂,也就是0,简单的0e绕过
找一个md5的值是0e开头的字符串:s878926199a
按照a[0]格式传
?b=a[0]=s878926199a
从num来说:
重要的代码:
if(intval($num,0) == 2024){
只有能执行这个语句。which才会被执行
意思是原始值不能等于2024,但结果要等于2024
而且过滤了字母,防止弱比较,
又过滤进制,防进制绕过,
可以直接用小数,上面代码分析所说num被转为整数,2024.1转为整数就是2024
传参:
num=2024.1
从which来说:
不用多说就是,输什么就拼接.php,然后输出(前提是以上代码执行到这一步)
which=flag
三个传参到此结束
出flag