您现在的位置是:首页 >其他 >网络空间安全---隐写术网站首页其他

网络空间安全---隐写术

XyLinzc 2024-10-24 12:01:04
简介网络空间安全---隐写术

-----XyLinzc

隐藏信息探索

  1. 从靶机服务器的FTP上下载文件,找出隐写文件夹1中的文件,将文件中的隐藏信息作为Flag值提交;

那到图片的第一时间就要想起将它往WinHex里面托,看看其信息

在ASCII这列发现类似于base64编码的东西

知识普及:

Base64编码的特征:

  1. 一定是4的倍数
  2. 结尾一般为”=”(以等号”=”结尾)
  3. 一共由64个字符(26个大写字母,26个小写字母,10个数字[0-9],2个其它字符(”+“,”=”),一般都是”=”号)

在Winhex里面看ASCII码字符看不清,有其它乱码混淆,我们就要用到kali专门用于打印可见字符串的工具命令strings

在虚拟机中可以直接把物理机的东西拖进终端

Strings : 用于打印文件中可见的字符(后面直接接文件路径)

我们发现此处就一个base64的编码,那我们进行解码

解码:exho 密文 | base64 -d

分别解出后发现是半个flag值,那我们把它合并后解密的出flag

Flag{ U5e_3x1ftoo1 }

  1. 找出隐写文件夹2中的文件,将文件中的隐藏信息作为Flag值提交;

 

老样子拖进Winhex看看

一般看流量分析与隐写的十六进制分析时,先看头,再看尾,在看看中间有没有可疑的字符串

发现文件头没什么可疑的地方,在看看文件尾,噢,发现GNP, 这说明什么,说明图片的数据是反的,那我们用Python进行修正

Python源码:

with open("flag2.jpg","rb") as img:       #"rb"以二进制的形式打开并读取

    temp = img.read()[::-1]               #读取文件后反序

with open("flag.jpg","wb") as new_img:    #创建一个二进制图像文件,并格式化

    new_img.write(temp)                   #写入反序后的文件类容

因为在Python中字符串也能进行切片操作,所以我们用[::-1]将读取到的二进制文件信息取反后写入新文件

得到Flag

Flag{ Mirrer_R3f3ct1on_H1dd3n_f14g }

  1. 找出隐写文件夹3中的文件,将文件中的隐藏信息作为Flag值提交;

文件是一个正在闪烁的gif, 可以隐约的发现图片中间有字

那么我们就可以采用Python中PIL库自带的函数Image来进行图像处理,也就是gif文件分离

Python源码:

#隐写术第3题Python解法

from PIL import Image   #PIL库是开源的图像处理库,Image为PIL中最基本的图像处理模块

picture = []            #创建一个空列表,用于存储文件打开的状态

with Image.open("flag3.gif") as img:        #打开文件

    for frame in range(0,img.n_frames):     #将gif文件变为一帧一帧的图片,n_frames是求图片的总帧数

        img.seek(frame)                     #seek定位图片的帧数,图片的索引一般都是0开头

        img.save(f"{frame}.png")            #save保存图片

        picture.append(Image.open(f"{frame}.png"))  #将打开的png图片的状态存入列表,方便下次使用

i = Image.new("RGB",(img.n_frames*img.width,img.height))    #创建一块新画布,颜色模式为RGB,图像大小为:画布的宽度=原本的gif图像的宽度width*图像分离出的的帧数,画布的高度=原本gif图像的高度height

locate = 0          #locate用于定位粘贴的位置

for state in picture:           #打开每一张png图像

    i.paste(state,(locate,0))   #将打开的图像粘贴到画布上,(locate,0)为粘贴的位置(左上角)

    locate += img.width         #每一次粘贴后,重新都需要移动粘贴的坐标,这样才能将图片完美的合在一张图上,locate += img.width每次定位的坐标要在x轴上依次加上原本图像的宽度

i.show()    #展示图片

得到Flag

