[2021 DASCTF July X CBCTF 4th]

just a gif

先用16进制编辑器打开看看有没有隐藏其他文件 打开后没发现其他文件

再用Stegsolve打开一帧一帧地看 发现一共451帧 有11帧是不同的 剩余的都以前11帧为一组循环

猜测相对应(图片内容基本相同)的2帧可能有些像素不同

先用脚本分离gif中的每一帧

#需要先安装pillow库
import os
from PIL import Image

gif=Image.open("E:/code/python-ctf/杂项/Just_a_GIF.gif")#gif路径
os.mkdir("./png")
for i in range(gif.n_frames):
    gif.seek(i)
    temp=Image.new("RGB",gif.size)
    temp.paste(gif)
    temp.save("./png/"+str(i)+".png")

然后再用脚本比较相对应(图片内容基本相同)的2帧

import os
from PIL import Image

p1=Image.open("./png/"+str(0)+".png")
a,b=p1.size
f=Image.new("RGB",p1.size,(255,255,255))
p2=Image.open("./png/"+str(11)+".png")
for x in range(0,a):
    for y in range(0,b):
        if p1.getpixel((x,y))!=p2.getpixel((x,y)):
            f.putpixel((x,y), (0,0,0))
f.save("./flag/temp.png")

和猜测的一样

image-20210806235315368

把后面所有图片都与相对应的第一帧比较

import os
from PIL import Image

os.mkdir("./flag")
for i in range(0,11):
    p1=Image.open("./png/"+str(i)+".png")
    a,b=p1.size
    f=Image.new("RGB",p1.size,(255,255,255))
    #f=Image.new("RGB",(83,83),(255,255,255))   改尺寸把上一句删了 把这句前面的注释删了
    for t in range(1,41):
        p2=Image.open("./png/"+str(t*11+i)+".png")
        for x in range(0,a):
            for y in range(0,b):
                if p1.getpixel((x,y))!=p2.getpixel((x,y)):
                    f.putpixel((x,y), (0,0,0))
    f.save("./flag/"+str(i)+".png")

image-20210805182123560

发现所有图片右边都是空白 说明图片的尺寸不对(应该为83*83) 把上面脚本改下

image-20210805182133193

发现后面2张图应该是前几张图片的拼法(我的图片从0开始编号 出题人从1开始)

然后用脚本拼图

from PIL import Image

a=[7,1,6,9,3,4,5,2,8]
f=Image.new("RGB", (83*3,83*3))
for i in range(0,3):
    for j in range(0,3):
        path="./flag/"+str(a[i+j*3]-1)+".png"
        x=Image.open(path)
        f.paste(x,(i*83,j*83))
f.save("flag.png")

image-20210805182320503

然后用barcode scanner(这个软件比较牛逼 谷歌商店有)扫码

image-20210805181245761

完整脚本(从头到flag)

import os
from PIL import Image

#gif分离
gif=Image.open("E:/code/python-ctf/杂项/Just_a_GIF.gif")
os.mkdir("./png")
for i in range(gif.n_frames):
    gif.seek(i)
    temp=Image.new("RGB",gif.size)
    temp.paste(gif)
    temp.save("./png/"+str(i)+".png")
#图片对比
os.mkdir("./flag")
for i in range(0,11):
    p1=Image.open("./png/"+str(i)+".png")
    a,b=p1.size
    f=Image.new("RGB",(83,83),(255,255,255))
    for t in range(1,41):
        p2=Image.open("./png/"+str(t*11+i)+".png")
        for x in range(0,a):
            for y in range(0,b):
                if p1.getpixel((x,y))!=p2.getpixel((x,y)):
                    f.putpixel((x,y), (0,0,0))
    f.save("./flag/"+str(i)+".png")
#图片拼接
a=[7,1,6,9,3,4,5,2,8]
f=Image.new("RGB", (83*3,83*3))
for i in range(0,3):
    for j in range(0,3):
        path="./flag/"+str(a[i+j*3]-1)+".png"
        x=Image.open(path)
        f.paste(x,(i*83,j*83))
f.save("flag.png")

nuclear wastewater

先扫描二维码 扫完后发现没啥用

image-20210805182426241

然后用16进制编辑器打开看看有没有隐藏其他文件 打开后没发现其他文件

再用Stegsolve打开看看有没有lsb隐写 发现没有

仔细观察图片发现有一部分图片被污染了

image-20210805182753069

猜测信息可能藏在被污染的部分

from PIL import Image

