2017年5月

[ISCC - 2017] 部分 WriteUP

2017年5月26日 排名今天出来了.
看了下, 全国赛排名为 142, 区赛排名 65. 这成绩着实有些丢人啊. orz
这是第二次参加 CTF 比赛, 上一次还是在 2014 年, 四叶草跟吹潮合作的那次.
之前一直瞧不起赛棍, 原因嘛..无非那几点, 这次比赛过后发现, 赛棍还是有赛棍的厉害之处.
不得不承认着实技不如人.
====================== 割以永治 ==============================
以下是战绩:
comment
因为学业的原因后期出的一道 WEB 和 BASIC 没有去打. 比赛只能当放松, 还是要以学业为重.

BASIC 01

加密表:
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

刚开始看这玩意, 摸不着头脑, 在书安群里一位前辈指点了一下说这是 "杰弗逊轮盘" 密码.
在 WIKI 上看了下, 还行, 根据给出的 密钥 将加密表按密钥的顺序排列. 得到密钥表

['KPBELNACZDTRXMJQOYHGVSFUWI']
['BDMAIZVRNSJUWFHTEQGYXPLOCK']
['GWTHSPYBXIZULVKMRAFDCEONJQ']
['IHFRLABEUOTSGJVDKCPMNZQWXY']
['JZQAWSXCDERFVBGTYHNUMKILOP']
['LVNCMXZPQOWEIURYTASBKJDFHG']
['XPLTDSRFHENYVUBMCQWAOIKZGJ']
['ZWAXJGDLUBVIQHKYPNTCRMOSFE']
['NOZUTWDCVRJLXKISEFAPMYGHBQ']
['UDNAJFBOWTGVRSCZQKELMXYIHP']
['RPLNDVHGFCUKTEBSXQYIZMJWAO']
['MNBVCXZQWERTPOIUYALSKDJFHG']
['AMKGHIWPNYCJBFZDRUSLOQXVET']

接着使用 PY 的字典特性, 将密钥表每行的列进行互换, 对比给出的密文得到明文表, FLAG 我已经标出来了.

NACZDTRXMJQOYHGVS F UWIKPBEL
FHTEQGYXPLOCKBDMA I ZVRNSJUW
QGWTHSPYBXIZULVKM R AFDCEONJ
KCPMNZQWXYIHFRLAB E UOTSGJVD
SXCDERFVBGTYHNUMK I LOPJZQAW
EIURYTASBKJDFHGLV N CMXZPQOW
VUBMCQWAOIKZGJXPL T DSRFHENY
OSFEZWAXJGDLUBVIQ H KYPNTCRM
QNOZUTWDCVRJLXKIS E FAPMYGHB
OWTGVRSCZQKELMXYI H PUDNAJFB
FCUKTEBSXQYIZMJWA O RPLNDVHG
NBVCXZQWERTPOIUYA L SKDJFHGM
PNYCJBFZDRUSLOQXV E TAMKGHIW

FLAG -> FIREINTHEHOLE

BASE 02

# IDAT = "636A56355279427363446C4A49454A7154534230526D6843";
# IDAT = "56445A31614342354E326C4B4946467A5769426961453067";
IDAT = "636A56355279427363446C4A49454A7154534230526D6
  84356445A31614342354E326C4B4946467A5769426961453067"
open("./test.txt","wb").write(IDAT.decode("hex"));

题目给出的是两串 HEX 编码, 写到文件里打开, 得到两串 BASE64 过的密文

cjV5RyBscDlJIEJqTSB0RmhC
VDZ1aCB5N2lKIFFzWiBiaE0g

base64 decode 之后得到两串键盘密码

# s1 = "r5yG lp9I BGjM tFhB";
# s2 = "T6uh y7iJ Q1sZ bhM";

讲道理我起初以为栅栏, 瞎鸡儿去算, 卡了几天, 有个大佬说看看键盘.
以为是和上次的 Oops 的一样是字符, 在那里瞎几把画, 没看懂. 最后是一位朋友提点才看出来是圈, 不是画.
r5yG 圈出了 T 字符. 按理得到 TONGYUAN 字符.
FLAG -> TONGYUAN

BASE 03

comment
没什么好说的, 隐写术. binwalk 拿到第二个数据段, 提取保存为另外一张图

root@abs:/home/abs/root$ binwalk base.png

