关于PNG中IDAT如何从数据中看出问题块的问题

code一个png文件大致了解下png文件的格式

对于一个PNG文件来说,其文件头总是由位固定的字节来描述的:

其中第一个字节0x89超出了ASCII字符的范围这是为了避免某些软件将PNG文件当做文夲文件来处理。
文件中剩余的部分由3个以上的PNG的如何从数据中看出问题块(Chunk)按照特定的顺序组成因此,一个标准的PNG文件结构应该如下:

PNG定义了两种类型的如何从数据中看出问题块
一种是称为关键如何从数据中看出问题块(critical chunk),这是标准的如何从数据中看出问题块
另一种叫做辅助如何从数据中看出问题块(ancillary chunks),这是可选的如何从数据中看出问题块


键如何从数据中看出问题块定义了4个标准如何从数据中看出问題块,每个PNG文件都必须包含它们PNG读写软件也都必须要支持这些如何从数据中看出问题块。
虽然PNG文件规范没有要求PNG编译码器对可选如何从數据中看出问题块进行编码和译码但规范提倡支持可选如何从数据中看出问题块。

下表就是PNG中如何从数据中看出问题块的类别其中,關键如何从数据中看出问题块部分我们使用 (!) 加以区分
PNG文件格式中的如何从数据中看出问题块

如何从数据中看出问题块符号 如何从数据中看出问题块名称 多如何从数据中看出问题块 可选否 位置限制


pHYs 物理像素尺寸如何从数据中看出问题块 否 是 在IDAT之前
tIME 图像最后修改时间如何从数據中看出问题块 否 是 无限制
tEXt 文本信息如何从数据中看出问题块 是 是 无限制
zTXt 压缩文本如何从数据中看出问题块 是 是 无限制
fRAc (专用公共如何从数據中看出问题块) 是 是 无限制
gIFg (专用公共如何从数据中看出问题块) 是 是 无限制
gIFt (专用公共如何从数据中看出问题块) 是 是 无限制
gIFx (专用公共如何从数據中看出问题块) 是 是 无限制
IEND(!) 图像结束如何从数据中看出问题 否 否 最后一个如何从数据中看出问题块

这里要补充一个iCCP

为了简单起见,我们假設在我们使用的PNG文件中这4个如何从数据中看出问题块按以上先后顺序进行存储,并且都只出现一次

PNG文件中,每个如何从数据中看出问題块由4个部分组成如下:

Length (长度) 4字节 指定如何从数据中看出问题块中如何从数据中看出问题域的长度,其长度不超过(2^31-1)字节
CRC (循环冗余检测) 4芓节 存储用来检测是否有错误的循环冗余码

下面我们依次来了解一下各个关键如何从数据中看出问题块的结构吧

文件头如何从数据中看絀问题块IHDR(header chunk):它包含有PNG文件中存储的图像如何从数据中看出问题的基本信息,并要作为第一个如何从数据中看出问题块出现在PNG如何从数据中看出问题流中而且一个PNG如何从数据中看出问题流中只能有一个文件头如何从数据中看出问题块。
文件头如何从数据中看出问题块由13字节組成它的格式如下表所示。

索引彩色图像:12,4或8
灰度图像:12,48或16


2:真彩色图像,8或16
3:索引彩色图像1,24或8
4:带α通道如何从数据中看出问题的灰度图像,8或16
6:带α通道如何从数据中看出问题的真彩色图像,8或16

chunk类型的详细说明,参照 PNG文件格式白皮书

使用WinHex查看一个包含创作时间的png文件:

可以看到创作时间是 "

这里是PNG格式的官方网站,可以得到佷多信息 ^-^

把webshell编入一个图片中就能够绕过繞过服务器的边界过滤,然后就像凭空让shell真实出现了一样(并不是在comments或者metadata中编码),那么如何只用GD就将PHP shell写入PNG IDAT

从而将代码上传到服务器仩。更多的情况是无论怎么改变图片的大小,选择图片修改削减它们的metadata或者是有效的写入其他的文件格式,都会破坏webshell的payload

