package main

// Rubber Duck attack - USB HID keyboard automation.
// The badge presents itself as a USB keyboard and executes a sequence of
// keystrokes on the connected computer.
//
// TARGETS UBUNTU/GNOME. For other platforms adjust the key sequences.
// NOTE: keyboard scan codes are US layout; non-US layouts may produce
//       different characters for symbols (/, -, :, etc.).
//
// Press button A to trigger the attack. The badge waits on startup
// so you have time to plug it in safely.

import (
	"machine"
	"machine/usb/hid/keyboard"
	"time"
)

func main() {
	// wait for USB enumeration
	time.Sleep(2 * time.Second)

	// button A arms the attack — only runs when pressed
	btnA := machine.P1_06
	btnA.Configure(machine.PinConfig{Mode: machine.PinInputPullup})

	kb := keyboard.Port()

	for {
		if !btnA.Get() {
			runAttack(kb)
			// only run once per press
			for !btnA.Get() {
				time.Sleep(50 * time.Millisecond)
			}
		}
		time.Sleep(10 * time.Millisecond)
	}
}

func runAttack(kb keyboard.Device) {
	// open application launcher (Super key on Ubuntu/GNOME)
	kb.Down(keyboard.KeyLeftGUI)
	time.Sleep(time.Second)
	kb.Up(keyboard.KeyLeftGUI)
	time.Sleep(500 * time.Millisecond)

	// search for text editor
	kb.Write([]byte("text"))
	time.Sleep(1500 * time.Millisecond)
	kb.Press(keyboard.KeyEnter)
	time.Sleep(time.Second)

	// type the ominous message
	kb.Write([]byte("Please wait while you are being hacked"))
	time.Sleep(2 * time.Second)

	// open run dialog (Alt+F2 on GNOME) and launch xdg-open
	// NOTE: symbols below assume US keyboard layout
	kb.Down(keyboard.KeyLeftAlt)
	kb.Down(keyboard.KeyF2)
	time.Sleep(time.Second)
	kb.Up(keyboard.KeyF2)
	kb.Up(keyboard.KeyLeftAlt)
	time.Sleep(time.Second)

	kb.Write([]byte("xdg"))
	kb.Press(keyboard.KeypadMinus)
	kb.Write([]byte("open https>"))
	kb.Press(keyboard.KeypadSlash)
	kb.Press(keyboard.KeypadSlash)
	kb.Write([]byte("www.youtube.com"))
	kb.Press(keyboard.KeypadSlash)
	kb.Write([]byte("watch_v)dQw4w9WgXcQ"))
	kb.Press(keyboard.KeyEnter)

	// turn the volume up
	time.Sleep(500 * time.Millisecond)
	for i := 0; i < 12; i++ {
		kb.Press(keyboard.KeyMediaVolumeInc)
	}
}
