ESP-SDR 拆解:你抽屜裡的 ESP32 其實是一台 80 MSa/s 軟體無線電

ESP32 開發板化身軟體無線電 SDR 的概念圖

每一顆 ESP32 的 Wi-Fi 接收器,本來就在做軟體無線電(SDR)最核心的那件事:把天線收到的 2.4 GHz 訊號降頻、用 ADC 取樣成 I/Q,再丟給後面的 modem 解調。差別只在於,這些 I/Q 樣本從來不會離開 modem,你寫韌體的人一個 byte 都碰不到。

直到最近。

ESPARGOS 團隊的 Florian Euchner 和 Zoltan Doczi 發布了 ESP-SDR ,在 ESP32 家族裡找到一條沒有文件記載的 debug 路徑,可以把 modem 前端的原始 I/Q 直接倒進 SRAM。結果就是一顆幾十塊台幣的 ESP32-C3,變成取樣率最高 80 MSa/s 的 2.4 GHz 頻譜分析儀。ESP32-C5 甚至可以看 5 GHz。

更有意思的是他們怎麼找到的:用 LLM 協助逆向 Espressif 的 RF 測試函式庫。這篇我會從接收鏈原理講到暫存器位址,教你用瀏覽器十秒燒好韌體,最後也會講清楚為什麼「它能發射」這件事,在台灣你最好別碰。

閱讀前提

  • 適合讀者:嵌入式/韌體工程師、玩 RTL-SDR 或 HackRF 的無線電愛好者
  • 前置知識:知道 I/Q 取樣、ADC、Wi-Fi 接收鏈的基本概念
  • 版本基準:ESP-SDR 2026 年 10 月版(GitHub main),授權 GPL-3.0-or-later
  • 硬體:任一 ESP32 / C2 / C3 / C5 / C6 / C61 / S2 / S3 / S31 / H2 開發板(P4 沒有射頻,不支援)

Wi-Fi 晶片本來就是半台 SDR

ESP32 Wi-Fi 接收鏈中被分流出來的隱藏 I/Q 路徑示意

先把接收鏈攤開來看。不管是 RTL-SDR 還是 ESP32,前端長得都差不多:低雜訊放大器把訊號放大,混頻器把 2.4 GHz 搬到基頻,ADC 取樣出 I(同相)和 Q(正交)兩路數位訊號。

分歧點在 ADC 之後。SDR 會把 I/Q 原封不動丟給電腦,讓你用 GNU Radio 想怎麼解就怎麼解;Wi-Fi 晶片則直接把 I/Q 餵給固定功能的 modem,modem 只吐出解好的封包。對使用者來說,那串 I/Q 根本不存在。

天線 -> LNA 低雜訊放大 -> 混頻器(2.4 / 5 GHz -> 基頻) -> ADC(I/Q 取樣)
                                                          |
                    +-------------------------------------+
                    |                                     |
                    v                                     v(未公開的 debug 路徑)
          Wi-Fi / BT modem                        Dump engine:寫入 SRAM
          解調成封包                                       |
                    |                                     v
                    v                              USB / UART -> 電腦
          MAC -> 你的韌體

ESP-SDR 做的事,就是打開圖中那條虛線。團隊推測這條路徑是 Espressif 留著做晶圓測試、modem 除錯用的,不過這只是他們的推論,Espressif 沒有證實過。

藏在 RF 測試函式庫裡的 dump engine

專案的 how-it-works 文件 開宗明義就說「Espressif 完全沒有記載這些東西」。整個機制的核心是一個他們稱為 dump engine 的 debug 區塊:它會把接收器的基頻樣本,一個 32-bit word 一筆,直接複製到晶片內部一塊固定的 SRAM。

以 ESP32-C3 為例,關鍵暫存器長這樣:

