前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >常见文件文件头和隐写术总结 CTF中Misc必备

常见文件文件头和隐写术总结 CTF中Misc必备

作者头像
红客突击队
发布2022-09-30 14:23:27
6.1K0
发布2022-09-30 14:23:27
举报
文章被收录于专栏:kaydenkayden

常见文件文件头和隐写术总结 CTF中Misc必备

前言

对常见文件文件头和隐写术做个归纳总结

  • 文件头文件尾
  • 图片隐写
  • 音频隐写
  • 电子文档隐写

一、文件头文件尾

1、图片

  • JPEG 文件头:FF D8 FF 文件尾:FF D9
  • TGA 未压缩的前4字节 00 00 02 00 RLE压缩的前5字节 00 00 10 00 00
  • PNG 文件头:89 50 4E 47 0D 0A 1A 0A 文件尾:AE 42 60 82
  • GIF 文件头:47 49 46 38 39(37) 61 文件尾:00 3B
  • BMP 文件头:42 4D 文件头标识(2 bytes) 42(B) 4D(M)
  • TIFF (tif) 文件头:49 49 2A 00
  • ico 文件头:00 00 01 00
  • Adobe Photoshop (psd) 文件头:38 42 50 53

2、office文件

  • MS Word/Excel (xls.or.doc) 文件头:D0 CF 11 E0
  • MS Access (mdb) 文件头:53 74 61 6E 64 61 72 64 20 4A
  • WordPerfect (wpd) 文件头:FF 57 50 43
  • Adobe Acrobat (pdf) 文件头:25 50 44 46 2D 31 2E
  • application/vnd.visio(vsd) 文件头:D0 CF 11 E0 A1 B1 1A E1
  • Email [thorough only] (eml) 文件头:44 65 6C 69 76 65 72 79 2D 64 61 74 65 3A
  • Outlook Express (dbx) 文件头:CF AD 12 FE C5 FD 74 6F
  • Outlook (pst) 文件头:21 42 44 4E
  • Rich Text Format (rtf) 文件头:7B 5C 72 74 66
  • txt 文件(txt) 文件头:Unicode:FE FF / Unicode big endian:FF FE / UTF-8:EF BB BF /ANSI编码是没有文件头的

3、压缩包文件

  • ZIP Archive (zip) 文件头:50 4B 03 04 文件尾:50 4B
  • RAR Archive (rar) 文件头:52 61 72 21

4、音频文件

  • Wave (wav) 文件头:57 41 56 45
  • audio(Audio) 文件头: 4D 54 68 64
  • audio/x-aac(aac)
  • 文件头:FF F1(9)

5、视频文件

  • AVI (avi) 文件头:41 56 49 20
  • Real Audio (ram) 文件头:2E 72 61 FD
  • Real Media (rm) 文件头:2E 52 4D 46
  • MPEG (mpg) 文件头:00 00 01 BA(3)
  • Quicktime (mov) 文件头:6D 6F 6F 76
  • Windows Media (asf) 文件头:30 26 B2 75 8E 66 CF 11
  • MIDI (mid) 文件头:4D 54 68 64

6、代码文件

  • XML (xml) 文件头:3C 3F 78 6D 6C
  • HTML (html) 文件头:68 74 6D 6C 3E
  • Quicken (qdf) 文件头:AC 9E BD 8F
  • Windows Password (pwl) 文件头:E3 82 85 96

7、其他类型

  • windows证书文件(der) 文件头:30 82 03 C9
  • CAD (dwg) 文件头:41 43 31 30
  • Windows Shortcut (lnk) 文件头:4C 00 00 00
  • Windows reg(reg) 文件头:52 45 47 45 44 49 54 34

二、图片隐写

1、附加式的图片隐写

操作系统识别,从文件头标志,到文件的结束标志位 当系统识别到图片的结束标志位后,默认是不再继续识别的 所以可以在文件尾后面加东西

(1)附加字符串

最简单的是附加字符串

附加方法

  • winhex直接附加再保存
  • copy /b a.jpg+b.txt c.jpg,在a图片里加b的内容,得到c图片

识别方法

  • winhex直接看
  • notepad也可以看
  • linux的strings指令

应用

  • 制作图片马,即把木马放到图片的最后

实例

  • Aesop_secret
  • Training-Stegano-1
(2)隐藏压缩文件

可以把压缩文件藏在图片文件尾后 看起来还是图片

附加方法

  • winhex直接附加再保存

识别方法

  • 有些直接改扩展名就可以用
  • linux的binwalk指令
  • stegsolve分离
  • winhex复制压缩文件内容重新保存

