備忘録

備忘録

.protoをシリアライズされているバイナリデータから作る

Ⅰ. はじめに

私の知る限りバイナリから自動で.protoを生成するツールは公開されていません。
よって、シリアライズされているバイナリデータを読み取る為の.proto作成は手動となります。

また、ProtocolBuffersはシリアライズした時key-valueのkey情報が失われる為非常に手間がかかります。
インデックス番号のみ含まれています。
key情報があれば値が何の値を表しているかの情報として利用できる為分かりやすいですが、
key情報が無い為データ値を見て手探りする必要があります。

本記事では少しでも楽に.protoファイルを作る方法をまとめます。

Protocol Buffers の原理についてはこちら
https://developers.google.com/protocol-buffers/docs/encoding

また、この記事でサンプルとして使う元データは以下の通りです。

armor.proto (proto3)

message Armor {
  uint64 id = 1;
  string name = 2;
  repeated Option attribute = 3;
}

message Option {
  uint32 id = 1;
  string detail = 2;
}

データ(C#)

var armors = new List<Armor>();

var fireOption = new Option() { Id = 1001, Detail = "火属性 耐性" };
var waterOption = new Option() { Id = 1002, Detail = "水属性 耐性" };
var woodOption = new Option() { Id = 1003, Detail = "木属性 耐性" };

armors.Add(new Armor() { Id = 100001, Name = "防具001", Attribute = new Option[] { fireOption } });
armors.Add(new Armor() { Id = 100002, Name = "防具002", Attribute = new Option[] { waterOption } });
armors.Add(new Armor() { Id = 100003, Name = "防具003", Attribute = new Option[] { waterOption, woodOption } });

Ⅱ. protofudger を使う方法

GO言語で書かれた非常に優秀なツールです。

ただし、文字列が 1024 * 32バイト(32,768バイト)を超えると例外を吐くので、
fork して修正したものも置いておきます。

使い方
protofudger.exe binary_file > out.txt
出力結果
1: {
  1: (varint) 100001
  2: (string) "防具001"
  3: {
    1: (varint) 1001
    2: (string) "火属性 耐性"
  }
}
1: {
  1: (varint) 100002
  2: (string) "防具002"
  3: {
    1: (varint) 1002
    2: (string) "水属性 耐性"
  }
}
1: {
  1: (varint) 100003
  2: (string) "防具003"
  3: {
    1: (varint) 1002
    2: (string) "水属性 耐性"
  }
  3: {
    1: (varint) 1003
    2: (string) "木属性 耐性"
  }
}

Ⅲ. Protobuf Viewerを使う方法


macOSでのみ動作します。(2017/03/17時点)
GUIがあるのでmacOSが使える状況であればコレが一番使いやすいです。
また、データが欠損している不完全なバイナリファイルでも解読が可能です。
(protoc --decode_rawしても「Filed to parse input.」と出るようなデータでも解析が可能)

https://sourceforge.net/projects/protobufviewer/

Ⅳ. protoc を使う方法

こちらからダウンロードできます。
https://github.com/google/protobuf/releases

また、NuGetから Google.ProtocolBuffers パッケージをインストールすると protoc.exe も含まれています。

使い方
protoc.exe --decode_raw < binary_file > out.txt
作った.protoをテストする場合
protoc --decode=PackageName.MessageName MessageName.proto < binary_file > out.txt
出力結果
1 {
  1: 100001
  2: "\351\230\262\345\205\267001"
  3 {
    1: 1001
    2: "\347\201\253\345\261\236\346\200\247 \350\200\220\346\200\247"
  }
}
1 {
  1: 100002
  2: "\351\230\262\345\205\267002"
  3 {
    1: 1002
    2: "\346\260\264\345\261\236\346\200\247 \350\200\220\346\200\247"
  }
}
1 {
  1: 100003
  2: "\351\230\262\345\205\267003"
  3 {
    1: 1002
    2: "\346\260\264\345\261\236\346\200\247 \350\200\220\346\200\247"
  }
  3 {
    1: 1003
    2: "\346\234\250\345\261\236\346\200\247 \350\200\220\346\200\247"
  }
}

Ⅴ. protobuf-inspectorを使う

説明省略
https://github.com/mildsunrise/protobuf-inspector

Ⅵ. d3を使う

Diablo 3というゲームの.protoを自動生成する為に作られたプロジェクトのようです。
私の環境でDiablo 3ではない物を対象にして.protoの自動生成を試みましたが上手くいきませんでした。
https://github.com/fry/d3