源码
- 两道题分别泄露
.index.php.swp和www.zip 
.index.php.swp
<?php
$flag = $_GET['flag'];
if ($flag != '15562') {
	if (strstr($flag, 'zctf')) {
		if (substr(md5($flag),8,16) == substr(md5('15562'),8,16)) {
			die('ZCTF{#########}');
		}
	}
}
die('ha?')
?>
www.zip中admin.php (解密:混淆phpjm, 3元)
<?php
require_once("db.php");
$auth = 0;
if (isset($_COOKIE["auth"])) {
    $auth = $_COOKIE["auth"];
    $hsh = $_COOKIE["hsh"];
    if ($auth == $hsh) {
        $auth = 0;
    } else if (sha1((string)$hsh) == md5((string)$auth)) {
        $auth = 1;
    } else {
        $auth = 0;
    }
} else {
    $auth = 0;
    $s = $auth;
    setcookie("auth", $s);
    setcookie("hsh", sha1((string)$s));
}
if ($auth) {
    if (isset($_GET['query'])) {
        $db = new SQLite3($SQL_DATABASE, SQLITE3_OPEN_READONLY);
        $qstr = SQLITE3::escapeString($_GET['query']);
        $query = "SELECT amount FROM my_wallets WHERE id=$qstr";
        $result = $db->querySingle($query);
        if (!$result === NULL) {
            echo "Error - invalid query";
        } else {
            echo "Wallet contains: $result";
        }
    } else {
        echo "<html><head><title>Admin Page</title></head><body>Welcome to the admin panel!<br /><br /><form name='input' action='admin.php' method='get'>Wallet ID: <input type='text' name='query'><input type='submit' value='Submit Query'></form></body></html>";
    }
} else echo "Sorry, not authorized.";
分析
关键部分1
if (strstr($flag, 'zctf')) {
	if (substr(md5($flag),8,16) == substr(md5('15562'),8,16)) {
		die('ZCTF{#########}');
	}
}
- 分析可知由于==为php弱类型相等,flag的MD5的8-16位为开头0e的全数字,且flag中包含zctf子串
 
关键部分2
else if (sha1((string)$hsh) == md5((string)$auth)) {
        $auth = 1;
- 分析可知由于==为php弱类型相等,$hsh的sha1值为0e开头的全数字,并且$auth的MD5值也为0e开头的全数字
 
爆破
- 爆破脚本的构造方式有如下分类思路
    
- 出口判断
        
- 0e数字
 - 题设相等
 
 - payload设置
        
- 数值递增
 - 字符递归
 
 
 - 出口判断
        
 
第一题的题设相等,数值递增的PHP脚本
<?php
for ($a = 1; $a <= 999999; $a++) {
    $flag = "zctf".$a;
        if (substr(md5($flag),8,16) == substr(md5('15562'),8,16)){
            echo $flag.":";
            echo substr(md5($flag),8,16)."\n";
        }
}
echo $flag;
?>
第一题的0e数字,数值递增的Python脚本
import hashlib
for i in range(10000000):
	s = 'zctf' + str(i)
	md5 = hashlib.md5(s).hexdigest()
	h = md5[8:24]
	flag = 1
	if md5[8:10] == '0e':
		for j in md5[10:24]:
			if j.isalpha():
				flag = 0
				break
		if flag == 1:
			print s
			break
第二题的0e数字,字符递归的php爆破脚本,其中sha1(40位)和MD5(32位)函数可互相更改
<?php
function find($a)
{
	$s='asdfghjklpoiuytrewqzxcvbnm1234567890ZXCVBNMLKJHGFDSAQWERTYUIOP{}._';
	$ss=substr(sha1($a), 0,2);
	if($ss=='0e') //判断前两位是否为0e
	{
		$flag = 0;
		for($i=2;$i<40;$i++)  // 40为摘要位数
		{
			if(sha1($a)[$i]>'9') //判断后38位是否为数字
			{
				$flag=1;
				break;
			}
		}
		if($flag==0)
		{
			echo $a."的sha1:".sha1($a)."\n";
		}
	}
	if(strlen($a)>7)  //递归字符串长度
		return;
	else
	{
		for($j=0;$j<strlen($s);$j++)
		{
			find($a.$s[$j]);  // 递归调用
		}
	}
}
$p='';
find($p);
?>
知识小结
- 花式源码泄露
 - php弱类型相等
 - 密码爆破脚本的构造