实例

  • a_good_idea
  • 攻防世界 Misc高手进阶区 2分题 Ditf
  • 攻防世界 Misc高手进阶区 2分题 再见李华
  • 攻防世界 Misc高手进阶区 3分题 miscmisc
  • 攻防世界 Misc高手进阶区 3分题 3-11

2、基于文件结构的图片隐写

主要是针对PNG图片

标准的PNG文件结构应包括:

  • PNG文件标志
  • PNG数据块:关键数据块和辅助数据块,其中正常的关键数据块有长度、数据块类型码、数据块数据和CRC这4种
(1)png图片文件头数据块(IHDR)

PNG图片的第一个数据块

  • 一张PNG图片仅有一个IHDR数据块
  • 包括了图片的宽,高,图像深度,颜色类型,压缩方法等信息

蓝色部分就是IHDR

可以修改高度值或宽度值对部分信息进行隐藏

  • 如果图片原本是800(宽)*600(高),然后图片的高度从600变成500
  • 这样下面800×100区域的信息就无法从图片中显示出来,我们可见的只有上方800*500的区域,这样就达成了图片隐写的目的
  • 同理可知图片的宽度也可以进行类似的修改以达到隐藏信息的目的

识别方法

  • 用winhex或者010Editor等编辑器打开图片
  • 修改长度或宽度值
  • 在修改文件后,需要利用CRC Calculator对CRC校验码进行重新计算赋值,以防图片被修改后,自身的CRC校验报错,导致图片不能正常打开

实例

  • 攻防世界 Misc高手进阶区 2分题 Ditf
  • 攻防世界 Misc高手进阶区 3分题 2-1
(2)IDAT 数据块
  • 存储实际的数据
  • 在数据流中可包含多个连续顺序的图像数据块
  • 写入一个多余的IDAT也不会多大影响肉眼对图片的观察

识别方法

  • 用pngcheck对图片进行检测pngcheck -v hidden.png

可能会出现一个size为0的异常块

提取内容的脚本

代码语言:javascript
复制
#!/usr/bin/python

from struct import unpack
from binascii import hexlify, unhexlify
import sys, zlib

# Returns [Position, Chunk Size, Chunk Type, Chunk Data, Chunk CRC]
def getChunk(buf, pos):
    a = []
    a.append(pos)
    size = unpack('!I', buf[pos:pos+4])[0]
    # Chunk Size
    a.append(buf[pos:pos+4])
    # Chunk Type
    a.append(buf[pos+4:pos+8])
    # Chunk Data
    a.append(buf[pos+8:pos+8+size])
    # Chunk CRC
    a.append(buf[pos+8+size:pos+12+size])
    return a

def printChunk(buf, pos):
    print 'Pos : '+str(pos)+''
    print 'Type: ' + str(buf[pos+4:pos+8])
    size = unpack('!I', buf[pos:pos+4])[0]
    print 'Size: ' + str(size)
    #print 'Cont: ' + str(hexlify(buf[pos+8:pos+8+size]))
    print 'CRC : ' + str(hexlify(buf[pos+size+8:pos+size+12]).upper())
    print

if len(sys.argv)!=2:
    print 'Usage: ./this Stegano_PNG'
    sys.exit(2)

buf = open(sys.argv[1]).read()
pos=0

print "PNG Signature: " + str(unpack('cccccccc', buf[pos:pos+8]))
pos+=8

chunks = []
for i in range(3):
    chunks.append(getChunk(buf, pos))
    printChunk(buf, pos)
    pos+=unpack('!I',chunks[i][1])[0]+12


decompressed = zlib.decompress(chunks[1][3])
# Decompressed data length = height x (width * 3 + 1)
print "Data length in PNG file : ", len(chunks[1][3])
print "Decompressed data length: ", len(decompressed)

height = unpack('!I',(chunks[0][3][4:8]))[0]
width = unpack('!I',(chunks[0][3][:4]))[0]
blocksize = width * 3 + 1
filterbits = ''
for i in range(0,len(decompressed),blocksize):
    bit = unpack('2401c', decompressed[i:i+blocksize])[0]
    if bit == '\x00': filterbits+='0'
    elif bit == '\x01': filterbits+='1'
    else:
        print 'Bit is not 0 or 1... Default is 0 - MAGIC!'
        sys.exit(3)

s = filterbits
endianess_filterbits = [filterbits[i:i+8][::-1] for i in xrange(0, len(filterbits), 8)]

flag = ''
for x in endianess_filterbits:
    if x=='00000000': break
    flag += unhexlify('%x' % int('0b'+str(x), 2))