DECIMAL     HEX         DESCRIPTION
-----------------------------------------------------------------------------
0           0x0         PNG image, 438 x 435, 8-bit/color RGB, non-interlaced
181626      0x2C57A     PNG image, 860 x 189, 8-bit colormap, non-interlaced

comment
起初看不懂, 以为是啥, 各种看通道各种翻, 最后在贴吧翻到一个 CTF 各种加密姿势, 才发现这玩意是猪圈密码.
其实题目已经给出了提示, 共济会. 只是没注意.
FLAG -> goodluck

BASE 04

没什么好说的, 不是伪加密, 跑密码爆破.

#!/usr/bin/env python
import zipfile
import threading
def zipbp(zfile, pwd):
    try:
        zfile.extractall(pwd=pwd)
        print 'password found : %s' % pwd
        exit(0);
    except:
        return
def main():
    zfile = zipfile.ZipFile('test.zip')
    # pwdall = open('aa.txt')
    # for pwda in pwdall.readlines():
    for pwd in xrange(0,99999999):
        print "[+] => "+str(pwd);
        # pwd = pwd.strip('\n')
        pwd = str(pwd);
        try:
            zfile.extractall(pwd=pwd)
            print "[!!!!!!!!!!] Password Is Found: "+pwd;
            break;
        except:
            continue;
        # t = threading.Thread(target=zipbp, args=(zfile, pwd))
        # t.start()
        # t.join()
    print "[-] check Done!;";
if __name__ == '__main__':
    main()

密码 123456, 解压得到 flag.txt, 打开得到 flag
FLAG ->daczcasdqwdcsdzasd

BASE 06

这题的最后一步其实我没做. 有个之前交流过思路的基佬直接发给我了...
这题主要考对 RSA 算法以及签名的理解, 以下是我的解题思路.
这题网上有原题. 地址 -> https://github.com/RandomsCTF/write-ups/tree/master/Hack.lu%20CTF%202015/Creative%20Cheating%20%5Bcrypto%5D%20(150)

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)
已知 N => 求 N 的模值 (http://factordb.com/);
Alice :
    0x53a121a11e36d7a84dde3f5d73cf  =>
      1696206139052948924304948333474767  =>
        38456719616722997 * 44106885765559411
Bob :
    0x99122e61dc7bede74711185598c7  =>
      3104649130901425335933838103517383  =>
        49662237675630289 * 62515288803124247
Alice
    bd = 1696206139052948841741342951192360
已知 p q e 求 d
    Alice :
      d => 37191940763524230367308693117833;
    Bob :
      d => 1427000713644866747260499795119265
Alice:
    n => 1696206139052948924304948333474767
    e => 65537
    d => 37191940763524230367308693117833
Bob:
    n = > 3104649130901425335933838103517383
    e => 65537
    d => 1427000713644866747260499795119265

以下是某基佬的解题代码

class RSAPerson(object):
    def __init__(self, e, p, q):
        self.n = p * q
        self.e = e
        self.p = p
        self.q = q
        self.d = long(gmpy2.invert(e, (p-1)*(q-1)))
        self.key = RSA.construct((long(self.n), long(self.e), self.d))
    def sign(self, message):
        return self.key.sign(message, '')
    def verify(self, message, signature):
        return self.key.publickey().verify(message, [signature])
    def encrypt(self, message):
        return self.key.publickey().encrypt(message)
    def decrypt(self, message):
        return self.key.decrypt(message)
alice = RSAPerson(
    0x10001,
    38456719616722997,
    44106885765559411
)
bob = RSAPerson(
    0x10001,
    49662237675630289,
    62515288803124247
)
packets = []
with open('test.txt') as lines:
    for line in lines:
        decoded = base64.b64decode(line)
        match = regex.match(decoded).groups()
        seq = int(match[0])
        signature = int(match[2], 16)
        data = int(match[1], 16)
        data = bob.decrypt(data)
        if alice.verify(data, signature):
            data = chr(data)
            packets.append((
                seq,
                data,
                signature
            ))
print ''.join([packet[1] for packet in sorted(packets)])

因为我本地装的是 py 2.7 不是 3 所以代码就不运行演示了.
以下为部分信号量数据, 从嗅探包中提取出来的.

U0VRID0gMTM7IERBVEEgPSAweDNiMDRiMjZhMGFkYWRhMmY2NzMyNmJiMGM1ZDZMOyBTSUcgPSAweDJlNWFiMjRmOWRjMjFkZjQwNmE4N2RlMGIzYjRMOw==
U0VRID0gMDsgREFUQSA9IDB4NzQ5MmY0ZWM5MDAxMjAyZGNiNTY5ZGY0NjhiNEw7IFNJRyA9IDB4YzkxMDc2NjZiMWNjMDQwYTRmYzJlODllM2U3TDs=

FLAG -> flag{n0th1ng_t0_533_h3r3_m0v3_0n}

BASE 07

comment
一张二维码, 扫了扫, 拿到提示: the password of the route is our flag
老规矩, binwalk 走一遭.

DECIMAL      HEX         DESCRIPTION
-------------------------------------------------------------------------------------------------------
0           0x0         PNG image, 370 x 370, 1-bit grayscale, non-interlaced
694         0x2B6       Zip archive data, at least v2.0 to extract, compressed size: 54990, 
                         uncompressed size: 292875, name: "C8-E7-D8-E8-E5-88_handshake.cap"
56152       0xDB58      End of Zip archive

提取 zip 爆破后解压得到C8-E7-D8-E8-E5-88_handshake.cap 和一个 "破解记录.txt".
提示为: "前四位是ISCC 后四位由大写字母和数字构成"
看了下嗅探包. 很明显是无线协议的包, 考虑到之前无线破解比较火, 根据提示生成字典, 开aircrack-ng 干它.
# aircrack-ng -w pass.txt -b c8:e7:d8:e8:e5:88 C8-E7-D8-E8-E5-88_handshake.cap
得到密码也就是 FLAG
FLAG ->ISCC16BA

BASE 08

这题也是在某基佬的提示下做出来的.
题目给了两个文件.
comment
根据第一个文件的格式, WINDoWsSeviCEss 一共十五位.
按照五位一组的培根加密方式得到密码. BIT
解压后拿到 BASE64 过的FLAG
FLAG ->Flag:{Ly319.i5d1f*iCult!}

BASE 09

给出了一个 encrypt 函数和一串密文

<?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);
} ?>
output: fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=

