ZIP 実装会
ZIP のお勉強として、PHP でバイナリを分解してみる。
とりあえず ZIP を作成する
$ cat yoya1.txt Hello. $ cat yoya2.txt Nice meet you! $ zip yoya.zip yoya1.txt yoya2.txt adding: yoya1.txt (stored 0%) adding: yoya2.txt (stored 0%)
幸い無圧縮形式の ZIP ファイルが生成されたので、これを元に調査する事にする
$ hexdump -C yoya.zip 00000000 50 4b 03 04 0a 00 00 00 00 00 40 72 36 40 51 c4 |PK........@r6@Q.| 00000010 da 37 07 00 00 00 07 00 00 00 09 00 1c 00 79 6f |.7............yo| 00000020 79 61 31 2e 74 78 74 55 54 09 00 03 08 9c 1b 4f |ya1.txtUT......O| 00000030 21 9c 1b 4f 75 78 0b 00 01 04 f5 01 00 00 04 14 |!..Oux..........| 00000040 00 00 00 48 65 6c 6c 6f 2e 0a 50 4b 03 04 0a 00 |...Hello..PK....| 00000050 00 00 00 00 49 72 36 40 8e 15 1e 4b 0f 00 00 00 |....Ir6@...K....| 00000060 0f 00 00 00 09 00 1c 00 79 6f 79 61 32 2e 74 78 |........yoya2.tx| 00000070 74 55 54 09 00 03 19 9c 1b 4f 23 9c 1b 4f 75 78 |tUT......O#..Oux| 00000080 0b 00 01 04 f5 01 00 00 04 14 00 00 00 4e 69 63 |.............Nic| 00000090 65 20 6d 65 65 74 20 79 6f 75 21 0a 50 4b 01 02 |e meet you!.PK..| 000000a0 1e 03 0a 00 00 00 00 00 40 72 36 40 51 c4 da 37 |........@r6@Q..7| 000000b0 07 00 00 00 07 00 00 00 09 00 18 00 00 00 00 00 |................| 000000c0 01 00 00 00 a4 81 00 00 00 00 79 6f 79 61 31 2e |..........yoya1.| 000000d0 74 78 74 55 54 05 00 03 08 9c 1b 4f 75 78 0b 00 |txtUT......Oux..| 000000e0 01 04 f5 01 00 00 04 14 00 00 00 50 4b 01 02 1e |...........PK...| 000000f0 03 0a 00 00 00 00 00 49 72 36 40 8e 15 1e 4b 0f |.......Ir6@...K.| 00000100 00 00 00 0f 00 00 00 09 00 18 00 00 00 00 00 01 |................| 00000110 00 00 00 a4 81 4a 00 00 00 79 6f 79 61 32 2e 74 |.....J...yoya2.t| 00000120 78 74 55 54 05 00 03 19 9c 1b 4f 75 78 0b 00 01 |xtUT......Oux...| 00000130 04 f5 01 00 00 04 14 00 00 00 50 4b 05 06 00 00 |..........PK....| 00000140 00 00 02 00 02 00 9e 00 00 00 9c 00 00 00 00 00 |................| 00000150
IO_Bit で分解
IO_Bit で素直に先頭からバイナリを分解してみる。
while (true) { $signature = $reader->getData(4); switch ($signature) { case "PK\x03\x04": // A. Local file header $header = array(); $header['Signature'] = $signature; $header['VersionNeeded'] = $reader->getUI16LE(); <略>
Local Header と Central Header を解きました。
DOS Datetime でハマり
リトルエンディアンでひっくり返したうえでビットを切り出すのが正しいのですが、
当初、ビッグエンディアンで初めの 7 bit を切り出して 2012 年だったので、そのまま続けてハマりました。
40 72 36 40 = (2012/1/22 14:18:00)
続き (2019年3月1日追記)
- SWFバイナリ編集のススメ番外編 (zlib 伸張)