【MISC】一道假的二维码题目学习zxing库[python解读二维码]
引言
这道题目的考点是文件格式、双图差值、Ook!编码、PRC等,我做这题的重点是复习巩固python读取二维码zxing库的使用。
例题
┌───────────────────────────────────────────────────┐
│ 马老师的秘籍 │
│ │
│ DASCTF2020 圣诞赛 Misc题目 │
│ │
└───────────────────────────────────────────────────┘
ps:考虑到某公司的不分享精神或许会有版权之类的争端,文件的解密需要你ctf一下,哈哈!
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搞定了,也把这两周的负面情绪扫扫空。