出题步骤 :

整理思路

首先整理好出题思路,之后将其倒推出题。

我的思路:伪加密、LSB隐写、二进制矩阵转化为二维码、二维码拼接。

出题思路:生成32位MD5值的flag->将flag转化为二维码图片->二维码图片打乱分割->将分割好的二维码图片转化为二进制矩阵->将二进制矩阵数据写入图片->将图片压缩后修改其全局方式位

图片、flag生成

首先生成32位MD5值的flag

image-20210806160919818

将flag转化为二维码图片

image-20210806160955749

二维码图片打乱分割,增加一些趣味性。

图片->二进制矩阵

将分割好的二维码图片转化为二进制矩阵,二维码是按一定规律在平面分布的黑白相间的图片,用到了0、1比特流,编写一个按照矩阵方式输出0、1比特流的脚本,之后正则去掉矩阵只留下信息即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# _*_ encoding:utf-8 _*_
import numpy
from PIL import Image

def treatment(ima):
ima=ima.convert('L')
im=numpy.array(ima)
print(im)
for i in range(im.shape[0]):
for j in range(im.shape[1]):
if im[i,j]==255:
im[i,j]=0
else:
im[i,j]=1
for i in im:
print(i)
result2txt=str(i)
with open('text.txt','a') as file_handle:
file_handle.write(result2txt)
file_handle.write('\n')
for i in range(im.shape[0]):
for j in range(im.shape[1]):
if im[i, j] == 0:
im [i, j] = 255
else:
im [i, j] = 0
new_in=Image.fromarray(im)
new_in.show()

ima=Image.open('flag.png')
im=treatment(ima)

image-20210806161659949

正则删除空格、”[“、”]”、回车

1
2
3
4
5
6
import re
str1=''
str1=re.sub(' ','',str1)
str1=re.sub('\[','',str1)
str1=re.sub(']','',str1)
print(str1)

image-20210806162023080

LSB隐写

将二进制矩阵数据写入图片,通过LSB隐写的方式,将二进制数据存储在图片的最低有效位上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# -*- coding: UTF-8 -*-
from PIL import Image
# PIL,Python Imaging Library.图像处理功能
def plus(str):
# Python zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0。
return str.zfill(8)

def get_key(strr):
# 获取要隐藏的文件内容
tmp = strr
f = open(tmp, "rb") # 要读取二进制文件,比如图片、视频等等,用'rb'模式打开文件
s = f.read()
str = ""

for i in range(len(s)):
# 逐个字节将要隐藏的文件内容转换为二进制,并拼接起来
# 1.使用bin()函数将十进制的ascii码转换为二进制
# 2.由于bin()函数转换二进制后,二进制字符串的前面会有"0b"来表示这个字符串是二进制形式,所以用replace()替换为空
# 3.又由于这样替换之后是七位,而正常情况下每个字符由8位二进制组成,所以使用自定义函数plus将其填充为8位
str = str + plus(bin(s[i]).replace('0b', '')) # s[i]为该位置字符的十进制表示的ascll码
# print str
f.closed
return str

def mod(x, y):
return x % y
# str1为载体图片路径,str2为隐写文件,str3为加密图片保存的路径
def func(str1, str2, str3):
im = Image.open(str1)
# 获取图片的宽和高
width = im.size[0]
print("width:" + str(width) + "\n")
height = im.size[1]
print("height:" + str(height) + "\n")
count = 0
# 获取需要隐藏的信息
key = get_key(str2)
keylen = len(key)

for h in range(0, height):
for w in range(0, width):
pixel = im.getpixel((w, h)) # 返回该像素点三原色的二进制信息,形成一个数组
a = pixel[0] # R
b = pixel[1] # G
c = pixel[2] # B
if count == keylen:
break
# 下面的操作是将信息隐藏进去
# 分别将每个像素点的RGB值余2,这样可以去掉最低位的值
# 再从需要隐藏的信息中取出一位,转换为整型
# 两值相加,就把信息隐藏起来了
a = a - mod(a, 2) + int(key[count])
count += 1
if count == keylen:
im.putpixel((w, h), (a, b, c))
break
b = b - mod(b, 2) + int(key[count])
count += 1
if count == keylen:
im.putpixel((w, h), (a, b, c))
break
c = c - mod(c, 2) + int(key[count])
count += 1
if count == keylen:
im.putpixel((w, h), (a, b, c))
break
if count % 3 == 0:
im.putpixel((w, h), (a, b, c))
im.save(str3)
# 原图
old = r"flag.bmp"
# 处理后输出的图片路径
new = r"111111.bmp"
# 需要隐藏的信息
enc = r"text.txt"
func(old, enc, new)

写入成功

image-20210806162538651

伪加密

将图片压缩后修改其全局方式位,伪加密的原理就是对全局方式位的修改,使软件识别为加密压缩文件。 image-20210806162819247

image-20210806162849057

修改成功

image-20210806162934268