2026-10-27
最近、GitHub Trendingで REA(Reverse Engineer Anything) というリポジトリをよく見かけるようになりました。スター数は約40万と、とんでもない数字です。「AIエージェントにリバースエンジニアリングをさせるツール」とのことで、どれくらいのことができるのか気になったので、実際に触ってみました。
リバースエンジニアリング自体が初めてだったので、今回はClaude Codeと一緒にREAを使ってどんなことができるのかを試してみました。 題材には、お絵描きツール Excalidraw の共同編集機能を選びました。「なぜサーバーに絵の中身が見えないのか」をREAで調べてみた結果と、使ってみて感じたことをまとめます。
REAは、一言でいうと「AIエージェントにリバースエンジニアリング用の道具箱を渡すMCPサーバー」です。
REAをMCPサーバーとして登録すると、AIが「このアプリの検索ってどう動いてる?」といった質問に対して、REAのツールを使って対象を調べ、根拠付きで答えてくれるようになります。
REA自身が解析エンジンを持っているわけではなく、Ghidraなどの既存ツールを、AIが扱いやすい形にまとめる「つなぎ役」になっています。
ここで出てくるGhidra・Hopper・IDAは、どれも実行ファイルの中身を人間が読める形に戻すための、リバースエンジニアリング用のツールです。実行ファイルはCPU向けの命令(機械語)の並びになっていて、そのままでは読めません。これらのツールは、機械語をアセンブリ(命令を文字で表したもの)に変換したり、さらにC言語に近い擬似コードに戻したりしてくれます。
| ツール | 特徴 |
|---|---|
| Ghidra | アメリカの国家安全保障局(NSA)が公開している無料のOSS |
| Hopper | macOS / Linux向けの有料ツール。比較的手頃な価格 |
| IDA | 業界標準と言われる有料ツール。機能を絞った無料版もある |
なお、これらのツールはREAに含まれていないので、使う場合は自分でインストールする必要があります(HopperとIDAは有料)。今回の検証ではブラウザ観察の機能だけを使ったので、どれもインストールしていません。
解析できる対象はかなり幅広いです。主なものを抜き出すとこんな感じです。
| 分類 | 例 | 必要なもの |
|---|---|---|
| ネイティブバイナリ | C / Rust / Go の実行ファイル → 擬似コード、アセンブリ、関数の呼び出し関係 | Ghidra / Hopper / IDA |
| JS / Electron / .NET | Electronアプリのモジュール構成や、画面側と裏側の通信(IPC) | 追加ツール不要 |
| Web | ページの構造、読み込まれたスクリプト、通信 | Chrome系ブラウザ |
他にもAndroidのAPK、Unity / Godotのゲームデータ、pcap(通信の記録ファイル)など、READMEの対応表はかなり長いです。
特徴的なのは、結論に必ず「根拠」と「限界」が付いて返ってくることです。「たぶんこう」ではなく、「このファイルのこの部分が根拠で、ここから先は分からない」という形で結果が返ってきます。
公式の手順では npx rea-agents setup を実行すると、対話形式で登録先のエージェントを選べます。
Excalidrawは、手書き風の図を描けて、URLを共有するだけで共同編集もできるホワイトボードツールです。共同編集の機能は「Live collaboration」と呼ばれていて、始めるとURLが次のような形に変わります。
Excalidrawは「共同編集のデータはE2E暗号化(送る人と受け取る人だけが読める暗号化)されている」と説明しています。そこで、「なぜサーバーに絵の中身が見えないのか」 を、REAを使って自分で確かめてみることにしました。
なお、Excalidraw は MITライセンスのOSS で、ソースコードが公開されています。最後にソースと答え合わせができるのも、題材に選んだ理由です。
検証に入る前に、そもそも鍵が何のためにあるのかを整理しておきます。
共同編集では、描いた図形を相手の画面に出すために、データが必ずExcalidrawのサーバーを経由します。暗号化しなければ、運営者やDBを提供しているGoogle、サーバーに侵入した攻撃者など、途中にいる誰にでも中身が読めてしまいます。
そこで、
という形にすれば、サーバーを経由してもデータを読まれずに済みます。鍵付きの箱で郵便を送り、合鍵は郵便局を通さずに相手へ直接渡すイメージです。サーバーは「どの部屋に届けるか」は分かっても、「何が描かれているか」は分かりません。
URLの #room= 以降の2つの値は、それぞれ次の役割を持っています。
| 部分 | 役割 | サーバーに渡る? |
|---|---|---|
| 部屋ID | どの部屋のメンバーにデータを中継するかの宛先 | 渡る |
| 暗号鍵 | データを暗号化・復号する | 渡らない |
裏を返すと、URLそのものが合鍵です。URLを知っている人は誰でも部屋に入って中身を読めますし、URLをなくすと運営者でも復元できません。共同編集のURLを気軽にチャットに貼らないほうがいいのは、このためです。
ここからは、本当にこの仕組みになっているのかを、REAで確かめていきます。
観察は次の流れで行いました。
REAのブラウザ観察は、REAがブラウザを起動してくれるわけではありません。Chromeの開発者向けの接続口(CDP: Chrome DevTools Protocol)を開けた状態で自分で起動し、そこにREAが接続する方式です。
※ WSLのターミナルからChromeを起動しています
--remote-debugging-port=9222: 127.0.0.1:9222 でCDPの接続を受け付ける--user-data-dir: 普段使いとは別の、使い捨てのプロファイルを使う(理由は後述)--password-store=basic: Linuxでキーリング(パスワードの保管庫)の確認に引っかかって、Chromeの起動が止まるのを防ぐ普段使っているChromeにつなげばいいのでは、と思うかもしれませんが、REAで調査するときは、このようにREA用のChromeを別で起動するのがおすすめです。理由は2つあります。
1つ目は、そもそも普段のプロファイルでは使えないことです。デバッグ用のポートが開いていると、接続したプログラムはCookieやログイン状態も含めてブラウザを丸ごと操作できてしまいます。これを悪用してCookieを盗むマルウェアがあったため、Chrome 136以降は、普段使いのプロファイルでは --remote-debugging-port が無視されるようになりました。
2つ目は、余計な情報をAIに渡さないためです。普段のプロファイルには、Googleアカウントや各サービスのログイン状態、開いている他のタブなどが含まれています。REAの観察結果はAIに渡されるので、普段のプロファイルにつなぐと、調べたいページと関係ない情報までAIに見えてしまう可能性があります。使い捨てのプロファイルなら空の状態から始まりますし、使い終わったらフォルダごと消すだけで済みます。
ログインが必要なページを調べたいときも、普段のChromeにつなぐのではなく、REA用のChromeで調べたいサービスにだけログインするのが安全だと思います。
REAのMCPサーバーは、自分で起動する必要はありません。claude mcp add で登録しておけば、Claude Codeの起動時に、登録したコマンド(npx -y rea-agents@6.8.0 mcp)が裏で自動的に実行されます。Claude Codeの中で /mcp を開くと、REAが接続済みになっているのを確認できます。
あとはClaude Codeに日本語で「Excalidrawの通信を観察して」と頼むと、REAのツールを順番に呼び出してくれます。実際に呼ばれたのは次の2つでした。
list_browser_targets: Chromeで開いているタブの一覧を取得して、ExcalidrawのタブのIDを調べるinspect_web_page: そのタブに接続して、指定した時間だけ通信やDOMを記録するinspect_web_page は、呼び出した時点から観察を始めます。接続する前の通信は記録されないので、観察が始まってから、自分の手でExcalidrawの共同編集を開始して、図形をいくつか描きました。
一度、観察の時間内に操作が間に合わず、何も記録されなかったことがありました。観察時間は、余裕を持って長めに取ったほうがいいです。
観察の結果は、JSONで返ってきます。
観察の結果、通信は大きく2種類ありました。
oss-collab.excalidraw.com とのWebSocket通信まず、URLに入っている暗号鍵の文字列を、観察結果の全体から検索しました。見つかったのはページ自身のURLの2か所だけで、通信先のURLには1回も出てきませんでした。
ただし、REAは安全のため、通信の本文(ボディ)を保存しない設計になっています。記録されるのは「どんな構造のデータか」という形だけです。なので、厳密には「本文の中に鍵が入っていない」ことまでは、この観察だけでは言い切れません。ここは後でコードを読んで補います。
Firestoreから返ってきたデータの構造は次のとおりでした。
絵の中身を読める形で持っているフィールドはありません。サーバー側のDBには、鍵がないと読めないデータしか置かれていないことが分かります。
WebSocketは、ブラウザとサーバーをつなぎっぱなしにして、どちらからでも好きなときにデータを送れる通信方式です。普通のHTTPは「ブラウザが頼んで、サーバーが答える」の一往復で終わりますが、WebSocketは電話をつなぎっぱなしにしているイメージです。共同編集のように、相手の動きをすぐに反映したい場面で使われます。
WebSocketで送る1回分のデータをフレームと呼びます。フレームには、文字列を送るテキストフレームと、生のデータを送るバイナリフレームがあります。
Excalidrawから送られていたフレームを集計すると、次のようになりました。
| フレーム | 回数 | 正体 |
|---|---|---|
| テキスト 116B | 214回 | 宛名(イベント名 server-volatile-broadcast と部屋ID) |
| テキスト 107B | 70回 | 宛名(イベント名 server-broadcast と部屋ID) |
| バイナリ 12B | 284回 | IV(暗号化のたびに作る使い捨ての乱数) |
| バイナリ 135〜938B | 多数 | 暗号化された絵のデータ |
宛名の数(214 + 70 = 284)と12Bのフレームの数(284)がぴったり一致しています。つまり、送信のたびに「宛名 → 暗号文 → IV」の3点セットを送っていることになります。
宛名が2種類あるのは、送る内容の重要度の違いです。volatile(揮発性)が付いているほうは「届かなくてもいい」通信で、マウスの位置のように頻繁に送るものに使われていそうです。116Bと107Bの差の9バイトは、イベント名の文字数の差(25文字 − 16文字)とちょうど一致します。ただ、どちらがどの操作に対応するかは、中身が暗号化されているので推測です。
ここで出てきたAES-GCMとIVについても整理しておきます。
AES-GCM は、今いちばん標準的に使われている暗号化の方式です。AESは、同じ鍵で暗号化と復号をする「共通鍵暗号」のアルゴリズムで、GCMはその使い方(モード)の1つです。GCMを使うと、中身を隠すだけでなく、暗号文が途中で書き換えられていないかも見抜けます。Excalidrawでは、URLで共有した鍵を使って、この方式で絵のデータを暗号化しています。
IV(Initialization Vector) は、暗号化するたびに鍵と一緒に混ぜる、使い捨ての乱数です。IVがないと、同じ鍵で同じデータを暗号化したときに毎回同じ暗号文になり、中身は読めなくても「さっきと同じ操作をした」というパターンが外から分かってしまいます。IVを毎回変えることで、同じデータでも暗号文が変わるようになります。
IVは受け取る側も復号に使うので、秘密にする必要はなく、暗号文と一緒にそのまま送ります。12バイトのフレームが毎回送られていたのは、このためです。AES-GCMでは、IVの長さは12バイトが推奨されています。
サーバーから見えるのは「どの部屋宛てか」だけで、「何が描かれたか」は分からない、という形になっています。
次に、REAの export_web_scripts で、ページに読み込まれていたJavaScriptをファイルとして書き出しました。圧縮されたメインのバンドル(約2.2MB)を検索すると、暗号化に関する処理が見つかりました。読みやすいように抜き出して整形すると、次のような処理です。
鍵の生成と暗号化には、ブラウザに標準で入っている Web Crypto API を使っています。鍵を作るのも、暗号化するのも、すべてブラウザの中で完結していることが分かります。
最後に、GitHubのソースコード とClaude Codeに見比べてらい、結果は、REAで観察・検索した内容と一致していました。
encryption.ts )では、AES-GCMで暗号化し、IVの長さは12バイトになっていたPortal.tsx )では、部屋の鍵で暗号化してから、イベント名・部屋ID・暗号文・IVを送っていた。これが観察で見えた「宛名+暗号文+IV」の3点セットの正体だった触ってみても、正直なところ「40万スターも付くほどなのか」という理由は、まだ分かりませんでした。
ただ、REAが紹介している事例は、古いゲームの計算処理をC言語で復元したものなど、ネイティブバイナリの解析がほとんどです。ネイティブバイナリは、CPUが直接実行する機械語だけで書かれた実行ファイルで、変数名やコメントがほとんど残っていません。読める形に戻すところから大仕事なので、ここをAIに任せられるのは、専門家にとって大きいのだと思います。
一方で、Webエンジニアの自分の普段の仕事には、ネイティブバイナリを解析する場面がほとんどありません。今回はREAの得意分野を試していないので、REAの良さが分からなかったのだと思います。
話題のREAを使って、Excalidrawの共同編集の仕組みを調べてみました。URLに入っている鍵がサーバーに送られていないことや、絵のデータがブラウザの中で暗号化されていることを、自分の目で確かめられたのは面白かったです。
ただ、実際にWebサービスの機能を解説してもらう体験は初めてで楽しかったですが、Webサービスではフロントエンドの処理しかリバースエンジニアリングできません。オープンソースでないサービスを調べると、中途半端な結果に終わることが多そうでした。組み込みなどでより力を発揮しそうなMCPだなと思いました。