t = open("a.txt", "w", encoding="utf-8")
png = Image.open("Nuclear wastewater.png")
a, b = png.size
for x in range(0, a):#改成for x in range(0, a, 10):
    for y in range(0, b):#改成for y in range(0, b, 10):
        temp = png.getpixel((x, y))
        if temp != (255, 255, 255) and temp != (0, 0, 0):
            t.write(str(temp) + "\n")
t.close()

发现每个数据都重复10次 RGB颜色中都只有一位不为0

image-20210805183507634

把上面循环的步长改成10再把这些不为0的数据提出来

from PIL import Image

t = open("a.txt", "w", encoding="utf-8")
png = Image.open("Nuclear wastewater.png")
a, b = png.size
for x in range(0, a, 10):
    for y in range(0, b, 10):
        temp = png.getpixel((x, y))
        if temp != (255, 255, 255) and temp != (0, 0, 0):
            R, G, B = temp
            if R != 0:
                t.write(str(R) + "\n")
            elif G != 0:
                t.write(str(G) + "\n")
            else:
                t.write(str(B) + "\n")
t.close()

image-20210805190546885

RGB颜色的范围是(0,0,0)-(255,255,255) 尝试把数据转成ASCII字符

from PIL import Image

png = Image.open("Nuclear wastewater.png")
a, b = png.size
for x in range(0, a, 10):
    for y in range(0, b, 10):
        R, G, B = png.getpixel((x, y))
        if 0 < R < 255:
            print(chr(R), end="")
        if 0 < G < 255:
            print(chr(G), end="")
        if 0 < B < 255:
            print(chr(B), end="")

image-20210805194502559

发现有好多重复出现的字符 去掉重复的试试

from PIL import Image
list=[]
png = Image.open("Nuclear wastewater.png")
a, b = png.size
for x in range(0, a, 10):
    for y in range(0, b, 10):
        R, G, B = png.getpixel((x, y))
        if 0 < R < 255:
            if chr(R) not in list:
                list.append(chr(R))
        if 0 < G < 255:
            if chr(G) not in list:
                list.append(chr(G))
        if 0 < B < 255:
            if chr(B) not in list:
                list.append(chr(B))
for i in list:
    print(i,end="")

image-20210805194434554

可能应该按重复字符的个数排序

from PIL import Image

list = []
png = Image.open("Nuclear wastewater.png")
a, b = png.size
for x in range(0, a, 10):
    for y in range(0, b, 10):
        R, G, B = png.getpixel((x, y))
        if 0 < R < 255:
            list.append(chr(R))
        if 0 < G < 255:
            list.append(chr(G))
        if 0 < B < 255:
            list.append(chr(B))
data = {}
for i in list:
    data[i] = data.get(i, 0) + 1
result = sorted(data.items(), key=lambda x: x[1], reverse=True)
for i in result:
    print(i[0], end="")

image-20210805194351302

密码到!结束 (因为后面词频为1 出题人肯定不会将1的放进去 不然就不知道顺序)

打开解压后的文件 发现第一行第二个字符不是第二列

image-20210805194723564

应该是0宽字节隐写

vim打开发现0宽字节是200c 200d 200e

image-20210805195302646

找个网站解码Unicode Steganography with Zero-Width Characters (330k.github.io)

解码前勾上200c 200d 200e

image-20210805195355332

解码结果

image-20210805195741247

是Citrix CTX1加密

用CyberChef梭哈一下(github上有该工具)

image-20210805195528329

解密1次没出flag 再解密一次试试

image-20210805195817820

ezSteganography

先用16进制编辑器打开看看有没有隐藏其他文件 打开后没发现其他文件

再用Stegsolve打开

在Red plane0 发现提示

image-20210805201732270

看G plane的每一位是否藏了信息

在G plane的0位发现了png文件头

image-20210805201911027

将数据导出

image-20210805201943749

网上查找有关qim量化的资料QIM量化 - 努力奋斗的阿贝拉 - 博客园 (cnblogs.com)

from PIL import Image
from Crypto.Util import number
import random
import time
import numpy as np
import matplotlib.pyplot as plt

def extract(delta,y):
    out=[]
    for i in (delta/2-y%delta):
        if i>0:
            out.append(1)
        else:
            out.append(0)
    out=np.array(out)
    return out

p=np.array(Image.open("E:/code/python-ctf/杂项/ezSteganography-flag.png"))
R,G,B=p[:,:,0],p[:,:,1],p[:,:,2]
G=G.ravel()

te_out=extract(20,G)
plt.imshow(np.array(te_out).reshape(1440,2560))
plt.show()

得出另一半flag

image-20210805203408583

posted @ 2021-08-07 00:36  地狱✟祈祷  阅读(188)  评论(0编辑  收藏  举报