Electromagnetic Fault Injection por dos duros

Abstract

En la entrada que hoy nos concierne, vamos a ver como fabricar un dispositivo capaz de realizar EM Fault Injection por menos de 5€.

¿Qué es Fault Injection?

Fault Injection, o en español,inyección de fallos (vaya nombre feo) es un término ampliamente utilizado en el mundo del hardware y de la seguridad informática. Consiste en introducir errores lógicos en las CPUs mediante la alteración del hardware. Esto permite que, aunque un procesador esté ejecutando un código 100% seguro y libre de fallos, podamos causarlos nosotros, extrayendo secretos o redirigiendo la ejecución a nuestro propio software no autorizado, entre otros escenarios.

Tipos de ataques

Como mencionamos, para llevar a cabo estos ataques hay que alterar el hardware de los procesadores. Las tres formas más comunes y efectivas (en términos calidad-precio) son las tres siguientes:

  1. Power glitch injection: se altera los suministros de corriente/voltaje del dispositivo.
  2. Clock glitch injection: se altera la señal de reloj que llega a un circuito síncrono (CPU, SRAM, etc)
  3. Electromagnetic Fault Injection: se utilizan campos magnéticos para inducir cambios de voltaje o corriente en el objetivo.

En ocasiones, estos ataques se clasifican en función de si son invasivos (el chip queda inutilizable o modificado permanentemente después del ataque) o no invasivos, como es el caso que nos concierne. Cabe destacar que estos ataques pueden llevarse a cabo no solo contra CPUs, sino también contra memorias y otros componentes.

Bendita Física

Lo siento. Toca hablar de física y de electrónica. Prometo no enrollarme. ¿Cómo es que un campo magnético puede provocar cambios en un dispositivo electrónico?


Electromagnetismo: Es la interacción entre cargas eléctricas, que se manifiesta por medio de campos eléctricos y de campos magnéticos, relacionados entre sí. Es una fuerza de largo alcance (teóricamente infinito), mucho más intensa que la gravedad.

Existen un par de leyes que nos interesan en especial. La Ley de Faraday y la Ley de Lenz. No voy a describirlas al detalle pero las menciono por si es de interés. Lo verdaderamente interesante es la relación entre el campo magnético y las corrientes eléctricas. Todo se resume en dos ideas:

Una corriente eléctrica circulando por un conductor, produce un campo magnético.

y al mismo tiempo:

Un campo magnético en movimiento, puede producir una corriente eléctrica si un conductor se encuentra a su alcance. (inducción)


Un imán (campo magnético) produce un voltaje en la espira

Este último caso es el que vamos a utilizar a nuestro favor. Generaremos un campo (electro)magnético cerca de nuestra CPU (no utilizaremos un imán, eso si). Este campo creará un voltaje en las pistas y circuitos del procesador, que están hechos de materiales conductores. Estos voltajes pueden ser confundidos con estados lógicos por las puertas lógicas. Por ejemplo, si el procesador funcionase a 3.3 voltios, un ‘1’ lógico sería cualquier línea en la que tuviésemos 3.3v. Si inducimos un voltaje en un lugar donde antes no había, estamos cambiando un ‘0’ lógico (no hay voltaje) por un ‘1’ (hay voltaje), y ahi está el truco.

Como un amigo suele decir, el fault injection es magia, si, pero magia fácil.

Circuito básico y sencillo para hacer ráfagas magnéticas y “EM Injection”

Para conseguir un campo magnético solo necesitamos 2 cosas, un inductor (que no es más que una bobina de un material conductor) y una corriente que pasar por la bobina.

La fuerza del flujo magnético viene dada por la siguiente ecuación:

$$ \Phi = L * I $$

Donde L es la inductancia(Henrios) y I corresponde a la intensidad de la corriente (Amperios). A mayor inductancia, o a mayor intensidad, mayor será el flujo magnético.

La ecuación para calcular la inductancia es la siguiente:

$$ L = \frac{N^2 * \mu * S}{l} $$

Donde:

  • N: número de espiras (sin unidad)
  • u: permeabilidad del núcleo (Wb/A*m)
  • S: sección del núcleo (metros cuadrados)
  • l: longitud de líneas del flujo (metros)

Para conseguir causar problemas en el circuito necesitamos un flujo magnético lo suficientemente grande. Tenemos dos opciones, aumentar la inductancia o aumentar la intensidad. Aumentar la intensidad es sencillo, pues según la ley de Ohm:

$$ I = \frac{V}{R} $$

Aumentando el voltaje conseguiremos una mayor intensidad. De esta forma no nos preocupamos por la inductancia, que tiene más parámetros a tener en cuenta.

Vamos a ver como obtener un circuito de converisón a alto voltaje, barato, accesible y ya montado. Con este alto voltaje generaremos nuestro campo con una intensidad considerable.

Construcción

Llegado este punto, si no te has enterado de nada anteriormente, no te preocupes. Vamos a ver como construir nuestro inyector. Los materiales que necesitamos son:

  1. Raqueta eléctrica matamosquitos (4.50€ aprox)
  2. Soldador y Estaño
  3. Cables para soldar, pistola termofusible (o cinta adhesiva)

Por menos de 5€, podemos encontrar en cualquier bazar raquetas eléctricas matamosquitos que contienen casi todos los componentes que necesitamos y ya montado. Solo hay que realizar un par de modificaciones.


Desmontamos el dispositivo

Veamos que contiene el circuito:


De izquierda a derecha: condensador grande, diodos(no importante), transformador.