用途 位址(C3) 說明
SRAM 擁有權 0x600c1020 bit 0–2 各把一塊 128 KiB 劃給 dump engine,bit 3 選上半 64 KiB
Lane 選擇 0x60033d90 四個 6-bit 欄位決定每條 lane 錄哪個內部訊號,0–3 是 I/Q 輸出
控制 0x60033d5c bit 0–14 樣本數、15–16 時脈除頻、18 完成旗標、19 觸發、31 致能

每個樣本的格式是:I、Q 各 10-bit 二補數,bit 20–27 另外帶著當下的接收增益索引。C3 的擷取區從 0x3fcb0000 開始,共 64 KiB,一次最多 16,380 個樣本;用 80 MSa/s 取樣的話,大約只有 205 µs。

觸發流程也很樸素:對 bit 19 寫 1 再寫 0 當作脈衝,然後輪詢 bit 18 等它完成,加個 timeout 免得卡死。

文件裡還特別警告了一個細節:CPU 會失去整個 128 KiB 區塊,不只是正在寫的那一半。C3 正是因為這樣做不了連續擷取,它的其他 SRAM 區塊都拿去放程式碼和 heap 了,借不出來。

LLM 在這裡扮演了什麼角色

用 LLM 逆向 librftest 找出 ESP32 隱藏功能的概念圖

這些暫存器 Espressif 沒有公開,那是怎麼挖出來的?

線索在 librftest.a,也就是 Espressif 隨 SDK 提供、給產線做 RF 測試用的閉源函式庫。裡面有個叫 adctrig 的函式,看名字就知道跟 ADC 觸發有關。根據 ESPARGOS 官網 的說法,團隊用 LLM 協助逆向這個函式,搞懂它怎麼設定硬體做原始 I/Q 擷取,再以此為基礎寫出 ESP-SDR。how-it-works 文件則補充,其餘資訊來自反組譯和在實體板子上反覆測試。

LLM 的角色還不只這樣。README 很坦白地說,部分韌體是 AI 生成的:團隊在 ESPARGOS One 用的 ESP32-C61 上對這套機制理解得很透,但要靠人力把它移植到整個 ESP32 家族,工作量實在太大。

身為每天在翻 datasheet 和反組譯的韌體工程師,我看到這段的心情很複雜。一方面,「把閉源 .a 丟給 LLM 讀」確實大幅降低了逆向門檻,以我自己反組譯韌體的經驗推測,以前要對著 objdump 推敲很久的東西,現在可能快很多就有頭緒;另一方面,AI 生成、沒有完整人工審查的韌體直接去碰 RF 暫存器,出事的機率也跟著上來。這不是在唱衰,而是提醒你:拿來玩可以,拿來當量測儀器就要自己驗證。

晶片支援與能力:能看到什麼、看不到什麼

ESP-SDR 2.4 GHz 頻譜瀑布圖概念

ESP-SDR 幾乎涵蓋了所有帶射頻的 ESP32,只有 H21、H4 尚未支援:

晶片 取樣率(MSa/s) 特色
ESP32 / S2 / C3 80、40、16 經典款,snapshot 模式
ESP32-C2 80、40、16 26 MHz 晶振,用 40 MHz 要重編
ESP32-C5 80 到 4 唯一能收 5 GHz
ESP32-C6 80、40、16 支援連續擷取(256 bins)
ESP32-C61 80 到 4 支援連續擷取(256 bins)
ESP32-S3 80、40、16 連續擷取,且 I/Q 可經原生 USB 輸出
ESP32-S31 80 到 4 連續擷取,另有串流韌體
ESP32-H2 32、16、10.667、6.4 走藍牙射頻

頻率方面,韌體接受 100–6000 MHz 的調諧指令,但 PLL 實際上只會在 2.4 GHz 附近鎖定(C5 另外加 5 GHz)。ESP32、C2、C3、S2、S3 靠 5/6 的本振除頻可以往下摸到約 1.85 GHz,C6 約 1.95 GHz。C61 據 CNX Software 報導 可到 2.7 GHz,收得到 LTE Band 7。

