比赛时间:2020年10月17日早上9点
比赛时限:一个月
0x1 一“页”障目
宣传单里藏有flag,不过分成了三份
拼好如图:
0x2 壮言壮语
工具:
0x3 秘技·反复横跳
下载文件
得到一种图片
将图片后缀名改成rar,用WinRAR打开(或者用binwalk分析,显然图片里藏有其他东西,或者foremost得到一个压缩包(foremost的使用方法)) ,里面是一张错位的二维码
位置调整
扫描得到flag
0x4 来拼图
给了一张图片source.jpg和一个压缩包,压缩包里为1600个小图片,这1600个小图片是将source.jpg 编辑 加上flag以后的图片切割得来的。
利用python的CV2库的图像匹配算法,由于修改原图,将flag写入到图片上会造成小图片与原图上相应位置的图片匹配度降低,当匹配度低于某个阈值时,可认为是将flag写到了这张小图片上,阈值取的是5e-10.。
同时将小图片拼接成原图片并且保存。
因为开启多线程,比较时间较短,但运行时比较占CPU
# python3
import cv2
from PIL import Image
import numpy as np
import os
import shutil
import threading
# 读取目标图片
source = cv2.imread(r"C:/Users/Lenovo/Desktop/pt/source.jpg")
# 拼接结果
target = Image.fromarray(np.zeros(source.shape, np.uint8))
# 图库目录
dirs_path = r"C:/Users/Lenovo/Desktop/pt/pingTu"
# 差异图片存放目录
dst_path = r"C:/Users/Lenovo/Desktop/pt/new1"
def match(temp_file):
# 读取模板图片
template = cv2.imread(temp_file)
# 获得模板图片的高宽尺寸
theight, twidth = template.shape[:2]
# 执行模板匹配,采用的匹配方式cv2.TM_SQDIFF_NORMED
result = cv2.matchTemplate(source, template, cv2.TM_SQDIFF_NORMED)
# 归一化处理
cv2.normalize(result, result, 0, 1, cv2.NORM_MINMAX, -1)
# 寻找矩阵(一维数组当做向量,用Mat定义)中的最大值和最小值的匹配结果及其位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
target.paste(Image.fromarray(template), min_loc)
return abs(min_val)
class MThread (threading.Thread):
def __init__(self, file_name):
threading.Thread.__init__(self)
self.file_name = file_name
def run(self):
real_path = os.path.join(dirs_path, k)
rect = match(real_path)
if rect > 5e-10:
print(rect)
shutil.copy(real_path, dst_path)
count = 0
dirs = os.listdir(dirs_path)
threads = []
for k in dirs:
if k.endswith('jpg'):
count += 1
print("processing on pic"+str(count))
mt = MThread(k)
mt.start()
threads.append(mt)
else:
continue
# 等待所有线程完成
for t in threads:
t.join()
target.show()
target.save(r"C:/Users/Lenovo/Desktop/pt/target.jpg")
拼接结果(不知道为什么存在色差)需要手动拼合部分内容