文章目錄
misc文件頭尾
文件隱寫和圖片隱寫步驟
misc思路
MISC文件隱寫總結(圖片,音頻,視頻,壓縮包等文件)
misc圖片類總結(新賽題)
一、改高寬
打開圖片發現下面好像少了什么。
WinHex打開可以看到PNG的文件頭
解析:
(固定)八個字節89 50 4E 47 0D 0A 1A 0A為png的文件頭
(固定)四個字節00 00 00 0D(即為十進制的13)代表數據塊的長度為13
(固定)四個字節49 48 44 52(即為ASCII碼的IHDR)是文件頭數據塊的標示(IDCH)
(可變)13位數據塊(IHDR)
前四個字節代表該圖片的寬
后四個字節代表該圖片的高
后五個字節依次為:
Bit depth、ColorType、Compression method、Filter method、Interlace method
(可變)剩余四字節為該png的CRC檢驗碼,由從IDCH到IHDR的十七位字節進行crc計算得到。
文件尾:AE 42 60 82
圖片尺寸為787x500(高x寬)
00 00 00 0D 說明IHDR頭塊長為13
49 48 44 52 IHDR標識
00 00 03 13 圖像的寬,787像素
00 00 01 F4 圖像的高,500像素
發現高寬錯誤
這里需要注意的是,文件寬度不能任意修改,需要根據 IHDR 塊的 CRC 值爆破得到寬度,否則圖片顯示錯誤不能得到 flag
import os
import binascii
import struct
crcbp = open("D:\\桌面文件\\bingbing.png", "rb").read() #打開圖片
for i in range(2000):
for j in range(2000):
data = crcbp[12:16] + \
struct.pack('>i', i)+struct.pack('>i', j)+crcbp[24:29]
crc32 = binascii.crc32(data) & 0xffffffff
if(crc32 == 0xda5a4a50): #圖片當前CRC
print(i, j)
print('hex:', hex(i), hex(j))
把高寬都改成787保存得flag
二、lsb(最低有效位)隱寫+base64編碼圖片
攻防世界Misc高手進階區 3-11
下載png文件,binwalk,發現zlib文件。
binwalk詳解
LSB隱寫,save bin,改后綴解壓,彈出已損壞,用winrar自帶的修復
結尾的=號判斷是base64編碼,開頭iVBORw0K說明是base64編碼的圖片。
用captfencoder加上頭,轉為圖片:FLAG{LSB_i5_SO_EASY}
CRC32碰撞腳本
Misc中的有一類題目是要求我們知道加密后的rar文件中的內容。但是rar文件密碼我們不知道,直接爆破密碼也不是很現實。
但是當文件的大小比較小,或者字符數量較少時,就可以根據crc校驗碼來爆破出rar內部文件的內容。
可以看到最后一列是對應文件的CRC校驗碼。並且每個文件只有4字節,所以可以看作每個CRC校驗碼都對應了唯一的文件。Python2爆破如下:
import binascii
import string
dic=string.printable #打印出字符表
crc1=0x7DE0AB32
crc2=0xB1441D53
crc3=0x49BD11F5
crc4=0xB42F1DFA
crc5=0x8163F43E
crc6=0x1FC8FEE5
for i in dic:
for j in dic:
for n in dic:
for m in dic:
s=i+j+n+m
if(crc1==(binascii.crc32(s) & 0xffffffff)):
text1=s
if (crc2 == (binascii.crc32(s) & 0xffffffff)):
text2=s
if (crc3 == (binascii.crc32(s) & 0xffffffff)):
text3=s
if (crc4 == (binascii.crc32(s) & 0xffffffff)):
text4=s
if (crc5 == (binascii.crc32(s) & 0xffffffff)):
text5=s
if (crc6 == (binascii.crc32(s) & 0xffffffff)):
text6=s
print text1+text2+text3+text4+text5+text6
三、盲水印+明文攻擊
攻防世界Misc的warmup,2017ciscn(全國大學生信息安全競賽)
下載打開,兩個一樣的open_forun.png, 明文攻擊,將open_forum.png壓縮成zip,然后使用ARCHPR的明文攻擊
注:兩個open_forum.png的crc32的值一樣,以及兩個文件被壓縮之后的大小,滿足明文攻擊要求。
解壓出來是這樣:
兩個圖,試試盲水印:
python bwmforpy3.py decode fuli.png fuli2.png flag.png --oldseed
注:如果要讓python3兼容python2的random算法請加 --oldseed參數。結果就是flag.png。
傅里葉盲水印
VNCTF021 冰冰好像藏着秘密
傅里葉盲水印原理:
圖片經過傅里葉變換后,水印圖片直接按像素覆蓋到頻率域,因為頻譜是中心對稱的,所以加水印也要對稱的加,具體就是圖片分上下兩部分,左上加了什么,右下也要加同樣的內容。之后傅里葉反變換回去。解水印的時候變換到傅里葉變換提取就可以了。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread('D:\\CTF\\FFT.png', 0) #直接讀為灰度圖像,不過此題已經是灰度圖片了
f = np.fft.fft2(img) #做頻率變換
fshift = np.fft.fftshift(f) #轉移像素做幅度譜
s1 = np.log(np.abs(fshift))#取絕對值:將復數變化成實數取對數的目的為了將數據變化到0-255
plt.subplot(121)
plt.imshow(img, 'gray')
plt.title('original')
plt.subplot(122)
plt.imshow(s1,'gray')
plt.title('center')
plt.show()
四、IDAT塊隱寫
提數據+zlib解壓+625二維碼
圖像數據塊 IDAT(image data chunk):它存儲實際的數據,在數據流中可包含多個連續順序的圖像數據塊。IDAT 塊只有當上一個塊充滿時,才會繼續一個新的塊。
pngcheck.exe -v sctf.png
前面的塊都是65524,到了0x150008變為45027,再到0x15aff7的138。
很明顯最后一個 IDAT 塊是有問題的,因為他本來應該並入到倒數第二個未滿的塊里。
0x150008中的45027位數據是正常的圖片信息。0x15aff7的138位數據是人為錄入的,且所在的數據塊也是人為創建的。
IDAT中的數據采用 LZ77 算法的派生算法進行壓縮,所以可以用 zlib 解壓縮。
可以用010 editor直接提取出數據,然后扔進zlib解壓腳本里解壓獲得原始數據。
查看異常數據塊的情況,使用010editor/winhex打開,導出異常數據塊:
查找78 9C文件頭標志,zlib。
將異常的IDAT數據塊斬頭去尾之后使用腳本解壓,在python2代碼如下:
import zlib
import binascii
IDAT = "789C5D91011280400802BF04FFFF5C75294B5537738A21A27D1E49CFD17DB3937A92E7E603880A6D485100901FB0410153350DE83112EA2D51C54CE2E585B15A2FC78E8872F51C6FC1881882F93D372DEF78E665B0C36C529622A0A45588138833A170A2071DDCD18219DB8C0D465D8B6989719645ED9C11C36AE3ABDAEFCFC0ACF023E77C17C7897667".decode('hex')
result = binascii.hexlify(zlib.decompress(IDAT))
print (result.decode('hex'))
print (len(result.decode('hex')))
得到壓縮后的文件:
發現是625,是一個二維碼的矩陣,使用python2代碼做成二維碼:
from PIL import Image
MAX = 25
pic = Image.new("RGB",(MAX,MAX))
str ="1111111000100001101111111100000101110010110100000110111010100000000010111011011101001000000001011101101110101110110100101110110000010101011011010000011111111010101010101111111000000001011101110000000011010011000001010011101101111010101001000011100000000000101000000001001001101000100111001111011100111100001110111110001100101000110011100001010100011010001111010110000010100010110000011011101100100001110011100100001011111110100000000110101001000111101111111011100001101011011100000100001100110001111010111010001101001111100001011101011000111010011100101110100100111011011000110000010110001101000110001111111011010110111011011"
i=0
for y in range(0,MAX):
for x in range(0,MAX):
if(str[i] == '1'):
pic.putpixel([x,y],(0,0,0))
else:pic.putpixel([x,y],(255,255,255))
i = i+1
pic.show()
pic.save("flag.png")
運行得到二維碼
png末尾藏zip
PNG (png),文件頭:89504E47 文件尾:49454E44AE426082
從0304后全部保存,在前面和后面加上504B,后保存為zip
用stegpy得到zip密碼:
五、分離與拼接
convert分離gif+montage拼接
攻防世界MISC進階:glance-50,mma-ctf-2nd-2016
下載拿到一個gif圖片,很窄(寬2px)。
(1)用kali的convert命令先把gif分解開:
convert glance.gif flag.png
補充:
水平鏡像反轉圖片
convert -flop reverse.jpg reversed.jpg
垂直鏡像反轉圖片
convert -flip reverse.jpg reversed.jpg
總共分離出來200個圖片。用工具:montage合成,命令:
montage flag*.png -tile x1 -geometry +0+0 flag.png
-tile是拼接時每行和每列的圖片數,這里用x1,就是只一行
-geometry是首選每個圖和邊框尺寸,我們邊框為0,圖照原始尺寸即可
flag:TWCTF{Bliss by Charles O’Rear}
(2)也可以直接用網站。GIF動態圖片是由多張靜態圖片組合而成,按照一定的順序和時間進行播放。該網站將GIF圖片反向分解成一張張靜態圖。GIF圖片有多少幀,就有多少張靜態圖片。
GIF分解網站
(3)也可以寫腳本
import os
from PIL import Image
im = Image.new('RGB', (2*201,600))#new(mode,size) size is long and width
PATH = 'E:/ctf/glance.gif'
FILE_NAME = [i for i in os.listdir(PATH)]
width = 0
for i in FILE_NAME:
im.paste(Image.open(PATH+i),(width,0,width+2,600))#box is 左,上,右,下
width += 2
im.show()
六、像素點合成
1、PPM格式+多種文件轉換網站
攻防世界 Misc Miscellaneous-200 defkthon-ctf
miscellaneous
adj. 混雜的; 各種各樣的;
(1)提供的flag.txt文件每行包含由三個逗號分隔的值組成的元組。這看起來像一個給定RGB值的圖像。
總共有61366行:
注:Linux wc命令用於計算字數。
-l或–lines 顯示行數。
-w或–words 只顯示字數。
-c或–bytes或–chars 只顯示Bytes數。
flag.txt文件的行數為61366、單詞數61366、字節數730988
圖像的尺寸是這個數字(61366)的等分,所以可能是:1,2,61,122,503,1006,30683,61366。
最可能的圖像大小是 122×503px 或 503×112px 。
注:px是分辨率的單位,是英語單詞pixel的縮寫,意為像素(組成屏幕圖像的最小獨立元素)。
將文本文件轉換為圖像的最可以將其轉換為PPM格式,其標題如下:
P3
122 503
255
注:PPM(Portable PixMap,便攜式像素映射)。這些圖片格式都相對比較容易處理,跟平台無關,所以稱之為portable,簡單理解,就是比較直接的圖片格式,比如PPM,其實就是把每一個點的RGB分別保存起來。所以,PPM格式的文件是沒有壓縮的,相對比較大,但是由於圖片格式簡單,一般作為圖片處理的中間文件(不會丟失文件信息),或者作為簡單的圖片格式保存。
PPM文件
PPM文件格式詳解
然后是flag.txt的內容,逗號用空格替換。(快捷鍵ctrl+h 實現替換的功能)
TXT到PPM轉換器
這個網站可以轉換許多東西!
結果是flag.ppm。用極速看圖軟件打開(kali中可以直接打開):
轉換為PNG,並翻轉+旋轉它,使它更容易閱讀,結果如下圖所示:
convert -flip -rotate 90 flag.ppm flag.png
(2)分析文本發現是道畫圖題,直接編寫 python 程序
from ast import literal_eval as make_tuple
from PIL import Image
f = open('flag.txt', 'r')
corl = [make_tuple(line) for line in f.readlines()]
f.close()
img0 = Image.new('RGB', (270, 270), '#ffffff')
k=0
for i in range(246):
for j in range(246):
img0.putpixel ([i , j], corl[k])
k=k+1
img0.save("result.png")
flag{ youc@n’tseeme }
七、流量類
1、wireshark提取數據流//tcpxtract
攻防世界misc進階Cephalopod
用wireshark搜索flag字符串,可以看到
PNG頭的16進制為89504E47,然后搜索該16進制,找到一條TCP報文,然后追蹤TCP流。
可以看到這是一個圖片數據流。尾為:文件尾:AE 42 60 82。保留原始數據。
然后復制進去winhex只保留png頭尾數據,然后修改文件后綴名為png,就可以得到flag圖片
tcpxtract
也可以直接
tcpxtract -f 1.pcap
得到一張png圖片 得到flag :HITB{95700d8aefdc1648b90a92f3a8460a2c}
Tcpxtract是用來從網卡抓包並將其還原成文件的一個開源軟件,它的基本原理是在抓取的數據包中匹配文件的特征頭和特征尾。
strings
strings webshell.pcapng | grep {
strings命令在對象文件或二進制文件中查找可打印的字符串。字符串是4個或更多可打印字符的任意序列,以換行符或空字符結束。 strings命令對識別隨機對象文件很有用。 grep 命令用於查找文件里符合條件的字符串
strings xxx.png
有時可以出flag
2、協議分級+導出HTTP對象
攻防世界-互相傷害!!!
wireshark打開,協議分級,基本都是TCP流量,又以超文本傳輸協議為主,導出HTTP對象。
八、二維碼類
1、bmp轉二維碼
攻防世界 Misc高手low
下來一個bmp文件,用stegsolve分析無果,但是通過觀察發現是RGB的通道有問題,利用的是圖片中最低位的奇偶性。
實驗吧原題直接用畫圖另存為png格式,用StegSolve打開后,調到RGB紅色位置。這里有所變化
轉QR Code,即二維碼(Quick Response Code)
# lsb隱寫
import PIL.Image as Image
img = Image.open('low.bmp')
img_tmp = img.copy()
pix = img_tmp.load()
width,height = img_tmp.size
for w in range(width):
for h in range(height):
if pix[w,h]&1 == 0:
pix[w,h] = 0
else:
pix[w,h] = 255
img_tmp.show()
用QR research解碼得:
2、16進制轉pyc
攻防世界 MISC 適合作為桌面(世安杯)
使用stegsolve發現在綠色的低位通道中有二維碼
使用二維碼掃描器掃描,並將16進制數字結果在winhex中打開
注:如果錯選中間這個(ANSI-ASCII),則再ASCII碼轉二進制(快捷鍵Ctrl+R)
03F3開頭,pyc文件。保存為.pyc然后反編譯,在腳本后加上flag(),運行之后即可得到flag。
或者,使用“uncompyle6 文件路徑\文件名.pyc > 文件路徑\文件名.py”命令
D:\Python385\Lib\site-packages\uncompyle6\bin
pyc隱寫Stegosaurus
Stegosaurus 是一款隱寫工具,它允許我們在 Python 字節碼文件( pyc 或 pyo )中嵌入任意 Payload 。由於編碼密度較低,因此我們嵌入 Payload 的過程既不會改變源代碼的運行行為,也不會改變源文件的文件大小。 Payload 代碼會被分散嵌入到字節碼之中,所以類似 strings 這樣的代碼工具無法查找到實際的 Payload 。 Python 的 dis 模塊會返回源文件的字節碼,然后我們就可以使用 Stegosaurus 來嵌入 Payload 了。
pyc文件存在無效空間,修改后大小不變,不影響運行,可以隱藏信息。
stegosaurus.py可以隱藏和解密pyc文件中隱藏的信息。
只能利用pyc文件中的無效空間(Python3.6后參數會占1字節,如果沒有參數用0x00填充,運行時被忽
略,修改不影響),編碼密度較低,嵌入 Payload 后不會改變源代碼的正常運行和大小,不容易被發現。
同時 Payload 會被分散嵌入到字節碼之中,類似 strings 這樣的代碼工具無法查找到實際的 Payload 。
通過github下載后(https://github.com/AngelKitty/stegosaurus)運行 python stegosaurus.py -h
可以發現有很多參數,-p 要隱藏的文本,-r 顯示最大隱藏字節,-x可以解密。
stegosaurus解密
使用 python stegosaurus.py py_py_py.pyc -x 得到如下結果 Extracted payload: Flag{HiD3_Pal0ad_1n_Python} 。
3、二進制作二維碼
攻防世界 Misc很普通的數獨
下載發現是一堆數獨圖片,把有數字的記為1,沒有數字的記為0,結果保存在txt文本中。也可以調節文件位置后用畫圖拼接,並將有數字的格塗黑。
# -*- coding:utf-8 -*-
from PIL import Image
x = 45
y = 45
im = Image.new("RGB", (x, y)) # 創建圖片
file = open('1.txt', 'r') # 打開rbg值文件
for i in range(0, x):
line = file.readline() # 獲取一行
for j in range(0, y):
if line[j] == '0':
im.putpixel((i, j), (255, 255, 255)) # rgb轉化為像素
else:
im.putpixel((i, j), (0, 0, 0)) # rgb轉化為像素
im.show()
掃描得到一串字符串,base64多次解碼得到flag:flag{y0ud1any1s1}
4、4個值轉二維碼
2019西湖論劍網絡安全技能大賽(大學生組)–奇怪的TTL字段
發現ttl.txt中的ttl只有4個值63,127,191,255,寫出他們的二進制表示后發現只有最高兩位不同(高兩位比特的數在數據傳輸中不容易受影響),拿下來,每4個TTL值湊出一個字節的二進制數來
63=00111111
127=01111111
191=10111111
255=11111111
於是考慮做如下轉換,發現寫出來的16進制數開頭是ffd8,應該是jpg,於是寫入文件中:
fp = open('ttl.txt','r')
a = fp.readlines()
p = []
for i in a:
p.append(int(i[4:]))
s = ''
for i in p:
if i == 63:
a = '00'
elif i == 127:
a = '01'
elif i == 191:
a = '10'
elif i == 255:
a = '11'
s += a
# print(s)
import binascii
flag = ''
for i in range(0,len(s),8):
flag += chr(int(s[i:i+8],2))
flag = binascii.unhexlify(flag)
wp = open('res.jpg','wb')
wp.write(flag)
wp.close()
寫完之后發現只有二維碼的一部分,應該是不止一張圖,用foremost直接分開就好了,之后用PPT拼在一塊,掃描之后得到如下信息:
key:AutomaticKey cipher:fftu{2028mb39927wn1f96o6e12z03j58002p}
是AutoKey加密,用在線網站解密得flag
autokey解密
自動密鑰密碼(Autokey Cipher)也是多表替換密碼,與維吉尼亞密碼密碼類似,但使用不同的方法生成密鑰。