print 'Flag: ' + flag

3、LSB隐写

LSB,最低有效位,英文是Least Significant Bit

  • 容量大、嵌入速度快、对载体图像质量影响小
  • 在PNG和BMP上可以实现

原理

  • 图片中的像素一般是由三种颜色组成,即三原色(红绿蓝),由这三种原色可以组成其他各种颜色
  • 在png图片的存储中,每个颜色占有8bit,即有256种颜色,一共包含256的三次方颜色,即16777216种颜色
  • 人类的眼睛可以区分约1,000万种不同的颜色,剩下无法区分的颜色就有6777216
  • LSB隐写就是修改了像素中的最低位,把一些信息隐藏起来

给个直观例子

这人眼看不出颜色区别,但最低位不一样

嵌入脚本

代码语言:javascript
复制
from PIL import Image
import math
 
class LSB:
  def __init__(self):
    self.im=None
 
  def load_bmp(self,bmp_file):
    self.im=Image.open(bmp_file)
    self.w,self.h=self.im.size
    self.available_info_len=self.w*self.h # 不是绝对可靠的
    print ("Load>> 可嵌入",self.available_info_len,"bits的信息")
 
  def write(self,info):
    """先嵌入信息的长度,然后嵌入信息"""
    info=self._set_info_len(info)
    info_len=len(info)
    info_index=0
    im_index=0
    while True:
      if info_index>=info_len:
        break
      data=info[info_index]
      x,y=self._get_xy(im_index)
      self._write(x,y,data)
      info_index+=1
      im_index+=1
 
  def save(self,filename):
    self.im.save(filename)
 
  def read(self):
    """先读出信息的长度,然后读出信息"""
    _len,im_index=self._get_info_len()
    info=[]
    for i in range(im_index,im_index+_len):
      x,y=self._get_xy(i)
      data=self._read(x,y)
      info.append(data)
    return info
 
  #===============================================================#
  def _get_xy(self,l):
    return l%self.w,int(l/self.w)
 
  def _set_info_len(self,info):
    l=int(math.log(self.available_info_len,2))+1
    info_len=[0]*l
    _len=len(info)
    info_len[-len(bin(_len))+2:]=[int(i) for i in bin(_len)[2:]]
    return info_len+info
 
  def _get_info_len(self):
    l=int(math.log(self.w*self.h,2))+1
    len_list=[]
    for i in range(l):
      x,y=self._get_xy(i)
      _d=self._read(x,y)
      len_list.append(str(_d))
    _len=''.join(len_list)
    _len=int(_len,2)
    return _len,l
 
  def _write(self,x,y,data):
    origin=self.im.getpixel((x,y))
    lower_bit=origin%2
    if lower_bit==data:
      pass
    elif (lower_bit,data) == (0,1):
      self.im.putpixel((x,y),origin+1)
    elif (lower_bit,data) == (1,0):
      self.im.putpixel((x,y),origin-1)
 
  def _read(self,x,y):
    data=self.im.getpixel((x,y))
    return data%2
 
if __name__=="__main__":
  lsb=LSB()
  # 写
  lsb.load_bmp('test.bmp')
  info1=[0,1,0,1,1,0,1,0]
  lsb.write(info1)
  lsb.save('lsb.bmp')
  # 读
  lsb.load_bmp('lsb.bmp')
  info2=lsb.read()
  print (info2)

识别方法

  • stegsolve,调通道
  • zsteg,神一样的工具

提取脚本

代码语言:javascript
复制
from PIL import Image

im = Image.open("extracted.bmp")
pix = im.load()
width, height = im.size

extracted_bits = []
for y in range(height):
    for x in range(width):
        r, g, b = pix[(x,y)]
        extracted_bits.append(r & 1)
        extracted_bits.append(g & 1)
        extracted_bits.append(b & 1)

extracted_byte_bits = [extracted_bits[i:i+8] for i in range(0, len(extracted_bits), 8)]
with open("extracted2.bmp", "wb") as out:
    for byte_bits in extracted_byte_bits:
                byte_str = ''.join(str(x) for x in byte_bits)
        byte = chr(int(byte_str, 2))
        out.write(byte)

实例

  • pure_color
  • 攻防世界 Misc高手进阶区 2分题 stage1
  • 攻防世界 Misc高手进阶区 2分题 打野
  • 攻防世界 Misc高手进阶区 2分题 倒立屋
  • 攻防世界 Misc高手进阶区 2分题 Erik-Baleog-and-Olaf
  • 攻防世界 Misc高手进阶区 3分题 flag_universe
  • 攻防世界 Misc高手进阶区 3分题 Excaliflag