根据 encrypt 函数写对应的 decrypt

<?php
function decrypt($str) {
    $mkey = "729623334f0aa2784a1599fd374c120d";
    $klen = strlen($mkey);
    $tmp = $str;
    $tmp = base64_decode($tmp);  // 对 base64 后的字符串 decode
    $md_len = strlen($tmp); //获取字符串长度
    for ($i=0; $i < $md_len; $i++) {  //  取二次加密用 key;
        if ($x == $klen)  // 数据长度是否超过 key 长度检测
            $x = 0;
        $char .= $mkey[$x];  // 从 key 中取二次加密用 key
        $x+=1;
    } 
    $md_data = array();
    for($i=0;$i<$md_len;$i++) { // 取偏移后密文数据
        array_push($md_data, ord($tmp[$i]));
    }
    $md_data_source = array();
    $data1 = "";
    $data2 = "";
    foreach ($md_data as $key => $value) { // 对偏移后的密文数据进行还原
        $i = $key;
        if($i >= strlen($mkey)) {$i = $i - strlen($mkey);}
        $dd = $value;
        $od = ord($mkey[$i]);
        array_push($md_data_source,$dd);
        $data1 .= chr(($dd+128)-$od);  // 第一种可能, 余数+128-key 为回归数
        $data2 .= chr($dd-$od);  // 第二种可能, 余数直接-key 为回归数
    }
    print "data1 => ".$data1."<br>\n";
    print "data2 => ".$data2."<br>\n";
}
$str = "fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=";
decrypt($str);
?>

FLAG ->Flag:{asdqwdfasfdawfefqwdqwdadwqadawd}

MISC 02

眼见非实, 一个 DOCX , 用解压软件解压, 找到 word/document.xml 拿到 FLAG
FLAG ->flag{F1@g}

MISC 03

给了一个嗅探包, 用 wireshark 的 follow 功能把 RSA 私钥公钥和 key.txt 拿出来,然后用 openssl 解密
openssl rsautl -decrypt -in key.txt -inkey test.key -out key.desc
cat key.desc 拿到 FLAG
FLAG ->haPPy_Use_0penSsI

MISC 04

用 Audacity 看到了文件头的那一部分诡异的高低电平, 但是无从入手. 没做

MISC 05

把每一张图片有数字的格子涂黑, 可以看到是一个分尸了的二维码. 还原后拿到 FLAG
FLAG ->flag{y0ud1any1s1}

MISC 06

