mcpField
L
leanrea

leanrea

github.com/aicodeking開発3.4k1.9k 回インストール2 週間前に更新
リポジトリ

leanrea について

leanreaは、バイナリやアプリケーションバンドル、データファイルを調べるリバースエンジニアリング用スキルです。証拠の迅速な収集と対象を絞ったコード調査を重視し、主張を根拠別に示します。

主な機能

  1. 01ファイル形式とマジックバイトで手順を選択
  2. 02迅速な調査コマンドを提示
  3. 03隠しファイルやバンドル内コードを検索
  4. 04観測・推論・不明を区別

活用シーン

  1. 01未知の実行ファイルの初期調査
  2. 02Electronアプリバンドルの確認
  3. 03展開したファイルからコードや文字列を検索

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/aicodeking/leanrea --skill leanrea

インストール後、Claude Code で/leanreaを入力して読み込まれたか確認します。

詳細

leanrea:最短手順

これらのツールの使い方はすでに把握している前提です。このファイルでは、対象ごとに最速のコマンドと注意点だけを記載します。

ルール

  • コピー上で作業します(APFS の cp -c なら瞬時です)。展開するごとに $TMPDIR/re/<name> の下に新しいディレクトリを作成します。すでに展開済みなら、その展開結果を再利用します。
  • まず file -b T とマジックバイトで対象を判別します。次に、最も手軽なインベントリを実行します。それから初めて、逆コンパイルするかコードを読みます。
  • rg は隠しファイルと無視対象のファイルをスキップし、バンドラーはコードを隠します(Electron:.webpack/、.vite/)。展開したツリーは必ず rg -uu で検索します。
  • 大きなファイルやミニファイされたファイルを cat してはいけません。必要な部分だけを切り出します:rg -o '.{0,200}NEEDLE.{0,200}' F | head。逆アセンブル結果は一度ファイルに出力し、そのファイルを grep します。
  • 独立した調査は、; と echo '--- name' のマーカーを使って、1 回のシェル呼び出しにまとめます(引用符で囲みます。zsh は引用符のない ==x を展開します)。すべての出力は head または -m で制限します。
  • 根拠に基づいて回答します。回答では各主張に 確認済み(file:offset、またはシンボル/文字列を引用)か 推定 の印を付けます。見つからなかった事実は「不明」であり、「存在しない」ではありません。静的な読み取りは、実行時の観測ではありません。
  • ツールが見つからなくても、作業を中断する必要はありません。同じ行の代替手段を使うか、ユーザーが許可している場合は brew install <x> を実行します。
  • バイト数よりターン数のほうがコストがかかります。ツール呼び出しは 2~4 回を目安にします。偵察をまとめて 1 回、必要な部分を狙って 1~2 回確認してから回答します。依頼された項目すべてに根拠がそろったら終了します。すでに確認したことは再確認しません。

最初の手順:それぞれ 1 回だけ呼び出し、貼り付けて実行

ネイティブ(Mach-O):

T=./bin; D=$TMPDIR/re/$(basename $T); mkdir -p $D; file $T; lipo -info $T; otool -L $T; echo '--- EXPORTS'; nm -gU $T | head -150; echo '--- IMPORTS'; nm -u $T | rg -v '^__Z|napi_' | tr '\n' ' '; echo; echo '--- STRINGS'; strings -a -n 6 $T | rg -v '^[_$.]' | head -400; otool -tV $T > $D/dis.txt; echo '--- FUNCS'; rg '^[_a-zA-Z].*:$' $D/dis.txt | rg -v '^_?_?Z?N?St3' | head -150

次に関数を 1 つ読みます:awk '/^FUNC_LABEL:$/{p=1;next} p&&/^[_a-zA-Z].*:$/{exit} p' $D/dis.txt | rg 'bl|b\.|cmp|literal|mov\s+w2'。

Electron:

A=./app.asar; X=$TMPDIR/re/asar; rm -rf $X; npx -y @electron/asar extract $A $X && jq '{name,version,main}' $X/package.json; find $X -path '*/node_modules' -prune -o -type f \( -name '*.js' -o -name '*.node' \) -print | head -60; ls ${A}.unpacked/node_modules 2>/dev/null; rg -uu -l --glob '!node_modules' 'exposeInMainWorld' $X

次に、バンドル全体から検索語の周辺を切り出します:rg -uu -o --glob '!node_modules' '.{0,250}NEEDLE.{0,250}' $X | head -20。

Go:通常は go version -m T だけで質問に答えられます。

ルーター

