라즈베리파이 피코로 만드는 러버더키 실습
러버더키가 무엇인가?
러버더키(Rubber Ducky)는 겉보기에는 일반 USB처럼 생겼지만, 사실은 키보드처럼 동작하는 해킹 도구(HID 디바이스)입니다. 연결하면 사람이 직접 키보드를 치는 것처럼 명령을 자동으로 입력하며, 보안 테스트나 공격 시나리오 검증 등에 사용됩니다.
보안 커뮤니티에서 러버더키는 다음과 같은 이유로 주목을 받아왔습니다:
- 플러그 앤 플레이: 꽂기만 하면 자동 실행됨
- 운영체제 독립적: Windows, Linux, macOS 등 대부분의 OS에서 작동
- 간단한 스크립트 작성: Ducky Script라는 쉬운 언어를 사용
그러나 원래의 러버더키 제품은 가격이 비싸거나(2025년 7월 7일 기준 $100.00…) 국내에서 구하기 어려운 경우가 많습니다.
그래서 이번 글에서는 저렴한 대안인 라즈베리파이 피코(Raspberry Pi Pico) 를 사용해서 러버더키를 직접 만들어보는 실습을 진행해보려 합니다. 알리익스프레스에서 할인까지 받으면 고~작 986원 밖에 안한다는 사실! (필자는 심지어 2000원에 샀는데 그세 더 싼 것도 올라왔네요 ㅎㄷㄷ)
이 포스트에서는 라즈베리파이 피코를 이용해서 비슷한 디바이스를 만들 생각이기에 만약 러버더키가 무엇인지, 어떻게 쓰는지 등을 간단히 알고 싶다면 해커스랩 : 플러그앤Hack! USB 러버덕키 사용후기를 보시면 좋습니다!
USB 자동실행 방식 (autorun.inf)도 있었지 않나요?
과거에는 USB에 autorun.inf
파일을 심어 PC에 꽂기만 해도 특정 프로그램이 자동 실행되도록 하는 방식이 널리 사용되었습니다. 하지만 이런 방식은 악성코드 유포 수단으로 자주 악용되었고, 이후 운영체제 제조사들이 이를 차단하는 보안 정책을 도입했습니다.
특히 Windows 7 이후로는 대부분의 USB 저장 장치에서 autorun
기능이 더 이상 작동하지 않게 되었습니다.
이로 인해 단순한 USB 방식의 자동 실행 공격은 어려워졌지만, 키보드 장치(HID)는 여전히 신뢰할 수 있는 입력 장치로 간주되기 때문에 보안적으로 허점을 가질 수 있습니다.
운영체제는 키보드 입력을 사용자 행동으로 인식하기 때문에, 러버더키는 이를 이용하여 자동으로 단축키를 누르거나 명령어를 입력하는 식의 공격을 수행할 수 있습니다.
USB 보안을 강화하는 법! 악성 펌웨어 ‘BadUSB’ 공격 방지
그리고 우리가 만들려는 장치는 BadUSB
이고 이에 대해 추가적인 이야기를 알고 싶다면 위 블로그를 읽어주세요!
그럼 우리가 BadUSB를 막기 위해 어떤 것들을 할 수 있을까?
오토런 바이러스로부터 내 컴퓨터 안전하게 보호하는 방법 [SK브로드밴드 공식블로그:티스토리]
위 블로그에서도 여러 방법이 자세히 나와있지만 솔직히 개인적인 생각으로는 일단 이상한 USB 장치들은 열어보지 않는게 좋겠죠? 책상에 그냥 놓아져 있는 USB는 나쁜 사람이 아니라면 당연히 가져가지 않을 것이고 바닥에 버려져있는 USB도 굳이 열어볼 이유가 없잖아요? 심지어 아래와 같은 경우도 있었으니까요.
[트립고잉 | 전 세계 곳곳에 약 2000여 개의 USB가 있다](https://www.instagram.com/p/CwwS21Rphzs/) |
이 사례는 ‘데드드롭(Dead Drops)’이라는 예술 프로젝트라고는 하지만,
오늘날 BadUSB 기법이 널리 퍼진 만큼 공공장소의 USB를 무작정 꽂는 것은 매우 위험한 행동이 될 수 있습니다.
자 이제 매우 간단한 사전 지식을 알아보았으니 장치를 가지고 직접 만들어보도록 하죠!
준비물
이제 본격적으로 라즈베리파이 피코를 이용한 러버더키 실습을 시작해봅시다.
먼저 아래와 같은 준비물이 필요합니다:
품목 | 설명 |
---|---|
Raspberry Pi Pico | RP2040 기반 마이크로컨트롤러. (Pico W도 가능하나 Wi-Fi 기능은 사용 안 함) |
USB 데이터 케이블 (USB-A to Micro-USB) | 피코를 PC에 연결할 때 사용. 꼭 충전 전용이 아닌 데이터 전송 가능 케이블을 사용하세요. |
컴퓨터 (Windows / Linux / macOS) | 피코에 펌웨어를 업로드하고, 스크립트를 작성할 작업 환경입니다. |
인터넷 연결 | CircuitPython 및 라이브러리 다운로드 시 필요합니다. |
사실상 라즈베리파이 피코만 있다면 다 준비가 되어있겠죠? 아 그리고 참고로 필자는 피코를 살 때 알리익스프레스에서 천원마트로 싸게 가격 맞춰서 사느냐고 와이파이 기능이 없는 pico w
를 구매했기에 와이파이 기능까지는 사용하지 못합니다만, 엄청 간단하니 만약 있다면 실습이 끝난 후에 추가적으로 진행해 보세요! 그런게 더 재밌는 법이죠!
소프트웨어 / 파일
항목 | 설명 |
---|---|
CircuitPython 펌웨어 | 라즈베리파이 피코에서 파이썬을 실행할 수 있게 해주는 펌웨어입니다. |
Adafruit HID 라이브러리 | 키보드/마우스 입력을 위한 라이브러리 (CircuitPython용) |
코드 에디터 (예: VS Code, 메모장, vi, vim 등) | 필자는 vscode를 매우 선호하지만 사실 메모장으로도 코드 편집은 가능하니 뭐든 상관 없답니다 |
그럼 이제 재료가 준비되었으니 요리를 시작해보죠
CircuitPython 설치하기
러버더키처럼 자동 입력을 구현하려면, Pico에서 키보드 입력을 제어할 수 있어야 합니다.
이를 위해 CircuitPython이라는 펌웨어를 설치해야 합니다.
CircuitPython이란?
CircuitPython은 Adafruit에서 만든 초보자 친화적인 마이크로컨트롤러용 Python 인터프리터입니다.
간단히 말하면, 마이크로컨트롤러에서도 Python 코드로 제어가 가능하도록 만든 경량 운영 환경입니다.
💡 비유하자면 이렇습니다:
일반 컴퓨터에는 Ubuntu나 Windows 같은 운영체제(OS) 가 깔리고, 그 위에서 파이썬을 실행할 수 있죠.
마찬가지로, 라즈베리파이 피코 같은 마이크로컨트롤러에는 아무런 OS가 없지만,
CircuitPython을 설치하면 일종의 ‘미니 리눅스 + 파이썬 환경’이 만들어지는 것이라 생각하면 이해가 쉽습니다.
즉, Pico에 CircuitPython을 올리면:
- USB 저장 장치처럼 연결되고
code.py
파일을 저장하면- 마치 리눅스에서
python3 myscript.py
하는 것처럼 자동으로 실행됩니다
그리고 여기에 Adafruit에서 제공하는 HID 라이브러리를 추가하면,
키보드/마우스 동작도 아주 쉽게 구현할 수 있습니다!
이제 CircuitPython을 설치해봅시다.
1. BOOTSEL 모드로 Pico 연결하기
CircuitPython을 설치하려면, 먼저 Pico를 BOOTSEL 모드로 연결해야 합니다.
이건 마치 컴퓨터에 새 운영체제를 설치할 때 USB 설치 모드로 부팅하는 것과 비슷합니다.
BOOTSEL 버튼이란?
Pico 보드 위에는 작은 버튼이 하나 있습니다.
이 버튼이 바로 BOOTSEL 버튼입니다.
‘BOOT Selection‘의 줄임말로, Pico에 전원이 들어올 때 어떤 모드로 부팅할지를 선택하는 역할을 합니다.
Pico의 부팅 모드 정리
Pico는 연결 방식에 따라 두 가지 모드로 부팅됩니다.
다만 중요한 점은, Pico를 처음 샀을 때(아직 아무 펌웨어도 설치되지 않은 상태) 와
펌웨어를 한 번이라도 설치한 이후는 동작이 다르다는 것입니다.
구분 | BOOTSEL 버튼 | 부팅 결과 | 설명 |
---|---|---|---|
초기 상태 (공장 출고) | 누르지 않음 | 외장하드 모드 | 내부에 프로그램이 없기 때문에 자동으로 RPI-RP2 USB 드라이브로 인식됩니다 |
펌웨어 설치 이후 | 누르지 않음 | 실행 모드 | 플래시 메모리에 저장된 프로그램이 자동 실행됩니다 |
항상 가능 | 누른 상태에서 연결 | 외장하드 모드 | 어떤 상태든 BOOTSEL 버튼을 누르면 강제로 RPI-RP2 드라이브로 진입합니다 |
💡 즉, 처음에는 BOOTSEL 버튼 없이도 외장하드 모드로 연결되지만,
펌웨어를 설치하고 나면 반드시 BOOTSEL 버튼을 눌러야 다시 외장하드 모드로 진입할 수 있습니다.
이 때문에 CircuitPython을 설치하려면, Pico를 BOOTSEL 모드 (외장하드 모드) 로 연결해 주어야 하고,
이를 위해 다음과 같이 하면 됩니다:
- BOOTSEL 버튼을 누른 상태로 USB 케이블을 컴퓨터에 연결
- 연결 후 버튼을 떼면,
RPI-RP2
라는 이름의 드라이브가 나타납니다
이제 BOOTSEL 모드로 잘 연결했다면, 다음 단계로 넘어가서 CircuitPython을 다운로드해봅시다.
2. CircuitPython 다운로드
이제 Pico에 올릴 CircuitPython 펌웨어 파일을 받아야 합니다.
아래 링크로 이동해서 해당 보드를 선택해 주세요:
페이지 하단의 “Download .UF2” 버튼을 클릭하면 .uf2
확장자의 펌웨어 파일이 다운로드됩니다.
이 파일은 라즈베리파이 피코에서 CircuitPython을 구동하게 해주는 역할을 합니다.
⚠U+FE0F 다운로드한 파일 이름 예시:
adafruit-circuitpython-raspberry_pi_pico-en-*.uf2
(버전에 따라 숫자나 날짜는 달라질 수 있습니다)
필자가 글을 작성중인 2025-07-17일에는 9.2.8 버전이네요.
한국어는 없으니 영어로 선택해 주면 됩니다.
3. 펌웨어 업로드
이제 다운로드한 .uf2
파일을 Pico에 올리는 작업만 남았습니다.
앞서 설명한 BOOTSEL 모드로 Pico를 연결했다면,
탐색기(또는 파인더)에 RPI-RP2
라는 이름의 USB 드라이브가 나타나 있을 것입니다.
이제 다음 단계를 따라 주세요:
- 다운로드한
.uf2
파일을RPI-RP2
드라이브에 그냥 드래그해서 복사합니다 - 복사가 끝나면 Pico는 자동으로 재부팅되며,
RPI-RP2
드라이브는 사라지고
새롭게CIRCUITPY
라는 이름의 드라이브가 생성됩니다
다시 시작되고 저런 파일을 들어가보면 Adafruit CircuitPython 9.2.8이라며 설치된 펌웨어가 보이고 라즈베리파 피코에서 계속 불이 깜빡거린답니다.
Adafruit HID 라이브러리 복사하기
CircuitPython이 설치된 Pico는 USB 저장장치처럼 동작하며, CIRCUITPY
라는 드라이브로 연결됩니다. 이제 여기 안에 HID(키보드/마우스 에뮬레이션) 기능을 사용할 수 있도록 라이브러리를 추가해보겠습니다.
1. Adafruit CircuitPython Bundle 다운로드
먼저 필요한 라이브러리가 들어있는 번들(zip 파일)을 다운로드해야 합니다.
Adafruit CircuitPython Library Bundle (버전별)
페이지에서 현재 사용 중인 CircuitPython 버전에 맞는 zip 파일을 선택해서 다운로드하세요. 예: bundle-9.x-mpy-20240710.zip
버전 번호가 설치된 CircuitPython과 일치하는지 확인해 주세요!
이번에 저는 boot_out.txt
에 써있듯 9.x 버전을 설치해야겠네요.
2. 압축 해제 및 필요한 라이브러리 추출
다운로드한 zip 파일을 압축 해제하면 이렇게 옃가지 파일이 보일텐데 우린 그 중 lib/
폴더 안에서 수 많은 파일 중 러버더키를 만들기 위해서는 adafruit_hid/
폴더를 복사합시다!
굳이 가뜩이나 127mb로 용량도 적은데 다른 것들까지 넣기엔 공간도 부족하잖아요?
3. CIRCUITPY 드라이브에 복사
CIRCUITPY
드라이브에lib
폴더가 없다면 새로 만듭니다 (/Volumes/CIRCUITPY/lib
또는E:\lib
같은 경로), 사실 처음엔 당연지사 없을겁니다. 고로 만드세요!- 위에서 복사한
adafruit_hid
폴더를lib
폴더 안에 붙여넣습니다
📁 폴더 구조 예시:
1
2
3
4
5
6
7
8
CIRCUITPY/
├── code.py (요건 이제 다음에 나올 내용)
└── lib/
└── adafruit_hid/
├── keyboard.py
├── keycode.py
├── mouse.py
└── ...
이제 CircuitPython에서 import adafruit_hid.keyboard
등으로 HID 기능을 사용할 준비가 끝났습니다!
✅ 참고:
adafruit_hid
라이브러리는 키보드 입력, 마우스 이동, 컨슈머 컨트롤(볼륨 조절 등)까지 지원합니다. 다양한 예제를 보고 싶다면 Adafruit HID GitHub를 참고하세요.
그리고 여기서 잠깐!!
폴더 구조 예시에 나온 .py
들과 실제 우리가 다운받은 파일을 잘 살펴보면 뭔가 다르다는 것을 알 수 있습니다.
바로 .py
와 .mpy
의 차이죠!
.py
vs .mpy
차이점
CircuitPython 라이브러리를 받으면 .py
가 아닌, .mpy
파일이 들어 있는 걸 볼 수 있습니다. 물론 다운로드 할 때에 .py
를 다운로드 할 수도 있답니다.
위는 .mpy
아래는 .py
파일이거든요.
이건 단순히 이름이 다른 게 아니라, 기술적으로 중요한 차이가 있습니다.
구분 | .py 파일 | .mpy 파일 |
---|---|---|
형식 | 일반 텍스트 | 컴파일된 바이너리 |
용도 | 사람이 읽고 편집 가능 | 실행 최적화된 코드 |
속도/효율 | 상대적으로 느림 | 빠르고 메모리 효율적 |
사용 가능성 | CircuitPython, CPython 모두 가능 | CircuitPython 전용 |
용량 | 큼 | 작음 |
정리하자면:
.py
는 우리가 흔히 아는 일반 Python 코드 파일입니다. 텍스트 에디터로 열어 수정할 수 있고, 초보자도 읽기 편합니다..mpy
는 CircuitPython에서 쓰기 위해 미리 컴파일된 Python 모듈입니다. 실행 속도가 빠르고, 마이크로컨트롤러의 작은 메모리에도 적합합니다.
그럼 사용 방법은?
code.py
에서는.mpy
파일을 그냥import
해서 쓸 수 있습니다 마치.py
모듈처럼 다뤄도 됩니다
1
from adafruit_hid.keyboard import Keyboard
.mpy
파일을 수정하고 싶다면, Adafruit GitHub 저장소에서 원본.py
파일을 받아 직접 수정 후 사용하거나, 필요시 다시.mpy
로 변환할 수도 있어요
code.py 작성 및 테스트
라즈베리파이 피코를 러버더키로 만들기에 앞서 어떻게 자동입력을 하게 되는지에 관해 간단히 코드를 작성해 봅시다.
1
2
3
4
5
6
7
8
CIRCUITPY/
├── code.py
└── lib/
└── adafruit_hid/
├── keyboard.py
├── keycode.py
├── mouse.py
└── ...
위에서 말했듯 이제 code.py
를 편집하여 코드를 작성하게 될 것이다.
기본 예제: 자동으로 메모장 열고 문자열 입력하기 (windows 기준)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import time
import board
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
# 키보드 객체 생성
kbd = Keyboard(usb_hid.devices)
layout = KeyboardLayoutUS(kbd)
# 잠깐 대기 (운영체제가 장치를 인식할 시간 확보)
time.sleep(2)
# Win + R (실행 창 열기)
kbd.press(Keycode.WINDOWS, Keycode.R)
kbd.release_all()
time.sleep(0.5)
# "notepad" 입력 후 Enter
layout.write("notepad")
kbd.press(Keycode.ENTER)
kbd.release_all()
time.sleep(1)
# 메모장에 문자열 입력
layout.write("Hello hacker?!\n")
이렇게 하여 진짜로 라즈베리파이 피코를 뽑았다 껴보면!
이렇게 자동으로 입력되는 장치가 완성되었다는것!!!
하지만 위 영상에서처럼 장치를 연결하면 폴더가 보이기도 하고 러버더키의 스크립트인 더키 스크립트를 이용하지도 못하니 말이죠..
사실 여기서 뭔가 더 나아가 직접 파이썬 페이로드를 구현하여 악성 디바이스를 만들 수도 있겠으나 우리는! 러버더키를 만들어보고자 했던 것이니까요?
실제 러버더키 구현하기
앞선 예제는 단순히 “자동으로 문자열을 입력하는” 동작이었다면, 이번에는 정식 Rubber Ducky 스크립트(Ducky Script) 를 읽고 실행하는 러버더키 장치를 만들어 보겠습니다.
다행히도 이미 많은 분들이 CircuitPython 기반으로 이를 구현해 둔 덕분에, 우리는 아주 쉽게 기능을 확장할 수 있습니다.
그 중 대표적인 프로젝트가 바로:
이 프로젝트는 Adafruit의
adafruit_hid
라이브러리를 활용하여, Ducky Script 구문을 해석하고 실행해 주는 코드까지 들어있어 이것을 참조해 봅시다.
혹시 위 코드를 실행해 보고 싶다면 readme
에 정말 자세히 설명되어있으니 읽어보시고 직접 해보세요!
하지만 우리에게는 picow가 아닌 pico에 맞는 코드만 필요하고 너무 길어보이니 우리에 맞게 코드를 짜봅시다.
물론 그게 코드가 짧을 거라는 의미가 아니긴 하지만요..
구현하기에 앞서: boot.py
?
우리가 위에서 코드를 구현하여 실행해 보았을 때에는 분명 code.py
를 만들어 실행했었죠?
하지만 pico-ducky
프로젝트를 보면 boot.py
라는 코드가 있는걸 볼 수 있습니다. 게다가 이 코드는 다른 코드에서 import
되어 사용되지도 않죠.
그럼 이건 뭘까요?
boot.py는 CircuitPython에서 피코가 부팅되며 가장 먼저 실행되는 파일입니다.
이 파일은 USB 드라이브의 노출 여부
나 USB 장치로서의 역할 설정
등 아주 중요한 초기 설정을 담당하고 있죠.
그래서 pico-ducky 프로젝트에서는 어떤 역할을 하고 있을까요?
바로, 특정 핀(GP15) 의 입력값에 따라 CIRCUITPY 드라이브를 노출할지 숨길지를 결정하는 역할을 합니다.
즉, 이 장치를 설정 모드 또는 실행 모드 로 나누는 판단을 여기서 하는 것이죠.
어떻게 동작하냐면?
GP15 핀에 아무것도 연결되어 있지 않으면:
- 피코에서는 USB 드라이브(CIRCUITPY)를 보이게(Enable) 합니다.
- 피코W에서는 USB 드라이브를 숨깁니다(Disable)
GP15 핀이 GND에 연결되어 있으면:
- 피코에서는 USB 드라이브를 숨깁니다(Disable)
- 피코W에서는 USB 드라이브를 보이게(Enable) 합니다.
즉, “설정하고 싶을 땐 GP15를 GND에 연결” 하면 되는 방식!
오 그렇다면 이걸 이용하면 위에서 봤듯이 연결했을 때에 USB 드라이브가 보이지 않게 할 수 있겠네요.
자세한 코드 설명은 깃헙에 들어가면 주석(#)
으로 정말 잘 설명되어있으니 읽어보시길 바래요!
우리에 맞게 구현하기 전 읽어봐야 하는 코드
좋아요! 이어지는 블로그 형식에 맞춰 duckyinpython.py
의 핵심 기능을 간결하고 이해하기 쉽게 정리해드릴게요:
우리에 맞게 구현하기 전 읽어봐야 하는 코드 : duckyinpython.py
그럼 boot.py
와 code.py
가 어떤 순서로 실행되는지 알게 되었으니 다음은 러버더키 페이로드를 실제로 실행시켜주는 핵심 로직 파일인 pico-ducky/duckyinpython.py
를 간단히 살펴보겠습니다.
duckyinpython.py는 어떤 역할을 할까?
이 파일은 전체적으로 다음과 같은 역할을 합니다:
.dd
확장자의 Ducky Script 파일을 읽어옴- 스크립트를 한 줄씩 파싱함
- 각 명령어를 실제 키보드 입력으로 변환하여 실행함
즉, DUCKY SCRIPT → CIRCUITPYTHON 키보드 명령으로 번역해주는 통역사 역할을 하는 파일인 것이다.
1. selectPayload()
- CIRCUITPY 루트 디렉터리에 있는
.dd
파일을 검색해서 하나 선택 - 기본 파일명은
payload.dd
지만 여러 개가 있을 경우 우선순위 선택 가능
2. getProgrammingStatus()
- code.py에서 import 하여 사용
- 마찬가지로
GP15
핀을 체크해서 지금이 설정 모드인지 실행 모드인지 판단 True
일 경우 CIRCUITPY 드라이브가 노출된 상태 → payload를 복사하거나 수정 가능False
일 경우 payload 실행 모드로 진입
3. runScript(path)
- code.py에서 import 하여 사용
- 지정된
.dd
파일을 읽고 한 줄씩 파싱 - 각 명령어 (
STRING
,ENTER
,CTRL
,DELAY
,REM
등)를 실제 키보드 입력으로 실행
4. parseLine(line)
- Ducky Script의 한 줄을 분석하여 어떤 동작을 할지 판단
예:
STRING Hello
→ “Hello”를 입력CTRL ALT DEL
→ 세 키를 동시에 누름DELAY 500
→ 0.5초 대기
5. pressKey()
및 releaseKey()
- 실제 HID 키보드 동작을 수행하는 함수들
adafruit_hid.keyboard
모듈을 이용해 가상 키보드 입력을 구현
예시
1
2
3
DELAY 1000
STRING Hello, world!
ENTER
위 세 줄이 들어있는 .dd
파일이 있다면, 실행 결과는:
- 1초 대기
- “Hello, world!” 입력
- 엔터키 누르기
이걸 실제 컴퓨터에 USB로 연결된 라즈베리파이 피코가 자동으로 수행하게 됩니다!
그럼 이제야 진짜 진짜 진짜로 우리 장치에 맞는 코드를 구현해보자
이라고는 하지만 말이죠… 저 pico-ducky/duckyinpython.py
는 너무 잘 만들어졌단 말이죠.. 굳이 바꿀 필요가 있나? 싶네요
고로 우리는 boot.py와 code.py에 있는 pico w에 관한 내용만 없애보도록 하죠.
code.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# License : GPLv2.0
# copyright (c) 2023 Dave Bailey
# Author: Dave Bailey (dbisu, @daveisu)
# Pico board only support (Pico W 관련 내용 제거)
import supervisor
import time
import digitalio
from board import *
import board
from duckyinpython import *
# sleep at the start to allow the device to be recognized by the host computer
time.sleep(.5)
# supervisor 자동 재실행 끄기
supervisor.runtime.autoreload = False
# LED 초기화 (Pico만 지원)
if board.board_id == 'raspberry_pi_pico' or board.board_id == 'raspberry_pi_pico2':
import pwmio
led = pwmio.PWMOut(board.LED, frequency=5000, duty_cycle=0)
else:
# Pico W가 아닌 다른 보드일 경우 LED 출력 설정 (필요 시 추가)
led = digitalio.DigitalInOut(board.LED)
led.switch_to_output()
progStatus = False
progStatus = getProgrammingStatus()
print("progStatus", progStatus)
if progStatus == False:
print("Finding payload")
# not in setup mode, inject the payload
payload = selectPayload()
print("Running ", payload)
runScript(payload)
print("Done")
else:
print("Update your payload")
led_state = False
import asyncio
async def main_loop():
global led, button1
button_task = asyncio.create_task(monitor_buttons(button1))
# Pico W 관련 비동기 작업 제거
pico_led_task = asyncio.create_task(blink_pico_led(led))
await asyncio.gather(pico_led_task, button_task)
asyncio.run(main_loop())
boot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import board
import digitalio
import storage
# GP15 핀 설정
noStoragePin = digitalio.DigitalInOut(board.GP15)
noStoragePin.switch_to_input(pull=digitalio.Pull.UP)
noStorageStatus = noStoragePin.value
# Pico에서는 GP15가 GND에 연결되어 있으면 CIRCUITPY를 숨깁니다
# GP15가 연결되어 있지 않으면 CIRCUITPY를 보이게 합니다
if not noStorageStatus:
# GP15가 GND에 연결되어 있음 → CIRCUITPY 숨김
storage.disable_usb_drive()
print("USB 드라이브 비활성화됨 (실행 모드)")
else:
# GP15가 연결되어 있지 않음 → CIRCUITPY 보임
print("USB 드라이브 활성화됨 (설정 모드)")
그리고 duckyinpython.py
의 코드는 별도로 손대지 않고 그대로 사용했습니다.
사실 code.py
나 boot.py
를 pico-ducky
프로젝트에 있는 걸 그대로 가져와도 문제 없습니다.
그리고 몇가지 추가해야지 duckyinpython.py
가 작동한다는 사실을 발견했기에 위에서 구현할 때 없었던 친구들을 아래 적어놨습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
E:.
│ boot_out.txt
│ code.py
│ boot.py
│ duckyinpython.py
│ payload.dd
│
└─lib
│ adafruit_debouncer.mpy <- 요놈
│ adafruit_ticks.mpy <- 요놈
│
├─adafruit_hid
│ consumer_control.mpy
│ consumer_control_code.mpy
│ keyboard.mpy
│ keyboard_layout_base.mpy
│ keyboard_layout_us.mpy
│ keycode.mpy
│ mouse.mpy
│ __init__.mpy
│
└─asyncio <- 요놈 파일 통째로
core.mpy
event.mpy
funcs.mpy
lock.mpy
stream.mpy
task.mpy
traceback.mpy
__init__.mpy
이 모든 파일은 adafruit-circuitpython-bundle-9.x-mpy-20250716
안에서 찾아 추가하시면 됩니다.
그리고… 드디어!
두둥 탁! 이제 우리가 만든 장치는, 단순히 문자열을 입력하는 수준이 아니라 페이로드 파일(payload.dd) 안의 Ducky Script를 읽고,실제 HID 키보드처럼 동작해서 자동으로 입력을 수행하는 진짜 러버더키 장치가 됩니다!
게다가 위 사진처럼 점퍼선을 연결하게 되면
이렇게 USB 드라이브 내부가 보이지 않지만 페이로드를 실행시킬 수 있다는점!
하지만 주의할 점도!
러버더키가 동작할 때 페이로드 입력 타이밍과 환경이 잘 맞지 않으면 예상치 못한 결과가 생길 수 있습니다.
예를 들어:
- 컴퓨터가 부팅 중이라 아직 키 입력을 받지 못하는 상태에서 실행되면 실패
- 프로그램이 완전히 켜지기 전에 입력이 들어오면 엉킴
- 입력 속도가 너무 빠르면 윈도우가 못 따라옴
그래서 DELAY
명령어를 적절히 넣는 것이 핵심입니다. 꼭 테스트하면서 타이밍을 조절하세요!
직접 피코에 파이썬 코드를 짜는 것이 아닌 HID를 이용한 방식이 무서운 이유는?
가장 중요한 점은 바로 이것:
이건 “악성코드를 다운로드하거나 실행하는 것”처럼 보이지 않습니다. 대신, 사용자가 직접 키보드로 입력하는 것처럼 보입니다.
즉, UAC(관리자 권한 요청) 창이 떠도, ENTER
키를 자동으로 입력시켜 실행까지 도달하게 만들 수 있다는 사실!
컴퓨터를 속이는 거죠, 마치 Pico가 사용자인 마냥.
그 의도 정말 좋아요. 보안 실습과 라즈베리파이 피코의 가능성을 배우는 건전한 목적으로 이 프로젝트를 소개하고 싶으신 거잖아요. 그런 맥락을 담아 아래처럼 마무리 문구를 다듬어볼 수 있습니다:
🎉 마무리하며
이렇게 해서 1000원으로 만들어본 USB 러버더키 실습이 마무리됐습니다.
하지만 이 글의 목적은 단순히 자동입력 장치를 만드는 데에 있는 게 아닙니다. 보안 실습을 통해 USB HID 공격 방식이 실제로 어떤 식으로 동작하는지 체험해보고, 또 동시에 라즈베리파이 피코를 활용해 직접 코드를 짜보는 즐거움을 함께 느껴보셨으면 합니다.
이런 코드를 해석하고, 실제로 입력이 이뤄지는 과정을 직접 구현해보는 것은 단순한 따라하기보다 훨씬 깊이 있는 학습이 될 수 있습니다.
아 혹시 duckyinpython.py
를 복사해 오기만 했다면 꼭 한 번 읽어보세요 — 러버더키가 실제로 어떻게 동작하는지에 대한 가장 중요한 내용들이 그 안에 담겨 있으니까요.
그럼 즐거운 해킹 되시길~!
Happy Hacking!
(2025-07-17-23-44)