真正的天花板不是 ADC,而是傳輸頻寬。ESPARGOS 官網 自己算過這筆帳:80 MSa/s、每筆 32-bit,modem 寫進 SRAM 的速度是 2,560 Mbit/s,但出口是這樣的:

傳輸介面 頻寬 結果
UART 約 3 Mbit/s 只能抓 snapshot
SPI(ESPARGOS One 內部) 約 13.3 Mbit/s 偵測到訊號才傳
High-speed USB(S31) 480 Mbit/s 連續串流最高 20 MSa/s
Gigabit Ethernet(S31) 1000 Mbit/s 連續串流最高 40 MSa/s

所以絕大多數晶片其實是低工作週期的 SDR:抓一段 205 µs 的快照、傳出去、再抓下一段,中間的訊號就漏掉了。拿來看 2.4 GHz 頻段誰在吵很夠用,要解調連續訊號就不行。S3 雖然能用第二顆核心把 16 MSa/s 降頻到 15.625–250 kS/s 後不間斷地從原生 USB 送出,但頻寬很窄。能以 MSa/s 等級連續串流的只有 ESP32-S31,用的是另一份實驗性的串流韌體,搭配還在開發中的 SoapyESPSDR,就能接進 Gqrx 和 GNU Radio。數字上 README 寫 USB 20 MSa/s、Ethernet 40 MSa/s,但 CNX 報導的 Ethernet 串流是 8–16 MSa/s,可能是版本不同,實際能跑多少還要看韌體進度。

十秒上手:瀏覽器燒錄,或自己編譯

最快的路是瀏覽器。用 Chrome 或 Edge 打開 ESP-SDR 燒錄頁 ,接上板子、選晶片、按燒錄,完成後切到 頻譜檢視器 就能看到即時頻譜和瀑布圖。整個過程不用裝任何東西,簡單到有點傻眼。

想自己改韌體,就照 README 用 ESP-IDF 編譯。先 checkout firmware-targets.json 裡釘住的 ESP-IDF commit,跑 install.sh <target>、source export.sh,再以 S3 為例:

# 編譯 ESP32-S3 版本
idf.py -B build-s3 -DIDF_TARGET=esp32s3 \
  -DSDKCONFIG=build-s3/sdkconfig \
  -DSDKCONFIG_DEFAULTS=sdkconfig.defaults.esp32s3 build

# 燒錄(Linux 下原生 USB 通常是 /dev/ttyACM0)
idf.py -B build-s3 -p /dev/ttyACM0 flash

S31 因為還是預覽晶片,要加 idf.py --preview。

韌體跟電腦之間走的是一套以行為單位的純文字協定,二進位資料再用 CRC32 保護。指令像是 INFO、FREQ 2442、CAP16 4096 0,完整清單在 repo 的 docs/protocol.md。所以你不一定要用官方檢視器,寫幾行 Python 就能自己控制:

# 需求:pip install pyserial
# 原生 USB 時 baud 會被忽略;走 UART 轉接器時需支援 2 Mbaud
import serial

PORT = "/dev/ttyACM0"   # macOS 多半是 /dev/cu.usbmodemXXXX

with serial.Serial(PORT, 2_000_000, timeout=1) as ser:
    ser.dtr = False                   # 避免開埠時拉 DTR/RTS 把板子重置
    ser.rts = False
    ser.write(b"INFO\n")              # 查詢韌體與晶片資訊
    for line in ser.readlines():
        print(line.decode(errors="replace").rstrip())

這段只負責送出查詢、印出回應的文字行,回應的確切格式以 protocol.md 為準。如果第一次沒有回應,多半是開埠瞬間板子被重置了,等一兩秒再送一次即可。要抓 I/Q 的話,CAP16 回來的二進位格式和 CRC 檢查方式請照 protocol.md 實作,別用猜的。

能拿來做什麼

ESPARGOS 多天線陣列定位訊號示意

