基于BMP图像的信息隐藏与检测


原理简介

针对文件结构的信息隐藏方法需详细掌握文件的格式,利用文件结构块之间的关系或根据块数据和块大小之间的关系来隐藏信息。

BMP(Bitmap-File)图形文件是 Windows 采用的常见图形文件格式,要利用 BMP 位图进行信息隐藏首先需要详细了解 BMP 文件的格式,BMP 图像文件结构比较单一而且固定,BMP 图像由文件头、信息头、调色板区和数据区四个部分组成,而 24 位真彩色图像中没有调色板信息。24 位真彩色 BMP 位图文件包括 3 部分。 第一部分是 BMP 文件头(14个字节)。前 2 个字节是“BM”,是用于识别 BMP文件的标志;第 3、4、5、6 字节存放的是位图文件的大小,以字节为单位;第7、8、9、10 字节是保留的,必须为 0;第 11、12、13、14 字节给出位图阵列相对于文件头的偏移,在 24 位真彩色图像中,这个值固定为 54;第二部分是位图信息头(40个字节)。第19,20,21,22字节表示的是图像文件的宽度,以像素为单位;第23,24,25,26 字节表示的是图像文件的高度,以像素为单位。从第 29个字节开始,第 29、30 字节描述的是像素的位数, 24 位真彩色位图。该位的值为 0x18; 第三部分是数据区。从第 55 个字节开始,每 3 个字节表示一个像素,这 3 个字节依次表示该像素的红、绿、蓝亮度分量值。

在不影响图像正常显示情况下,可使用以下四种方法在 24 位真彩色 BMP 图像中隐藏信息。

  • 在图像文件尾部添加任意长度的数据,秘密信息存放在文件尾部可以减少修改文件头的数据量,仅需修改文件头中文件长度的值即可。
  • 在调色板或者位图信息头和实际的图像数据之间隐藏数据,如果将秘密数据放在文件头与图像数据之间,则至少需要修改文件头中文件长度、数据起始偏移地址这两个域的值。
  • 修改文件头和信息头中的保留字段隐藏信息。
  • 在图像像素区利用图像宽度字节必须是 4 的倍数的特点,在补足位处隐藏数据。

操作环境

Windows 10 操作系统

MATLAB 2019a 版本软件

BMP 格式图片文件

010 编辑工具

技术过程

在实际的图像数据后隐藏信息

待隐藏的秘密信息文件名称为 hidden.txt, Qftm.bmp 为载体图像,将载体和秘密信息放置在同一个目录下,在 Windows 的 MS-DOS 方式下执行命令 Copy Qftm.bmp /b + hidden.txt /a QftmModify1.bmp ,其中参数/b 指定以二进制格式复制、合并文件,参数/a 以 ASCII 格式复制、合并文件。执行该命令后,生成一个新的 QftmModify1.bmp 文件,使用图像浏览工具浏览该文件发现与原始载体图像几乎完全相同,信息隐藏在 QftmModify1.bmp 文件的尾部。

从 BMP 图像的结构中可知,图像的 3、4、5、6 四个字节存放整个 BMP 图像的长度。使用该方法隐藏信息时,未修改图像文件的文件长度字节,通过比较文件的实际长度和文件中保存的文件长度,就可发现该图像是否隐藏秘密信息。

(1)制作隐藏信息的图片QftmModify1.bmp

创建Hidden.txt文件

img

制作QftmModify1.bmp

copy  Qftm.bmp/b + hidden.txt/a QftmModify1.bmp

img

十六进制查看QftmModify1.bmp:

(2)Matlab脚本检测文件是否存在隐藏信息

检测图片QftmModify1.bmp文件长度

clc;
clear;
fid=fopen('QftmModify1.bmp','r'); %读入载体图像文件
[a,length]=fread(fid,inf,'uint8');%length 是文件的实际长度
fclose(fid);
fid=fopen('QftmModify1.bmp','r');
status=fseek(fid,2,'bof');
fileb=fread(fid,4,'uint8');
filelength=fileb(1)*1+fileb(2)*256+fileb(3)*256^2+fileb(4)*256^3 %文件图像中保存的文件长度
diff=length-filelength;
%diff 表示隐藏的信息长度如果相同,表示图像没有隐藏任何信息。
fclose(fid);

