首页 » PHP教程 » phpcurlgzip解压技巧_Linux下的压缩和解压gzip编码逆向解析

phpcurlgzip解压技巧_Linux下的压缩和解压gzip编码逆向解析

访客 2024-12-08 0

扫一扫用手机浏览

文章目录 [+]

开始

让我们制作一个gzip压缩文件,看看里面有什么。
我们将保持大略:只需将8个字符串“aaaaaaaa”写入到文件。

echo "aaaaaaaa" >hello.out

用xxd查看二进制内容:

phpcurlgzip解压技巧_Linux下的压缩和解压gzip编码逆向解析

xxd hello.out0000000: 6161 6161 6161 6161 0a aaaaaaaa.

如上所示,文件有9字节长。
8个字节的“aaaaaaaa”,结尾写入了一个换行(LF)字符。

phpcurlgzip解压技巧_Linux下的压缩和解压gzip编码逆向解析
(图片来自网络侵删)
gzip编码头

用gzip对其压缩。
我们选用gzip -1,这是最快的压缩模式。
gzip命令的详细利用方法不再赘述,基本命令参数如下:

gzip -1 hello.out

连续用xxd查看二进制内容:

xxd hello.out.gz0000000: 1f8b 0808 9494 a061 0403 6865 6c6c 6f2e ....'..a..hello.0000010: 6f75 7400 4b4c 8400 2e00 b666 d7ad 0900 out.KL.....f....0000020: 0000

内容剖析:

前几个字节非常大略:

1f8b:是gzip文档格式,硬编码的gzip标头。

08:表示DEFLATE压缩方法。

08(00001000):位3被设置,所以是一个文件名。

9494 a061:2021-11-26日星期五16:28:12。

04,表示压缩是利用最快的算法(-1标志的)。

03,Unix操作系统(LF/CLRF)。

接下来的几个字节对应的是文件名: 。

6865 6c6c 6f2e 6f75 74 00h e l l o . o u t NUL

压缩数据

数据从字节0x13开始,以4b开头的为压缩的数据要解码,须要查看各个位,由于DEFLATE将信息打包成可以超过字节边界的位。
具有5位或9位代码的情形并不少见。

xxd -s 21 -b test.out.gz0000013: 00000000 01001011 01001100 10000100 00000000 00101110 .KL...0000019: 00000000 10110110 01100110 11010111 10101101 00001001 ..f...000001f: 00000000 00000000 00000000

接着来分解一下。
xxd 将字节一个一个地打印出来,其顺序为MSB到LSB。
但是在gzip 中,字节被打包是LSB到MSB顺序的。
以是必须逐字节反转字符串。

解码块

8bitswise: 11010010 00110010 00100001 00000000 01110100 00000000转化后: 1 10 10010001 10010001 0000100 00000 00111010 0000000 00用固定的霍夫曼代码压缩(不要忘却,虽然比特流说“10”,但它被读为01,由于数据文本将以小端格式阐明)

接下来解码霍夫曼码。
固定霍夫曼码(别号静态霍夫曼码)的要点是它们是一堆经由商定的霍夫曼码,长度范围为7-9位。
与所有霍夫曼代码一样,每个代码都是无前缀的,这意味着当一点一点地读取比特流时,每个代码何时结束都无任何歧义。

霍夫曼表规范中:

Lit Value Bits Codes--------- ---- -----0 - 143 8 00110000 through10111111144 - 255 9 110010000 through111111111256 - 279 7 0000000 through0010111280 - 287 8 11000000 through11000111

要解码霍夫曼码,必须(可能)读取接下来的9位。
从一点一点地读取比特流开始,直到识别出一个唯一标识它是哪个字符的前缀。
可以从观点年夜将其视为沿着霍夫曼树的边缘遍历下去。

接下来的9位是100100011-其前缀100,它表示这是0-143之间的文本。
以是它只有8位 (1001 0001)。

霍夫曼代码将LSB打包为MSB,但将被阐明为大端格式的整数。
解码得到:

val = (10010001 - 00110000)=145-48=97。

97是'a'ASCII码。
解码别的各字节得到:

1 10 10010001 10010001 0000100 00000 00111010 0000000 0097 97 260 0 58 256 -'a' 'a' repeat 6x 1 behind 0x10 (LF) HALT <padding>LIT LIT LEN DIST LIT

有8'a',两个’aa\后跟 6 'a'重复,然后是LF。

“repeat 6x, 1 behind”是一个长度+间隔(LEN,DIST)的代码它见告解码器要重复的字符是它刚刚解码的前一个字符。
在这种情形下它是“a”。

已经将8 'a's 和 LF(最初是72 位)编码为46位和2个添补位。

校验和及大小

让我们完成gzip文件。
接下来一个CRC32。
看到带有换行符的未压缩 8 'a 将天生:ad d7 66 b6.十六进制流:

xxd hello.out.gz0000000: 1f8b 0808 27a5 a061 0403 6865 6c6c 6f2e ....'..a..hello.0000010: 6f75 7400 4b4c 8400 2e00 b666 d7ad 0900 out.KL.....f....0000020: 0000 ^^^^^^^^^^

可以清楚地看到 b6 66 d7 ad, 以小端字节顺序。
为crc校验和。

接下来的4个字节09 00 00 00是9个字节的小端字节序。
事实上,解码了9个字节,输入文件中有9个字节。

总结

全体压缩文件剖析如下:

gzip info: 1f8b 0808 27a5 a061 0403filename: 7465 7374 2e6f 7574 00DEFLATE data: 4b 4c 84 00 2e 00crc32: b6 66 d7 adsize: 09 00 00 00

以上我们通过对gzip二进制内容解析剖析其详细编码过程,通过这样剖析来让我们理解压缩和文件编码,当然gzip最主要的动态霍夫曼算法,干系内容感兴趣的同学可以自己去学习,也可以参考gzip源码学习详细代码实现过程,这便是后话了。

相关文章

php动态特点技巧_PHP 7 新特点

PHP 7 中的函数的形参类型声明可以是标量了。在 PHP 5 中只能是类名、接口、array 或者 callable (PHP...

PHP教程 2024-12-10 阅读0 评论0

断定结尾php技巧_PHP入门PHP基本语法一

认识PHP代码标识利用不同的四对标记指令分隔符程序注释变量什么是变量如何定义变量变量名的命名规则4.1 PHP标量类型—整型4.2...

PHP教程 2024-12-10 阅读0 评论0