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

关注 2017-01-03 15:13:39 查看数 6770 ,评论数 0 专题

前言


隐写术(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整理发布

交流评论(0)
Loading...
点击 ,就能发表评论哦~如果您还没有账号,请 一个吧
css.php
正在加载中...