Calendrier de l'Avent du Département étudiant LOCAL Jour 11
J'avais peur que tout le monde soit têtu et "N'est-ce pas trop faible ...?", Alors j'ai décidé de lancer une balle changeante. Dans la mesure où j'ai cherché, il n'y a pas de littérature japonaise, donc je pense que les personnes qui recherchent ceci à l'avenir verront cet article presque automatiquement. Je voudrais vous demander à tous. Si vous pensez: "De quoi parlez-vous? N'est-ce pas plein d'informations incorrectes?", Veuillez commenter. Je ferai de mon mieux pour y remédier.
Officiel: kaitai.io
Kaitai Struct est un langage déclaratif utilisé pour décrire des structures de données binaires.
Le code source de l'analyseur de données binaires peut être généré automatiquement en fonction de la structure de données écrite dans votre propre langue.
license Le compilateur et le visualiseur décrits plus tard sont GPL v3 +, et la bibliothèque pour chaque langage est MIT (JS est Apache v2). Cela signifie-t-il que le code source généré à l'aide du compilateur infectera la GPL ...? Veuillez me dire une personne détaillée.
Kaitai Struct Compiler (KSC)
Pour plus d'informations sur l'installation ici
Mac est un coup avec brew install kaitai-struct-compiler
.
Pour Windows, suivez le lien ci-dessus pour télécharger le programme d'installation.
# Import GPG key, if you never used any BinTray repos before
sudo apt-key adv --keyserver hkp://pool.sks-keyservers.net --recv 379CE192D401AB61
# Add stable repository
echo "deb https://dl.bintray.com/kaitai-io/debian jessie main" | sudo tee /etc/apt/sources.list.d/kaitai.list
# ... or unstable repository
echo "deb https://dl.bintray.com/kaitai-io/debian_unstable jessie main" | sudo tee /etc/apt/sources.list.d/kaitai.list
sudo apt-get update
sudo apt-get install kaitai-struct-compiler
Kaitai Struct Visualizer (KSV)
Ceci est un visualiseur simple pour les fichiers .ksy
.
Écrit en «Ruby», il est disponible sous forme de paquet «gem».
gem install kaitai-struct-visualizer
Pour les fichiers bien connus, il existe un fichier .ksy
dans le dépôt officiel github (https://github.com/kaitai-io/kaitai_struct_formats).
(Si vous souhaitez utiliser le fichier .ksy
qui existe ici, veuillez vérifier la licence décrite dans meta / license
dans le fichier.)
Si vous écrivez un nouveau .ksy
, envoyez une pull request.
(kaitai_struct_formats/CONTRIBUTING.md)
<détails> La structure du fichier est du début Écrivons ceci dans KSY (Kaitai Struct YAML) déclare un seul type défini par l'utilisateur (littéralement traduit de officiel).
Type défini par l'utilisateur meta Décrivez le nom du type défini par l'utilisateur à décrire dans seq Décrivez la structure des données dans types Les types définis par l'utilisateur peuvent être imbriqués dans L'utilisation est très similaire à «seq».
ʻId Certains champs (dans ce cas, Visualize À ce stade, vous avez écrit le code suivant. Visualisons cela en utilisant ksv (Kaitai Struct Visualizer).
L'utilisation est Il semble qu'il puisse être bien lu. C'est le sujet principal.
J'ai fait un fichier compressé dans l'article ici.
Cette fois, décompressez ce fichier compressé à l'aide de KS.
Voir l'article pour la structure du fichier. Générez du code à partir de Le code généré par «mcp.py».
Écrivons un script de décompression en utilisant ceci. Vous pouvez répondre avec Pour lire le fichier, utilisez Je pense que KS est assez pratique.
C'est facile à écrire et vous pouvez l'utiliser dans votre langue préférée, de sorte que le coût d'apprentissage de nouvelles choses est très faible.
La référence officielle est honnêtement difficile à lire, mais plus de gens comme moi écriront des articles sur KS à l'avenir (probablement). Souhaitez-vous "démonter" avec KS?
Recommended Posts
matrix.py
import numpy as np
import struct
def create_header(*mats: [np.ndarray], magic: bytes = None) -> bytes:
header = magic
header += struct.pack('<H', len(mats))
length = len(header) + 8 * len(mats)
for mat in mats:
header += struct.pack('<HH', mat.shape[0], mat.shape[1])
header += struct.pack('<I', length)
length += 4 * mat.shape[0] * mat.shape[1]
return header
mat1 = np.random.randint(-1024, 1024, [3, 3], dtype=np.int32)
mat2 = np.random.randint(-1024, 1024, [5, 9], dtype=np.int32)
mat3 = np.random.randint(-1024, 1024, [2, 2], dtype=np.int32)
with open('test.matrix', 'wb') as o:
magic = b'THIS IS MAT FILE.\x01\x02'
o.write(create_header(mat1, mat2, mat3, magic=magic))
for mat in [mat1, mat2, mat3]:
for y in mat:
for x in y:
o.write(struct.pack('<i', x))
test.matrix
Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000: 4D 41 54 01 02 2F 03 00 03 00 03 00 20 00 00 00 MAT../..........
00000010: 05 00 09 00 44 00 00 00 02 00 02 00 F8 00 00 00 ....D.......x...
00000020: DC FE FF FF 49 01 00 00 A7 FF FF FF 17 02 00 00 \~..I...'.......
00000030: 25 FC FF FF 35 FF FF FF B5 00 00 00 CF FE FF FF %|..5...5...O~..
00000040: E2 FF FF FF 5D 00 00 00 15 FE FF FF 30 FC FF FF b...]....~..0|..
00000050: 4C 03 00 00 C1 FF FF FF B0 FD FF FF 31 02 00 00 L...A...0}..1...
00000060: 54 03 00 00 C4 FF FF FF 65 FF FF FF D0 FE FF FF T...D...e...P~..
00000070: 75 01 00 00 DE FE FF FF ED 00 00 00 ED FC FF FF u...^~..m...m|..
00000080: BE FD FF FF E5 02 00 00 EC FE FF FF 22 FE FF FF >}..e...l~.."~..
00000090: C3 02 00 00 11 00 00 00 29 03 00 00 00 01 00 00 C.......).......
000000a0: 78 00 00 00 C4 FC FF FF 4C 02 00 00 88 00 00 00 x...D|..L.......
000000b0: 43 FF FF FF 35 FF FF FF A4 00 00 00 CF 02 00 00 C...5...$...O...
000000c0: 3A FF FF FF 33 FF FF FF BD FE FF FF F9 01 00 00 :...3...=~..y...
000000d0: 22 FF FF FF 3A 02 00 00 7C 00 00 00 15 FF FF FF "...:...|.......
000000e0: D8 FE FF FF 42 00 00 00 82 02 00 00 24 02 00 00 X~..B.......$...
000000f0: 8A FE FF FF AF FF FF FF EF 02 00 00 96 01 00 00 .~../...o.......
00000100: 83 01 00 00 2F 02 00 00
b'MAT\x01\x02/'
matrix.ksy
.
meta
doc
seq
types
instances
enums
Consiste en.
Vous n'êtes pas obligé de tout avoir.
Voir la référence officielle pour plus d'informations.meta
meta:
id: matrix
endian: le
meta / id
. Il doit toujours être dans le fichier «.ksy».
meta / endian
décrit l'endian par défaut utilisé dans la structure ( le
/ be
)seq
seq:
- id: magic
contents: ['MAT', 1, 0x2, '/']
- id: header_num
type: u2
- id: headers
repeat: expr
repeat-expr: header_num
type: header
seq
.
ʻIdest le nom de la variable. Si les données sont une constante, écrivez la constante dans
contents. Si vous voulez obtenir la valeur, décrivez le type de données dans
type(voir [ici](https://doc.kaitai.io/ksy_reference.html#primitive-data-types) pour plus de détails). Vous pouvez également utiliser les types décrits dans
typesdécrits plus loin. Ici, le type «header» est utilisé.
repeat peut contenir n'importe lequel de ʻexpr
, ʻeos, ʻuntil
(voir ici pour plus de détails). )
Si vous entrez ʻexpr, entrez le nombre de répétitions dans
repeat-expr`.types
types:
header:
seq:
- id: shape0
type: u2
- id: shape1
type: u2
- id: offset
type: u4
instances:
mat_body:
pos: offset
io: _root._io
type: matrix
matrix:
seq:
- id: dim0
repeat: expr
repeat-expr: _parent.shape0
type: dim1
types:
dim1:
seq:
- id: dim1
repeat: expr
repeat-expr: _parent._parent.shape0
type: s4
types
.
Le type «en-tête» utilise des «instances», qui peuvent être utilisées pour lire des données autres que celles qui existent en séquence, telles que «seq».header.instances
instances:
mat_body:
pos: offset
io: _root._io
type: matrix
est le
mat_body ici. ʻO
est le flux IO à utiliser.
pos
est le nombre d'octets depuis le début de ʻio`.
«type» est le même que pour «seq».À propos des variables
repeat-expr
, pos
, ʻio) peuvent faire référence à des variables ainsi qu'à des valeurs constantes. Vous ne pouvez pas voir les données qui n'ont pas encore été lues. Les données ont une structure arborescente (c'est facile à comprendre si vous utilisez ksv), et vous pouvez spécifier l'élément parent avec
_parent. Vous pouvez également spécifier l'élément supérieur avec
_root`.matrix.ksy
meta:
id: matrix
endian: le
seq:
- id: magic
contents: ['MAT', 1, 0x2, '/']
- id: header_num
type: u2
- id: headers
repeat: expr
repeat-expr: header_num
type: header
types:
header:
seq:
- id: shape0
type: u2
- id: shape1
type: u2
- id: offset
type: u4
instances:
mat_body:
pos: offset
io: _root._io
type: matrix
matrix:
seq:
- id: dim0
repeat: expr
repeat-expr: _parent.shape0
type: dim1
types:
dim1:
seq:
- id: dim1
repeat: expr
repeat-expr: _parent._parent.shape0
type: s4
ksv <file_to_parse.bin> <format.ksy>
.shell
$ ksv test.matrix matrix.ksy
ksv
[-] [root] 00000000: 4d 41 54 01 02 2f 03 00 03 00 03 00 20 00 00 00 | MAT../...... ...
[.] magic = 4d 41 54 01 02 2f 00000010: 05 00 09 00 44 00 00 00 02 00 02 00 f8 00 00 00 | ....D...........
[.] header_num = 3 00000020: dc fe ff ff 49 01 00 00 a7 ff ff ff 17 02 00 00 | ....I...........
[-] headers (3 = 0x3 entries) 00000030: 25 fc ff ff 35 ff ff ff b5 00 00 00 cf fe ff ff | %...5...........
[-] 0 00000040: e2 ff ff ff 5d 00 00 00 15 fe ff ff 30 fc ff ff | ....].......0...
[.] shape0 = 3 00000050: 4c 03 00 00 c1 ff ff ff b0 fd ff ff 31 02 00 00 | L...........1...
[.] shape1 = 3 00000060: 54 03 00 00 c4 ff ff ff 65 ff ff ff d0 fe ff ff | T.......e.......
[.] offset = 32 00000070: 75 01 00 00 de fe ff ff ed 00 00 00 ed fc ff ff | u...............
[-] mat_body 00000080: be fd ff ff e5 02 00 00 ec fe ff ff 22 fe ff ff | ............"...
[-] dim0 (3 = 0x3 entries) 00000090: c3 02 00 00 11 00 00 00 29 03 00 00 00 01 00 00 | ........).......
[-] 0 000000a0: 78 00 00 00 c4 fc ff ff 4c 02 00 00 88 00 00 00 | x.......L.......
[-] dim1 (3 = 0x3 entries) 000000b0: 43 ff ff ff 35 ff ff ff a4 00 00 00 cf 02 00 00 | C...5...........
[.] 0 = -292 000000c0: 3a ff ff ff 33 ff ff ff bd fe ff ff f9 01 00 00 | :...3...........
[.] 1 = 329 000000d0: 22 ff ff ff 3a 02 00 00 7c 00 00 00 15 ff ff ff | "...:...|.......
[.] 2 = -89 000000e0: d8 fe ff ff 42 00 00 00 82 02 00 00 24 02 00 00 | ....B.......$...
[-] 1 000000f0: 8a fe ff ff af ff ff ff ef 02 00 00 96 01 00 00 | ................
[-] dim1 (3 = 0x3 entries) 00000100: 83 01 00 00 2f 02 00 00 | ..../...
[.] 0 = 535
[.] 1 = -987
[.] 2 = -203
[-] 2
[+] dim1
[-] 1
[.] shape0 = 5
[.] shape1 = 9
[.] offset = 68
[-] mat_body
[+] dim0
[+] 2
Décompression de fichier
mcp.ksy
meta:
id: mcp
encoding: UTF-8
endian: le
seq:
- id: file
type: file
repeat: eos
types:
file:
seq:
- id: filename_len
type: u4
- id: filebody_len
type: u4
- id: filename
type: str
size: filename_len
- id: filebody
size: filebody_len
process: zlib
meta / encoding
spécifie l'encodage par défaut à utiliser avec type: str
.
repeat: eos
se répète jusqu'à la fin du flux.
process: zlib
répond aux données lues avec zlib. (Très pratique)
process
, cliquez ici](https://doc.kaitai.io/ksy_reference.html#spec-process)mcp.ksy
en utilisant ksc (Kaitai Struct Compiler).usage
Usage: kaitai-struct-compiler [options] <file>...
<file>... source files (.ksy)
-t, --target <language> target languages (graphviz, csharp, all, perl, java, go, cpp_stl, php, lua, python, ruby, javascript)
-d, --outdir <directory>
output directory (filenames will be auto-generated)
-I, --import-path <directory>:<directory>:...
.ksy library search path(s) for imports (see also KSPATH env variable)
--go-package <package> Go package (Go only, default: none)
--java-package <package>
Java package (Java only, default: root package)
--java-from-file-class <class>
Java class to be invoked in fromFile() helper (default: io.kaitai.struct.ByteBufferKaitaiStream)
--dotnet-namespace <namespace>
.NET Namespace (.NET only, default: Kaitai)
--php-namespace <namespace>
PHP Namespace (PHP only, default: root package)
--python-package <package>
Python package (Python only, default: root package)
--opaque-types <value> opaque types allowed, default: false
--ksc-exceptions ksc throws exceptions instead of human-readable error messages
--ksc-json-output output compilation results as JSON to stdout
--verbose <value> verbose output
--debug enable debugging helpers (mostly used by visualization tools)
--help display this help and exit
--version output version information and exit
shell
$ ksc -t python mcp.ksy
mcp.py
# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
from pkg_resources import parse_version
from kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO
import zlib
if parse_version(ks_version) < parse_version('0.7'):
raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version))
class Mcp(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None):
self._io = _io
self._parent = _parent
self._root = _root if _root else self
self._read()
def _read(self):
self.file = []
i = 0
while not self._io.is_eof():
self.file.append(self._root.File(self._io, self, self._root))
i += 1
class File(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None):
self._io = _io
self._parent = _parent
self._root = _root if _root else self
self._read()
def _read(self):
self.filename_len = self._io.read_u4le()
self.filebody_len = self._io.read_u4le()
self.filename = (self._io.read_bytes(self.filename_len)).decode(u"UTF-8")
self._raw_filebody = self._io.read_bytes(self.filebody_len)
self.filebody = zlib.decompress(self._raw_filebody)
extract.py
from mcp import Mcp
import os
import sys
mcps = Mcp.from_file(sys.argv[1])
out = 'output/'
if len(sys.argv) >= 3:
out = sys.argv[2]
for f in mcps.file:
if os.path.dirname(f.filename):
os.makedirs(os.path.join(out, os.path.dirname(f.filename)), exist_ok=True)
with open(os.path.join(out, f.filename), 'wb') as o:
o.write(f.filebody)
python extract.py <target.mcp> [dossier_sortie]
KaitaiStruct.from_file (file_path)
.
Si vous voulez lire la chaîne d'octets telle quelle, utilisez KaitaiStruct.from_bytes (bytes)
.
Pour les flux IO, utilisez KaitaiStruct.from_io (io)
.à la fin