Memakai Raspberry Pi Pico sebagai USB Rubber Ducky

Gambar ini dibuat dengan Dall-E

USB Rubber Ducky adalah nama produk dari Hack5, bentuknya seperti USB biasa, tapi sebenarnya mengemulasikan keyboard. Ketika dicolok ke USB, benda ini akan bisa mengetikkan berbagai perintah dan menekan shortcut secara otomatis. Benda ini sudah dijual sejak belasan tahun yang lalu, di kalangan security sudah sangat dikenal, dan bisa dipakai untuk bagian dari pentesting ataupun red teaming.

Saya baru menyadari bahwa banyak orang di luar security yang belum kenal benda ini, padahal USB Rubber Ducky ini bisa berguna sekali untuk otomasi setup komputer. Di posting ini saya akan bercerita tentang otomasi yang belum lama saya lakukan di IOI 2022 untuk mensetup laptop untuk perlombaan.

Hardware “asli” rubber ducky cukup mahal (sekitar 60 USD, belum termasuk ongkos kirim). Tapi kita bisa menggunakan berbagai microcontroller, termasuk juga RPI Pico yang harganya relatif murah (bisa kurang dari 5 USD, sudah termasuk ongkos kirim) untuk melakukan hal yang sama (saya sudah membahas Raspberry Pi Pico di blog ini).

Mengenai nama rubber ducky sendiri: setahu saya ini karena waktu dikembangkan, bentuk USB device yang dipakai bentuknya berupa rubber ducky. Tentunya bentuk USBnya bisa seperti apa saja, contohnya Red Team dari Google menggunakan bentuk USB Plasma Globe.

Video perkenalan Rubber Ducky

Sekilas cara kerja USB

Ketika sebuah USB device dicolok ke sebuah komputer (atau TV, atau device lain yang punya colokan USB, istilahnya: USB host), maka USB host akan bertanya: kamu ini apa? dengan meminta descriptor ke device USB tersebut. Device USB akan menjawab dengan descriptor yang mendeskripsikan dirinya.

Kita bisa membuat device yang mengaku sebagai device apa saja. Device ini bisa dibuat dengan microcontroller, atau menggunakan embedded Linux (misalnya Raspberry Pi bukan Pico) menggunakan gadget driver. Bagian mengaku sebagai device lain sangat mudah: kirimkan saja descriptor hasil salinan dari device lain. Bagian sulitnya adalah mengemulasikan device lain tersebut jika belum ada yang mengimplementasikan.

Kalau kita ingin membuat device yang pura-pura menjadi keyboard atau mouse, kita tidak perlu banyak coding, karena sudah ada banyak yang mengimplementasikan. USB rubber ducky berpura-pura sebagai keyboard, jadi mudah ditiru dengan berbagai microcontroller.

Mengenal USB Human Interface Device

Ada banyak kelas device USB, dan dalam pembahasan kali ini saya hanya akan fokus pada HID (human interface device). Contoh device ini: keyboard, mouse, dan game controller. Cara kerja berbagai device ini cukup sederhana, setiap n kali dalam satu detik, host akan bertanya: kamu ada laporan status baru? Untuk jenis device keyboard, report ini akan dikirim oleh device ke host untuk memberi tahu tombol apa yang ditekan saat ini.

Ketika kita mencolokkan keyboard atau mouse ke sebuah komputer, biasanya tidak akan muncul pertanyaan apapun sebelum keyboard atau mouse bisa dipakai, kecuali di macOS. Di macOS, kita akan ditanya layout keyboard dengan menekan tombol di sebelah shift (kiri dan kanan). Tapi jika device mengaku sebagai Apple keyboard, maka macOS tidak akan menanyakan hal ini.

Karena device USB HID tidak perlu driver di berbagai OS, dan tidak perlu disetup dulu, maka ini cocok sekali untuk otomasi, atau untuk menyerang komputer tertentu. Contoh berbagai hal yang bisa dikirimkan ada di repository ini.

Contoh aksi yang bisa dilakukan dengan Rubber Ducky

Sebagai informasi: ada HID device yang didukung oleh BIOS/UEFI, dan ada yang tidak. USB device yang mendukung boot protocol bisa dipakai, dan akan menghasilkan report sederhana yang mudah dipahami oleh BIOS/UEFI. Beberapa implementasi clone rubber ducky tidak mendukung mode ini, jadi hanya bisa dipakai jika komputer sudah masuk ke sistem operasi.