対象(検出方法)最速の手順
Electron アプリ(*.app/Contents/Resources/app.asar)npx -y @electron/asar extract app.asar X(.node アドオンについては app.asar.unpacked/ も確認してください)。エントリーポイント:jq .main X/package.json。サーフェス:`rg -n -o '.{0,120}(ipcMain.(handle
Web バンドル/最小化された JSsourceMappingURL を探します。マップに sourcesContent がある場合は、ソースを出力します:jq -r '.sources[]'。webpack の場合はモジュール ID を grep し、ヒットした箇所の前後を切り出します。整形するには:npx -y prettier --parser babel F > F.pretty.js を実行し、行範囲を指定して読みます。
Hermes/bytenode/V8 スナップショットHermes のマジックナンバーは c6 1f bc 03(index.android.bundle)です。hermes-dec/hbc-decompiler を使います。.jsc(bytenode)は逆コンパイルできません。strings とランタイムフックを使います。
Mach-O(file の結果が Mach-O)lipo -info(先に薄型化:lipo -thin arm64 -o T1 T)。続いて:otool -L(ライブラリ)、xcrun dyld_info -exports -imports、nm -gU(エクスポート)/nm -u(インポート=機能マップ)、strings -a -n 6、otool -l | rg -A3 'LC_(RPATH|BUILD_VERSION)'、codesign -d --entitlements :- T、otool -ov(ObjC クラス/メソッド)、xcrun swift-demangle --compact。
ネイティブコードのロジックotool -tV T > $D/dis.txt(または llvm-objdump -d --no-show-raw-insn -C)。関数を探します:rg -n '^_?.*Name.*:$'。呼び出し/文字列の手がかりを読み取ります:awk '/^FUNC:/{p=1} p&&/^[_a-zA-Z].*:$/&&!/FUNC/{exit} p' dis.txt | rg 'bl|call|literal|cmp'。otool は文字列リテラルとスタブをインラインで表示するため、多くの場合これで十分です。擬似コードが本当に必要な場合に限り、Ghidra の analyzeHeadless $D p -import T -postScript DecompileAll.java -deleteProject または r2 -qc 'aaa; pdc @ sym.X' T を使います。
ELF/PEreadelf -hlSW、readelf -dW(NEEDED)、nm -D --defined-only、objdump -d -M intel。PE:objdump -x、リソースには pefile/wrestool。checksec:pwn checksec。
Go(__go_buildinfo、.go.buildinfo)go version -m T を実行すると、ツールチェーン、パス、mod、依存関係、ビルドフラグを一度に取得できます。Go がない場合:strings -a T | rg -m1 -A200 'Go buildinf' 。シンボルは strip 後も残ります:go tool nm T | rg main\.。
Rust依存関係(cargo-auditable):cargo audit bin T を実行するか、.dep-v0/__DATA,.dep-v0 を抽出して zlib で展開します。コンパイラー:strings -a T | rg -o '/rustc/[0-9a-f]{40}' | sort -u。パスからクレートを取得:strings -a T | rg -o '[a-z0-9_-]+-[0-9]+\.[0-9]+\.[0-9]+/src' | sort -u。
.NET(file の結果が Mono/.Net)ilspycmd -p -o X T.dll(インストール:dotnet tool install -g ilspycmd)を実行し、その後 rg を使います。P/Invoke:rg DllImport X。NativeAOT/IL2CPP はネイティブです。ネイティブの行を参照してください。
Android APKjadx -d X --show-bad-code a.apk を実行し、その後 rg を使います。リソース/マニフェストのみの場合:apktool d --no-src -o X a.apk。簡易確認:unzip -l a.apk。lib/*/libflutter.so があれば Flutter(Dart AOT:blutter)、libhermes.so があれば React Native(Hermes の行を参照)です。
Flutter スナップショットハッシュlibapp.so 内でマジックナンバー f5 f5 dc dc を探します。+20 にある 32 桁の 16 進数がスナップショットハッシュです。対応する Dart バージョンを調べます。
WASMwasm-objdump -x、wasm2wat、wasm-decompile(WABT)。
SQLiteDB をコピーします。存在する場合は -wal ファイルもコピーします。sqlite3 'file:C?mode=ro' '.schema' を実行し、続いて SELECT * FROM t LIMIT 20 を実行します。
plist/nib/carplutil -p F。Info.plist にはバンドル ID、URL スキーム、プライバシー文字列が含まれます。アセットカタログ:assetutil --info Assets.car。
pcap/HARtshark -r C -q -z conv,tcp、tshark -r C -T fields -e dns.qry.name -e tls.handshake.extensions_server_name -e http.request.full_uri | sort -u。HAR:jq -r '.log.entries[].request | .method+" "+.url'。
ファームウェアbinwalk -e F または unblob -e X F。その後、抽出された各バイナリをこの表に沿って調べます。
Web サイトHTML と script src を取得するには curl -sL URL を使い、その後 JS を取得して必要な箇所を切り出します。ランタイムの動作を確認するには、ネットワークログを記録するヘッドレスブラウザー(Playwright の page.on('request'))または Chrome の --remote-debugging-port を使います。
実行中のアプリ/ランタイムmacOS:lldb -p PID、dtrace/fs_usage/log stream --predicate 'process=="X"'。Electron のメインプロセス:--inspect(RunAsNode/inspect フューズが許可する場合のみ)。Android:adb logcat、frida -U -f pkg -l hook.js。

速度を重視したパターン

  • まず文字列とインポートを確認します。小さなバイナリなら、nm -u、strings、エクスポート一覧で、逆アセンブルせずに通常は「何をするのか」が分かります。
  • 文字列を使用している箇所を見つけるには、otool -tV の「literal pool for」コメントからアドレスを取得するか、rg -n 'literal pool for: "X' を使います。その行より上にある、対象を囲む関数ラベルを探します。
  • bl のターゲットにある C++ の名前から、プロトコルがすでに分かる場合があります(例:getpeereid、write、std::hash)。すべての命令ではなく、呼び出しの流れを読みます。
  • JS では、ネイティブ/JS 境界から内側へたどります。ネイティブ呼び出しを見つけ、次にその呼び出し元のクラス、IPC の登録、レンダラー/プリロードの順に確認します。
  • バージョンを比較するときは、コードを比較する前にインベントリ(nm、モジュール一覧、go version -m)の差分を確認します。
  • 再構築では、最小限の再実装を書き、オリジナルと照合してテストします(入力と出力を同じにします)。

インストール(リクエストがあった場合のみ)

brew install jadx apktool radare2 binwalk wabt wireshark ghidra · npm i -g @electron/asar · dotnet tool install -g ilspycmd · cargo install cargo-audit.

コメント