引言
這道題目的考點是檔案格式、雙圖差值、Ook!編碼、PRC等,我做這題的重點是複習鞏固python讀取二維碼zxing庫的使用。
例題
┌───────────────────────────────────────────────────┐
│ 馬老師的秘籍 │
│ │
│ DASCTF2020 聖誕賽 Misc題目 │
│ │
└───────────────────────────────────────────────────┘
ps:考慮到某公司的不分享精神或許會有版權之類的爭端,檔案的解密需要你ctf一下,哈哈!
提取碼:pZrX
Writeup(WP)
- 開啟影像《馬老師的秘籍.png》是一排排的二維碼,掃描一下看看:
【注意】真正解題不要掃描這些二維碼(網上流行馬保國的一段話而已,跟做題沒有關係),就是一個浪費時間的坑
- 檢視影像《馬老師的秘籍.png》二進位制,發現PK壓縮包,手動或者使用foremost分解出zip包《00002236.zip》,使用winrar可以看到裡面有3個加密的檔案,但用其它壓縮軟體如360zip檢視卻是亂碼:
- 二進位制檢視《00002236.zip》發現偽加密,9改為0,zip包恢復:
- 解壓出《馬老師的奇妙棋盤.jpg》,折騰一會兒發現是雙圖差值,跟《馬老師的秘籍.png》XOR:
- 根據提示md5(NianQingRenBuJiangWuDe)=c57988283c92f759585a0c1aebfdd743,得到解壓密碼解開《00002236.zip》
- 寫指令碼得到Ook!密文,解密得到flag:
本題得解。
相關指令碼
圖片分隔
from PIL import Image, ImageDraw
# 建立一個 400x400 的黑色畫素圖
#image = Image.new('RGB', (400, 400), (255, 255, 255))
img = Image.open("馬老師的秘籍.png")
img_size = img.size
print(img_size)
w = img_size[0] # 圖片寬度
h = img_size[1] # 圖片高度
# 數一數得到二維碼的邊長為99
'''
# 建立一個 ImageDraw 物件
draw = ImageDraw.Draw(img)
# 縱向
qidian=0
kuand=99
jiange=0
while qidian+kuand<w:
draw.line((qidian,0,qidian,h),fill=(255, 0, 0),width=1)
draw.line((qidian+kuand,0,qidian+kuand,h),fill=(0,255,0),width=1)
qidian += (kuand+jiange)
# 橫向
qidian=0
kuand=99
jiange=0
while qidian+kuand<h:
draw.line((0,qidian,w,qidian),fill=(0, 0,255),width=1)
draw.line((0,qidian+kuand,w,qidian+kuand),fill=(0,255, 0),width=1)
qidian += (kuand+jiange)
# 儲存影像
img.save('key.png')
'''
n=0
wq=hq=0
side =99
while side+hq<=h:
wq=0
while side+wq<=w:
img_name = f'./qrcodes/'+str(n).zfill(3)+'.png'
cropped = img.crop((wq, hq, wq+side, hq+side))
cropped.save(img_name)
n+=1
# cropped.show()
wq+=side
hq+=side
二維碼批次讀取
import zxing #匯入解析包
reader = zxing.BarCodeReader()
imgs = glob.glob(r'./qrcodes/*.png')
#print(imgs)
# 測試【注意】zxing被我給修改了,直接安裝的不能用,詳見下方的擴充套件
#print(reader.decode(imgs[0],encoding='gb18030').parsed)
# 一個一個讀,很慢!
'''
msg=''
for i in imgs:
msg += reader.decode(i).parsed
'''
# 批次讀取
info = reader.decode(imgs,encoding='gb18030')
msg = ''.join([x.parsed for x in info])
print(msg)
一一替換
with open('GoodLuck.txt',encoding='utf-8') as k:
key = k.read().split('\n')
with open('閃電五連鞭.txt',encoding='utf-8') as c:
cipher = c.read()
k={}
for i in key:
t=i.split(' -> ')
k[t[0]]=t[1]
cipher=cipher.replace(t[0],t[1])
print(cipher)
擴充套件知識點
zxing庫在windows上整合
- zxing安裝:
> pip install zxing
> pip list zxing | findstr "zxing"
zxing 1.0.3
- zxing安裝目錄
D:\\coding\\Anaconda3\\lib\\site-packages\\zxing
- 錯誤修正
3.1. 報錯:zxing.BarCodeReaderException: ('Java JARs not found in classpath ...)
找到__init__.py檔案中的class BarCodeReader(object):
裡面關於檔案路徑分隔符的判斷:classpath_sep = ';' if sys.platform == 'nt' else ':' # https://stackoverflow.com/a/60211688
【修正】 因為我們是在windows裡面用,直接改為 classpath_sep = ';' 即可。
3.2. 報錯:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xdf in position 0: invalid continuation byte
找到__init__.py檔案中的class BarCodeReader的decode函式中codes = [BarCode.parse(result) for result in file_results]
使用了BarCode.parse(result)中有兩處bytes.decode()呼叫,顯然是utf-8與中文編碼GB18030/GBK/GB2312 不相容導致
parsed = parsed[:-1].decode()
raw = raw[:-1].decode()
【修正】 增加一個引數,改動如下:
BarCode.parse(cls, zxing_output, encoding='utf-8'):
parsed = parsed[:-1].decode(encoding)
raw = raw[:-1].decode(encoding)
BarCodeReader.(self, filenames, try_harder=False, possible_formats=None, pure_barcode=False, products_only=False, encoding='utf-8'):
codes = [BarCode.parse(result, encoding=encoding) for result in file_results]
【使用】可以傳參編碼方式:zxing.BarCodeReader().decode(imgs[0],encoding='GBK')
PS使用之圖層操作
- 開啟ps,檔案>開啟:
- 開啟第一張圖片,新建一個圖層(Ctrl+Shfit+N),隱藏“背景”圖層,放大編輯視窗:
- 再開啟第二張圖片,Ctrl+A複製圖層:
- 回到第一張圖片,圖層1中Ctrl+V貼上:
- 圖層1選擇“差值”
結束語
今天是兒童節又是週末,天公作美,一早就下起了大雨,吃過早飯,寫點程式碼,把zxing搞定了,也把這兩週的負面情緒掃掃空。