最直接的用途是 2.4 GHz 頻譜巡檢。家裡 Wi-Fi 卡卡的時候,你可以看到到底是隔壁的 AP、藍牙耳機還是微波爐在搶頻道,這是一般 Wi-Fi 掃描工具給不了的畫面,因為它們只看得到「解得出來的 Wi-Fi 封包」。

ESPARGOS 本來的主業更進階。ESPARGOS One 是一個八天線、相位同步的 Wi-Fi 感測陣列,以前只能拿 Wi-Fi 的 CSI(通道狀態資訊)做定位。有了原始 I/Q 之後,連藍牙、BLE、Zigbee、802.11b 這些 CSI 處理不了的訊號都能定位,還能做陣列增益提升弱訊號解碼,甚至實驗脈衝壓縮雷達。

社群的速度更快。Hackaday 10 月 17 日的整理 提到,另一位研究者 h0m3us3r 幾乎同時獨立發現了同一個 debug 模式;另外,Samson1te 也在另一顆晶片,也就是 Semtech 的 LR2021 LoRa 晶片裡,找到類似的隱藏 SDR,可以收 150–960 MHz。晶片裡「藏著一台 SDR」這件事,看起來不是 Espressif 的特例。

跟傳統 SDR 比,ESP-SDR 的定位很清楚(RTL-SDR 與 HackRF 的規格分別參考 RTL-SDR.com 與 HackRF 官方文件 ):

ESP-SDR RTL-SDR HackRF One
頻率範圍 約 1.85–2.7 GHz,C5 加 4.8–6.0 GHz 約 24–1766 MHz 1 MHz–6 GHz
連續串流 S3 窄頻(≤250 kS/s)、S31 最高 40 MSa/s 可以,約 2.4 MSa/s 可以,最高 20 MSa/s
發射 官方不提供 不行 可以(半雙工)
適合 2.4/5 GHz 頻譜巡檢、陣列研究 入門收聽、ADS-B 全頻段研究、需要發射

另外要記得,ESP-SDR 的增益沒有校準成 dB,不能拿來當量測儀器。

如果你本來就有 RTL-SDR,ESP-SDR 剛好補上它收不到的 2.4 GHz;如果要做嚴肅的射頻量測,還是乖乖用正規儀器。

能發射,但在台灣你最好別碰

ESP32 改裝發射的法規風險示意

這是我最想講清楚的一段。

既然 I/Q 能讀,那能不能寫?答案是可以。ESPARGOS 官網直接承認任意發射是可行的,ESPARGOS One 上甚至能做相位同步發射,但他們刻意不釋出發射功能,理由是可能被拿去干擾別人。

社群可沒這麼克制。marble 做出了發射功能 ,並接上標準的 osmosdr 資料流,現有工具可以直接用;jochenhammes 和 z1000biker 也各自做了能收能發的版本,還有人 用 ESP32-C3 的射頻硬體發 DVB-S2 影像 。

技術上很帥,但請想清楚法規。台灣的 ESP32 模組是以「低功率射頻器材」取得審驗的。依模組廠商文件轉述的 NCC《低功率射頻器材技術規範》(LP0002)第 3.8.2 節,取得審驗證明的器材,非經核准,使用者不得擅自變更頻率、加大功率或變更原設計的特性及功能,發現干擾時要立即停用(Microchip 模組文件 )。把 Wi-Fi 模組改成能發任意波形的發射機,很難說沒有「變更原設計功能」,實際適用請以 NCC 公告的規範原文為準。另外,如果你把改過的板子拿去賣,那就是另一回事了:NCC 曾公告,販售未經審驗的電信管制射頻器材 依電信管理法最重可罰 20 萬元 。

我的建議很簡單:收可以,發不要。真的想玩發射,就在屏蔽箱裡、用假負載,或去考業餘無線電執照,走正規管道。

README 列出的常見問題

以下四點整理自 ESP-SDR 的 README 與 FAQ,解法則是我的建議:

