图片隐写

2023-07-30 17:22:43 浏览数 (2)

常规图片隐写:

1.使用Stegsolve查看不同的图层,最低有效位隐藏的数据,图片异或等。

2.使用16进制编辑器查看隐藏的数据和文件,发现文件格式,文件修复。

特殊的图片隐写:

1.图像隐写 将消息编码为图像像素的颜色值,可使用在线工具直接解码。 pixeljihad:在线图片解析工具,能直接将像素值解码为消息 站点:https://sekao.net/pixeljihad/

2.图片嵌入隐藏-大容量的信息隐藏算法 对每个像素点进行判断,根据HVS的特性,在最高非0有效位后的指定位(y)开始嵌入隐藏信息,嵌入到另一个指定位(z)为止。 参考帖子:https://blog.csdn.net/A657997301/article/details/82747506

合并图像

代码语言:javascript复制
% 各通道肉眼可接受位差
yr = 4;
yg = 5;
yb = 3;

% 读取原图
Img = imread('原图.png');
figure;imshow(Img,[]);title('原图');

% 读取待隐藏的图
Imgmark = imread('待隐藏的图.png');
figure;imshow(Imgmark,[]);title('待隐藏的图');
% 转为灰度图
Imgmark = rgb2gray(Imgmark);
Imgmark = double(Imgmark);
[markm, markn] = size(Imgmark);
% 将灰度图的二维数组转成一列
Imgmarkline = Imgmark(:);

% 这一列再转化为更长的一列,二进制八位表示
Imgmarklinebin = zeros(markm*markn*8,1);
for ii = 1 : markm*markn
    [Imgmarklinebin(8*ii-7), Imgmarklinebin(8*ii-6), Imgmarklinebin(8*ii-5), Imgmarklinebin(8*ii-4), Imgmarklinebin(8*ii-3),...
        Imgmarklinebin(8*ii-2), Imgmarklinebin(8*ii-1), Imgmarklinebin(8*ii)] = Find8bits(Imgmarkline(ii));   
end

%%
% 获得RGB各通道分量图
Img = double(Img);
ImgR = Img(:,:,1);
ImgG = Img(:,:,2);
ImgB = Img(:,:,3);
% 嵌入
% 对于红色通道
embedNumsed = 0; % 已嵌入个数
[M, N, Z] = size(Img);
y = zeros(8, 1);
flag = 0; % 辅助跳出的标志

ImgRline = ImgR(:); % 转换为一列
ImgRlineNew = ImgRline; % 嵌入后
for ii = 1 : M*N
    if flag == 1; % 跳出外层循环
       break;
    end
    
    [y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1)] = Find8bits(ImgRline(ii));   
    posNzreo = FindNotZero(y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1));
    embedNums = posNzreo - yr; % 能嵌入的个数
    if  embedNums > 0 %符合嵌入条件
        for jj = 1 : embedNums
            embedNumsed = embedNumsed   1; % 已嵌入个数
            if embedNumsed > markm*markn*8 % 嵌入完成
               flag = 1; % 设置标识,使外层循环也跳出
               break;
            end
            
            y(jj) = Imgmarklinebin(embedNumsed);% 嵌入
        end
    end
    ImgRlineNew(ii) = bin2dec_trans(y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1));% 嵌入后的  
end
ImgR2 = reshape(ImgRlineNew, [M, N]);


% 对于G通道
ImgGline = ImgG(:); % 转换为一列
ImgGlineNew = ImgGline; % 嵌入后
for ii = 1 : M*N
    if flag == 1; % 跳出外层循环
       break;
    end
    
    [y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1)] = Find8bits(ImgGline(ii));   
    posNzreo = FindNotZero(y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1));
    embedNums = posNzreo-yg; % 能嵌入的个数
    if  embedNums > 0 % 符合嵌入条件
        for jj = 1 : embedNums
            embedNumsed = embedNumsed   1; % 已嵌入个数
            if embedNumsed > markm*markn*8 % 嵌入完成
               flag = 1; % 设置标识,使外层循环也跳出
               break;
            end
            
            y(jj) = Imgmarklinebin(embedNumsed); % 嵌入 
        end
    end
    ImgGlineNew(ii) = bin2dec_trans(y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1)); % 嵌入后的  
end
ImgG2 = reshape(ImgGlineNew, [M, N]);

% 对于B通道
ImgBline = ImgB(:); % 转换为一列
ImgBlineNew = ImgBline; % 嵌入后
for ii = 1 : M*N
    if flag == 1; % 跳出外层循环
       break;
    end
    
    [y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1)] = Find8bits(ImgBline(ii));   
    posNzreo = FindNotZero(y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1));
    embedNums = posNzreo - yb; % 能嵌入的个数
    if  embedNums > 0 % 符合嵌入条件
        for jj = 1 : embedNums
            embedNumsed = embedNumsed   1; % 已嵌入个数
            if embedNumsed > markm*markn*8 % 嵌入完成
               flag = 1; % 设置标识,使外层循环也跳出
               break;
            end
            
            y(jj) = Imgmarklinebin(embedNumsed); % 嵌入 
        end
    end
    ImgBlineNew(ii) = bin2dec_trans(y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1)); % 嵌入后的  