4、基于DCT域的JPG图片隐写

JPEG图像格式使用离散余弦变换(Discrete Cosine Transform,DCT)函数来压缩图像

  • 通过识别每个8×8像素块中相邻像素中的重复像素来减少显示图像所需的位数
  • 使用近似估算法降低其冗余度
  • 有损压缩(Loss Compression)技术
  • 常见的隐写方法有JSteg、JPHide、Outguess、F5

Jsteg隐写

  • 将秘密信息嵌入在量化后的DCT系数的LSB上
  • 原始值为-1,0,+1的DCT系数除外
  • 量化后的DCT系数中有负数

实现

代码语言:javascript
复制
import math
import cv2
import numpy as np
 
def dct(m):
    m = np.float32(m)/255.0
    return cv2.dct(m)*255

class Jsteg:
  def __init__(self):
    self.sequence_after_dct=None
 
  def set_sequence_after_dct(self,sequence_after_dct):
    self.sequence_after_dct=sequence_after_dct
    self.available_info_len=len([i for i in self.sequence_after_dct if i not in (-1,1,0)]) # 不是绝对可靠的
    print ("Load>> 可嵌入",self.available_info_len,'bits')
  
  def get_sequence_after_dct(self):
    return self.sequence_after_dct
 
  def write(self,info):
    """先嵌入信息的长度,然后嵌入信息"""
    info=self._set_info_len(info)
    info_len=len(info)
    info_index=0
    im_index=0
    while True:
      if info_index>=info_len:
        break
      data=info[info_index]
      if self._write(im_index,data):
        info_index+=1
      im_index+=1
 
 
  def read(self):
    """先读出信息的长度,然后读出信息"""
    _len,sequence_index=self._get_info_len()
    info=[]
    info_index=0
 
    while True:
      if info_index>=_len:
        break
      data=self._read(sequence_index)
      if data!=None:
        info.append(data)
        info_index+=1
      sequence_index+=1
 
    return info
 
  #===============================================================#
 
  def _set_info_len(self,info):
    l=int(math.log(self.available_info_len,2))+1
    info_len=[0]*l
    _len=len(info)
    info_len[-len(bin(_len))+2:]=[int(i) for i in bin(_len)[2:]]
    return info_len+info
 
  def _get_info_len(self):
    l=int(math.log(self.available_info_len,2))+1
    len_list=[]
    _l_index=0
    _seq_index=0
    while True:
      if _l_index>=l:
        break
      _d=self._read(_seq_index)
      if _d!=None:
        len_list.append(str(_d))
        _l_index+=1
      _seq_index+=1
    _len=''.join(len_list)
    _len=int(_len,2)
    return _len,_seq_index
 
  def _write(self,index,data):
    origin=self.sequence_after_dct[index]
    if origin in (-1,1,0):
      return False
 
    lower_bit=origin%2
    if lower_bit==data:
      pass
    elif origin>0:
      if (lower_bit,data) == (0,1):
        self.sequence_after_dct[index]=origin+1
      elif (lower_bit,data) == (1,0):
        self.sequence_after_dct[index]=origin-1
    elif origin<0:
      if (lower_bit,data) == (0,1):
        self.sequence_after_dct[index]=origin-1
      elif (lower_bit,data) == (1,0):
        self.sequence_after_dct[index]=origin+1
 
    return True
 
  def _read(self,index):
    if self.sequence_after_dct[index] not in (-1,1,0):
      return self.sequence_after_dct[index]%2
    else:
      return None
 
if __name__=="__main__":
  jsteg=Jsteg()
  # 写
  sequence_after_dct=[-1,0,1]*100+[i for i in range(-7,500)]
  jsteg.set_sequence_after_dct(sequence_after_dct)
  info1=[0,1,0,1,1,0,1,0]
  jsteg.write(info1)
  sequence_after_dct2=jsteg.get_sequence_after_dct()
  # 读
  jsteg.set_sequence_after_dct(sequence_after_dct2)
  info2=jsteg.read()
  print (info2)

Outgusee算法

  • 针对Jsteg算法的缺陷提出的一种方法
  • 嵌入过程不修改ECT系数值为0,1的DCT系数
  • 利用为随机数发生器产生间隔以决定下一个要嵌入的DCT系数的位置
  • 纠正过程消除对效应的出现

识别方法

  • Stegdetect:检测到通过JSteg、JPHide、OutGuess、Invisible Secrets、F5、appendX和Camouflage等这些隐写工具隐藏的信息
  • JPHS:针对JPHide
  • Outguess:针对OutGuess

