スープの上で

雑多なメモ

SECCON2016のIoT CTF Challengeに参加してきました

かなり遅いレポートですが、1月末に開催されたSECCON2016決勝大会(のワークショップの方)に行ってきました。

f:id:haruna_nishiwaki:20170202224757j:plain

私が参加したのは土曜日だけでしたが、「王様達のヴァイキング」がつくられた裏話などが聞けてとても面白かったです。 そして公演の後はワークショップ、「IoT CTF Challenge」に参加してきました。 環境は手元にはないので、内容の全てを詳細にレポートできませんが、参加していない方でも雰囲気を味わっていただけるかと思います。 また、配線図は公開可能か不明だったので、ネットに落ちている配線図を引っ張ってきましたが、もし不明点や補足点などあれば、ご連絡いただければと思います。

今回開催されたIoT CTF Challengeは、

  • 前半:九州大会予選で使用されたIoT CTF Challengeに関するハンズオン・解説
  • 後半:IoT CTF(実践)

という構成で行われました。

## 前半

Lチカ〜EEPROMをRaspberry piから読み書き

写真は撮っていないのですが、テーブルにはRaspberry Piが既にセッティングされており(ローカルネットワークに接続されている状態)、sshVNC ViewerRAspberry Piに接続するところからワークショップが始まりました。

今回使わせていただいたRaspberry PiRaspberry Pi 2 Model B。Amazonでは5000円くらいで買えるようです。

Raspberry Piに接続できると、定番のLチカを行った後、以下の練習問題とともにIC「24LC256」が手渡されました。 これは実際に九州大会予選で使用された問題だそうです(ICの内容自体は違った様子です)。

特務機関JN○Aのミッションを遂行せよ

あなたは特務機関JN○Aに属しているエージェン トである.当局からとあるミッションを8ピンの ICを受け取るかたちで受けた.ミッションを果た
せ!

akizukidenshi.com

データシートを確認するとI2C通信するICだということがわかるので、Raspberry PiでI2C通信ができるようにします。

デバイスドライバ

Rasberry Pi I2C EEPROM Program - richud.com

書き込みソフトウェア

GitHub - tat/eeprog: eeprog is a Linux C program that allows you to read and write to 24Cxx EEPROMs.

ワークショップで利用したRaspberry Piには既に準備されていたので上記手順は行わずに問題に着手することができました。 ブレッドボード上にICを置き、配線をし、試しに書き込み・読み出しをしてみます。 ※回路図は公開可能か不明だったので記載しませんが、こちらなどを参考に配線すれば大丈夫かと思います。

Raspberry pi and i2c. Connecting a 24Cxx eeprom.

pi@raspi03:~/work/eeprom/eeprog $ date | ./eeprog -f -16 -w 0 -t 5 /dev/i2c-1 0x50  // ←dateコマンドの結果を書き込み
eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
  Bus: /dev/i2c-1, Address: 0x50, Mode: 16bit
  Operation: write at offset 0, Input file: <stdin>
  Write cycle time: 5 milliseconds
  Writing <stdin> starting at address 0x0
.............................

pi@raspi03:~/work/eeprom/eeprog $ ./eeprog -16 -r 0:29 -f /dev/i2c-1 0x50
eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
  Bus: /dev/i2c-1, Address: 0x50, Mode: 16bit
  Operation: read 29 bytes from offset 0, Output file: <stdout>
  Reading 29 bytes from 0x0
Sat 21 Jan 17:41:58 UTC 2017 // ←先ほど書き込んだdateコマンドの結果

うまく読み書きできました。 実際に出題された問題は、同様にこのICからデータを読み出すと、以下のようにファイルが取り出せるという問題だったようです。

pi@raspberrypi:~/work/eeprom/eeprog $ ./eeprog -f -16 -r 0:0x8000 /dev/i2c-1 0x50 > image
eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
  Bus: /dev/i2c-1, Address: 0x50, Mode: 16bit
  Operation: read 32768 bytes from offset 0, Output file: <stdout>
  Reading 32768 bytes from 0x0