end
ImgB2 = reshape(ImgBlineNew, [M, N]);

ImgNew = zeros(M, N, Z);
ImgNew(:,:,1) = ImgR2;
ImgNew(:,:,2) = ImgG2;
ImgNew(:,:,3) = ImgB2;

figure;imshow(uint8(ImgNew),[]);title('合并后的RGB图');
imwrite(uint8(ImgNew), '合并后的RGB图.png'); % 保存图片

分离图像

代码语言:javascript复制
% 各通道肉眼可接受位差
yr = 4;
yg = 5;
yb = 3;

% 读取合并后的RGB图
Img = imread('合并后的RGB图.png');
[M, N, Z] = size(Img);
Img = double(Img);
ImgR2 = Img(:,:,1);
ImgG2 = Img(:,:,2);
ImgB2 = Img(:,:,3);

% 提取嵌入图像
flag = 0;
Imgmark_extractlinebin = zeros(M*N*8, 1);
extractNumsed = 0; % 已提取个数

% R通道
ImgRline2 = ImgR2(:); % 转换为一列
for ii = 1 : M*N
    if flag == 1; % 跳出外层循环
       break;
    end
    
    [y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1)] = Find8bits(ImgRline2(ii));   
    posNzreo = FindNotZero(y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1));
    embedNums = posNzreo - yr; % 已嵌入的个数
    if  embedNums > 0 % 符合嵌入条件
        for jj = 1 : embedNums
            
            extractNumsed = extractNumsed   1; % 已提取个数
            if extractNumsed > M*N*8 % 提取完成
               flag = 1; % 设置标识,使外层循环也跳出
               break;
            end 
            
           Imgmark_extractlinebin(extractNumsed) = y(jj); % 提取
        end  
    end  
end

% G通道
ImgGline2 = ImgG2(:); % 转换为一列
for ii = 1 : M*N
    if flag == 1; % 跳出外层循环
       break;
    end
    
    [y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1)] = Find8bits(ImgGline2(ii));   
    posNzreo = FindNotZero(y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1));
    embedNums = posNzreo - yg; % 已嵌入的个数
    if embedNums > 0 % 符合嵌入条件
        for jj = 1:embedNums
            
            extractNumsed = extractNumsed   1; % 已提取个数
            if extractNumsed > M*N*8 % 提取完成
               flag = 1; % 设置标识,使外层循环也跳出
               break;
            end
            
           Imgmark_extractlinebin(extractNumsed) = y(jj);% 提取
        end
    end
end

%  G通道
ImgBline2 = ImgB2(:); % 转换为一列
for ii = 1:M*N
    if flag == 1; % 跳出外层循环
       break;
    end
    
    [y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1)] = Find8bits(ImgBline2(ii));   
    posNzreo = FindNotZero(y(8), y(7), y(6), y(5), y(4), y(3), y(2), y(1));
    embedNums = posNzreo - yb; % 已嵌入的个数
    if embedNums > 0 % 符合嵌入条件
        for jj = 1 : embedNums
            
            extractNumsed = extractNumsed   1; % 已提取个数
            if extractNumsed > M*N*8 % 提取完成
               flag = 1; % 设置标识,使外层循环也跳出
               break;
            end
            
           Imgmark_extractlinebin(extractNumsed) = y(jj); % 提取
        end
    end
end

% 二进制转十进制
Imgmarklinedec = zeros(M*N, 1); % 转化为十进制
for ii = 1 : M*N
    Imgmarklinedec(ii) = bin2dec_trans(Imgmark_extractlinebin(8*ii-7), Imgmark_extractlinebin(8*ii-6), Imgmark_extractlinebin(8*ii-5), Imgmark_extractlinebin(8*ii-4),...
                                     Imgmark_extractlinebin(8*ii-3), Imgmark_extractlinebin(8*ii-2), Imgmark_extractlinebin(8*ii-1), Imgmark_extractlinebin(8*ii));
end
Imgmarkextract = reshape(Imgmarklinedec, [M, N]);
figure;imshow(Imgmarkextract,[]);title('提取出的隐藏图');
imwrite(uint8(Imgmarkextract), '提取出的隐藏图.png'); % 保存图片

公共函数

% 二进制转十进制

代码语言:javascript复制
function Data=bin2dec_trans(y7,y6,y5,y4,y3,y2,y1,y0)
   Data=y7*128 y6*64 y5*32 y4*16 y3*8 y2*4 y1*2 y0;
