ハンズオン
ハンズオン1: ATmega328P に対する FIA-1
事前準備
ここでは ATmega328P に対する FIA を試行します.
ATmega328P は Arduino に実装されている場面を見ることが多いと思います. しかし,Arduino は電源ラインにカップリングコンデンサが実装されているため, ATmega328P が Arduino の基板に実装されたままだと FIA がうまくいきません.
そこで,ATmega328P だけブレッドボードに移し替えて,コンデンサがない状態で FIA を実施します. そのために,まず ATmega328P がブレッドボードにある状態で動かせるようにしてください. Arduino を一台用意し,ISP 化することで,ATmega328P がブレッドボードにある状態でも書き込みができるようになります.
課題1: ATmega328P をブレッドボードに配置し,動作できるようにしてください.条件は以下です
- ATmega328P の出力は PC のシリアルターミナルから確認できる状態であること
- クロックは Arduino ではなく,自前で用意した 16 MHz の水晶振動子から供給すること
- (可能であれば)Arduino をもう一台用意し,ISP 化することで,ブレッドボードに ATmega328P がある状態でも書き込みができるようにすること
ATmega328P に書き込んでほしいコードを以下に記載します.
#include <Arduino.h>
void setup() {
Serial.begin(115200);
}
void loop() {
int ctr = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
delay(100);
if (i < 0 || i > 1 || j < 0 || j > 1 || ctr != i * 2 + j) {
Serial.print("FLAG{glitch_detected} ");
Serial.print("i: ");
Serial.print(i);
Serial.print(" j:");
Serial.print(j);
Serial.print(" ctr:");
Serial.println(ctr);
while (1) {}
}
Serial.print("i: ");
Serial.print(i);
Serial.print(" j:");
Serial.print(j);
Serial.print(" ctr:");
Serial.println(ctr);
ctr++;
}
}
}
課題2: ESP32 に Injector を書き込み,2N7000 を活用し,fault を入れられる回路をブレッドボードに構築してください.条件は以下です
- 3.3 V の定常状態から 0 V まで落とせること
- 0 V の期間は 10 us とすること
- ATmega328P の出力を ESP32 で受け取れるようにすること(UART)
課題3: 課題1 で構築した ATmega328P の実験環境に対して,課題2 で構築した Injector を用いて Injection を行い,カウンタが壊れ,flag が出力されることを確認してください.
ハンズオン2: ログインバイパス
課題4: ATmega328P に以下のプログラムを書きこんでください.そのうえで,間違ったパスワードを入れてもログインができるような Injector を構築してください
void setup() {
Serial.begin(115200);
}
void loop() {
char buf[8] = {0};
Serial.println("Password:");
while (!Serial.available()) {}
Serial.readBytesUntil('\n', buf, 7);
if (strcmp(buf, "password") == 0) {
Serial.println("Access granted");
} else {
Serial.println("Access denied");
}
}
ハンズオン3: AES
課題5: ATmega328P に以下のプログラムを書きこんでください.そのうえで,鍵を取り出してください
#include <Arduino.h>
const uint8_t SBOX[16] = {0x9,0x4,0xA,0xB,0xD,0x1,0x8,0x5,0x6,0x2,0x0,0x3,0xC,0xE,0xF,0x7};
const uint8_t DBG = 4; // you can change
uint8_t mul2(uint8_t x){ x <<= 1; if (x & 0x10) x ^= 0x13; return x & 0xF; }
uint8_t mul4(uint8_t x){ return mul2(mul2(x)); }
uint16_t subnib(uint16_t s){
uint16_t r = 0;
for (int i = 0; i < 4; i++)
r |= (uint16_t)SBOX[(s >> (12 - 4*i)) & 0xF] << (12 - 4*i);
return r;
}
uint16_t shiftrow(uint16_t s){
uint8_t n1 = (s >> 8) & 0xF, n3 = s & 0xF;
return (s & 0xF0F0) | ((uint16_t)n3 << 8) | n1;
}
uint16_t mixcol(uint16_t s){
uint8_t n[4] = {(uint8_t)((s>>12)&0xF),(uint8_t)((s>>8)&0xF),
(uint8_t)((s>>4)&0xF),(uint8_t)(s&0xF)};
for (int c = 0; c < 4; c += 2) {
uint8_t a = n[c], b = n[c+1];
n[c] = a ^ mul4(b); n[c+1] = mul4(a) ^ b;
}
return ((uint16_t)n[0]<<12)|((uint16_t)n[1]<<8)|((uint16_t)n[2]<<4)|n[3];
}
uint8_t g(uint8_t w, uint8_t rcon){
return ((SBOX[w & 0xF] ^ rcon) << 4) | SBOX[(w >> 4) & 0xF];
}
uint16_t RK[3];
void setup() {
Serial.begin(115200);
pinMode(DBG, OUTPUT);
digitalWrite(DBG, LOW);
uint8_t w0 = 0x3A, w1 = 0xF0; // secret key
uint8_t w2 = w0 ^ g(w1,0x8), w3 = w2 ^ w1;
uint8_t w4 = w2 ^ g(w3,0x3), w5 = w4 ^ w3;
RK[0] = (w0<<8)|w1; RK[1] = (w2<<8)|w3; RK[2] = (w4<<8)|w5;
}
uint16_t saes_encrypt(uint16_t pt) {
uint16_t s = pt ^ RK[0];
s = subnib(s);
s = shiftrow(s);
digitalWrite(DBG, HIGH);
delayMicroseconds(20); // easy
s = mixcol(s); // attack here
digitalWrite(DBG, LOW);
s ^= RK[1];
s = subnib(s);
s = shiftrow(s);
s ^= RK[2];
return s;
}
void loop() {
if (Serial.available() >= 2) {
uint8_t hi = Serial.read(), lo = Serial.read();
uint16_t ct = saes_encrypt(((uint16_t)hi << 8) | lo);
Serial.write(ct >> 8);
Serial.write(ct & 0xFF);
}
}
ハンズオン4: X-Box
課題6 (発展): X-box 360 Slim に対して Reset Glitch Hack を行ってください.
参考:RGH/RGH3