
Goバイナリを解析してシンボル、関数メタデータ、型、ファイルパス、埋め込み文字列を復元します。ストリップ済みやUPXでパックされたサンプルにも対応し、IDA Proへのインポートもサポートします。

GoReSymは、プログラムのメタデータ(CPUアーキテクチャ、OS、エンディアン、コンパイラバージョンなど)、関数のメタデータ(開始・終了アドレス、名前、ソース)、ファイル名と行番号のメタデータ、および埋め込まれた構造体や型を抽出するGoシンボルパーサーです。このクロスプラットフォームプログラムは、オープンソースのGoコンパイラとランタイムコードに直接基づいています。
上流のGoランタイムコードは、以下を処理できるように拡張されています:
moduledata構造体の位置リバースエンジニアリングの詳細と使用例については、https://www.mandiant.com/resources/blog/golang-internals-symbol-recovery を参照してください。
ビルド済みのlinux、macos、windows用GoReSymバイナリは、Releasesタブからダウンロードできます。
最近のGoコンパイラを使用してソースからビルドするには、Goコンパイラを実行します:
go build
GoReSym をビルドしたら、次のようにして呼び出します:
GoReSym.exe -t -d -p /path/to/input.exe
この例では、GoReSym に対して、ファイル /path/to/input.exe 内に埋め込まれた型名 (-t)、ユーザーパッケージ名、標準 Go パッケージ名 (-d)、および入力ファイルパス (-p) を復元するよう要求します。出力は次のようになります:
{
"Version": "1.14.15",
"BuildId": "Zb9QmokKTiOUgHKmaIwz/wd2rtE3W9PN-um1Ocdzh/qTdqcTY_jVajHy_-TtYv/Z_kJu9M77OjfijEiHMcF",
"Arch": "amd64",
"TabMeta": {
"VA": 5174784,
"Version": "1.2",
"Endianess": "LittleEndian",
"CpuQuantum": 1,
"CpuQuantumStr": "x86/x64",
"PointerSize": 8
},
"ModuleMeta": {
"VA": 5678816,
"Types": 4845568,
"ETypes": 5171904,
"Typelinks": {
"Data": 5171904,
"Len": 695,
"Capacity": 695
},
"ITablinks": {
"Data": 5174688,
"Len": 11,
"Capacity": 11
},
"LegacyTypes": {
"Data": 0,
"Len": 0,
"Capacity": 0
}
},
"Types": [ ... ],
"Files": [ ... ],
"Strings": [ ... ],
"UserFunctions": [ ... ],
"StdFunctions": [ ... ]
}
利用可能なフラグは以下のとおりです:
-d("default"、任意)フラグは、ユーザーパッケージに加えて標準 Go パッケージを出力します。-p("paths"、任意)フラグは、pclntab に埋め込まれたファイルパスを出力します。-t("types"、任意)フラグは、Go の型名を出力します。-strings(任意)フラグは、文字列インターンテーブルを解析してバイナリに埋め込まれた Go 文字列を抽出します。-m <virtual address>("manual"、任意)フラグは、指定された仮想アドレスにある RTYPE 構造体を再帰的にダンプします-v <version string>("version"、任意)フラグは、自動バージョン検出を上書きし、指定されたバージョンを使用します。これは一部のストリップされたバイナリで必要です。バージョンが正確でない場合、型の解析は失敗します。-human(任意)フラグは、JSON の代わりにフラットなテキスト一覧を出力します。特に構造体型やインターフェース型を出力する際に便利です。-about(任意)フラグは、ライセンス情報を出力しますこの情報を IDA Pro にインポートするには、https://github.com/mandiant/GoReSym/blob/master/IDAPython/goresym_rename.py にあるスクリプトを実行します。このスクリプトは GoReSym が生成した json ファイルを読み取り、IDA 内のシンボル/ラベルを設定します。
Go コンパイラとランタイムが変更されるにつれて、埋め込まれたメタデータ構造も変化してきました。GoReSym は以下の Go リリースとメタデータの組み合わせをサポートしています:
pclntab の解析:Go 1.2 以降moduledata の位置特定:Go 1.2 以降moduledata の型解析:Go 1.5 以降型を抽出するために使用される moduledata テーブルは Go 1.5 より前には存在しないため、このライブラリが非常に古い Go バージョンから型を抽出することをサポートすることは決してありません。
このライブラリは現在、1.2 より前、1.2、1.16、1.18、1.20 の pclntab レイアウトを処理します。pclntab のバージョンは常に Go ランタイムのバージョン以下であることに注意してください(例:Go ランタイム 1.19 は 1.18 の pclntab レイアウトを使用します)。私たちは_常に最新のランタイムバージョンをサポートする_ことを目指しています。
GoReSym のソースコードの多くは、アップストリームの Go コンパイラのソースディレクトリ /internal からコピーされています。これを機能させるために、ソースを多少調整する必要がありました。GoReSym に貢献したい場合は、このインポートプロセスについて説明しますので、以下をお読みください。
Go パッケージの仕組み上、ソースファイルツリーから /internal パスを削除する必要がありました。その結果、多くの内部 Go ファイルをコピーすることになり、ディレクトリツリーはほぼそのままですが、多くのファイルのインポートに小さな変更が加えられています:/internal パスへの参照は github.com/mandiant/GoReSym/ に置き換えられました。
また、多くの内部構造体を変更してフィールドとメソッドをエクスポートするようにしました。これらはユーザーが依存すべきではないため、Go アップストリームではエクスポートされていません。しかし、このツールの目的は内部情報を抽出することであるため、私たちはこれらの構造体を維持するタスクを引き受けています。良い状況ではありませんが、簡単に避けられるものでもありません。このリポジトリを更新する場合は、これらの変更をそのまま維持するよう注意する必要があります。アップストリームのファイルを丸ごとコピーするよりも、アップストリームからコミットを手動でマージする方がおそらく良いでしょう。
典型的な go build でコンパイルしながらこれらの問題を回避するために、このプロジェクトをより良く構成する方法についての提案を歓迎します。Go のメンテナーを巻き込んだ以前の議論がこちらにあります。
いくつかの些細な変更を除けば、ほとんどの新しいロジックは /objfile にあります。例えば、ファイル objfile/internals は GoReSym が解析する逆順の内部 Go 構造体を定義しています。
pclntab 仕様: golang.org/s/go12symtabpclntab マジック値: pclntab.go#L169objfile のバグ:
buildID のレガシーバグ: golang/go#50809runtime_modulesinit 初期化メソッドのシグネチャに基づいて pclntab の検索も試みるようになり、pclntab マジック値が変更されている場合にはその修復も試みます。objfile/<fileformat> 内の pcln() 関数を拡張し、pclntab マジック値のバイトスキャンをサポートしました。/debug/<fileformat> 内のファイルフォーマットパーサーでシグネチャスキャンをサポートするため、DataAfterSection などのルーチンを追加しました。debug/gosym/symtab.go の walksymtab にチェックを追加し、オプションの symtab セクションが空の場合に早期に終了するようにしました。objfile/objfile.go の PCLineTable() から goobj の liner サポートを削除しました。loadPeTable(およびその他のフォーマット変種)の周辺に追加の健全性チェックを追加し、シンボルが存在するものの悪意をもって無効に改変されている場合のパニックを回避しました(参照: golang/go#47981)。read_memory ルーチンを実装し、仮想アドレスによってファイルデータを読み取れるようにしました。moduledata スキャンルーチンを導入しました。readStringTable に追加しました。解析失敗も無視されるようになりました。MIT