1. 程式人生 > >世安杯 型別 writeup

世安杯 型別 writeup

開啟題目頁面後先出現的程式碼

// An highlighted block

<?php 
show_source(__FILE__); 
$a=0; 
$b=0; 
$c=0; 
$d=0; 
if (isset($_GET['x1'])) 
{ 
        $x1 = $_GET['x1']; 
        $x1=="1"?die("ha?"):NULL; 
        switch ($x1) 
        { 
        case 0: 
        case 1: 
                $a=1; 
                break; 
        }
} $x2=(array)json_decode(@$_GET['x2']); if(is_array($x2)){ is_numeric(@$x2["x21"])?die("ha?"):NULL; if(@$x2["x21"]){ ($x2["x21"]>2017)?$b=1:NULL; } if(is_array(@$x2["x22"])){ if(count($x2["x22"])!==2 OR !is_array($x2["x22"][0])) die("ha?"); $p = array_search
("XIPU", $x2["x22"]); $p===false?die("ha?"):NULL; foreach($x2["x22"] as $key=>$val){ $val==="XIPU"?die("ha?"):NULL; } $c=1; } } $x3 = $_GET['x3']; if ($x3 != '15562') { if (strstr($x3, 'XIPU')) { if (substr(md5($x3),8,16) == substr
(md5('15562'),8,16)) { $d=1; } } } if($a && $b && $c && $d){ include "flag.php"; echo $flag; } ?> ---------------------

依據程式碼可得需要a,b,c,d都要為1的時候,才可以得到flag。

先來看第一段程式碼

// A code block
var foo = 'bar';
// An highlighted block
if (isset($_GET['x1'])) 
{ 
        $x1 = $_GET['x1']; 
        $x1=="1"?die("ha?"):NULL; 
        switch ($x1) 
        { 
        case 0: 
        case 1: 
                $a=1; 
                break; 
        } 
} 

die是php的一個函式,相當於exit()就是是輸出的作用,但是輸出完 會退出本指令碼,所以我們要避免輸出die。 就可得x1需要等於0.

// A code block
var foo = 'bar';
// An highlighted block
$x2=(array)json_decode(@$_GET['x2']); 
if(is_array($x2)){ 
    is_numeric(@$x2["x21"])?die("ha?"):NULL; 
    if(@$x2["x21"]){ 
        ($x2["x21"]>2017)?$b=1:NULL; 
    } 
    if(is_array(@$x2["x22"])){ 
        if(count($x2["x22"])!==2 OR !is_array($x2["x22"][0])) die("ha?"); 
        $p = array_search("XIPU", $x2["x22"]); 
        $p===false?die("ha?"):NULL; 
        foreach($x2["x22"] as $key=>$val){ 
            $val==="XIPU"?die("ha?"):NULL; 
        } 
        $c=1; 
} 
} 

首先是json_decode解碼,詳情請看 http://php.net/manual/en/function.json-decode.php 鍵x21的值不可為純數字,但是需要大於2017,所以只要讓鍵x21的值為2018a就可以。因為php中大於小於是不會判斷型別是否相同,所以前面是數字就可以通過前面並且大於2017.

x22裡面需要是一個數組,且有兩個元素,第一個元素也需要是陣列,利用array_search有如下特性:

在這裡插入圖片描述

// A code block
var foo = 'bar';
// An highlighted block
$x3 = $_GET['x3']; 
if ($x3 != '15562') { 
    if (strstr($x3, 'XIPU')) { 
        if (substr(md5($x3),8,16) == substr(md5('15562'),8,16)) { 
            $d=1; 
        } 
    } 
} 

最後的x3是因為15562的MD5是0e開頭,在弱比較的時候會判斷為0。然後php的MD5是32位的,所以只需要找到前面XIPU加上後面是的數字經過MD5後也為0e開頭即可。附上大神指令碼。

// A code block
var foo = 'bar';
// An highlighted block
import hashlib

for i in xrange(1000000):
    s = 'XIPU' + str(i)
    mymd5 = hashlib.md5()
    mymd5.update(s)
    mymd5 = mymd5.hexdigest()
    flag = 1
    if mymd5[8:10] == '0e':
        for j in mymd5[10:24]:
            if j.isalpha():
                flag = 0
                break
        if flag == 1:
            print s
            break

在這裡插入圖片描述