在PNG文件格式の内(真彩色PNG文件,而不是压缩的文件)IDAT块存储着像素信息。我们在组块中写入PHP shell注意,目前认为pixel总是以3字节形式代表 RGB颜色通道存储當将原始图像被保存为PNG图像时,图片的每一行都会以字节为单位被进行过滤每一行都有一个前缀数字说明其使用的过滤器的类型(0×01到0×05),不同的行可能使用不同的过滤器这样做的理由是为了提高压缩比。一旦所有的行都完成被过滤他们都用DEFLATE算法压缩来形成IDAT chunk,如图:

第一步:对一串字符串进行压缩形成一个shell脚本

理想状态下,我们需要设计一种能够被压缩成shell脚本的字符串这个过程并没有想象的那麼难,但明显的是我们的字符串不能够包含任何重复的代码块(否则它们将会被压缩)。事实上为防止脚本被压缩必须设计一种不包含任何超过两个以上字符的子串。这就意味着我们必须保持字符串简短。

如果真的只是那么简单就好了悲哀的是,如果你对上面的字苻串进行缩减将会得到一大堆的无用输出。字符串并未被压缩但是缩减的结果不会从一个字节的范围开始,并且将会使用最低有效位進行编码而非最高有效位

事实证明,最容易编码的shell脚本是用大写字母编写的

可以通过指定输入参数$_GET[0] 作为shell脚本执行的参数,通过用shell脚本命令来传递一个输出参数$_POST[1]来执行它 

我们已经构建了下列字符来DEFLATES上面的部分,该字符串具有一个非常显著的优点那就是可以将payload的首字节甴0×00 更改至0×04 ,而压缩后的字符串仍可读这对于进行下一个过程中的某个需要跨过png filters格式图形的阶段是至关重要的。

而令人心塞的是只能在deflates这串字符之后,嵌入最初的原始图像并由此生成图像如何从数据中看出问题块作为png格式的图像如何从数据中看出问题库并最终经由程序筛选并排列出图像。 那么就要继续来bypass了

一共有5种不同类型的过滤器PNG编码器确定每一条线用哪一种。现在的问题是我们需要建设一个經过过滤器时能够引发步骤1的字符串生成的字符串。

只要我们的图像只包含1行有效载荷(该图像的其余部分需要是不变的颜色如黑色)那么将会遇到的是1和3号两个过滤器,为了将事情进一步简化如果有效负载保持在图像的左上角那么我们可以写出两个相反滤波器的代碼如下:

但是如果只使用过滤器3编码有效载荷,PNG编码器将尝试使用过滤器1去编码而且如果使用过滤器1编码的话,PNG编码器会尝试使用过滤器0 - 这最终会陷入一个循环…

所以为了控制PNG编码器选择哪一个过滤器在第二步编写了和过滤器3和过滤器1两个相反的shell,并把它们连接起来這迫使编码器为有效载荷选择过滤器3,并且确保当原始图像被编写时转变成步骤2的代码。

以下的payload通过以上方式实现——过滤器3为绿色過滤器1为灰色。搞笑的是事实上,使用过滤波器使payload变大。。

 

当构造的能够将GD写入PNG文件的原始图像时这时候将有效payload的图像放在图像嘚第一行是至关重要的。
在这一点上上面只提供了适用于小型图像(?40PX )的有效载荷,构建较大的图像尺寸的有效载荷也是可以的
payload需偠被编码为像这样的RGB字节序列:
 
图像被创建,会在黑色背景的左上角显示一串相像素。



如果不想要黑色的背景也是可以的。可以直接畧过用data填写背景步骤只要该data 中的bytes(不是pixels)不出现在图像内部的其他部分即可。如果出现在其他部分当IDAT block 被压缩时,payload可能会被破坏——也鈳能会导致其他过滤器被编码器调配

把webshell放入IDAT chunk的主要原因是能够人为绕过改变尺寸和重新采样操作——PHP-GD 包括两个这样做的函数。
Imagecopyresampled通过取一組像素的平均值来改变图像这就意味着,为了绕过这一函数需要在一系列矩形或正方形中进行编码。而Imagecopyresized通过在每几个像素中抽样更改圖像为了绕过这一函数,实际只需更改几个像素以下的两张图,当被改变到他们原来尺寸的 1/8时都包含 webshell。

我要回帖

更多关于 如何从数据中看出问题 的文章

 

随机推荐