年画
题目:
from secret import key
flag = b'NSSCTF{******FAKE*********}'
enc_c = b''
for i in range(len(key)):
enc_c += (key[i]^(flag[i%7])).to_bytes(1,'big')
print(f'enc_c={enc_c}')
from PIL import Image
class Depart:
def get_pixel(self, image):
#打开图片
image = Image.open(image)
imageRGB = image.convert('RGB')
#获取图片宽
width=image.size[0]
#获取图片高
height=image.size[1]
imageBin=''
for i in range(width):
for j in range(height):
#遍历对应宽高的
r, g, b = imageRGB.getpixel((i, j))
# 将红色通道的值按8位二进制格式添加到imageBin字符串中。
imageBin+='{:08b}'.format(r)
# 将绿色通道的值按8位二进制格式添加到imageBin字符串中。
imageBin+='{:08b}'.format(g)
# 将蓝色通道的值按8位二进制格式添加到imageBin字符串中。
imageBin+='{:08b}'.format(b)
return imageBin
def departBin(self, bin_data):
#初始化一个空列表以存储分割后的二进制数据块
imageBinList=[]
#获取输入的二进制数据的长度。
data_length=len(bin_data)
#使用循环来将二进制数据分割为64位的块,直到数据长度小于64
while data_length>=64:
imageBinList.append(bin_data[:64])
data_length-=64
bin_data=bin_data[64:]
# 填充字节大小为8。
if data_length == 0:
# 创建一个由8位填充字节组成的填充数据
padding_byte_size=8
padding_data=('{:08b}'.format(padding_byte_size))*padding_byte_size
imageBinList.append(padding_data)
#对于剩余数据长度小于64的情况
else:
#计算需要填充的长度
padding_length = 64 - data_length
# 计算填充字节的大小。
padding_byte_size = (padding_length)//8
padding_data = ('{:08b}'.format(padding_byte_size))*padding_byte_size
imageBinList.append(bin_data + padding_data)
return imageBinList
def make_cipher(self, imageBinList):
f=open('cipher.txt','w')
for i in imageBinList:
f.write(i+'\n')
f.close()
from Crypto.Cipher import AES
from Crypto.Util.Padding import *
from PIL import Image
class Convert:
def encrypt_image(self, image_path, key):
#打开图片地址
image = Image.open(image_path)
pixels = image.tobytes()
#生成一个加密的key
cipher = AES.new(key, AES.MODE_ECB)
#对像素数据进行加密,使用AES密码对象加密并填充数据块。
encrypted_pixels = cipher.encrypt(pad(pixels, AES.block_size))
#将加密后的像素数据重新构造为图像对象。
encrypted_image = Image.frombytes(image.mode, image.size, encrypted_pixels)
return encrypted_image
def run(self):
image_path = "flag.png"
encrypted_image = self.encrypt_image(image_path, key)
encrypted_image.save("cipher.png")
import random
class Same:
def generate_random_image(self, image_path):
cipher_image = Image.open(image_path)
width, height = cipher_image.size
random_image = Image.new("RGB", (width, height))
random_pixels = random_image.load()
for x in range(width):
for y in range(height):
red = random.randint(0, 255)
green = random.randint(0, 255)
blue = random.randint(0, 255)
random_pixels[x, y] = (red, green, blue)
random_image.save("random_image.png")
def drawNewYearPicture():
convert = Convert()
convert.run()
depart = Depart()
image_dir = "cipher.png"
#获得图片的对应每个像素的RGB值的二进制字符串imageBin
bin_data = depart.get_pixel(image_dir)
imageBinList = depart.departBin(bin_data)
depart.make_cipher(imageBinList)
getRandom = Same()
getRandom.generate_random_image(image_dir)
if __name__ == '__main__':
drawNewYearPicture()
# enc_c=b'&2#3-(\x1e9*6"&$\x02=&'
代码审计
1.通过aes对原始图片加密-不够64位的填充
2.读取加密后图片的rgb通道值-存储在txt文件中
3.用原始图片的宽高生成新的随机图片
解题思路
1.key通过给出的enc提示对位异或还原出来
2.读取随机图片的宽高,读取txt文件还原出rgb值,填充到新图片中
3.key解密新图片 getflag
exp
def restore_bin_data(file_path):
with open(file_path, 'r') as f:
bin_data = f.read().replace('\n', '') # 将所有行连接起来,并移除可能的换行符
return bin_data
def restore_image_from_bin(image_bin, width, height):
image = Image.new('RGB', (width, height))
pixels = []
# 从二进制串中获取RGB值并按列放置到二维像素列表中
index = 0
for i in range(width):
#空列
column_pixels = []
for j in range(height):
#提取的红色通道的值
r = int(image_bin[index:index + 8], 2)
#提取的红色通道的值
g = int(image_bin[index + 8:index + 16], 2)
#提取红色通道的值
b = int(image_bin[index + 16:index + 24], 2)
#将提取到的RGB值作为元组(r, g, b)添加到列的像素列表column_pixels中
column_pixels.append((r, g, b))
index += 24
pixels.append(column_pixels)
# 将二维像素列表放入图像中(按列放置)
for i in range(width):
for j in range(height):
image.putpixel((i, j), pixels[i][j])
return image
#计算key
enc_c=b'&2#3-(\x1e9*6"&$\x02=&'
key=b''
flag = b'NSSCTF{******FAKE*********}'
for i in range(len(enc_c)):
key += (enc_c[i]^(flag[i%7])).to_bytes(1,'big')
print(key)
from PIL import Image
#计算图片宽高
image_dir = "random_image.png"
im=Image.open(image_dir)
width =im.size[0]
height =im.size[1]
# 从 "cipher.txt" 文件中恢复二进制数据
bin_data_restored = restore_bin_data('cipher.txt')
# 从二进制数据中恢复图像
restored_image = restore_image_from_bin(bin_data_restored, width, height)
restored_image.save("1.png")
image_path="1.png"
#key解密图片
from Crypto.Util.Padding import *
from Crypto.Cipher import AES
image = Image.open(image_path)
pixels = image.tobytes()
cipher = AES.new(key, AES.MODE_ECB)
#aes解码
encrypted_pixels = cipher.decrypt(pad(pixels, AES.block_size))
encrypted_image = Image.frombytes(image.mode, image.size, encrypted_pixels)
encrypted_image.show()
5206

被折叠的 条评论
为什么被折叠?