USB Rubber Ducky Pico

Proyek pertama yang saya temukan ketika mencari implementasi Rubber Ducky untuk Pico adalah ini:

GitHub – dbisu/pico-ducky: Create a USB Rubber Ducky like device using a Raspberry PI Pico

Implementasi ini berbasis CircuitPython. Cukup ikuti petunjuk di situ, dan akan langsung berjalan. Sayangnya defaultnya ini tidak mendukung USB HID boot device. Ada issue yang dibuka untuk ini, sudah ada 68 komentar, dan statusnya masih open saat artikel ini ditulis. Status terakhirnya adalah: sudah berhasil untuk PC tertentu, tapi masih gagal di Mac, dan untuk kasus saya: saya coba gagal di laptop yang ingin saya pakai.

CircuitPython memiliki support emulasi berbagai USB device, dan kodenya menjadi cukup kompleks, sedangkan debugging Python tidak mudah dilakukan di Pico, masih lebih mudah debugging kode dalam bahasa C. Saya menemukan kode dalam C yang cukup sederhana:

GitHub – guruthree/pico-superkey-board: A single key keyboard, a demonstration of a USB HID device for the Raspberry Pi Pico in C

Tapi ini juga tidak mendukung USB HID Boot device, untungnya ada yang menanyakan ini di bagian issue, jawabannya sangat mudah, dan bisa jalan.

Setup Laptop di IOI 2022

Laptop untuk IOI 2022 dipersiapkan dengan cloning menggunakan CloneZilla. Sayangnya ada dua hal yang perlu disetup yang tidak bisa dilakukan dengan cloning:

  1. Masalah setting keyboard yang hanya bisa diganti di UEFI (bisa dibaca lengkapnya di posting saya yang ini)
  2. Masalah setting IP Address

Keduanya ini akhirnya diselesaikan dengan Pico. Saya sudah punya beberapa Pico (bawa dari Thailand), dan membeli beberapa lagi dri Shopee, jadi settingnya bisa dilakukan paralel oleh beberapa orang panitia.

Keyboard

Setiap laptop setelah diletakkan di meja perlombaan perlu ditest ulang secara manual oleh panitia untuk memastikan banyak hal: keyboard berjalan baik (semua key tidak ada yang macet), charger bisa berjalan, network dicolok dengan benar, tidak error ketika startup, dsb.

Panitia bisa saja mengganti setting UEFI sekalian ketika melakukan pengecekan manual, tapi langkah manual ini butuh waktu agak lama, panitia harus tepat waktu menekan F2, atau jika terlewat perlu masuk UEFI dari Windows yang butuh cukup banyak langkah (restart, lalu Troubleshoot > Advanced options > UEFI Firmware Settings option, lalu restart lagi).

Susahnya masuk UEFI/BIOS

Dengan Pico yang sudah diprogram, langkah ini bisa dilakukan dengan tepat, dan butuh waktu kurang dari 30 detik. Colok Pico, nyalakan komputer, tunggu sampai restart, cabut lagi Pico. Video berikut ini adalah sebelum saya kurangi delaynya.

Begini aksinya

Awal kodenya seperti ini: Kita tekan F2 sampai yakin masuk menu UEFI. Lalu setelah itu saya mengemulasikan tombol apa yang harus ditekan sampai ke setting BIOS-nya (karena ini sangat spesifik ke laptop ACER, saya tidak akan tuliskan lengkapnya di sini). Di akhir saya berhenti dengan while(1).

    // F2 spamming
    for (int i = 0; i < 20; i++)
    {
        Keyboard.press(KEY_F2);
        sleep_ms(300);
    }
    Keyboard.write(KEY_RIGHT_ARROW);
    //etc
    while (1);

Setting IP Address

Untuk kemudahan monitoring, panitia sudah mengalokasikan bahwa tiap blok kursi memiliki IP tertentu. Jadi jika terdeteksi ada koneksi yang putus, tim network bisa memeriksa jalurnya dengan cepat.

Alokasi IP di IOI 2022

Idealnya tiap laptop dikonfigurasi dengan DHCP, dan IP diset berdasarkan MAC addressnya. Tapi ada beberapa masalah dengan pendekatan ini di IOI 2022. Event ini diselenggarakan di hotel, dan tidak ada ruang khusus untuk menyimpan laptopnya. Jadi usaha untuk mencatat MAC address, memasukkan ke tabel DHCP, akan butuh waktu lama.