运行脚本查看diff结果

img

从结果可以看出来当没有对bmp的文件头文件长度进行修改时,隐藏的图片diff差值不等于0,得到图片存在信息隐藏。

文件头与图像数据之间隐藏信息

在数据区开始之前隐藏信息,隐藏的秘密信息从 hidden.txt 文件中读取(隐藏整个文件的数据),此种方法修改图像数据的偏移量和图像数据的文件长度。

(1)Matlab脚本进行隐藏信息

clc;
clear;
wm=randsrc(1,300, [0 1]); %  产生随机水印
fid=fopen('Qftm.bmp','r'); %读入载体图像文件
[a,length]=fread(fid,inf,'uint8');
fclose(fid);
msgfid=fopen('hidden.txt','r');%打开秘密文件
[msg,count]=fread(msgfid);
fclose(msgfid);
wa=a;
j=1;
wa(11)=54+count;
wa(3)=wa(3)+count;
for i=55:54+count
    wa(i)=uint8(msg(j,1));%隐藏密码信息
    j=j+1;
end
for i=55:length
    wa(i+count)=a(i);
end
figure;
wa=uint8(wa);
fid=fopen('watermarked.bmp', 'wb');
fwrite(fid,wa);
fclose(fid);
I=imread('Qftm.bmp');
J=imread('watermarked.bmp');
subplot(1,2,1)
imshow(I)
title('未修改图像');
subplot(1,2,2)
imshow(J)
title('修改后图像')

运行结果查看嵌入前、嵌入后的感官效果

img

分析《watermarked.bmp》16进制清晰查看隐藏效果

img

BMP 图像文件隐藏信息的检测

在BMP图像中隐藏信息的时候一般都是通过修改文件的偏移量和图像文件中图像的长度来隐藏信息,但在BMP图像文件中,file_length=biwidthbiBytecountbiHeight+bfoffBits,其中 biwidth,biheight表示

图像文件的宽度和高度,bfoffBits表示文件头到实际位图图像数据之间的偏移量。

(1)Matlab脚本对Bmp进行信息隐藏多层Check

clc;
clear;
wm=randsrc(1,300, [0 1]); %  产生随机水印信息
fid=fopen('watermarked.bmp','r'); %读入载体图像文件
[a,length]=fread(fid,inf,'uint8');
status=fseek(fid,2,'bof');
fileb=fread(fid,4,'uint8');
filelength=fileb(1)*1+fileb(2)*256+fileb(3)*256^2+fileb(4)*256^3 %文件图像的理论长度
status=fseek(fid,10,'bof');
b=fread(fid,4,'uint8');
bfoffbitsmodify=b(1)*1+b(2)*256+b(3)*256^2+b(4)*256^3 %读取偏移量
status=fseek(fid,18,'bof');
b=fread(fid,4,'uint8');
biwidth=b(1)*1+b(2)*256+b(3)*256^2+b(4)*256^3
status=fseek(fid,22,'bof');
b=fread(fid,4,'uint8');
biHeight=b(1)*1+b(2)*256+b(3)*256^2+b(4)*256^3;
bfoffbits=54;%偏移量
biBytecount=3;%24 位真彩色图像为 3
filetruelength=biwidth*biBytecount*biHeight+bfoffbits %图片实际真实长度(固定偏移54)
filelengthbfoffbits=biwidth*biBytecount*biHeight+bfoffbitsmodify %读取偏移计算文件长度
fclose(fid);
diff1=length-filelength;        %未修改图片长度时Check1
diff2=filelength-filetruelength %修改了图片长度时Check2
diff3=filelengthbfoffbits-filetruelength %修改了图片偏移时Check3
diff=diff1+diff2+diff3

对watermarked.bmp(文件长度和文件偏移都被修改了)进行测试,根据diff的值进行判定该图片是否存在信息隐藏,运行结果查看:

img

从结果diff != 0可以看出来该图片存在信息隐藏。

在图像文件头和信息头的保留字段中隐藏信息

BMP 图像文件中有很多从不使用的保留字节,如 7、8、9、10 字节是保留的,必须为 0,可在第 7、8、9、10 字节隐藏秘密信息。

(1)Matlab脚本对Bmp的保留字段隐藏信息

