隐写技巧——利用PNG文件格式隐藏Payload(一)

前言


隐写术(Steganography)由来已久,其中有很多好玩儿的细节,所以打算系统的研究一下,这次先从PNG的文件格式开始。

640

01 简介


隐写术可以理解为信息隐藏,在渗透测试中最主要的应用是对Payload的隐藏。本文会对PNG的文件格式进行分析,编写c程序实现自动解析文件格式,并按照其文件格式添加自定义的payload,不仅不会影响图片的正常浏览,同时可将图片上传到网络,使用时将图片下载再以特定格式解密,最终执行payload。

注:所有程序源码已上传github,地址为: https://github.com/3gstudent/PNG-Steganography

02 PNG文件格式


1、PNG文件署名域

前8字节

固定格式,16进制为: 89 504e 47 0d 0a 1a 0a

2、数据块

Chunk Type Code(数据块类型码): 4字节,数据块类型码

Chunk Data(数据块数据): 可变长度,存储数据

CRC(循环冗余检测): 4字节,存储用来检测是否有错误的循环冗余码

数据块类型:

1. 关键数据块(criticalchunk)

(1) 文件头数据块IHDR(headerchunk) – 包含PNG文件的基本信息 – 一个PNG数据流中只能有一个IHDR – 必须在PNG文件最前面

(2) 调色板数据块PLTE(palettechunk) – 包含有与索引彩色图像(indexed-color image)相关的彩色变换数据 – 必须在IDAT之前

(3) 图像数据块IDAT(imagedata chunk) – 存储实际的数据 – 可存在多个 -必须与其他IDAT连续

(4) 图像结束数据IEND(imagetrailer chunk) – 固定格式,16进制为: 0000 00 00 49 45 4E 44 AE 42 60 82 – 必须在PNG文件最尾部

2. 辅助数据块(ancillarychunk)

用于辅助指示PNG图像中的层、文字等信息

可删除,不影响图片浏览,但图像将失去原来的可编辑性

(1) 背景颜色数据块bKGD(backgroundcolor)

(2) 基色和白色度数据块cHRM(primarychromaticities and white point)

(3) 图像γ数据块gAMA(image gamma)

(4) 图像直方图数据块hIST(imagehistogram)

(5) 物理像素尺寸数据块pHYs(physicalpixel dimensions)

(6) 样本有效位数据块sBIT(significantbits)

(7) 文本信息数据块tEXt(textualdata)

(8) 图像最后修改时间数据块tIME(image last-modification time)

(9) 图像透明数据块tRNS(transparency)

(10) 压缩文本数据块zTXt(compressed textual data)

03 实例格式分析


工具:Hex Editor

优点:可对16进制字符串进行标记,设置颜色,方便格式分析

测试文件:如图

640

 

源下载地址:http://www.easyicon.net/language.en/1172671-png_icon.html

标记好的文件格式如图

640

641

###(1) PNG文件署名域

固定格式:

89 50 4e 47 0d 0a 1a 0a ###(2) IHDR

00000008h: 00 00 00 0D 49 48 44 52 00 00 001A 00 00 00 1A ; ….IHDR…….. 00000018h: 08 04 00 00 00 03 43 84 45 ; ……C凟

数据块结构:

Length: 00 00 00 0D

前4字节,定义长度,00 00 000D十进制为13,代表长度为13个字节

Chunk Type Code: 4948 44 52

4字节,定义数据块类型码,此处为IHDR

Chunk Data: 00 0000 1A 00 00 00 1A 08 04 00 00 00

共13字节,定义数据内容

CRC: 4字节,对Chunk Type Code+Chunk Data作CRC32计算得出的值

即对以下十六进制作计算: 49 48 44 52 00 00 00 1A 00 0000 1A 08 04 00 00 00

编写程序对CRC算法进行验证,保存为example1.cpp,源代码如下:

#include <string.h>
unsigned int GetCrc32(char* InStr,unsignedint len){        
 unsigned int Crc32Table[256];     
  inti,j;        
 unsigned int Crc;        
  for(i = 0; i < 256; i++){        
            Crc= i;        
            for(j = 0; j < 8; j++){        
              if (Crc & 1)        
                        Crc= (Crc >> 1) ^ 0xEDB88320;        
              else      
                        Crc>>= 1;      
            }        
            Crc32Table[i]= Crc;        
 }        

 Crc=0xffffffff;        
  for(intm=0; m<len; m++){          
            Crc= (Crc >> 8) ^ Crc32Table[(Crc & 0xFF) ^ InStr[m]];        
 }     

  Crc^= 0xFFFFFFFF;     
 return Crc;        
}       
int main(int argc, char* argv[])
{
            charbuf[17]={0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x1A,0x00,0x00,0x00,0x1A,0x08,0x04,0x00,0x00,0x00};
            unsignedint crc32=GetCrc32(buf,sizeof(buf));
            printf("%08X\n",crc32);
            return0;
}

运行后如图,输出03438445,同文件中的CRC32校验码相同

644

(2) gAMA

00000021h: 00 00 00 04 67 41 4D 41 00 00 B18F 0B FC 61 05 ; ….gAMA..睆.黙.

数据块结构:

Length: 00 00 00 04

Chunk Type Code: 6741 4D 41

Chunk Data: 00 00B1 8F

CRC: 0B FC 61 05

(3) cHRM

00000031h: 00 00 00 20 63 48 52 4D 00 00 7A26 00 00 80 84 ; … cHRM..z&..€? 00000041h: 00 00 FA 00 00 00 80 E8 00 00 7530 00 00 EA 60 ; ..?..€?.u0..阘 00000051h: 00 00 3A 9800 00 17 70 9C BA 51 3C ; ..:?..p満Q<

数据块结构:

Length: 00 00 00 20

Chunk Type Code: 6348 52 4D

Chunk Data: 00 007A 26 00 00 80 84 00 00 FA 00 00 00 80 E8 00 00 75 30 00 00 EA 60 00 00 3A 9800 00 17 70

CRC: 9C BA 51 3C

(4) IDAT

(5-14) tEXt

(15)IEND

数据块结构:

Length: 00 00 00 00

Chunk Type Code: 4945 4E 44

Chunk Data:

CRC: AE 42 60 82

固定结构,CRC的值为对ChunkType Code作CRC32校验

645

*来源:RoarTalk    作者:3gstudent  Mottoin整理发布

原创文章,作者:3gstudent,如若转载,请注明出处:http://www.mottoin.com/sole/topic/87685.html

发表评论

登录后才能评论

评论列表(1条)

联系我们

021-62666911

在线咨询:点击这里给我发消息

邮件:root@mottoin.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code