El transformador se encarga de convertir los 3 voltios de entrada a alto voltaje. Advertencia: El alto voltaje es peligroso y hay que manejar estos circuitos con cuidado y precaución.

La salida del condensador (lado izquierdo) es la que va a la raqueta de metal. La entrada de las pilas se encuentra en el lado derecho de la imagen.


Modificaciones

Debemos desconectar todo lo que haya después del condensador (la parte de la raqueta), y reemplazarlo por un spark gap y un inductor.

Fabricar Inductor

Para fabricar el inductor solo hay que hacer una bonina con un cable que tengamos disponible. Podéis probar diferentes grosores y número de espiras:


Primera prueba, bobina con 8 espiras y algo de separación entre ellas.


Segundo inductor, 6 espiras en paralelo. Colocado en el dispositivo final

Fabricar Spark Gap

El spark gap no es ni más ni menos que un espacio entre dos cables. Cuando el condensador acumule suficiente carga, será capaz de romper la diferencia de potencial del aire y atravesarlo. Es entonces cuando vemos que una chispa atraviesa de un lado a otro.



Para fabricarlo solo necesitamos un par de cables, y dejarlos fijos cerca uno del otro sin que se toquen. En mi caso, utilizé cables tipo jumper.


En el centro de la imagen podéis ver el spark gap, cuyos cables son de color verde

Teniendo todo listo, lo re-ensamblamos y vamos a testearlo.

Observación: cuanto mayor sea la distancia del spark gap, mayor voltaje se necesitará para romper la diferencia de potencial y atravesar el aire. Nuestro inyector tardará más en cargarse, pero en contraste el campo magnético será más intenso.

Resultados

Vamos a utilizar la siguiente pieza de código en todas las plataformas:

#include <stdio.h>


int main(void){
    int i,j,k,cnt;
    k = 0;
    while(1){
     cnt = 0;
     for(i=0; i<5000; i++){
       for(j=0; j<5000; j++){
          cnt++;
       }
     }
     printf("%d %d %d %d\n", cnt, i, j,k++);
    }
}

Observaremos si somos capaces de provocar fallos en la ejecución del programa.

Arduino UNO

El arduino UNO es el objetivo perfecto para las primeras pruebas, puesto que el microcontrollador (el ATMEGA 328P) es muy grande y está expuesto directamente.


ATMEGA A la derecha. Será nuestro objetivo.

Compilamos el código C anterior, lo subimos, y desde el arduino IDE abrimos una terminal serie para recibir el output.


Nada mas empezar conseguimos algunos fallos aritméticos, con el inyector a una distancia de 5-6 cm.

Después de un par de intentos, es fácil deducir en qué áreas debemos colocar nuestro dispositivo. El lateral izquierdo del ATMEGA produce buenos glitches (errores aritméticos, cambios en la velocidad, cuelgues) mientras que el lateral derecho normalmente congela totalmente el ATMEGA e incluso hace que deje de ser detectado por el PC. De esto podemos deducir que en el lateral izquierdo probablemente se encuentre la memoria SRAM o los registros.


Más cambios de bits, esta vez, convertimos el contador a negativo.

Uno de los error más interesantes que introduje fue con una versión preliminar del dispositivo, y no estuve lo suficientemente ávido para recordar hacer capturas (¡así que tendrás que creerme!). Este glitch probablemente afectó a la función sprintf o a su argumento nº 2, la cadena con formato. El arduino empezó a volcar todo el contenido de la memoria y a enviarlo por la conexión serie al PC. Aparecían algunas cadenas de texto como Arduino co. o todas las letras del set de caracteres imprimibles abcd…ABCD..1234567890 etc.

Intenté reproducir este fenómeno con la versión final pero esto es lo que he conseguido hasta el momento:


¿Volcado de memoria?

Arduino MEGA

Arduino MEGA es la versión en esteroides de Arduino, posee un microcontrolador ATmega2560 con mayor cantidad de salidas y entradas de datos.


Arduino MEGA

Por su formato más compacto, parece ser algo más resiliente, aunque no en exceso. Lograr errores aritméticos como en el caso anterior fue trivial así que no le dedicaré mucho tiempo más.

Si conseguí de nuevo sacar por la conexión serie algunos datos aunque desconozco el origen o tipo de glitch causado:





Raspberry Pi B+

La Raspberry Pi B+ utiliza un SoC Broadcom BCM2835, con una CPU ARM7. Ejecutaremos armbian (fork de debian) para las pruebas.


SoC de la Raspberry Pi B+

Dependiendo del área de la CPU en la que posicionemos el inyector, obtendremos unos resultados u otros.


Fallo en la aritmética del programa, que continua ejecutándose

A veces, dependiendo de la intensidad del pulso y de la zona, causaremos un reset de la CPU, o un fallo temporal en la salida HDMI (la señal se corrompe, y tarda unos segundos en volver a ser correcta).


Hemos introducido un glitch que puede haber afectado a un acceso de memoria, causando una excepción.

En la última imagen, hemos observado como el glitch introducido ha desembocado en un segmentation fault, probablemente provocado por un acceso inválido a memoria. Esto es muy interesante porque demuestra que podemos provocar excepciones, lo cual nos permitiría atacar componentes como el bootloader o el kernel, mediante corrupción de la tabla de excepciones y una posterior excepción causada por nosotros mediante hardware.

Agradecimientos

Gracias a @MatyFM y @marunmagesh por las ideas y la ayuda sobre el hardware y la electrónica.

comments powered by Disqus