坑一:UART 轉接器掉資料。 ESP-SDR 走 UART 時用 2 Mbaud,有些 CH340 轉接板跟不上,資料會亂掉。解法是換原生 USB 的板子,或在檢視器裡按「Switch to 1 Mbaud」降速。

坑二:開機無限重啟。 README 提到,啟動時的電流尖峰可能讓從 USB-UART 轉接器 3.3 V 腳供電的板子 brownout,然後一直重開。解法是改用正規的 USB 供電或獨立 LDO,別省這條線。

坑三:Linux 下裝置一直被重置。 ModemManager 會去探測 Espressif 的 USB 裝置,順手把它 reset 掉。解法是停用 ModemManager,或寫一條 udev 規則讓它忽略這個 VID/PID。

坑四:把增益數字當成 dBm 在讀。 增益沒有校準成 dB,畫面上的強度只能做相對比較。拿它當功率計去量東西,結論就會是錯的。

我手上只有初代 ESP32,能玩嗎?

可以。初代 ESP32 支援 80、40、16 MSa/s 的 snapshot 模式,看 2.4 GHz 頻譜沒問題,只是沒有原生 USB,要走 UART(GPIO1/GPIO3)。

能拿來解 Wi-Fi 或藍牙封包嗎?

大部分晶片不行。snapshot 之間有空檔,連續的封包會被切斷。要解調得用 S3 的降頻連續模式(15.625–250 kS/s)或 S31 的串流韌體。

這算是 ESP32 的資安漏洞嗎?

ESPARGOS 的 FAQ 明確表示,他們不認為這是漏洞或後門。他們的看法是,如果你擔心 ISM 頻段的訊號被側錄,真正的問題是那些訊號沒有加密,而不是 ESP32 能收得到。

結語:晶片裡沒寫進 datasheet 的那一面

前一篇我寫 GPU Unlock 的時候,主角是 NVIDIA 藏在暫存器裡的產品分級;這週換成 Espressif 藏在 RF 測試函式庫裡的 debug 路徑。兩件事有個共同點:晶片的真實能力,常常比 datasheet 寫的多,而 LLM 正在讓「把它挖出來」這件事變得便宜很多。

對韌體工程師來說,這是雙面刃。你可以把手上的 ESP32 變成一台頻譜分析儀;但你自己的產品裡,那些「反正沒人知道」的 debug 路徑,也越來越不可能永遠沒人知道。

如果你手邊有 ESP32-C5,可以先用瀏覽器燒錄頁燒一次,看看 5 GHz 頻段;只有 C3 或 S3 的話,就從家裡的 2.4 GHz 開始。記得天線要接好,PCB 天線的板型收到的訊號會弱一些。

參考資料

來源 標題
GitHub ESPARGOS/esp-sdr
GitHub ESP-SDR: how it works
ESPARGOS ESP-SDR: Raw IQ Capture with Espressif's ESP32 Chips
CNX Software ESP-SDR firmware turns ESP32 into a 2.4/5 GHz SDR
Hackaday Discovering SDRs Everywhere
Hackaday ESP-SDR Can Now Transmit
Hackaday Using an ESP32-C3's RF Hardware for DVB-S2 Video Transmission
RTL-SDR.com About RTL-SDR
HackRF 官方文件 HackRF One
Microchip(轉述 NCC LP0002) Labeling and User Information Requirements
1111 新聞 NCC:販賣不法電信管制射頻器材 最重罰20萬元罰鍰

沒有留言:

張貼留言

91APP 被駭的起點竟是 Appsmith:自架低代碼工具為何成了企業後門

上個月有朋友傳來一則簡訊截圖問我是不是詐騙。對方報得出她在某品牌官網買了什麼、寄到哪裡、哪天下單,然後說「訂單設定錯誤,請加 LINE 協助解除分期」。這種劇本大家都聽過,但這次的細節準到讓人頭皮發麻,因為資料是真的。 兩週後答案揭曉:台灣電商 SaaS 龍頭 91APP 的...