pi@raspberrypi:~/work/eeprom/eeprog $ file image
image: gzip compressed data, last modified: Tue Jan 17 06:07:30 2017, from Unix
pi@raspberrypi:~/work/eeprom/eeprog $ mv image image.gz ; gzip -d image.gz

gzip: image.gz: decompressing OK, trailing garbage ignored
pi@raspberrypi:~/work/eeprom/eeprog $ file image
image: POSIX tar archive (GNU)
pi@raspberrypi:~/work/eeprom/eeprog $ mv image image.tar ; tar xvd image.tar
flag
xxx.jpg
xxx.py

flagの中身はSECCON{assemble this circuit}で、取り出したxxx.jpgに記載された回路図を組み、Raspberry Piでxxx.pyを実行すれば解けるものだったようです。

ArduinoをAVRライタとして使う準備

次に、Raspberry PiからArduinoにプログラムを書き込んでArduinoをAVRマイコンライタにして、AVRにプログラムを(Arduinoを介して)書き込みました。 入れ子のようでややこしいですが、Raspberry Pi上でArduino IDEを起動させ、そこからArduinoを介してAVRにプログラムを書き込みます。

今回利用したArduinoArduino nanoなので、Raspberry Pi-Arduino間はUSBで接続します。

まずは、Arduino IDEの設定を整えます。

  • File->Preferencesの「Additional Board Manager URLs」にhttp://drazzy.com/package_drazzy.com_index.jsonを追加してOKを押す
  • Tools->Board->BoardManagerからATTinyCore by Spence Kondeをインストールする
  • Tools->Bard:“xxx(今の設定)”->Arduino Nanoを選択
  • Tools->Processor:“xxx(今の設定)”->ATmega328を選択
  • File->Examples->ArduinoISP->ArduinoISPを選択
  • Uploadボタンを押し、Arduinoに(ArduinoSIPプログラムを)書き込む

以上でArduinoをAVRライタとして動かす準備ができました。

今回利用するAVRは、ATTniy85なので、Arduino-AVR間は以下のような感じで配線します。

ATtiny85にArduinoで書き込んでみた - Qiita

※上記に加えてRST-GND間にコンデンサを入れるとエラーを連発させず書き込めるらしい…プルアップ抵抗つけとけということなのだろうか…(内臓されてるとか書いてありますがライタがあんまりそのへんを考慮してない作りなのでしょうか?)

そして以下でArduinoからAVRに書き込みます

  • Tools->Bard:“xxx(今の設定)”->ATtiny25/45/85を選択
  • Tools->Chip:“xxx(今の設定)”->ATtiny85を選択
  • Tools->Programmer: “xxx(今の設定)”->“Arduino as ISP"を選択
  • Uploadボタンを押し、AVRにプログラムを書き込む

これでAVRにプログラムを書き込む準備ができました。

後編

ここで前半のハンズオンが終わり、IoT CTFに

出題された問題は、IC一つのみ(問題文なし)。前半でも利用された24LC256が手渡されました。 ここまででやってきたことで回答できるということなので、先ほどと同じ手順でICからデータを読み出します。

pi@raspi03:~/work/eeprom/eeprog $ ./eeprog -f -16 -r 0:0x8000 /dev/i2c-1 0x50 > image
eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
  Bus: /dev/i2c-1, Address: 0x50, Mode: 16bit
  Operation: read 32768 bytes from offset 0, Output file: <stdout>
  Reading 32768 bytes from 0x0
pi@raspi03:~/work/eeprom/eeprog $ ls
24cXX.c  24cXX.o    dist    eeprog.c  i2c-dev.h  Makefile  WARNING
24cXX.h  ChangeLog  eeprog  eeprog.o  image      README
pi@raspi03:~/work/eeprom/eeprog $ file image 
image: gzip compressed data, last modified: Thu Jan 19 11:35:52 2017, from Unix
pi@raspi03:~/work/eeprom/eeprog $ mv image image.gz
pi@raspi03:~/work/eeprom/eeprog $ gzip -d image.gs
gzip: image.gs.gz: No such file or directory
pi@raspi03:~/work/eeprom/eeprog $ gzip -d image.gz 

