「STM32F103でHIDデバイス」
https://qiita.com/nanbuwks/items/f7f2377c2b252e936baa
を元に再構成した記事です。
概要
STM32F1マイコンのUSBインターフェースをHIDデバイスとして簡単にプログラムできます。
この技術を使って、キーボードから入力があったように振る舞うようにしてみましょう。
元々、STM32_Arduino の bootloader を書き込むとシリアル通信としてのUSBデバイスは使えるようになっていました。更に、以下のライブラリを使うとUSBHIDができるようになり、キーボードやマウスを模した動作ができるようになります。
このサイトの説明を見ると、USB HID 以外に MIDIやMass storage もできるとあります。夢が広がりますね!
設定方法
- 先のサイトからライブラリをダウンロード。
- 今回の例ではZIPでダウンロードしました。
- 展開
- Arduinoスケッチを保存するところのフォルダ中の、hardware/Arduino_STM32-master/STM32F1/libraries に配置
- 例えば、ポータブル環境だと以下に展開することになります。
- .../(ポータブル環境ディレクトリ)/hardware/Arduino_STM32-master/STM32F1/libraries
ZIPを展開すると USBHID_stm32f1-master という名前のフォルダができるますが、それを USBHID_stm32f1 というフォルダ名に変更し、上記の場所に移動する。
動作テスト
#include <USBHID.h>
void setup() {
USBHID_begin_with_serial(HID_KEYBOARD);
Keyboard.begin();
}
void loop() {
Keyboard.println("Hello,world.");
delay(5000);
}
とすると、5秒おきに Hello,World が出力されます。
うまく動かない場合
Norton や Kaspersky などのウイルス対策ソフトがブロックすることがある?
https://qiita.com/nanbuwks/items/7026c4bf9937eed5ded8
(参照:「STM32duino 環境のトラブルシューティング」)
Webブラウザを出す
#include <USBHID.h>
void setup() {
USBHID_begin_with_serial(HID_KEYBOARD);
Keyboard.begin();
}
void loop(){
delay(5000);
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('r');
delay(100);
Keyboard.releaseAll();
Keyboard.println("lowleveltokyo.connpass.com\n");
}
Windowsキーを押して「ファイル名を指定して実行」を出し、ブラウザを出しています。
(低レベル勉強会のイベントサイトが出ます。決してブラウザクラッシャーではありません。)
なお、特殊キーの一覧は
BadUSB
当然、悪いこともしまくりです。
攻撃コード
以下は、プログラムコードではなくキーボードコンビネーションを示します。
Windows
LogOUT:
Ctrl+Alt+Delete
+
Alt + I
Command Prompt:
Windows key + R
+
CMD + Enter
Mac OSX
LogOut:
COMMAND Key + Shift Key + Q
+
Enter
Ubuntu
LogOut:
Ctrl+Alt+Delete
+
Enter
Android
Depend on each device.
Logout: (few device )
Ctrl+Alt+Delete
iOS
機材持ってないのでスミマセン
やるなよ! 絶対やるなよ! Do Not
sudo rm /*
キーボードだけで実行コードを作り出す(Windows)
「HIDプラント」と名づけています。HIDデバイスだけで、実行プログラムを作り出す方法です。
Windowsのバージョンによって動作は異なります。特に、Windows10とそれより前のバージョンではかなり異なるようです。
管理者としてコマンドプロンプト起動
Windows key
Cmd + shift + F10
↓ + Enter + ← Enter
16進コード作成
Copy con code.hex
Abcdef012345689 (16進コードを記述します)
Ctrl+Z
バイナリ生成+実行
certutil -f -decodehex code.hex code.exe 12
あらかじめ、16新コードは別マシンで作成し、hexファイルに変換します。 copy con code.hex でそのhexファイルの内容を書き出すようにプログラムを作ります。
Arduinoの内部に格納できるコードは限られているので、ある程度小さなコードにする必要があります。
脅威に対する対策
単純にキーボードとして動作するようなものは判別が簡単ですが、以下のように動作するものを作るのは簡単です。
- 最初は、
- センサやタイマーなどの条件が揃うと発動
- キーボードデバイスに変化する
- キーボード入力を模して動作する。
こういったものを排除するためには事前に動作をよく確認することが必要ですが、トリガ発動条件を工夫して、動作検証時にはバレないようにすることは簡単です。フォレンジックで検出できないデバイスが簡単にできてしまうことがよくわかるでしょう。
参考資料
keyboard.hで定義されている特殊キー
#define KEY_LEFT_CTRL 0x80
#define KEY_LEFT_SHIFT 0x81
#define KEY_LEFT_ALT 0x82
#define KEY_LEFT_GUI 0x83
#define KEY_RIGHT_CTRL 0x84
#define KEY_RIGHT_SHIFT 0x85
#define KEY_RIGHT_ALT 0x86
#define KEY_RIGHT_GUI 0x87
#define KEY_UP_ARROW 0xDA
#define KEY_DOWN_ARROW 0xD9
#define KEY_LEFT_ARROW 0xD8
#define KEY_RIGHT_ARROW 0xD7
#define KEY_BACKSPACE 0xB2
#define KEY_TAB 0xB3
#define KEY_RETURN 0xB0
#define KEY_ESC 0xB1
#define KEY_INSERT 0xD1
#define KEY_DELETE 0xD4
#define KEY_PAGE_UP 0xD3
#define KEY_PAGE_DOWN 0xD6
#define KEY_HOME 0xD2
#define KEY_END 0xD5
#define KEY_CAPS_LOCK 0xC1
#define KEY_F1 0xC2
#define KEY_F2 0xC3
#define KEY_F3 0xC4
#define KEY_F4 0xC5
#define KEY_F5 0xC6
#define KEY_F6 0xC7
#define KEY_F7 0xC8
#define KEY_F8 0xC9
#define KEY_F9 0xCA
#define KEY_F10 0xCB
#define KEY_F11 0xCC
#define KEY_F12 0xCD
今回の解説ではキーボードのエミュレーションのみですが、マウスやUSBストレージなどもエミュレーションできます。自信のある方はチャレンジしてみてください。