Flag{ Bliss by Charles O'Rear }

  1. 找出隐写文件夹4中的文件,将文件中的隐藏信息作为Flag值提交;

发现有104张黑白不一的图片

那么我们就要想到 白0黑1 的原则

这样就达到了104位二进制,将它们依次分为13个字节(一个字节8位),然后将每一个字节转为十进制后在用chr转ASCII码即可

但手动输入太麻烦了,我们就借助Python中PIL库中的Image函数中的getpixel((x,y))去获取图像的像素点,

纯黑的RGB代码是: 00000000

纯白的RGB代码是: FFFFFFFF

所以计算它是否为

黑就是让R==0 or G==0 or B==0

白就是让R==255 or G==255 or B==255

但在这个文件中除了黑就只有白了,所以判断它是不是黑就行了

Python源码:

import re

from PIL import Image                   #导入图像处理库

                                        #解题思路: 白0黑1, 将104张黑白图片根据白0黑1的规则转为104位二进制数(切记图像的顺序不能打乱)

strs = ""                               #       然后将104位二进制分为13组字节(也就是一组8位二进制)

                                        #       在将每一组二进制转化成十进制, 在化为ASCII码依次输出即可

for img in range(104):

    i = Image.open(f"{img}.jpg")        #用循环依次打开104张图片

    r,g,b = i.getpixel((0,0))           #在左上角取一个像素,分析红对应的色数,绿对于的色数,蓝对应的色数,并分别赋予r,g,b

    if r==0 or g==0 or b==0:            #判断是否为黑色(00000000)

        strs += "1"                     #是黑色就添加一个 "1"

    else:                               #因为在此相册中只有黑白两色,所以除了黑色以外就只有白色了

        strs += "0"                     #是白色就添加一个 "0"

locate = 0                              #用于定位每一组字节的结尾也就是下一组的开头

byte = []                                  #用于分组

# byte = re.findall(r".{8}", strs)      #正则表达式  .表示任意字符 {8}表示每次找8位  用正则表达式找出的东西会自动整理成列表输出

for n in range(len(strs)+1):            #将104位二进制分组为13组字节

    if n % 8 == 0 and n != 0:           #一个字节8位

        byte.append(strs[locate:n])     #将每一组字节存入列表,方便查找

        locate = n                      #定位每一组字节的结尾也就是下一组的开头(因为切片取值是顾头不顾尾)  

flag = ""                               #用于存取flag值

for bits in byte:                       #取出字节

    sum = 0                             #用于求和, 也用于重置

    cf = 7                              #次方, 因为8位二进制转十进制的次方范围是: 2的0次方-2的7次方

    for bit in bits:                    #取出字节的每一位

            sum += int(bit)*pow(2,cf)   #转为十进制, 因为字符串取值是从左往右,而二转十是从右往左, 所以次方需要依次递减, 又因为从字符串取出后还是字符, 所以需要转为int

            cf -=1                      #次方递减, 因为是逆序

    flag += str(chr(sum))               #将十进制转为ACSII码存入字符串

print(flag)                               #打印flag

Flag{ FuN_giF }

  1. 找出隐写文件夹5中的文件,将文件中的隐藏信息作为Flag值提交

是一个gif的文件打开后出现错误

拖进Winhex看看它的文件头与后缀名能不能对上

发现是一个不存在的文件头,大概率是出题人将文件头改了,那我们改回它原先的GIF文件头 ==> 47 49 46 38 39 61

GIF的文件头(47 49 46 38 39 61)一定要记住,这都是常考的

它的真面目浮出了水面

看起来和普通的静态图片是一样的,那这张图片就不正常了,说明这张图的闪烁频率特别快,想到频率,你会不会联想到摩斯密码,以GIF文件闪烁的时间间隔当做一串二进制数,然后再解密

那么解密的思想就来了,先记录GIF文件每一帧的闪烁频率,然后看GIF文件的总帧数是不是8的倍数,如果是就转二进制,如果不是,那就找规律把它变成8的倍数,然后按照规律将他的每一帧的间隔看成0或1,按顺序摆出来,在和上一题样,分组成字节,在转换为十进制后转ASCII依次输出即可

发现有306个数据,可它不是8的倍数,然后往下看,找到了2个不同的数据,306-2=304,正好304是8的倍数,所以我们可以方心的将这两个不一样的数据删除了,然后观察剩余的100和200,我们知道二进制就只有0和1两个值,所以就可以明摆的说这200就是0,反之100就是1,因为你想想在这里是不是只有100上能薅到1,所以200就只能是0了

Python源码:

from PIL import Image                               #从PIL库中导入图像处理函数Image

duration = []                                       #用于存储每一帧的帧率

with Image.open("flag5.gif") as img:                #打开GIF文件

    for frame in range(0,img.n_frames):             #查询所有帧

        img.seek(frame)                             #定位帧

        duration.append(img.info["duration"])       # duration : 持续时间  ==> 也就是帧率  #在info中的信息都是存在字典里的,所有要用查字典的方法获取帧率

while 660 in duration:                              # while 条件 in 可迭代对象  ==> 判断条件在迭代对象中出现了几次,出现几次就执行几次循环

    duration.remove(660)                            # remove : 删除列表中指定的元素

for loc in range(len(duration)):                    #获取duration列表中全部的下标

    if duration[loc] == 100:                        #判读下标所对应的值是否等于100

        duration[loc] = 1                           #若是100,则将值替换成1

    else:                                           #在这个列表中除了100后就只有200了,所以不用在写一个elif

        duration[loc] = 0                           #若是200,则将值替换成0

flag = ""                                           #用于存储flag值

value = ""                                          #用于存储字节(一个字节8位二进制)

for key in duration:                                #依次取出duration中的二进制值

    value += str(key)                               #将值依次存入value中

    if len(value) == 8:                             #当value中的值满8位,也就是刚好到一个字节

        sums = 0                                    #用于存储8位二进制转为十进制后的值

        cf = 7                                      #用于存储次方

        for bit in value:                           #将一个字节分为8位二进制

            sums += int(bit) * pow(2,cf)            #二进制转十进制

            cf -= 1                                 #因为Python读取文件是从左往右,而我们算二转十是从右往左,所以要逆序

        flag += chr(sums)                           #将化为十进制后的值转为ASCII

        value = ""                                  #用于清空使用后字节,方便下次使用冲突

print(flag)                                         #打印flag值

Flag { 96575beed4dea18ded4735643aecfa35 }

各题Flag值

  1. Flag{ U5e_3x1ftoo1 }0
  2. Flag{ Mirrer_R3f3ct1on_H1dd3n_f14g }

     3.Flag{ Bliss by Charles O'Rear }

     4.Flag{ FuN_giF }

     5.Flag { 96575beed4dea18ded4735643aecfa35 }

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。