文章目录
- WEB
-
- BestDB
- ez_serialize
- baby_flask
- ez_login
- MISC
-
- 签到
- 简单的png隐写
- 雾都孤儿
- 小田的秘密
- Ascii_art
- 问卷调查
和团队的师傅们组队拿了个第十,师傅们带飞,我就是团队的MVP(Most Vegetable People)
WEB
等官方给的环境出来再复现
BestDB
ez_serialize
baby_flask
ez_login
MISC
签到
公众号语音识别:
异世相遇!尽享美味!安恒赛高!
见笑了,偶四南方银,藕的普通话不镖准哈哈哈~
DASCTF{welcome_to_march_dasctf}
简单的png隐写
一开始以为hint.png
是伪加密,flag.jpg
是真加密,结果后面尝试了一下发现两个都是伪加密
,直接修改ushort deFlags
为偶数
,解压得到两张图
题目说是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
未满,后面又开始满了,所以猜测这里是两张图片,而且chunk
的length
都一样,感觉像一张图片拆成两张图,然后将另外一张的IDAT Chunk
放入这张hint.png
,所以直接将后面的chunk
和结尾全部提取出来加上png头和IHDR
组成另外一张png图片
得到新的提示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的十六进制文件数据
Python简单处理
from binascii import *
hexdata = "1F8B08089180785E0003666C61672E747874004BCB494CAF36B030344D3549B64C33353334B14835B7484A3533484932354B4E35314931B5ACE5E20200468B223F28000000"
with open('flag.gz','wb') as f:
f.write(unhexlify(hexdata))
或者CyberChef
直接可以base64->hex->Gzip
:https://gchq.github.io/CyberChef/
flag{0815e4c9f56148e78be60db56ce44d59}
雾都孤儿
1.png
是一种Colorful programming
叫npiet
: https://www.bertnase.de/npiet/
npiet-online
: https://www.bertnase.de/npiet/npiet-execute.php
得到信息:Tetris
然后继续查看Oliver Twist.docx
只有这一张图片了,改docx
后缀为zip
取出原图image1.jpeg
JPG图片,然后有密钥:Tetris
,试了几个常见的jpg隐写,发现是outguess
隐写
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_!!}
小田的秘密
解压,得到一个有密码的压缩包和一个流量包misc.pcapng
猜测要从misc.pcapng
中找到压缩包密码,追踪下TCP
流量,找到一个gift
的文件
到处对象->HTTP
在index.php
中得到这个gift
文件
first ️ c0f1b6a831c399e2second ️ 9b675bd57058fd46third️e6ae2fec3ad71c77fourth ️ 89f58062f10dd731fifth ️ 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
文件内容进行编译,得到可执行文件
运行之后发现每次运行之后的第二段内容不一定一样,稍微试了几次发现misc.zip
的压缩包密码是:c0f1b6a831c399e226602a67be14ea8c
解压得到flag.rar
和64
,64
是一种叫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
得到:NOT AN EGG
解压flag.rar
得到flag
6bffd0d9321df3c229cdff714bb5a0b0
Ascii_art
流量分析,整个包就只有一个流,很长要细心看
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/
Figlet
的larry3d
字体样式,内容是:Coolest 3D
,猜测这里是想提示上面的内容是aa3d
Larry3D字体:http://www.figlet.org/fontdb_example.cgi?font=larry3d.flf
用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/
part1: "flag{"
part2: 10b56405cb78a92c and cxagfJPekxDGqPYoej0znrGB1LR
part3: "*".upper()
part4key:key for part4:jFHotPW4nMIQPp0
part4: part4.zip(有密码)
part3
就是aa3d
的那个立体图,内容是十六进制大写字母经过figlet
和aa3d
处理得到下图
找了下以往CTF题目中aa3d
的题目,都是使用图片对差偏移,来看清楚原来的内容,但是这里移来移去看不太清楚,就有点迷
连总共有八位,十位,十二位都看不清楚,猜了很多个试了很多次校验了一下都不对,可能思路不对吧,part3猜不出来
part4.zip
的密码并不是给出的part4 key
,也是不是part2
后面的,part4 key
可能是part4.zip
解出来的密文的密钥,至于压缩包密码,也不知道怎么做,伪加密不是,试了下爆破也没出,这题就卡在这里了
问卷调查
DASCTF{3d579ef3b2b5c44066454b7fb7edb4f8}