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'標記(需要引號:zsh 會展開裸的==x)將獨立的探查批次處理為一個 shell 調用。每個輸出都用head或-m限制。 - 根據證據回答。在答案中,將每個主張標記為已見(引用文件:偏移量,或符號/字串)或推斷。您未找到的事實是未知,而不是「不存在」。靜態閱讀不是觀察到的執行。
- 缺少工具不是障礙。使用同一行中的後備方案,或者如果使用者允許,則執行
brew install <x>。 - 調用次數比位元組數成本更高。目標是 2-4 次工具調用:一次批次偵測調用,一到兩次目標切片,然後回答。當您被問到的每個項目都有證據時停止。不要重新驗證您已經看到的內容。
第一步:每個一次調用,貼上並執行
原生(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
然後閱讀一個函數: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(另見 app.asar.unpacked/ 中的 .node 插件)。入口點:jq .main X/package.json。表面:`rg -n -o '.{0,120}(ipcMain.(handle |
| 網路捆綁包 / 最小化 JS | 找到 sourceMappingURL。如果映射包含 sourcesContent,則傾印來源:jq -r '.sources[]'。對於 webpack,grep 模組 ID,然後在命中點周圍切片。對於美化列印: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)無法反編譯:使用字串和執行時鉤子。 |
Mach-O(file:Mach-O) | lipo -info(先 thin: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 |
| 原生程式碼邏輯 | 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 / PE | readelf -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 一次調用給出工具鏈、路徑、模組、依賴項和構建標誌。如果沒有 Go:strings -a T | rg -m1 -A200 'Go buildinf'。符號在剝離後仍然存在:go tool nm T | rg main\.。 |
| Rust | 依賴項(cargo-auditable):cargo audit bin T,或提取 .dep-v0 / __DATA,.dep-v0 並進行 zlib-inflate。編譯器:strings -a T | rg -o '/rustc/[0-9a-f]{40}' | sort -u。來自路徑的 crate: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 APK | jadx -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 個十六進位字元是快照雜湊。將其映射到 Dart 版本。 |
| WASM | wasm-objdump -x、wasm2wat、wasm-decompile(WABT)。 |
| SQLite | 複製資料庫,以及 -wal 檔案(如果存在)。sqlite3 'file:C?mode=ro' '.schema',然後 SELECT * FROM t LIMIT 20。 |
| plist / nib / car | plutil -p F。Info.plist 包含套件 ID、URL 方案和隱私權字串。資產目錄:assetutil --info Assets.car。 |
| pcap / HAR | tshark -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。然後將每個提取的二進位檔案通過此表格進行路由。 |
| 網站 | curl -sL URL 獲取 HTML 和腳本 src,然後提取 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 fuses 允許時)。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 註冊,然後是渲染器/preload。
- 比較版本:在比較任何程式碼之前,先 diff 盤點清單(
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。