end

% Find8bits.m
function [y7,y6,y5,y4,y3,y2,y1,y0]=Find8bits(Data)
y0=mod(Data,2);
y7=fix(Data/128);Data=Data-y7*128;
y6=fix(Data/64); Data=Data-y6*64;
y5=fix(Data/32); Data=Data-y5*32;
y4=fix(Data/16); Data=Data-y4*16;
y3=fix(Data/8);  Data=Data-y3*8;
y2=fix(Data/4);  Data=Data-y2*4;
y1=fix(Data/2);  Data=Data-y1*2;
end

% FindNotZero.m
%找出第一个不为零的数位 从最高位(第八位)开始
function posNzreo=FindNotZero(y7,y6,y5,y4,y3,y2,y1,y0)
if y7~=0      posNzreo=8;
elseif y6~=0  posNzreo=7;
elseif y5~=0  posNzreo=6;
elseif y4~=0  posNzreo=5;
elseif y3~=0  posNzreo=4;
elseif y2~=0  posNzreo=3;
elseif y1~=0  posNzreo=2;
else          posNzreo=1;
end
end

3.像素近邻法

github:https://github.com/3150601355/SimpleScaleDown

图片特征:图片上均匀分布像素点

将图片嵌入另一个图片

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


#将small_img中的像素用近邻法嵌入到big_img中
def my_nearest_resize(big_img, small_img):

    big_w, big_h = big_img.size
    small_w, small_h = small_img.size

    dst_im = big_img.copy()

    stepx = big_w/small_w
    stepy = big_h/small_h

    for i in range(0, small_w):
        for j in range(0, small_h):
            map_x = int(i*stepx   stepx*0.5)
            map_y = int(j*stepy   stepy*0.5)

            if map_x < big_w and map_y < big_h:
                dst_im.putpixel((map_x, map_y), small_img.getpixel((i, j)))

    return dst_im


if __name__ == '__main__':
    big_img = Image.open(sys.argv[1])     # 大图
    small_img = Image.open(sys.argv[2])   # 小图

    dst_im = my_nearest_resize(big_img, small_img)
    dst_im.save(sys.argv[3])            # 嵌入小图像素的大图

使用ps或脚本改变图片尺寸

改变图像尺寸

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

img = Image.open(sys.argv[1])

img = img.resize((192, 108), Image.NEAREST)
img.save(sys.argv[2])

4.文本写入bmp

图片特征:图片只有不规则像素点,无图案

将文本写入bmp

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


def encode(text):
    str_len = len(text)
    width = math.ceil(str_len ** 0.5)
    im = Image.new("RGB", (width, width), 0x0)

    x, y = 0, 0
    for i in text:
        index = ord(i)
        rgb = (0, (index & 0xFF00) >> 8, index & 0xFF)
        im.putpixel((x, y), rgb)
        if x == width - 1:
            x = 0
            y  = 1
        else:
            x  = 1
    return im


if __name__ == '__main__':
    with open("xxx.txt", encoding="utf-8") as f:
        all_text = f.read()

        im = encode(all_text)
        im.save("encode.bmp")

从bmp中导出文本

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


def decode(im):
    width, height = im.size
    lst = []
    for y in range(height):
        for x in range(width):
            red, green, blue = im.getpixel((x, y))
            if(blue | green | red) == 0:
                break
            index = (green << 8)   blue
            lst.append(chr(index))
    return ''.join(lst)


if __name__ == '__main__':

    all_text = decode(Image.open("encode.bmp", "r"))
    with open("decode.text", "w", encoding="utf-8") as f:
        f.write(all_text)

PNG:

文件头:

代码语言:javascript复制
89 50 4E 47 0D 0A 1A 0A  00 00 00 0D 49 48 44 52
00 00 03 30 00 00 04 DB  08 06 00 00 00 46 2C 50
D4
  • 89 50 4E 47 0D 0A 1A 0A:PNG文件标识
  • 00 00 00 0D:IHDR数据块数据域长为13
  • 49 48 44 52:IHDR数据类型码(标识)
  • 00 00 03 30:表示图像的宽度,816像素
  • 00 00 04 DB:表示图像的高度,1243像素
  • 08 06 00 00 00:对图片的一些描述
  • 46 2C 50 D4:CRC校验码

文件尾:

代码语言:javascript复制
00 00 00 00 49 45 4E 44  AE 42 60 82

JPG:

文件头:

代码语言:javascript复制
FF D8 FF

文件尾:

代码语言:javascript复制
FF D9

GIF:

文件头:

代码语言:javascript复制
47 49 46 38

文件尾:

代码语言:javascript复制
00 3B

TIFF:

文件头:

代码语言:javascript复制
49 49 2A 00

0 人点赞