被輻射燒短路的邏輯閘
GaianSpace CTF 2026「05-rad-hard-rampage」系列第三篇。
前兩篇(SEU、SEL)都是單粒子事件,都是一顆粒子、一個位元、一瞬間發生的事情,而這一篇換成累積效應,不是某一下,而是幾個月的輻射劑量慢慢把電晶體搞壞。這題的故障模型也從資料被更改變成邏輯本身壞掉,所以解法跟著完全不同
系列其他篇:〈感測器漂移 / Degradift〉
題目在講什麼
Total ionizing dose does not flip a bit and move on — it leaves transistors shorted, stuck, permanently. The encoder now spits nonsense. We still have the original design, gate for gate, with the damaged nodes marked.
翻成白話:累積好幾個月的輻射劑量終於讓 Foundation One 的狀態編碼器出事了,總游離劑量(TID)不是翻一個位元就沒事,它會把電晶體永久燒短路、卡死。 編碼器現在吐出來的是垃圾。我們還留著原始設計,一個閘一個閘都在,損壞的節點也標出來了。
編碼器會把一串探針字組轉成一行狀態字,而在板子上量到的是垃圾,因為有幾個閘被短路了,不管輸入是什麼,輸出都卡死。
也就是說,會需要要重建編碼器本來該做的事,把探針字組跑過「設計時」的邏輯,狀態行就會回來
給的檔案是一份閘級網表 status_encoder.netlist,短路的閘有標記,探針字組列在最後
Flag 格式
GAIANSPACE{...}。
讀懂網表
1 | INPUTS i0 i1 i2 i3 i4 i5 i6 i7 |
8 個輸入、8 個輸出,全部是 XOR 鏈加上 NOT。其中 n6、n15 兩個節點被標成 [SHORTED=0]、[SHORTED=1]
這就是題目說的「電晶體被燒短路、輸出永久卡死在某個值,不管輸入是什麼」
短路值是謊言,要用設計值
這是整題的轉折,對應提示 A short is a lie
Total Ionizing Dose(TID,總游離劑量) 是另一種完全不同的輻射效應,它不是某一顆粒子的瞬間事件,而是長期累積的電荷陷在氧化層裡,慢慢讓電晶體的臨界電壓漂移、漏電,到最後一些閘就「黏」在某個固定輸出、再也不隨輸入改變了
所以板子上現在量到的,是損壞後那兩個被卡死的值——那是故障的結果,不是設計本意。[SHORTED=0]/[SHORTED=1] 只是在記錄 它現在壞成什麼樣子,所以重建時要完全忽略這個標記,n6、n15 一樣照原本的邏輯算(n6 = i0 XOR i1、n15 = i1 XOR i3),跟其他正常的 Gate 沒有兩樣
把探針字組餵進「設計版」邏輯
網表的註解寫明:每個Probe Byte 的 Bit對應 i7..i0(位元 0 → i0,位元 7 → i7)
把 32 個 Probe,依序餵進設計版的邏輯(忽略短路標記),算出每組 o0..o7,再組回一個位元組。
為了同時看清楚短路造成的差異,我把「照故障跑」跟「照設計跑」兩種都模擬了一次:
1 | def run(byte, damaged): |
兩種輸出放在一起看,結論一目了然:

有趣的是,損壞的開頭幾個字元因為巧合還看得出 GE、ENSPE 的影子(應該是有些輸出位元剛好沒受那兩個卡死的閘影響),但整體完全不成文字,只有 完全照設計版(兩個閘都當正常 XOR)跑過,32 個 Probe 才對應出完整乾淨的Flag
Flag
1 | GAIANSPACE{t0tal_1onizing_d0se} |
心得
- 「卡死」和「翻轉」是兩種完全不同的故障模型。 翻轉(SEU)只改一個值,窮舉找回來就好(見第一篇);卡死(TID)會讓受影響的閘對所有輸入都回同一個值,而且會往下游擴散。解法不是去猜「正確值是多少」,而是直接重建設計時的邏輯。
- 題目明說那個標記是「壞掉的樣子」,就別被它牽著走。
[SHORTED=...]的值是用來描述故障的,不是拿來用的;把它當成該忽略的雜訊即可。這題真正的工作量其實在「把網表正確轉成模擬程式」,邏輯本身很單純。 - 把「照故障跑」和「照設計跑」都做出來對照,不只驗證理解,也很有畫面。 一眼就能看到短路對下游訊號的破壞範圍,也順便確認自己的模擬器沒寫錯。








