- rev.ngはデコンパイラバックエンド revng-c を公開し、デコンパイルエンジンをオープンソース化するとともに、UIのクローズドベータ・新Webサイト・rev.ng Hub・ドキュメントをあわせて公開
- ローカルではインストールスクリプトでCLIを構成した後、
revng artifact と revng ptml を使って 有効なCコード 形式のデコンパイル結果を確認できる
- インタラクティブUIは VSCodeベース で、ブラウザ版とスタンドアロンアプリの両方を目指しており、ニュースレター購読者をFIFO方式で招待するクローズドベータで提供される
- 自動データ構造復元、協調リバースエンジニアリング、多様なアーキテクチャ対応、拡張性が中核目標だが、現在のQAは Linux x86-64バイナリ に最も注力している
- フレームワークとCLIはオープンソースで、クラウドUIは公開プロジェクトに無料提供され、非公開プロジェクト・オフラインのスタンドアロンUIは有料モデルとして区分される
オープンソース化とクローズドベータ
- rev.ngはデコンパイラバックエンド
revng-c をオープンソースとして公開
- これにより、デコンパイルエンジン全体が オープンソース になった
- 初期の ドキュメント もあわせて提供されている
- UIはニュースレター購読者向けに クローズドベータ 招待を開始予定
- 新Webサイトと rev.ng Hub も同時に公開
- rev.ng Hubはクラウド版への入口
- ベータユーザーはプロジェクトを作成し、ブラウザでUIを実行し、他のユーザーと協業できる
- クローズドベータ対象でなくても 公開プロジェクト は閲覧できる
- rev.ngの機能を直接確認したいユーザー向けに 非公開デモ も実施
CLIでrev.ngを試す
revng はroot権限なしで単一ディレクトリにインストールでき、そのディレクトリを削除すればアンインストールできる
curl -L -s https://rev.ng/downloads/revng-distributable/master/install.sh | bash
cd revng
source ./environment
- サンプル
example.c は argc * 3 を返すシンプルなプログラム
int main(int argc, char *argv[]) {
return argc * 3;
}
gcc でコンパイルした後に revng artifact を実行すると、単一ファイル 形式のデコンパイル結果を取得できる
gcc example.c -o example -O2
revng artifact \
--analyze \
--progress \
decompile-to-single-file \
example \
| revng ptml --color \
| grep -A2 -B1 '[^_]main\b' \
> decompiled.c
ベータの範囲とテスト対象
- UIを利用するには ニュースレター に登録する必要があり、招待は少人数のバッチで進められる
- 今回のリリースは、UIとデコンパイル結果を一部のバイナリでデモし、実際のバイナリ作業に関するフィードバックやバグレポートを受け取ることに重点を置く
- テストに使用した複雑なバイナリと
.text サイズは以下の通り
- rev.ngは複数のABIとプラットフォームをサポートするが、この段階での初期QAは Linux x86-64バイナリ に集中している
- 問題が発生した場合は Discourse で支援を受けられる
rev.ngが目指すデコンパイル体験
- rev.ngの主な注力点は、自動データ構造復元、モダンなUX、協調リバースエンジニアリング、幅広いプラットフォーム対応、拡張性
-
自動データ構造復元
- Data Layout Analysisにより、
struct レイアウトを プロシージャ間解析 を通じて自動復元できる
- 連結リストノードの例では、
int64_t data[5] 配列と次ノードへのポインタを持つ構造体を対象とする
- rev.ngの出力は、配列サイズ5と次要素ポインタへのアクセスを自動検出した構造体と関数コードを生成する
- デコンパイラ出力は構文的に有効なCコード
- この機能は現在利用可能
-
VSCodeベースのインタラクティブUI
- UIは VSCodeベース で、VSCodeユーザーは馴染みある形で利用できる
- ブラウザタブとスタンドアロンアプリケーションの両方で動作可能
- 主なショートカットは以下の通り
Ctrl + Click: カーソル下の関数または型定義へ移動
N: 名前変更
Y: 型編集
X: 参照を表示
- rev.ngは変更があると影響を受ける部分だけを再計算する インタラクティブデコンパイラ
- UIは現在クローズドベータ参加者に提供されている
-
協調リバースエンジニアリング
- rev.ng UIはクライアント・サーバーアーキテクチャを採用
- 複数ユーザーが同じデーモンインスタンスに接続し、同じプロジェクトで同時に作業できる
- クラウド版では、プロジェクト管理のためのGitHubライクなアプリケーション rev.ng Hub を利用できる
- 協業機能は動作しているが、ユーザー体験の改善が必要で、ロードマップ項目 #797 で追跡されている
アーキテクチャとプラットフォーム対応方式
- rev.ngはQEMUパイプラインの前段を使って実行コードを tiny code にリフトし、それをLLVM IRへ変換した後にデコンパイルを行う
- この構造により、QEMUが対応するアーキテクチャ を比較的容易にサポートできる
- アーキテクチャ対応と同じくらい、プラットフォーム、特にABI対応も重要
- 現在の対応状況は以下の通り
- アーキテクチャ: x86、x86-64、ARM、AArch64、MIPS、s390xを異なる成熟度でサポート
- バイナリ形式: ELF、PE/COFF、Mach-Oに対応
- インポート:
.idb、DWARFデバッグ情報、PDBデバッグ情報に対応
- QAの大半はLinux x86-64バイナリで実施されており、その他は追加QAが必要
- より多くのプラットフォームQAは ロードマップ項目 #58 で追跡されている
拡張性とスクリプティング
- rev.ngはリバースエンジニアリングツール向けのフレームワークを目指しており、インタラクティブUIを除くプロジェクト全体がオープンソース
- プロジェクトファイルである model はYAML文書のため、JSONまたはYAMLを解析できればrev.ngをスクリプトから扱える
- modelには、デコンパイル対象バイナリのアーキテクチャ、デフォルトABI、セグメント、関数一覧、型一覧などが含まれる
- PythonおよびTypeScript向けラッパーでmodelを編集できる
- 現時点ではmodel操作用ラッパーはあるが、解析実行やアーティファクト取得を簡単に行う仕組みはまだない
- 完全なPythonクライアントは ロードマップ項目 #17 で追跡されている
- 内部表現ではLLVM IRが多用されており、LLVMエコシステムのツールを活用できる
オープンソースCLIと有料UIの切り分け
- rev.ngフレームワークは完全にオープンソースで、CLIから任意の対象をデコンパイルできる
- UIの提供形態は3つに分かれる
- 公開プロジェクト向けクラウドUIは無料で利用可能
- 非公開プロジェクト向けクラウドUIは購読が必要
- 完全スタンドアロン・完全オフラインUIは有料で提供
- クラウド利用方法は以下の通り
- rev.ng Hub でプロジェクトを作成し、共同作業者を招待する
- UIはブラウザで実行される
- バックエンドはrev.ngクラウド上で動作する
- プロジェクトファイルを公開しても問題なければ、UIを含むクラウド版rev.ngを無料で利用できる
- Kubernetesを使うオンプレミスのプライベートクラウドサービス導入についても相談可能
1.0ロードマップと連絡チャネル
- 1.0までのロードマップは4つのティアに分かれる
- Tier 1: アルファ版、知人向けデモ、完了
- Tier 2: ベータ版、ニュースレター購読者にクラウド版アクセスを提供、現在開始
- Tier 3: オープンベータ、予定
- Tier 4: 1.0リリース、予定
- 詳細な進捗状況は ロードマップページ で確認できる
- プロジェクト情報とサポートチャネルは以下の通り
1件のコメント
Hacker News の意見
価格モデルは、rev.ng フレームワークが完全にオープンソースで、CLI では何でもデコンパイルできるという構成
UI は公開プロジェクトならクラウド上で無料、非公開プロジェクトではクラウドサブスクリプション、完全に独立したオフラインアプリは有料で提供される予定
比較すると、Hopper は1年間のアップデート込みで100ドル https://www.hopperapp.com/index.html、Ghidra と Radare2 はフリーかつオープンソースなので完全無料、IDA Pro は非常に高価
使ってみた限りでは IDA とかなり似ているが、よりユーザーフレンドリーで、生産性を高めるよく設計された機能が多かった
Hopper は使ったことがないが、Ghidra と Radare2 は開発体験があまり良くなく、生成された C コードも読みやすくなかった。ただし、どちらも数年前に使った時点での話
Binja は300ドル、商用は1500ドルで、学生割引もある: https://binary.ninja/features
それでも良い C デコンパイラは常に不足しているので、新しい試みはいつでも歓迎
ただ、アプリにインターネット接続を必須にせず、それをどう強制するのかは気になる
チームページ https://rev.ng/about とコード貢献 https://github.com/revng/revng/graphs/contributors を見ると、CEO(aleclearmind) が CTO(pfez) よりもはるかに多くのコミットを持っているのが少し珍しく見える
他の CEO はコーディングする時間がほとんどないとよく言うし、CTO もたいていはマネジメント寄りで、実際のコーディングは少なめ
それでもこのやり方がうまく回っているなら、チームとしてはかなり面白そう。追記: タイムラインは確認していなかった
最終的には2つのリポジトリを統合する予定
それに私は毎日開発しているのだが、どういうわけか GitHub が私のユーザーを正しく拾えていない
実際にも楽しい
むしろこういう姿は気に入ったし、他で見たものと違っていて興味深かった
面白くない、または珍しくないという理由でダウンボートされたのだろうか?
現存する最高のプログラミング言語理論の本の1つから力を得た、素晴らしい会社に見える: https://link.springer.com/book/10.1007/978-3-662-03811-6
「彼は共犯者となる Pietro にも出会った。かなりロマンチックなことに、会社の土台となる本のおかげで彼に出会った。」
https://rev.ng/about
そんな時、凝縮されているが明快に見えるこの本を見つけ、指導教員に買ってよいか尋ねたところ、「まず大学図書館を確認しなさい」と言われた
図書館には所蔵があったがすでに貸出中で、コンパイラ研究をしている唯一のグループにいた私は「うちのグループ以外で、いったい誰がコンパイラなんてやっているんだ?」と思った
図書館へ行って誰が借りたのか尋ねたが、個人情報なので教えられないと言われ、姓の3文字目と名の2文字目だけを聞いて Z と I を引き出した
ここで見つけ出した: https://www.deib.polimi.it/ita/personale-lista-alfabetica
時が経って友人になり、一緒に会社を始めた
リリースまでには本当に多くの作業が必要だった
コードが変数や構造体メンバーをどう扱っているかに基づいて、変数名と構造体メンバー名を自動で付けられるとよい
たとえば連結リストの next ポインタは
nextとして識別しやすいはずGitHub 全体をダウンロードして、コード内でレイアウトと相互作用が最も似ている変数を探し、信頼度が十分に高ければその名前を使う、という方法が可能に見える
たとえば誘導変数を検出したら
iにリネームする、という具合だが今では、こうしたことの正しいやり方は LLM を使うことだとかなり明確に見える
ただ現段階では、私たちは堅牢な基盤を作る側に近く、基盤が整えば既製のモデルで名前を変えたりコメントを追加したりするのは比較的簡単
要点は、100% の正確性が必要な難しいデコンパイル作業は私たちが行い、名前やコメントのように近似が許される部分には LLM を導入できるということ
いずれにせよ、リネーム用スクリプトを書くのはかなり簡単なので、ドキュメントを見るとよい: https://docs.rev.ng/user-manual/model-tutorial/
JSNice が内部で何をしているかを説明する論文: https://files.sri.inf.ethz.ch/website/papers/jsnice15.pdf
自分の ELF ファイルでは動作しない
./revng artifact --analyze --progress decompile-to-single-file ../maytag.koを実行するとOnly ELF executables and ELF dynamic libraries are supportedと表示され、ファイルはELF 64-bit LSB relocatable, x86-64, version 1 (FreeBSD), not strippedと出るFreeBSD バイナリをサポートしていないということ?
追記: カーネルモジュールをサポートしていないことを見落としていて、FreeBSD のせいというより単純な実行ファイルではないからのようだ
これをロードするのはそれほど難しくなさそう
コラボレーションワークフローにもっと注目が集まるといい
IDA Teams のようなものは使ったことがないが、Google Docs のように摩擦のないリバースエンジニアリング体験が実現できたらすごいと思う
以前は UI ベースで QtCreator を使っていたが、ひどい選択だった
その後 VSCode に切り替えたところ、ちょうどブラウザでも実行できた
そこで Kubernetes を少し組み合わせて、完全スタンドアロン版とまったく同じユーザー体験を持つ クラウドデコンパイラを作った
コラボレーション部分はまだ QA がもう少し必要だが、基本的には動作している
デーモン 1 つに複数クライアントという非常に単純な構成
以前 CTF で、サーバー上の X セッションに IDA のウィンドウを複数開き、カーソルも複数ある状態で「共同作業」していた経験から着想を得たのだと思う。非常に呪われたやり方だったが、効果はあった
型推論をサポートする予定はある?
現状ではすべての変数が
generic64_tに見えるようだが、Ghidra のように型を自動検出してくれるとよさそう。もちろん Ghidra も時々間違えるがロードマップ項目: https://rev.ng/roadmap#feature-798
設計パッド: https://pad.rev.ng/s/eDHi2PUoP#
面白そう
完全スタンドアロン版を試してみたい
おおよその価格について何か情報はある? 趣味ユーザーでも手が届く程度だとうれしい
バイナリハッキングツールが増えるのはいつでも歓迎
自分でも試してみたいと思うかもしれないので、選ばれたパッケージ形式についてかなり細かい提案を残しておく
source ./environmentは良くない兆候。tar を取得してみると、実際に PATH を含む複数の環境変数を設定しており、幸いLD_LIBRARY_PATHではなかったほとんどが
HARD_プレフィックスで、おそらく固有だろうが、REVNGのほうが明確に見えるし、既存の環境変数と衝突するのは良くないAWS_EC2_METADATA_DISABLED="true"も設定しているが、自分は AWS を使っていないので壊れはしないものの、一般的には疑わしいRPATH_PLACEHOLDER、HARD_FLAGS_CXX_CLANG、長い PATH、mingw32/gentoo/mips 文字列などは脆弱に見える実行手順に「次に環境変数を変更せよ」とあると、たいていは諦める。Ubuntu 以外のシステムでまともに動かないプログラムと強く相関している
アプリケーションの制御フローを実行環境に結び付けると、最初に見える以上に失敗モードが多く、グローバル変数に非常によく似ている
Clang はビルド時に
-DCLANG_DEFAULT_CXX_STDLIB=libc++のようなデフォルト値を焼き込めるし、DEFAULT_SYSROOTも有用rpathを使っていても、ユーザーがLD_LIBRARY_PATHを設定した状態で実行すると、バイナリのDT_RUNPATHが上書きされることがある最近の
-Wl,rpathは実際には rpath ではなく、あまり有用でないrunpathを意味する。おそらく望ましい呼び出しは-Wl,rpath -Wl,--disable-new-dtagsで、ローダーがライブラリ探索時にLD_LIBRARY_PATHを無視するようにするものだClang のビルドフラグ、静的リンク、バイナリ内へのバイナリ埋め込みなどを組み合わせれば、環境変数の操作を完全になくせる可能性が高い
clang-16バイナリが動的リンクされていて、実行時にlibLLVMAArch64CodeGen.so.16のようなものを探すのも失敗モードを増やすLLVM_BUILD_STATIC=ONなら、HPC モジュールのツールチェーンが有効な環境で間違ったライブラリを拾う問題を減らせるツール群は
libc++.so、libc++abi.soなどにリンクされているが、静的 libc++ を検討する価値があり、少なくともlibc++abiとlibunwindは libc++ の中へ静的にリンクしたほうがよいLinux で動的リンクされたプログラムを配布することへの忍耐が完全に尽きた
README の
source ourhackやモジュールシステムが残した環境変数が自分のアプリケーションのランタイムライブラリを変えてしまうと、ユーザー体験とその後のバグ報告対応コストがひどいことになるそれに比べて静的リンクは本当に良い
source environmentをするという前提でのみ当てはまる実のところ、それを提案した理由はデモ用バイナリ向けに、われわれが配布している GCC を使わせるためだけで、意図された使い方は
./revngスクリプトこの場合、環境の変更は
revngの呼び出しにだけ影響するドキュメントはこちら: https://docs.rev.ng/user-manual/working-environment/
source ./environmentについて警告を追加したほうがよさそうLD_LIBRARY_PATHは使わないように多くの時間を費やし、各 ELF が相対パスで依存関係を参照する完全に自己完結したバイナリセットを作った。LD_LIBRARY_PATHは悪HARD_変数はコンパイララッパーでのみ使われ、実際に衝突する可能性はほぼないと思うAWS_EC2_METADATA_DISABLED="true"の元の議論は https://github.com/revng/revng/pull/309#discussion_r12805759... にあるAWS SDK にパッチを当てて避けることもできるだろうが、いずれにせよ rev.ng がクラウド上で実行されるときにだけ影響がある
RPATH_PLACEHOLDERとHARD_FLAGS_CXX_CLANGは revng が変換したバイナリをリンクするときに使われ、エンドツーエンドのバイナリ変換に関心がないなら重要ではないわれわれは意図的に
DT_RUNPATHを望んでいる。DT_RPATHは廃止予定であり、LD_LIBRARY_PATHでわれわれのライブラリを置き換える必要があるユースケースもあり得る「環境操作」についての指摘は、非公開の環境変数でない場合にだけ妥当だと思う
RPATH_PLACEHOLDER、HARD_*、REVNG_*は非公開変数で、すべてバイナリ変換目的より小さい範囲のコンパイララッパー内へ押し込むことはできるが、Python も一緒に配布しているため、環境を完全になくすことはできない
Clang に一部のフラグを焼き込むだけでは不十分。このフラグ群はリンカにも影響し、ラッパー機能の中には単純に内蔵できないものがある
ただし、より非公開な場所へ移すことはできる
動的リンクを警戒しているようだが、われわれはここに労力をかけており、今ではかなりうまく動作し、常に正しい場所を見つける
絶対パスをハードコードせず、バイナリを「パッチ」するインストール手順もない。展開したディレクトリはどこへでも移動できる
われわれの解決策は
LD_LIBRARY_PATHを使わず、すべてのバイナリが$ORIGINを通じて堅牢に互いを参照するというもの./root/bin/python ./root/bin/revng artifact --helpを実行してみると動作する繰り返すが、
source environmentはほぼデモ用であり、実際の使用では./revngだけ実行すれば環境はそのままPython も一緒に配布しているが、必ずそれを使う必要はない。
./revngを使うか、デーモンモードでネットワーク経由で相互作用すればよいアプローチとしては、好きなスクリプトツールで YAML プロジェクトファイルをパース・修正してから
./revng artifactを呼び出すか、デーモンと相互作用する: https://docs.rev.ng/user-manual/model-tutorial/結果として、われわれは最新の Python バージョンを使え、ユーザーは好きな言語を使える
今後は、さまざまな Python バージョンと互換性のある補助ラッパーを PyPI で提供する予定です
要するに、
source ./environmentはせずに./revngを使えばよいということですこうした点を気にかけてくれる人がいてうれしいです
次の大きなイテレーションでは、nix + mount namespace を導入して、root 権限なしで
/nix/storeを使えるようにし、多くのことを単純化できるかもしれませんこうした議論は、ここよりも Discord サーバーで話したほうがよいかもしれません
QEMU TCGにリフティングを任せたことについて後悔はある? それとも、うまく機能した?
まず、QEMUのフォークを数年間リベースしていなかったため、よくない状況になっていた
それでも、まさに今日チームメンバーが最新のQEMUでリフティングに成功し、私たちがQEMUへのサポート追加を手伝ったQualcomm Hexagonのコードもリフティングできた
結果的に、私たちは初のまともなHexagonデコンパイラになるはず
次に、QEMUに集中しすぎたせいで、フロントエンドがQEMUと強く結合してしまった
今後、QEMUベースではない追加のフロントエンドをサポートするには多少の作業が必要だが、不可能ではない
構想としては、ユーザーが新しいアーキテクチャのサポートを追加するときに、CでCPU状態構造体と、その上で動作する関数をいくつか定義するだけで済むようにすること
内部表現を学ぶ必要はない
要するに、QEMUは素晴らしい選択で、あまりにもうまく動いたため、そのコードベース部分に長く手を入れず、技術的負債が生まれたが、今まさに解消しているところ