Alternatif lain: komputer dinyalakan satu per satu, sambil di catat (baik manual ataupun otomatis) tiap IP address-nya. Setelah didapatkan semua urutan MAC address sesuai posisi komputer, baru dibuat permanen IP-nya. Langkah ini pun akan butuh waktu lama untuk hampir 300 komputer secara bergiliran dan memastikan sudah dapat IP.

Untuk dua pendekatan di atas: andaikan sudah didapatkan semua MAC address, jika di tengah lomba ada perlu pergantian laptop, maka butuh langkah ekstra mengupdate tabel DHCP sesuai dengan kursinya.

Alternatif berikutnya menggunakan DHCP option 82. Ini perlu dibarengi fitur port-based allocation yang ada di switch dari Cisco, Juniper dan beberapa switch lain. Ini merupakan langkah yang cukup ideal yang bisa dilakukan. Tapi belum pernah ada yang mencoba cara ini sebelumnya, terutama dengan banyak switch (tiap blok peserta ada switch terpisah). Selain itu beberapa meja ternyata tidak konsisten urutan cabling-nya karena layout ruangan yang kurang ideal, sehingga kadang laptop diarahkan ke kabel terdekat saja, bukan yang seharusnya sesuai skema awal.

Akhirnya cara yang dipilih adalah setup IP manual. Untuk setting IP di Windows, kita perlu menggunakan account dengan hak admin. Jadi butuh waktu cukup lama untuk login admin, membuka halaman setting IP, mengetikkan IP, netmask, DHCP. Supaya lebih cepat, Pico digunakan.

Pico diset agar otomatis menjalankan shell dengan hak admin, mengetikkan password, lalu mengetikkan script Powershell untuk set IP. Script ini akan dijalankan lalu scriptnya bertanya: meja mana komputer ini berada (misalnya R2), lalu akan mengeset IP sesuai alokasinya.

void type_slowly(const char *inp, int delay_time=1)
{
    for (int i = 0; inp[i] != '\0'; i++)
    {
        Keyboard.write(inp[i]);
        delay(delay_time);
    }
}
int main() {
    //initialization code
    Keyboard.write(KEY_LEFT_GUI);
    sleep_ms(500);
    type_slowly("powershell", 100);
    sleep_ms(1000);
    Keyboard.write(KEY_RIGHT_ARROW);
    sleep_ms(300);
    # ini akan memilih run as administrator
    Keyboard.write(KEY_DOWN_ARROW);
    sleep_ms(100);
    Keyboard.write(KEY_RETURN);
    sleep_ms(500);
    type_slowly("PASSWORD", 100);
    Keyboard.write(KEY_RETURN);
    sleep_ms(500);
    type_slowly("function AssignIP {\n");
    //
}
Yang dilakukan script di atas

Sementara itu kode powershell yang diketikkan adalah seperti ini:

function AssignIP {
  #tabel parsial, aslinya lebih banyak
  $ipm = @{
    r1=11;r2=12;r3=13;r4=14;
  }
  $wmi = Get-WmiObject win32_networkadapterconfiguration -filter {(servicename='rt640x64')};
   #tabel parsial, aslinya lebih banyak
  $bm = @{
    r1=1;r2=1;r3=1;r4=1;r5=2;r6=2;
  }
  $code= Read-Host -Prompt "Enter Code";
  $block= $bm[$code] + 10
  $ip= $ipm[$code]
  $wmi.EnableStatic("192.168.$block.$ip","255.255.255.0");
  $wmi.SetGateways("192.168.$block.1");
  $s = "118.98.44.10","118.98.44.20"
  $wmi.SetDNSServerSearchOrder($s);
}

AssignIP

Sebagai catatan: untuk kasus kedua ini, sebenarnya memakai versi CircuitPython akan lebih efisien. Kita bisa mengemulasikan USB disk dan keyboard, jadi scriptnya bisa dibuat lebih cepat (tidak mengetik seluruh script, tapi langsung membaca dari USB disk).

Penutup

Saya cukup senang karena pengetahuan pentest dan embedded system saya ternyata terpakai di tempat yang tidak terduga. Semoga sharing ini bisa berguna untuk otomasi hal-hal tertentu (misalnya konfigurasi BIOS/UEFI untuk server headless).

Tinggalkan Balasan

Situs ini menggunakan Akismet untuk mengurangi spam. Pelajari bagaimana data komentar Anda diproses.