From 013cc2f68f9c79083ad8dfda4680ec5375092f20 Mon Sep 17 00:00:00 2001 From: Ronsor Date: Sat, 19 Aug 2023 07:07:10 -0700 Subject: [PATCH] caff: eliminate gaps and specify unused fields --- format/caff/caff.go | 27 +++++++---- format/caff/testdata/test.cmo3.fqtest | 68 +++++++++++++++------------ 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/format/caff/caff.go b/format/caff/caff.go index ecef3b5e..04b836e7 100644 --- a/format/caff/caff.go +++ b/format/caff/caff.go @@ -49,6 +49,11 @@ const ( compressOptionSmall = 0x25 ) +var bool8ToSym = scalar.UintMapSymBool{ + 0: false, + 1: true, +} + var imageFormatNames = scalar.UintMapSymStr{ imageFormatUnknown: "unknown", imageFormatPNG: "png", @@ -91,7 +96,6 @@ func decodeCAFF(d *decode.D) any { obfsU8 := func(d *decode.D) uint64 { return d.U8() ^ uint64(obfsKey&0xff) } obfsU32 := func(d *decode.D) uint64 { return d.U32() ^ uint64(obfsKey&0xffff_ffff) } obfsU64 := func(d *decode.D) uint64 { return d.U64() ^ uint64(obfsKey<<32|obfsKey) } - obfsBool := func(d *decode.D) bool { return obfsU8(d) != 0 } // "Big Endian Base 128" - LEB128's strange sibling obfsBEB128 := func(d *decode.D) (v uint64) { @@ -123,18 +127,18 @@ func decodeCAFF(d *decode.D) any { d.FieldUTF8("format_id", 4) d.FieldStruct("format_version", decodeVersion) obfsKey = d.FieldS32("obfuscate_key") - d.SeekRel(8 * 8) + d.FieldU64("unused0") d.FieldStruct("preview_image", func(d *decode.D) { d.FieldU8("image_format", imageFormatNames) d.FieldU8("color_type", colorTypeNames) - d.SeekRel(2 * 8) + d.FieldU16("unused0") d.FieldU16("width") d.FieldU16("height") - d.FieldU64("start_pos") + d.FieldU64("start_pos", scalar.UintHex) d.FieldU32("file_size") }) - d.SeekRel(8 * 8) + d.FieldU64("unused1") fileInfoListSize := d.FieldUintFn("file_info_map_size", obfsU32) fileInfoList := make([]fileInfoListEntry, int(fileInfoListSize)) @@ -146,11 +150,11 @@ func decodeCAFF(d *decode.D) any { entry.filePath = d.FieldStrFn("file_path", obfsVarStr) d.FieldStrFn("tag", obfsVarStr) - entry.startPos = int64(d.FieldUintFn("start_pos", obfsU64)) + entry.startPos = int64(d.FieldUintFn("start_pos", obfsU64, scalar.UintHex)) entry.fileSize = int(d.FieldUintFn("file_size", obfsU32)) - entry.isObfuscated = d.FieldBoolFn("is_obfuscated", obfsBool) + entry.isObfuscated = d.FieldUintFn("is_obfuscated", obfsU8, bool8ToSym) != 0 entry.compressOption = uint8(d.FieldUintFn("compress_option", obfsU8, compressOptionNames)) - d.SeekRel(8 * 8) + d.FieldU64("unused0") fileInfoList[int(i)] = entry }) @@ -166,7 +170,12 @@ func decodeCAFF(d *decode.D) any { d.FieldValueBool("is_obfuscated", entry.isObfuscated) d.FieldValueUint("compress_option", uint64(entry.compressOption), compressOptionNames) - rawBytes := d.BytesLen(entry.fileSize) + rawBr := d.FieldRawLen("raw", int64(entry.fileSize) * 8) + rawBytes := make([]byte, entry.fileSize) + if n, err := rawBr.ReadBits(rawBytes, int64(entry.fileSize) * 8); err != nil || n != int64(entry.fileSize) * 8 { + return + } + if entry.isObfuscated { for i, v := range rawBytes { rawBytes[i] = v ^ uint8(obfsKey) diff --git a/format/caff/testdata/test.cmo3.fqtest b/format/caff/testdata/test.cmo3.fqtest index 180deaf0..75a6520c 100644 --- a/format/caff/testdata/test.cmo3.fqtest +++ b/format/caff/testdata/test.cmo3.fqtest @@ -12,66 +12,67 @@ $ fq dv test.cmo3 0x000000| 00 | . | patch: 0 0xd-0xd.7 (1) 0x000000| af de| ..| obfuscate_key: -1344390416 0xe-0x11.7 (4) 0x000010|3a f0 |:. | -0x000010| 00 00 00 00 00 00 00 00 | ........ | gap0: raw bits 0x12-0x19.7 (8) +0x000010| 00 00 00 00 00 00 00 00 | ........ | unused0: 0 0x12-0x19.7 (8) | | | preview_image{}: 0x1a-0x2d.7 (20) 0x000010| 7f | . | image_format: "no_preview" (127) 0x1a-0x1a.7 (1) 0x000010| 7f | . | color_type: "no_preview" (127) 0x1b-0x1b.7 (1) +0x000010| 00 00 | .. | unused0: 0 0x1c-0x1d.7 (2) 0x000010| 00 00| ..| width: 0 0x1e-0x1f.7 (2) 0x000020|00 00 |.. | height: 0 0x20-0x21.7 (2) -0x000020| 00 00 00 00 00 00 00 00 | ........ | start_pos: 0 0x22-0x29.7 (8) +0x000020| 00 00 00 00 00 00 00 00 | ........ | start_pos: 0x0 0x22-0x29.7 (8) 0x000020| 00 00 00 00 | .... | file_size: 0 0x2a-0x2d.7 (4) -0x000010| 00 00 | .. | gap1: raw bits 0x1c-0x1d.7 (2) -0x000020| 00 00| ..| gap2: raw bits 0x2e-0x35.7 (8) +0x000020| 00 00| ..| unused1: 0 0x2e-0x35.7 (8) 0x000030|00 00 00 00 00 00 |...... | 0x000030| af de 3a f4 | ..:. | file_info_map_size: 4 0x36-0x39.7 (4) - | | | file_info_list[0:4]: 0x3a-0xc0.7 (135) - | | | [0]{}: file_info 0x3a-0x52.7 (25) + | | | file_info_list[0:4]: 0x3a-0xc8.7 (143) + | | | [0]{}: file_info 0x3a-0x5a.7 (33) 0x000030| f9 99 9d 91 97 95| ......| file_path: "image.png" 0x3a-0x43.7 (10) 0x000040|de 80 9e 97 |.... | 0x000040| f0 | . | tag: "" 0x44-0x44.7 (1) -0x000040| ff ff ff ff af de 3a 39 | ......:9 | start_pos: 201 0x45-0x4c.7 (8) +0x000040| ff ff ff ff af de 3a 39 | ......:9 | start_pos: 0xc9 0x45-0x4c.7 (8) 0x000040| af de 3a| ..:| file_size: 96 0x4d-0x50.7 (4) 0x000050|90 |. | -0x000050| f1 | . | is_obfuscated: true 0x51-0x51.7 (1) +0x000050| f1 | . | is_obfuscated: true (1) 0x51-0x51.7 (1) 0x000050| e0 | . | compress_option: "raw" (16) 0x52-0x52.7 (1) - | | | [1]{}: file_info 0x5b-0x75.7 (27) +0x000050| 00 00 00 00 00 00 00 00 | ........ | unused0: 0 0x53-0x5a.7 (8) + | | | [1]{}: file_info 0x5b-0x7d.7 (35) 0x000050| fb 99 9d 91 97| .....| file_path: "image_0.png" 0x5b-0x66.7 (12) 0x000060|95 af c0 de 80 9e 97 |....... | 0x000060| f0 | . | tag: "" 0x67-0x67.7 (1) -0x000060| ff ff ff ff af de 3b d9| ......;.| start_pos: 297 0x68-0x6f.7 (8) +0x000060| ff ff ff ff af de 3b d9| ......;.| start_pos: 0x129 0x68-0x6f.7 (8) 0x000070|af de 3a a3 |..:. | file_size: 83 0x70-0x73.7 (4) -0x000070| f1 | . | is_obfuscated: true 0x74-0x74.7 (1) +0x000070| f1 | . | is_obfuscated: true (1) 0x74-0x74.7 (1) 0x000070| e0 | . | compress_option: "raw" (16) 0x75-0x75.7 (1) - | | | [2]{}: file_info 0x7e-0x98.7 (27) +0x000070| 00 00 00 00 00 00 00 00 | ........ | unused0: 0 0x76-0x7d.7 (8) + | | | [2]{}: file_info 0x7e-0xa0.7 (35) 0x000070| fb 99| ..| file_path: "image_1.png" 0x7e-0x89.7 (12) 0x000080|9d 91 97 95 af c1 de 80 9e 97 |.......... | 0x000080| f0 | . | tag: "" 0x8a-0x8a.7 (1) -0x000080| ff ff ff ff af| .....| start_pos: 380 0x8b-0x92.7 (8) +0x000080| ff ff ff ff af| .....| start_pos: 0x17c 0x8b-0x92.7 (8) 0x000090|de 3b 8c |.;. | 0x000090| af de 3a bb | ..:. | file_size: 75 0x93-0x96.7 (4) -0x000090| f1 | . | is_obfuscated: true 0x97-0x97.7 (1) +0x000090| f1 | . | is_obfuscated: true (1) 0x97-0x97.7 (1) 0x000090| e0 | . | compress_option: "raw" (16) 0x98-0x98.7 (1) - | | | [3]{}: file_info 0xa1-0xc0.7 (32) +0x000090| 00 00 00 00 00 00 00| .......| unused0: 0 0x99-0xa0.7 (8) +0x0000a0|00 |. | + | | | [3]{}: file_info 0xa1-0xc8.7 (40) 0x0000a0| f8 9d 91 99 9e de 88 9d 9c | ......... | file_path: "main.xml" 0xa1-0xa9.7 (9) 0x0000a0| f8 9d 91 99 9e af| ......| tag: "main_xml" 0xaa-0xb2.7 (9) 0x0000b0|88 9d 9c |... | -0x0000b0| ff ff ff ff af de 3b 37 | ......;7 | start_pos: 455 0xb3-0xba.7 (8) +0x0000b0| ff ff ff ff af de 3b 37 | ......;7 | start_pos: 0x1c7 0xb3-0xba.7 (8) 0x0000b0| af de 1a 50 | ...P | file_size: 8352 0xbb-0xbe.7 (4) -0x0000b0| f1| .| is_obfuscated: true 0xbf-0xbf.7 (1) +0x0000b0| f1| .| is_obfuscated: true (1) 0xbf-0xbf.7 (1) 0x0000c0|d1 |. | compress_option: "fast" (33) 0xc0-0xc0.7 (1) -0x000050| 00 00 00 00 00 00 00 00 | ........ | gap3: raw bits 0x53-0x5a.7 (8) -0x000070| 00 00 00 00 00 00 00 00 | ........ | gap4: raw bits 0x76-0x7d.7 (8) -0x000090| 00 00 00 00 00 00 00| .......| gap5: raw bits 0x99-0xa0.7 (8) -0x0000a0|00 |. | -0x0000c0| 00 00 00 00 00 00 00 00 79 a0 be b7 fd fa ea| ........y......| gap6: raw bits 0xc1-0x2266.7 (8614) -0x0000d0|fa f0 f0 f0 fd b9 b8 b4 a2 f0 f0 f0 b0 f0 f0 f0|................| -* |until 0x2266.7 (8614) | | - | | | files[0:4]: 0xc9-0x1c6.7 (254) - | | | [0]{}: file 0xc9-NA (0) +0x0000c0| 00 00 00 00 00 00 00 00 | ........ | unused0: 0 0xc1-0xc8.7 (8) + | | | files[0:4]: 0xc9-0x2266.7 (8606) + | | | [0]{}: file 0xc9-0x128.7 (96) | | | file_path: "image.png" 0xc9-NA (0) | | | file_size: 96 0xc9-NA (0) | | | is_obfuscated: true 0xc9-NA (0) | | | compress_option: "raw" (16) 0xc9-NA (0) +0x0000c0| 79 a0 be b7 fd fa ea| y......| raw: raw bits 0xc9-0x128.7 (96) +0x0000d0|fa f0 f0 f0 fd b9 b8 b4 a2 f0 f0 f0 b0 f0 f0 f0|................| +* |until 0x128.7 (96) | | |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| uncompressed{}: (png) 0x0-0x5f.7 (96) 0x0000|89 50 4e 47 0d 0a 1a 0a |.PNG.... | signature: raw bits (valid) 0x0-0x7.7 (8) | | | chunks[0:3]: 0x8-0x5f.7 (88) @@ -110,11 +111,14 @@ $ fq dv test.cmo3 0x0005| 4e | N | reserved: false 0x5a.3-0x5a.3 (0.1) 0x0005| 44 | D | safe_to_copy: false 0x5b.3-0x5b.3 (0.1) 0x0005| ae 42 60 82| .B`.| crc: 0xae426082 (valid) 0x5c-0x5f.7 (4) - | | | [1]{}: file 0x129-NA (0) + | | | [1]{}: file 0x129-0x17b.7 (83) | | | file_path: "image_0.png" 0x129-NA (0) | | | file_size: 83 0x129-NA (0) | | | is_obfuscated: true 0x129-NA (0) | | | compress_option: "raw" (16) 0x129-NA (0) +0x000120| 79 a0 be b7 fd fa ea| y......| raw: raw bits 0x129-0x17b.7 (83) +0x000130|fa f0 f0 f0 fd b9 b8 b4 a2 f0 f0 f0 d0 f0 f0 f0|................| +* |until 0x17b.7 (83) | | |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| uncompressed{}: (png) 0x0-0x52.7 (83) 0x0000|89 50 4e 47 0d 0a 1a 0a |.PNG.... | signature: raw bits (valid) 0x0-0x7.7 (8) | | | chunks[0:3]: 0x8-0x52.7 (75) @@ -154,11 +158,14 @@ $ fq dv test.cmo3 0x0004| 44 | D | safe_to_copy: false 0x4e.3-0x4e.3 (0.1) 0x0004| ae| .| crc: 0xae426082 (valid) 0x4f-0x52.7 (4) 0x0005|42 60 82| |B`.| | - | | | [2]{}: file 0x17c-NA (0) + | | | [2]{}: file 0x17c-0x1c6.7 (75) | | | file_path: "image_1.png" 0x17c-NA (0) | | | file_size: 75 0x17c-NA (0) | | | is_obfuscated: true 0x17c-NA (0) | | | compress_option: "raw" (16) 0x17c-NA (0) +0x000170| 79 a0 be b7| y...| raw: raw bits 0x17c-0x1c6.7 (75) +0x000180|fd fa ea fa f0 f0 f0 fd b9 b8 b4 a2 f0 f0 f0 e0|................| +* |until 0x1c6.7 (75) | | |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| uncompressed{}: (png) 0x0-0x4a.7 (75) 0x0000|89 50 4e 47 0d 0a 1a 0a |.PNG.... | signature: raw bits (valid) 0x0-0x7.7 (8) | | | chunks[0:3]: 0x8-0x4a.7 (67) @@ -197,11 +204,14 @@ $ fq dv test.cmo3 0x0004| 4e | N | reserved: false 0x45.3-0x45.3 (0.1) 0x0004| 44 | D | safe_to_copy: false 0x46.3-0x46.3 (0.1) 0x0004| ae 42 60 82| | .B`.| | crc: 0xae426082 (valid) 0x47-0x4a.7 (4) - | | | [3]{}: file 0x1c7-NA (0) + | | | [3]{}: file 0x1c7-0x2266.7 (8352) | | | file_path: "main.xml" 0x1c7-NA (0) | | | file_size: 8352 0x1c7-NA (0) | | | is_obfuscated: true 0x1c7-NA (0) | | | compress_option: "fast" (33) 0x1c7-NA (0) +0x0001c0| a0 bb f3 f4 e4 f0 f8 f8 f8| .........| raw: raw bits 0x1c7-0x2266.7 (8352) +0x0001d0|f0 8b 6a e2 a7 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0|..j.............| +* |until 0x2266.7 (8352) | | |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| 0x0000|50 4b 03 04 14 00 08 08 08 00 7b 9a 12 57 00 00|PK........{..W..| compressed: raw bits 0x0-0x209f.7 (8352) * |until 0x209f.7 (end) (8352) | |