バイナリファイル解析 CLI ツール fq のご紹介
株式会社ソラコム プリンシパル ソフトウェア エンジニア 小熊 崇 (@ogu)
2023年4月27日開催 オリィ研究所・ソラコム共催イベント 「Web通信/配信サービスの裏側公開」 で発表した資料です。
バイナリファイル解析 CLI ツールfqのご紹介株式会社ソラコムプリンシパル ソフトウェア エンジニア小熊 崇 (@ogu)
View Slide
© SORACOM自己紹介小熊 崇(おぐま たかし)@oguSORACOM API GatewaySORACOM CLIモバイルコアネットワークSORACOM Orbitソラカメ API fukabori.fm ep.91 & 92 ぜひ聞いてみてください
© SORACOMWhat's fq?https://github.com/wader/fq
© SORACOMWhat's fq?- "jq for binary formats"- バイナリフォーマットをデコード- ツリー状のデータ構造を作成- jq と同じクエリで値を取り出したり加工したりできる- Go で書かれている- Windows / Mac / Linux で動作
© SORACOMSupported formats- Media containers- MP4, MP3, Ogg, FLAC, Matroska, PNG, JPEG, Exif …- Media codecs- AAC, NALU, H.264, MP3 frames …- Network protocols- PCAP, Ethernet, IPv4, IPv6, TCP, UDP, …- TCP reassembly and IPv4 defragmentation- Serialization formats- MsgPack, ASN1 BER, CBOR, ProtoBuf, bplist, …- and more!
© SORACOMフォーマットの組み合わせも可能例)- pcap > ether8023_frame > ipv4_packet >tcp_segment- mp3 > id3v2 > jpeg > exif > icc_profile
© SORACOMDemo$ fqUsage: fq [OPTIONS] [--] [EXPR] [FILE...]
© SORACOMSupported formats$ fq -h formatsaac_frame Advanced Audio Coding frameadts Audio Data Transport Streamadts_frame Audio Data Transport Stream frameamf0 Action Message Format 0apev2 APEv2 metadata tagar Unix archiveasn1_ber ASN1 BER (basic encoding rules, also CER and DER)av1_ccr AV1 Codec Configuration Recordav1_frame AV1 frameav1_obu AV1 Open Bitstream Unitavc_annexb H.264/AVC Annex Bavc_au H.264/AVC Access Unitavc_dcr H.264/AVC Decoder Configuration Recordavc_nalu H.264/AVC Network Access Layer Unitavc_pps H.264/AVC Picture Parameter Setavc_sei H.264/AVC Supplemental Enhancement Informationavc_sps H.264/AVC Sequence Parameter Setavro_ocf Avro object container filebencode BitTorrent bencodingbitcoin_blkdat Bitcoin blk.datbitcoin_block Bitcoin blockbitcoin_script Bitcoin scriptbitcoin_transaction Bitcoin transactionbsd_loopback_frame BSD loopback framebson Binary JSONbzip2 bzip2 compression
© SORACOMTop level elements$ fq . example.mp4|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: example.mp4 (mp4)0x000000|00 00 00 20 66 74 79 70 69 73 6f 6d 00 00 02 00|... ftypisom....| boxes[0:4]:* |until 0xaf8b1c.7 (end) (11504413) | |0x000030|de 02 00 4c 61 76 63 35 38 2e 35 34 2e 31 30 30|...Lavc58.54.100| tracks[0:2]:* |until 0xaf8b1c.7 (end) (11504365) | |
© SORACOMDig into children$ fq .boxes[] example.mp4|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.boxes[0]{}: box0x00|00 00 00 20 |... | size: 320x00| 66 74 79 70 | ftyp | type: "ftyp" (File type and0x00| 69 73 6f 6d | isom | major_brand: "isom"0x00| 00 00 02 00| ....| minor_version: 5120x10|69 73 6f 6d 69 73 6f 32 61 76 63 31 6d 70 34 31|isomiso2avc1mp41| brands[0:4]:|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.boxes[1]{}: box0x20|00 00 00 08 |.... | size: 80x20| 66 72 65 65 | free | type: "free" (Free space)| | | data: raw bits|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.boxes[2]{}: box0x000020| 00 af 41 44 | ..AD | size: 114855080x000020| 6d 64 61 74| mdat| type: "mdat" (Mediadata0x000030|de 02 00 4c 61 76 63 35 38 2e 35 34 2e 31 30 30|...Lavc58.54.100| data: raw bits* |until 0xaf416b.7 (11485500) | ||00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.boxes[3]{}: box0xaf4160| 00 00 49 b1| ..I.| size: 188650xaf4170|6d 6f 6f 76 |moov | type: "moov" (Container0xaf4170| 00 00 00 6c 6d 76 68 64 00 00 00 00| ...lmvhd....| boxes[0:4]:0xaf4180|00 00 00 00 00 00 00 00 00 00 03 e8 00 00 ea d6|................|* |until 0xaf8b1c.7 (end) (18857) | |
© SORACOMConvert to JSON values$ fq tovalue example.mp4{"boxes": [{"brands": ["isom","iso2","avc1","mp41"],"major_brand": "isom","minor_version": 512,"size": 32,"type": "ftyp"},{"data": "<0>","size": 8,"type": "free"},{"data":"<11485500>3gIATGF2YzU4LjU0LjEwMAAB6GhZKpB2RYXYAHFbnRmdY7u+QB+4mc2yKb1ftL+JGFMaI7AZ2A0wLMG4PyF85+/E
© SORACOMREPL$ fq -i . example.mp4mp4>
© SORACOMREPL$ fq -i . example.mp4mp4> .|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: example.mp4 (mp4)0x000000|00 00 00 20 66 74 79 70 69 73 6f 6d 00 00 02 00|... ftypisom....| boxes[0:4]:* |until 0xaf8b1c.7 (end) (11504413) | |0x000030|de 02 00 4c 61 76 63 35 38 2e 35 34 2e 31 30 30|...Lavc58.54.100| tracks[0:2]:* |until 0xaf8b1c.7 (end) (11504365) | |mp4>
© SORACOMREPL$ fq -i . example.mp4mp4> .|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: example.mp4 (mp4)0x000000|00 00 00 20 66 74 79 70 69 73 6f 6d 00 00 02 00|... ftypisom....| boxes[0:4]:* |until 0xaf8b1c.7 (end) (11504413) | |0x000030|de 02 00 4c 61 76 63 35 38 2e 35 34 2e 31 30 30|...Lavc58.54.100| tracks[0:2]:* |until 0xaf8b1c.7 (end) (11504365) | |mp4> .tracks[]|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.tracks[0]{}: track0x000210| 00 00 db b7 65 b8 00 04 00 00 04 1e 4c 50| ....e.......LP| samples[0:1200]:0x000220|00 37 27 27 27 27 27 11 c7 d2 72 72 72 62 80 61|.7'''''...rrrb.a|* |until 0xaf416b.7 (11485018) | || | | id: 1| | | data_foramt: "avc1"|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.tracks[1]{}: track0x000030|de 02 00 4c 61 76 63 35 38 2e 35 34 2e 31 30 30|...Lavc58.54.100| samples[0:470]:* |until 0xaf3521.7 (11482354) | || | | id: 2| | | data_foramt: "mp4a"mp4>
© SORACOMREPL$ fq -i . example.mp4mp4> .tracks[0].samples[0]|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e0f|0123456789abcdef|.tracks[0].samples[0][0:2]: sample (avc_au)0x00210| 00 00 db b7 65 b8 00 04 00 00 04 1e 4c 50| ....e.......LP| [0]{}: nalu0x00220|00 37 27 27 27 27 27 11 c7 d2 72 72 72 62 80 61|.7'''''...rrrb.a|* |until 0xddcc.7 (56251) | |0x0ddc0| 00 00 ba| ...| [1]{}: nalu0x0ddd0|2a 65 00 08 70 b8 00 04 00 00 04 1e 23 14 00 09|*e..p.......#...|* |until 0x197fa.7 (47662) | |mp4>
© SORACOM他にもまだまだ便利な機能が- jq の関数・機能がすべて使える (gojq のおかげ)- select() とか @csv とか- 独自の関数を定義して読み込ませることもできる- 対応してないフォーマットは自分でデコーダを書ける(ライブラリが充実しているのですごく簡単)CI のスクリプトに組み込んで、生成したメディアファイルの自動チェックとかがきっと捗るはず
© SORACOM宣伝(というか自慢)- 私が fq に送った 2 つの PR がマージされました- WebAssembly Module (.wasm) (PR #383)- Timezone Information Format (.tzif) (PR #498)
© SORACOM宣伝 その2- fq にインスパイアされて「日付・時刻」を jq っぽく扱えるコマンド dq を作りました!https://github.com/bitbears-dev/dq$ dq -r 'guess("2022-10-23T23:03:01+09:00") | add(-3 | hours) | .rfc3339'2022-10-23T20:03:01+09:00