0×00 前言最近有一部劇人氣非常高,,據(jù)說是將軍官和醫(yī)生的浪漫故事,。咦,?!,!這不是好幾年前的老片子了么,。 后來有人告訴我,是一部韓劇,,里面的歐巴超帥妹子超靚,。~\(≧▽≦)/~ 說起韓劇,很多真是在用心做劇,,拋開里面的細節(jié),,光憑人氣來說, 不得不佩服其文化輸出軟實力,。小伙伴們還記得2012年出品的黑客劇《幽靈》嗎,?該劇以網(wǎng)絡犯罪和網(wǎng)絡刑警為題材,講述了虛擬搜查隊在揭開一個個不為人知的隱藏在網(wǎng)絡世界尖端技術中的秘密時,,所經(jīng)歷的各種駭人聽聞事件和奇遇,。劇中出現(xiàn)了Encase、wireshark,、od,、process、nmap,、DDOS,、winhex、bt5等等多款大家熟悉的工具,,不得不佩服其做劇的專業(yè)程度,。 今天我們就來看看其第二集,男主角在所謂的“證據(jù)”面前,,堅稱自己是清白的,,說“證據(jù)”視頻其實是使用了隱寫技術,里面隱藏著重要秘密,,為了證明自己,,便在警察面前當場進行了隱寫信息的提取。 根據(jù)視頻,,我們可以判斷出,,男主角使用的是openstego隱寫軟件,但是視頻中的情節(jié)確實有些瑕疵,,有穿幫的成分,。 這是男主角在挑選隱藏有信息的載體視頻文件,大家可以看到里面全都是avi格式的視頻。
這是選中后的畫面,,明顯可以看到載體文件實際上是png圖像文件,。
下面是提取出的秘密文件,該文件記錄了被害人遇害的一些重要信息,。
劇中講述的是,,男主角從一段視頻中提取出了另外一段視頻。而根據(jù)上面的細節(jié)判斷,,顯然不是這樣,,而是從一個png文件中提取了視頻文件,。 這是該軟件在選取載體文件時的顯示,,可以看出只支持圖像文件作為載體進行隱寫,難怪劇組為了劇情的完整性,,不惜使用改后綴名的方式來走捷徑,。其實劇組可以專門去找支持視頻隱寫的軟件來進行這段劇情,估計是不太好找,。o(︶︿︶) 既然都講到這了,,那我們不妨一起來看看劇中所使用的隱寫術到底是神馬鬼。 隱寫術是信息隱藏( Information Hiding )的一個重要分支,,而 信息隱藏 是為了 不讓除預期接收者之外的任何人知曉信息的傳遞事件或者信息內(nèi)容 ,, 可見信息隱藏與信息加密的不同處在于前者很好地隱蔽了傳遞事件。 隱寫術英文名為 Steganography ,,來源于特里特米烏斯的一本講述 密碼學 與隱寫術的著作 Steganographia ,,該書書名源于希臘 詞匯 stegons 和 graphia ,意為 “ 隱秘書寫 ” ,。 0×01 數(shù)字圖像隱寫原理 圖像隱寫,,顧名思義就是將目標信息隱藏在載體圖片中,而這里的目標信息包含任何格式的數(shù)字文件(圖像,、文本,、視頻、聲音等),??赡苡型瑢W會說,這個我也會,, copy /b 分分鐘搞定隱寫,。是這樣嗎??。,。∥覀兿葋砜纯?/font> copy /b 是何方神術,。 C opy /b 命令 命令格式: copy/b file1+file2+ …… +fileN 合并后的輸出文件名 命令講解:使用“ + ”將多個相同或不同格式的二進制文件合并為一個文件 例: copy/b 1.mpg+2.mpg 3.mpg ,,即把視頻 1.mpg 和 2.mpg 合并為 3.mpg 使用 copy/b image.jpg+text.txt new.jpg 命令將文本 text.txt 附加到圖片 image.jpg 中
可以從源文件和生成文件的文件信息中觀察到,,源文件的文件大小相加正好等于生成文件的大小。 同時打開原圖片和生成的新圖片,,視覺上并沒有任何差別,。 使用 UE 對比兩圖片的二進制差異,發(fā)現(xiàn)新生成的圖片末尾追加了 text.txt 文本內(nèi)容,。 疑問:為什么新生成的圖片末尾添加了新的數(shù)據(jù),,卻用圖片查看器查看時并沒有看到圖片新增了其他內(nèi)容? 釋疑: jpg 格式圖片中,,文件頭中包含有圖片 X 軸,、 Y 軸的像素數(shù)目,所以圖像查看器只根據(jù)像素信息進行圖像的解析顯示,,而不會將末尾追加的二進制信息進行顯示(即使將追加的信息也顯示出來,,也不會是文本內(nèi)容,而是一堆雜亂的像素噪點),。 由此可見,, copy /b 命令只是將幾個文件進行了簡單的追加合并,以達到隱蔽傳送信息的目的,,但是這種方法通過對比圖像大小和文件大小,,很容易檢測到圖像后面是否追加數(shù)據(jù),所以 copy/b 只能算作一種簡單的圖像隱寫技術,。 而通常的圖像隱寫為了躲避檢測,,會利用載體的冗余度,在不破壞圖像畫質(zhì)信息的基礎上,,嵌入被隱寫信息,,達到隱寫目的。所以,,如何利用圖像文件的冗余來進行信息的隱藏,,是隱寫技術的關鍵所在。 0×02 bmp圖像文件格式常見的圖像文件格式有 BMP ,、 JPG ,、 JPEG 、 PNG ,、 GIF ,。由于 BMP 采用位映射存儲格式,除了圖像深度可選以外,,不采用其他任何壓縮,,占用的空間很大,所以存在著較多的冗余空間利用,并且在 bmp 格式圖片中進行隱寫較為容易,。這里我們選用 BMP 格式的圖片來做接下來的講解,。首先我們先了解 bmp 圖像文件的格式。 BMP 圖形文件,,又叫 Bitmap (位圖)或是 DIB(Device-Independent Device ,,設備無關位圖 ) ,是 Windows 采用的圖形文件格式,,在 Windows 環(huán)境下運行的所有圖象處理軟件都支持 BMP 圖象文件格式,,并且 Windows 系統(tǒng)內(nèi)部各圖像繪制操作都是以 BMP 為基礎。 BMP 文件頭: BITMAPFILEHEADER typedef struct tagBITMAPFILEHEADER { // bmfh WORD bfType; // 文件類型,,該值必需是 0x4D42 ,,也就是字符 'BM' DWORD bfSize; // 說明該位圖文件的大小,用字節(jié)為單位 WORD bfReserved1; // 保留,,必須設置為 0 WORD bfReserved2; // 保留,,必須設置為 0 DWORD bfOffBits; // 文件頭開始到實際的圖象數(shù)據(jù)之間的字節(jié)的偏移量 } BITMAPFILEH EADER; 注釋:位圖信息頭和調(diào)色板的長度會根據(jù)不同情況而變化,,所以可以根據(jù) bfOffBits 這個偏移值迅速的從文件中讀取到位數(shù)據(jù),。 以上圖作為測試圖,查看其文件頭的對應信息
位圖信息段:BITMAPINFOHEADER typedef struct tagBITMAPINFOHEADER{ DWORD biSize; //該結構所需要的字節(jié)數(shù) LONG biWidth; //圖象寬度,,以像素為單位 LONG biHeight; //圖象的高度,,以像素為單位 WORD biPlanes; // 表示 bmp 圖片的平面屬,恒等于 1 WORD biBitCount // 說明比特數(shù) / 象素,,其值為 1 ,、 4 、 8 ,、 16 ,、 24 、或 32 DWORD biCompression; //圖象數(shù)據(jù)壓縮的類型 DWORD biSizeImage; //圖象的大小,,以字節(jié)為單位 LONG biXPelsPerMeter; // 水平分辨率,,用象素 / 米表示 LONG biYPelsPerMeter; // 垂直分辨率,用象素 / 米表示 DWORD biClrUsed; // 位圖實際使用的彩色表中的顏色索引數(shù)(設為 0 的話,,則說明使用所有調(diào)色板項) DWORD biClrImportant; // 對圖象顯示有重要影響的顏色索引的數(shù)目,,如果是 0 ,表示都重要 } BITMAPINFOHEADER;
調(diào)色板 根據(jù)圖像尺寸和信息頭大小,我們可以得知這幅圖是不含調(diào)色板信息的,。這是為什么呢,? 首先需要了解一下圖像文件中顏色的表示方法,我們知道自然界中的所有顏色都由紅、綠,、藍( R ,, G , B )組合而成,,下表位常見的 RGB 組合,。 給一幅圖中每個象素賦予不同的 RGB 值,就形成了彩色圖,。但是,,如果有一個長寬各為 200 個象素,顏色數(shù)為 16 色的彩色圖,,每一個象素都用 R ,、 G 、 B 三個分量表示,。每個象素需要用 3 個字節(jié),,整個圖象要用 200 × 200 × 3 ,約 120k 字節(jié),!這也太浪費了,! 這幅圖中最多只有 16 種顏色,而我們卻為每一個像素付出了 3 個字節(jié)的空間,。為了壓縮,,我們可以用一個表來記錄這 16 種顏色,表中的每一行記錄一種顏色的 R ,、 G ,、 B 值。這樣表示一個象素的顏色時,,只需要指出該顏色是在第幾行,,即該顏色在表中的索引值。例如,,如果表的第 5 行為 255 ,, 0 , 0 (紅色),,那么當某個象素為紅色時,,只需要標明 5 即可。 這樣可以節(jié)省多少空間呢,? 16 種狀態(tài)可以用 4 位( bit )表示,,所以一個象素要用半個字節(jié)。整個圖象要用 200 × 200 × 0.5 ,,約 20k 字節(jié),,再加上表占用的字節(jié)為 3 × 16=48 字節(jié),,整個占用的字節(jié)數(shù)約為前面的 1/6 ,可見這個壓縮效果非常明顯,。 調(diào)色板( Palette )的作用便是上面的顏色查找表,。調(diào)色板在 windows 里的結構定義如下: typedef struct tagPALETTEENTRY { // pe BYTE peRed; BYTE peGreen; BYTE peBlue; BYTE peFlags; } PALETTEENTRY; 該結構除了 R 、 G ,、 B 三個元素外,,還有一個顏色深度信息。 既然調(diào)色板可以壓縮存儲空間,,為什么這張 BMP 不帶調(diào)色板呢,? 這張 BMP 是 24 位真彩色的 BMP ,所謂真彩色圖( true color ),,就是它的顏色數(shù)高達 256 × 256 × 256 種,,也就是說包含我們上述提到的 R 、 G ,、 B 顏色表示方法中所有的顏色,。真彩色圖并不是說一幅圖包含了所有的顏色,而是說它具有顯示所有顏色的能力,,即最多可以包含所有的顏色,。如果用調(diào)色板,則調(diào)色板的長度高達 24 位,,即索引需要 24 位來表示,,則一個象素也要用 24 位,,和直接用 R ,, G , B 三個分量表示用的字節(jié)數(shù)一樣,。這樣即沒有起到壓縮的作用,,反而因為有一個龐大的調(diào)色板的存在而體積增大。所以真彩色圖直接用 R ,、 G ,、 B 三個分量表示,又叫做 24 位色圖,。 數(shù)據(jù)區(qū)域 B mp文件最后的區(qū)域則是數(shù)據(jù)區(qū)域,,存儲著圖像像素信息,從前面信息段里得知該圖為24位圖,,所以每一個像素都以3字節(jié)的RGB形式進行存儲,。
現(xiàn)在我們大體了解了 BMP 圖片的基本結構,那么要把隱寫的數(shù)據(jù)藏在哪里呢,?顯然,,藏在文件頭或者信息頭里是不現(xiàn)實的,,因為這些區(qū)域中的每一個字段都對應著明確的值,改變這些值會徹底破壞原有的結構而導致圖片損壞,,雖然文件頭中有保留字段,,但是這些字段容量有限不適合用于隱寫??磥碇皇O聢D像數(shù)據(jù)段適合用于隱寫了,,如何利用像素的 RGB 來進行隱寫呢? 0×03 像素視覺差異bmp圖像中一個像素點使用 3 個字節(jié)(即 RGB 結構)來記錄色彩,,而隱寫是把信息拆解后分別藏入像素點中,,并且不會產(chǎn)生視覺上的變化。首先來看一下像素色彩在發(fā)生不同變化時的色彩差異,。 可見 RGB 最低位的變化不會產(chǎn)生視覺上的差異,。 上圖可以看出隨著改變位數(shù)的增加,像素點的顏色開始發(fā)生變化,,當?shù)?位均變化后,,與原像素點相比發(fā)生了較為明顯的顏色改變。我們可以利用圖像的這一特性,,將信息分拆為若干比特位,,將其逐一放入圖像的像素點的低位,這便是著名的LSB(Least Significant Bit)隱寫,。 0×04 LSB隱寫實戰(zhàn)我們采用 LSB 方式進行隱寫,,下圖為需要隱寫的文本信息。 將文件按比特分拆后,,逐一寫入載體圖片的像素信息中,。問題來了,解密的時候怎么知道需要解密的信息有多長,??。∷栽陔[寫數(shù)據(jù)前需要把隱寫的信息長度寫入,。 關鍵代碼 count = struct.unpack('<L', all_the_bmp[10:14])[0]# 獲取 bmp 像素數(shù)據(jù)偏移值 bmplength=len(all_the_bmp) - count;# 獲取 bmp 像素數(shù)據(jù)大小 txtlength=len(all_the_text)#獲取文本數(shù)據(jù)大小 bit=1;# 按照 bit 個比特位進行數(shù)據(jù)拆分 if(bmplength< txtlength*int(8/bit) ):# 判斷 bmp 空間是否足夠隱寫 print('too small') sys.exit() result=[] pos=0 for i in range(4):#將文本數(shù)據(jù)大小進行隱寫 bchar = (txtlength>>(i*8)) & 0xff for j in range(int(8/bit)): temp = (bchar>>j*bit) & (pow(2,bit)-1) result.append(((all_the_bmp[count+pos]>>bit)<<bit) | temp) pos=pos+1 for bchar in all_the_text:#將文本數(shù)據(jù)進行隱寫 for i in range(int(8/bit)): temp = (bchar>>i*bit) & (pow(2,bit)-1) result.append(((all_the_bmp[count+pos]>>bit)<<bit) | temp) pos=pos+1 圖片一個字節(jié)隱寫 1 比特數(shù)據(jù),,效果如下圖所示。 兩張圖的具體對比信息,。 可以從兩圖的字節(jié)差異數(shù)中看到,,并不等于隱寫信息字節(jié)數(shù) *8 。這是因為原數(shù)據(jù)的最低位恰好與隱寫的比特值相等,,從而使原數(shù)據(jù)并未發(fā)生變化,。 現(xiàn)在我們將代碼中控制拆分尺寸 bit=1 修改為 bit=2 ,即圖像數(shù)據(jù)字節(jié)的低 2 比特位用于隱寫,,效果如下,。 可見低 2 比特的改變并不會引起視覺上的差異,,但卻使得隱寫空間增加了 2 倍。 設置 bit=4 ,,即使用低 4 比特位用于隱寫,,效果如下。 可見隱寫后的圖片像素已經(jīng)發(fā)生了明顯變化,。 再瘋狂一點,,我們將 bit 設置為 8 ,即把像素字節(jié)全部用于隱寫,,其實這已經(jīng)相當于覆蓋數(shù)據(jù),,結果則如下圖慘不忍睹。 圖中對應位置的原始像素值完全被破壞,,完全成了文本文件的數(shù)據(jù),。由此可見,使用 LSB 技術隱寫時,,最佳選擇最低位的 1-2bit 進行隱寫,。 下面是還原隱寫信息的關鍵代碼 bit=1#比特拆分尺寸 for i in range(4): #讀取信息長度 bchar = 0 for j in range(int(8/bit)): bchar=((all_the_image[count+pos]&(pow(2,bit)-1))<<j*bit) | bchar pos=pos+1 lencontext = lencontext | (bchar << i*8) result=[] for i in range(lencontext):#讀取隱寫數(shù)據(jù) bchar = 0 for j in range(int(8/bit)): bchar=((all_the_image[count+pos]&(pow(2,bit)-1))<<j*bit) | bchar pos=pos+1 result.append(bchar) 還原后的文本信息對比。
0×05 隱寫升級由于上面采用順序隱寫的方法,,所以導致信息集中在圖片的某一部分(下圖中的差異對比圖下方出現(xiàn)較寬區(qū)域的噪點),。 為了消除信息過于集中而導致圖片某一區(qū)域像素信噪比過高,可以采用隨機分配隱寫位置的方式,,將信息分散隱寫在圖片當中,。這里需要注意的是,為了提取隱寫信息的方便,,我們并不會真正采用隨機的方式進行隱寫,,否則需要將隨機序列也一同記錄在圖片中。為了方便起見,,我們采用將密碼作為隨機數(shù)生成器的種子,,來生成一組偽隨機數(shù)。 隨機序列生成函數(shù) def buildRandlist(key,length,size):#key 種子,, length 圖片長度, size 隱寫信息的 bit 數(shù) if size > length: print('too small') sys.exit() random.seed(key) rlist=[] pos=0 num=0 while num < size: maxvalue = int((length-pos)/(size - num)) minvalue = int(maxvalue/2) if(maxvalue > 30): minvalue=maxvalue-10 interval = random.randint(minvalue,maxvalue) rlist.append(interval) pos = pos + interval num = num + 1 if pos > length: print('too small') sys.exit() return rlist 可以看出生成隨機數(shù)列有三個輸入?yún)?shù),,其中圖片長度可以根據(jù)圖片文件的信息頭進行獲取,,而其他兩個參數(shù)可以作為密鑰由用戶保存,在信息提取時,,必須在知道 key 和 size 的情況下才可以正確地提取完整信息,。 下圖為采用隨機 LSB 隱寫后的差異結果。 0×06 隱寫與加密隱寫技術的基本原理和步驟了解后,,我們會發(fā)現(xiàn),,如果對像素數(shù)據(jù)進行逐比特位提取,,則很容易還原出原始數(shù)據(jù),所以在實際應用中,,隱寫技術都配合加密技術一同使用,,在隱寫前,信息先進行加密處理,,然后將加密后的密文進行隱寫,。這樣便很好地保護了信息的安全性,即使信息被提取,,也只是密文被暴露,。 0×07 一些思考圖像的像素點在改變較低位比特數(shù)值時,并不會引起視覺的變化,,那么視頻,、音頻等一樣可以作為隱寫載體進行信息的隱寫??梢娔茏鳛檩d體的素材很多,,在互聯(lián)網(wǎng)上也是海量的,如果一些有害信息通過這種技術來傳播,,則危害極大,。 如何對含有隱寫信息的載體進行快速檢測便顯得非常重要,圖像各區(qū)域之間的像素值是有關聯(lián)性的,,而隱寫的數(shù)據(jù)則打破了像素之間的關聯(lián)性和圖像的平滑性,,而一些針對隱寫技術的檢測技術正是根據(jù)這一特性來進行的,感興趣的同學可以查閱相關領域的研究資料,,網(wǎng)上有很多相關素材,。 |
|