gzip: image.gz: decompression OK, trailing garbage ignored
pi@raspi03:~/work/eeprom/eeprog $ file image 
image: POSIX tar archive (GNU)
pi@raspi03:~/work/eeprom/eeprog $ mv image image.tar; tar xvf image.tar
flag
xxx.ico
xxx.py
pi@raspi03:~/work/eeprom/eeprog $ cat flag 
SECCON{Assemble this circuit, and execute this code on ATtiny85.}

第一段階のフラグはSECCON{Assemble this circuit, and execute this code on ATtiny85.} 「This」はどれを指しているのでしょうか?「コードを実行しろ」と言っているので、xxx.icoが回路図なのでしょうか?

pi@raspi03:~/work/eeprom/eeprog $ file xxx.ico 
xxx.ico: ASCII text
pi@raspi03:~/work/eeprom/eeprog $ cat xxx.ico
int clk = 3;
int q7 = 4;
int oe = 0;
int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int prevClock = LOW;
int flag = HIGH;

void setup() {
  pinMode(clk, INPUT);
  pinMode(q7,  OUTPUT);
  pinMode(oe,  INPUT);
}

void loop() {
  if (flag == HIGH && digitalRead(clk) == LOW) {
    if (digitalRead(oe)==HIGH) {
      d[7]=d[6]=d[5]=d[4]=d[3]=d[2]=d[1]=d[0]=0;
      return;
    }
    int tmp = !(d[6] ^ d[5]) & 1;
    d[7] = d[6];
    d[6] = d[5];
    d[5] = d[4];
    d[4] = d[3];
    d[3] = d[2];
    d[2] = d[1];
    d[1] = d[0];
    d[0] = tmp;
    if (d[7] != 0) {
      digitalWrite(q7, HIGH);
    } else {
      digitalWrite(q7, LOW);
    }
    flag = LOW;
  }
  if (flag == LOW && digitalRead(clk) == HIGH) {
    flag = HIGH;
  }
}
pi@raspi03:~/work/eeprom/eeprog $ cat xxx.py 
#!/usr/bin/env python

import RPi.GPIO as GPIO
import time
import sys

CLOCK = 36
Q7    = 38
OE    = 40
COUNT = 127

def init() :
    GPIO.setwarnings(False) 
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(CLOCK, GPIO.OUT)
    GPIO.setup(Q7, GPIO.IN)
    GPIO.setup(OE, GPIO.OUT)
    GPIO.output(CLOCK, GPIO.LOW)
    GPIO.output(OE, GPIO.HIGH)
    clock()
    GPIO.output(OE, GPIO.LOW)

def clock() :
    GPIO.output(CLOCK, GPIO.HIGH)
    time.sleep(0.001)
    GPIO.output(CLOCK, GPIO.LOW)
    time.sleep(0.001)

def main() :
    init()
    for _ in xrange(COUNT) :
        data = GPIO.input(Q7)
        sys.stdout.write(str(data))
        sys.stdout.flush()
        clock()
    sys.stdout.write("\n")
    GPIO.cleanup()

main()

xxx.pyもxxx.icoもプログラムですが、xxx.pyはpythonの(おそらくRaspberry pi用の)プログラム、xxx.icoマイコン向けのプログラムのようなので、ATtiny85にこのxxx.icoを書き込んだ上でRaspberry Piの上でxxx.pyを実行すればよいのかな?と思ったのですが、ここでブレッドボード上に回路を組んでいる間にタイムアップ。最後のフラグは取得できませんでした。

まとめ

久しぶりにマイコンやブレッドボードに触れられて、とても楽しいワークショップでした。 実際にIoT CTFで出題された問題も解説していただき、IoT CTFの雰囲気を感じることができ参考になりました。

また機会があればセキュリティ系だけではなくIoT系のワークショップに参加したいです( ´ ▽ ` )ノ