clc;
clear;
fid=fopen('Qftm.bmp','r'); %读入载体图像文件
[a,length]=fread(fid,inf,'uint8');
fclose(fid);
wa=a;
% 在BMP的7、8、9、10保留字中隐藏秘密信息Qftm,ASCII值为0x51 0x66 0x74 0x6d
wa(7)=81;
wa(8)=102;
wa(9)=116;
wa(10)=109;
figure;
wa=uint8(wa);
fid=fopen('watermarkedReserve.bmp', 'wb');
fwrite(fid,wa);
fclose(fid);
I=imread('Qftm.bmp');
J=imread('watermarkedReserve.bmp');
subplot(1,2,1)
imshow(I)
title('未修改图像');
subplot(1,2,2)
imshow(J)
title('修改后图像')

运行结果查看嵌入前、嵌入后的感官效果

img

分析《watermarkedReserve.bmp》16进制清晰查看隐藏效果

img

利用LSB进行信息隐藏

准备隐藏的数据文件(message.txt)和载体图像(Qftm.bmp)

(1)Matlab脚本对Bmp图像进行LSB隐藏信息

Bmp_LSB_embed.m

P=imread('Qftm.bmp');
A=P(:,:,1);
P_g=P(:,:,2);
P_b=P(:,:,3);
[m,n]=size(A); 
a=A(:);


allpath = 'message.txt';
fid = fopen(allpath);
data = textscan(fid,'%s');   
d=vertcat(data{:});  
q=cell2mat(d);        %cell转化为数组
p=dec2bin(q,8);       %10进制转8位2进制
pp=p';                %转置
msg=pp(:);            %变成一维的
fclose(fid);
msg_len=length(msg);

water=a;
lsb=A;
for i=1:length(a)
    water(i)=bitset(water(i),1,0);
end

start=randi(floor(length(a)/(msg_len+1)),1,1)
water(start)=1;
for i=1:msg_len
    water((i+1)*start)=bitset(water((i+1)*start),1,str2double(msg(i)));
end


for i=1:m
    for j=1:n
        lsb(j,i)=water((i-1)*n+j);
    end
end


W=cat(3,lsb,P_g,P_b);
figure;
subplot(1,2,1);imshow(P);title('normal');
subplot(1,2,2);imshow(W);title('serect');
imwrite(W,'Qftm_lsb.bmp','bmp');

Runing:

运行结果查看嵌入前(Qftm.bmp)、嵌入后(Qftm_lsb.bmp)的感官效果

可以看到,人眼看起来没有多大区别

Qftm.bmp与Qftm_lsb.bmp的十六进制对比

(2)Matlab脚本对嵌入后(Qftm_lsb.bmp)的图像进行LSB隐藏信息提取

Bmp_LSB_extract.m

W=imread('Qftm_lsb.bmp');
B=W(:,:,1);

for i=1:m*n
   re2(i)=bitget(B(i),1);
end
for i=1:m*n
    if re2(i)==1
         start2=i
         break;
    end
end

for i=1:m*n/start2-1
     se(i)=re2(start2*(i+1));
end

fid=fopen('serect.txt','wt');
for i=1:length(se)/8
    b=num2str(se(1+(i-1)*8:8+(i-1)*8));
    c=bin2dec(b);
    d=char(c);
   fprintf(fid,'%s',d);
end
fclose(fid);

Runing:

提取得到隐藏的信息数据


Author: Qftm
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Qftm !
 Previous
初识PE文件结构 初识PE文件结构
前言目前网络上有关PE文件结构说明的文章太多了,自己的这篇文章只是单纯的记录自己对PE文件结构的学习、理解和总结。 基础概念PE(Portable Executable:可移植的执行体)是Win32环境自身所带的可执行文件格式。它的一些特性
2019-09-30
Next 
MATLAB之图像与音频信号处理 MATLAB之图像与音频信号处理
原理简介离散傅立叶、离散余弦和离散小波变换是图像、音频信号常用基础操作,时域信号转换到不同变换域以后,会导致不同程度的能量集中,信息隐藏利用这个原理在变换域选择适当位置系数进行修改,嵌入信息,并确保图像、音频信号经处理后感官质量无明显变化。
2019-09-14
  TOC