5、数字水印隐写

数字水印(digital watermark)

  • 在数字化的数据内容中嵌入不明显的记号
  • 被嵌入的记号通常是不可见或不可察的
  • 可以通过计算操作检测或者提取

盲水印

  • 对图像进行傅里叶变换,起始是一个二维离散傅里叶变换,图像的频率是指图像灰度变换的强烈程度
  • 将二维图像由空间域变为频域后,图像上的每个点的值都变成了复数,也就是所谓的复频域,通过复数的实部和虚部,可以计算出幅值和相位,计算幅值即对复数取模值,将取模值后的矩阵显示出来,即为其频谱图
  • 对模值再取对数,在在0~255的范围内进行归一化,这样才能够准确的反映到图像上,发现数据之间的差别,区分高频和低频分量

识别方法

  • bwm

实例

  • 攻防世界 Misc高手进阶区 3分题 warmup
  • 攻防世界 Misc高手进阶区 3分题 信号不好先挂了

6、图片容差隐写

容差

  • 在选取颜色时所设置的选取范围
  • 容差越大,选取的范围也越大
  • 其数值是在0-255之间

容差比较的隐写

  • 若是有两张图片,则对两张图片的每一个像素点进行对比,设置一个容差的阈值α,超出这个阈值的像素点RGB值设置为(255,255,255),若是没超过阈值,则设置该像素点的RGB值为(0,0,0)。因此,通过调整不同的α值,可以使对比生成的图片呈现不同的画面。比如两张图完全一样,设置阈值α为任何值,最后得到的对比图都只会是全黑。若两张图每一个像素点都不同,阈值α设置为1,则对比图将是全白。如果将隐藏信息附加到某些像素点上,这时调整阈值α即可看到隐藏信息。
  • 如果是一张图片,则根据每一像素点周围像素的值进行判断,同样设置一个阈值,若当前像素点超过周围像素点的均值,或者其它的某种规则,则将该像素点RGB值置为(255,255,255),反之则不进行处理,或者设置为全0.这样也可以获得隐藏的信息。

识别方法

  • beyond compare比较图片

7、打乱进制

比如把整个二进制都逆序 得到一堆乱码

识别方法

  • winhex,看文件头尾是不是互换且逆序

实例

  • 攻防世界 Misc高手进阶区 2分题 Reverse-it

8、GIF的组合

gif每帧是某个图的一部分 提取每帧再拼接

工具

  • ps

实例

  • 攻防世界 Misc高手进阶区 2分题 glance-50
  • 攻防世界 Misc高手进阶区 3分题 双色块

三、音频隐写

简单提一下

  • 频谱图藏信息
  • 高低位二进制
  • 波形藏摩斯密码
  • MP3Stego
  • 音频中也有LSB

本来想自己整理下 看到国光大佬的很全面 就直接放个链接

CTF中音频隐写的一些整理总结

实例

  • 攻防世界 Misc高手进阶区 2分题 Hear-with-your-Eyes
  • 攻防世界 Misc高手进阶区 3分题 很普通的Disco
  • 攻防世界 Misc高手进阶区 4分题 intoU

四、电子文档隐写

1、隐藏文字

看图说话

2、文件隐藏

类似图片隐藏文件 直接看例子吧 攻防世界 Misc高手进阶区 3分题 小小的PDF

结语

对常见文件文件头和图片音频文档隐写术做了个总结


红客突击队于2019年由队长k龙牵头,联合国内多位顶尖高校研究生成立。其团队从成立至今多次参加国际网络安全竞赛并取得良好成绩,积累了丰富的竞赛经验。团队现有三十多位正式成员及若干预备人员,下属联合分队数支。红客突击队始终秉承先做人后技术的宗旨,旨在打造国际顶尖网络安全团队。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-09-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 红客突击队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 常见文件文件头和隐写术总结 CTF中Misc必备
  • 前言
  • 一、文件头文件尾
    • 1、图片
      • 2、office文件
        • 3、压缩包文件
          • 4、音频文件
            • 5、视频文件
              • 6、代码文件
                • 7、其他类型
                • 二、图片隐写
                  • 1、附加式的图片隐写
                    • 2、基于文件结构的图片隐写
                      • 3、LSB隐写
                        • 4、基于DCT域的JPG图片隐写
                          • 5、数字水印隐写
                            • 6、图片容差隐写
                              • 7、打乱进制
                                • 8、GIF的组合
                                • 三、音频隐写
                                • 四、电子文档隐写
                                  • 1、隐藏文字
                                    • 2、文件隐藏
                                    • 结语
                                    领券
                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档