再见李华... 一时之间没有脑洞, 基佬说注意读题. 这题密码要爆破, 一共九位数, 前四位是随机数, 后五位为 LiHua
直接跑就行了. 解压拿到 FLAG
FLAG ->Stay hungry, Stay foolish.

WEB 01

签到题, 据基佬指出,读题发现 FLAG 字样为 f1ag, 根据提示一步步构造最后在返回头拿到 FLAG
flag=f1ag&hiddenflag=f1ag&f1ag=f1ag 一共三个 f1ag
FLAG ->f1ag: {N0w_go1Odo!otherw3b}

WEB 02

Welcome to Mysql
通过分析发现不能直接上传 .php 文件, 最后扔了一个 .php5 上去, 找到 数据库连接方式, 拿到 FLAG
FLAG -> Flag:{Iscc_1s_Fun_4nd_php_iS_Easy}

WEB 03

i have a jpg, i upload txt
这题卡了蛮久, 主要是没注意看给出的代码, 注意力全在 upload 那一块的. 根据大佬指出目标转移到 rename 那里.

                    $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";

这才是核心代码.可以看到 fclose 是在 fwrite 事务完成后才执行的. 那么只要 key 不等于 0, 我们就能直接绕过 upload 的限制.
通过自带的 fwrite 拼接两个文件, 构造成一个完整的可执行 php.
rename 之后访问构造的 php, 随着 302 跳转会返回一个 flag. 至于怎么绕过 KaIsA, 直接写了个脚本跑了下 0x00 到 0xff, 拿到了解密表.
FLAG ->flag{54a5bd4fe6193580020487b56acff6c5}

WEB 04

一起来日站. 最轻松的一题.
robots.txt -> 御剑扫后台 -> 登录框注入.
构造 username=admin'&password=a' and select 1-- 拿到 FLAG
FLAG ->Flag:{ar32wefafafqw325t4rqfcafas}

WEB 05

打破常规

<?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){
        echo $c[0].$d;
        eregi("3|1|c",$d.$c[0])?die("nope4"):NULL;
        strpos(($c[0].$d), "isccctf2017")?$v3=1:NULL;
    }
}
echo $v1,$v2,$v3;
if($v1 && $v2 && $v3){ 
   echo "success";
}
?>

分析代码构造对应的 URL 即可. 这里感谢雨牛给出的 %00 截断提示.
?iscc={"bar1":"83333ff","bar2":[[true],"1","1","1",true]}&cat[]=%00isccctf2017&cat[]=aaa&dog[]=false
FLAG ->flag{sfklljljdstuaft}

WEB 08

where is your flag
卡了好一会,摸不着头脑, 不知道什么玩意, 基佬提示 宽字节注入和 ID 关键字. (妹的, 以后看见个玩意我一定要随手打个 id 试试)
懒得琢磨直接丢 sqlmap. 拿到 flag
flag:{441b7fa1617307be9632263a4497871e}

[5.12]蠕虫事件应急响应

2017 年 5 月 12 日晚. 项目群有人发了一张图, 某大学被勒索病毒攻击.
十分钟后截了一张公告, 病毒使用 "MS17-010" 进行传播, 看到这马上想起 4 月底 FB 上的一篇帖子.
NSA 漏洞库, MS17-010, 通杀全版本. 马上安排相关人员对涉外及与教育网内部连接的服务器进行加固.
于第二日 5 月 13 日, 九点, 上课途中, 领导连来五个电话安排对机房的相关服务器进行排查.
同时在机房内发现机子出现被攻击成功, 即刻联系组员进中心机房, 对相关机房进行断网处理.
临时对涉毒大楼进行物理阻隔(拔网线). 同时对服务器数据进行备份.
因为实验大楼使用的是云端教学, 被攻击的客户端为云端镜像, 不算什么大事. 对客户端进行升级即可.
于 十一点左右 联系相关负责人, 通过核心交换, 配置 ACL, 阻隔相应端口, 封闭对应 Vlan / IP 段. 阻止进一步传播.
同时对网段内电脑进行排查. 发现实验大楼内有另一教室也出现勒索病毒. 教师端也不能幸免.
考虑云端的特殊性. 便把教室与云端服务器进行物理断网. 关闭所有在用客户端. 从源下手. 对镜像进行升级加固.
于下午五点半, 升级完毕. 晚八点恢复网络进行机房测试, 至晚 十点半 无发现病毒复现状况. 自此事件响应完毕.

总结:

主要是漏洞威力过于巨大, 只要对 SMB 服务进行阻隔即可.