
2026/09/04 16:17
非公式なデータベースのストレージ形式のリバースエンジニアリング
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
最も重要な成果は、Codex を用いて構築された改良版オープンソースツール「cronodump」を使用して、破損した CronosPro データベースファイル(.dat および .tad)から重要データを成功裡に復元したことである。元の
cronodump は、CroBank および CroIndex が KOD エンコードされていると誤って推定していたために失敗したが、新しいアプローチは、統計的再構成と正確なバグ修正を組み合わせることで実現された。チームは有効な Cronos 構造から統計的参照データを構築し、バイトの頻度を推定した上で、SciPy のハンガリアンアルゴリズム(linear_sum_assignment)を用いて 256 バイトのパージョン制約を解いた。また、重要な解析器のエラーも修正された。具体的には、Cronos v4 で 0x08 フラグによって示されているように、12 バイトの extents ヘッダーが誤って含まれて位置オフセットを引き起こす問題、そして Windows-1251 エンコーディングで文字化けしたテキスト値を UTF-8 に明示的にデコードしない問題であった。さらに、idx2 プロパティによって指定された隠れた内部フィールドを考慮することにより、可視定義と保存された値を整列させるためのフィールドマッピングも修正された。この堅牢なソリューションは、今や読み取れない十六進数データではなく、修正されたフィールドマッピング付きで正確な CSV エクスポートを生成し、貴重な歴史的アーカイブへのアクセスを回復させ、このレガシーシステムを使用している組織に必要なデータ移行を可能にしている。本文
「壊れた」とされる CronosPro データベースの完全復号化:Cronodump の改良と分析
既存のツールで解析不能とされていたクロノスプロ(CronosPro)データベースファイル(
CroBank.dat、CroIndex.dat、CroStru.dat)を、Codex を用いて正常にダンプし、AlephData の Cronodump プロジェクトを改良しました。
クロノスプロのアーキテクチャとファイル構造
独自所有のデータベースシステム
- クロノス(Cronos)/ CronosPro:ロシアや旧ソビエト圏で広く使用されたデスクトップ情報管理システム。
- 独自の用語体系
- Database → Bank
- Table → Base
- Record ID → System Number
ファイルの役割と関係性
クロノスデータベースは複数の関連するバイナリファイルで構成されます。
| ファイル | 目的 |
|---|---|
/ | データベース構造(テーブル、フィールド定義) |
/ | 実際のレコードデータ |
/ | 検索インデックス |
/ | システム情報 |
ファイル:実際のデータを格納。.dat
ファイル:ディレクトリのような役割(レコードの位置指示)。.tad- メンタルモデル
- CroStru: データベースの外観と定義。
- CroBank: 行(レコード)自体。
- CroIndex: レコードの検索を支援。
⚠️ 注意点:レコードデータは読み取り可能ですが、それを解釈するスキーマは暗号化されています。
パース処理における課題と定義
「正規化」の意味
ここではリレーショナルデータベースの「正規形」ではなく、バイナリデータの可搬性・審査可能性への変換を指します。
- クロノスバイナリファイルからの変換。
- デコードされたテーブルとフィールドへのマッピング。
- 正しい型付けおよび位置調整された値の確保。
- UTF-8 CSV ファイルへの出力。
保持すべき関係性
単なる文字列抽出ではなく、以下の関係を維持することが不可欠です。
- テーブルとレコード間の関係。
- カラム名と値の関係。
- 日付とその意味の関係。
- テキストとその元の符号化方式(Windows-1251 など)の関係。
- 内部フィールド位置の関係。
❌ 誤ったヘッダーの危険性 ヘッダーがずれている CSV は、有効に見えるだけですが実質的に意味を喪失しています。
解析プロセスと改良点
既存ツールの失敗要因
Cronodump で失敗した主な理由は以下の通りです。
(スキーマファイル)が KOD エンコードされていたため、通常のパーサーは読み込めなかった。CroStru.dat
およびCroBank.dat
は KOD エンコードされていないはずだったものの、既存の推測手法(クラック)が失敗した。CroIndex.dat
解決のための技術的アプローチ
1. 圧縮と保護の区別
- 圧縮: データの占有スペース削減(バイト変形)。
- KOD 保護: バイト値の置換(
)。Substitution Table - 既存ツールの限界:KOD テーブルを学習するための仮定が誤っていたため復号失敗。
2. KOD テーブル(置換テーブル)の復元
クロノスは 256 エントリの置換テーブルを用いてデータを保護します。さらに複雑に、位置とレコード番号にも依存して変化するアルゴリズムを使用しています。
plaintext[i] = KOD[ciphertext[i]] - i - record_number (mod 256)
3. 統計的アプローチによる割り当て問題の解決
KOD テーブルは完全な置換(パーミュテーション)である必要があり、各シフタバイトが一意のマッピングを持つ必要があります。これをハンガリアンアルゴリズムを用いて解決しました。
- 参照分布の構築: 既知のテストデータベースから、有効なスキーマデータに存在する傾向(ゼロバイト、ASCII プロパティ名など)を学習。
- スコア表の生成: 各可能な KOD マッピングについて妥当性のスコア付けを実施。
- 最適化コード:
from scipy.optimize import linear_sum_assignment # スコアを負にして最大尤度割り当てを選択 rows, columns = linear_sum_assignment(-scores)
4. 構造検証と追加ヘッダーの発見
復元したスキーマレコードには、12 バイトの拡張ヘッダーが存在することが判明しました。
- 問題: パースャがこれを無視してデコードすると、すべてのバイト位置に誤差が生じる。
- 解決:
の v4 フラグ(CroStru
)を検知し、ヘッダーをスキップしてからペイロードをデコードするロジックを実装。0x08
5. テキストエンコーディングの修正
- 問題: Windows-1251 で表現されたテキストが 16 進数としてエクスポートされていた(例:
)。c1 c8 d7... - 解決: 文書化されたタイプ(1, 2, 3)に対して明示的に
からユニコードへの変換を実装。cp1251elif self.typ in (1, 2, 3): self.content = data.rstrip(b"\x00").decode("cp1251", "ignore")
6. 物理的なフィールド位置の追跡
クロノスレコードには「見えない」内部フィールドが存在することがあります。可視定義と実際のデータ位置を照合する必要があります。
- 手法: フィールド定義の
(物理的位置)と、現在の読み込みインデックスを比較し、隠れたフィールドを読み取るまでループ処理を行うロジックを実装。idx2source_index = 1 for field_definition in table_definition[1:]: while source_index < field_definition.idx2 and not reader.eof(): read_field_data(reader) # 隠れたフィールドを消費 source_index += 1 value = read_field_data(reader) if not reader.eof() else b"" source_index += 1
結論:統合されたソリューション
最終的な CSV コンバージョンは、以下の要素を統合したものです。
- オープンソースの
パッケージCronodump - 曖昧な KOD 問題に対する PR #22 のアイデア(対話型回復ワークフロー)
- 統計的 KOD 再構成
- ハンガリアンアルゴリズムによるグローバル割り当て
- 正しい CroStru v4 エクステンション処理
- Windows-1251 からユニコードへの自動変換
- 物理的なフィールド位置追跡
- 有界な意味論的検証(日付や名前が正しいカラムにあるか確認)
これにより、「壊れている」と見なされていたデータベースを、完全に解析可能な CSV に変換することができました。