2020/12/30

Nexys4 DDR FPGA: Implementación de MD5

¿Venís de leer la intro, la parte 1, la parte 2, la parte 3,  la parte 4 y la parte 5?

 Contexto


Tenía unos pocos días para implementar en el Zynq de la Parallella el forzador brutal de MD5 para proponerlo a un evento.

Como veía que se me venía difícil, intenté prepararme un [entorno de TDD] que no usé, pero me puso en sintonía.

(Nota: cada texto entre llaves indica un link que aún no está disponible, en algún momento actualizaré)

Sabía algo de VHDL, pero mi punto de entrada a esa plataforma es Verilog así que intenté aprender un poco [migrando ejemplos] e investigando y eso me dejó con soltura en el lenguaje y el entorno de desarrollo.

En lugar de respetar el plan que me había propuesto, fui más tipo blitzkrieg, tomé algunos componentes de la migración y los hice funcionar juntos, en una primera etapa un contador con botones de start, stop y reset, display de 7 segmentos y unos leds de estado, lo cual ocupa casi nada de la PL disponible:



Sin el pipeline




Luego agregué el pipeline:



Diagrama de bloques simplificado



Y lo fui implementando stage por stage, primero a mano y luego me cansé y programé un [generador en C]. Tambien hice una salida de referencia con los valores intermedios y conectando sucesivamente la entrada del selector de display a estos estados intermedios en el pipeline, verifiqué que funcionara ok.



8 stages



Y así hasta el stage63... puse lógica de detección de coincidencia y perdí un tiempo ridículo en conseguir que start/stop, reset, found, done y running hicieran lo que yo quería.


El pipeline completo

Resultados


Tengo un circuito que calcula 4 GHashes en 40 segundos, esto es 100 MHashes por segundo, que es exactamente lo que había previsto.



Los IO no importan pues no harían falta en cada instancia, no?



Para la demo y para github lo instancié ocho veces, se acerca a 1100 MHashes que había alcanzado con GPGPU. Tambien para probar la superficie instancié 10 pero sin la lógica necesaria para distribuir los rangos de exploración, las potencias de 2 son más fáciles.


Deuda técnica y aprendizajes


Como que esto fué tiro con arco zen, pero sin la sabiduría que implica, casi que manotazos de ahogado, entiendo que si funciona es por una acumulación inconsciente de conocimiento, hay partes que no puedo explicar responsablemente.

El tiempo de síntesis e implementación arrancó en cuatro minutos y se duplicó con el pipeline completo, yo aproveché para ir haciendo estas entradas en el blog o ir pensando el siguiente paso (sin salvar, que puede afectar el flujo actual o siguiente), no es bueno irse a colgar ropa o ponerse a pensar en otra cosa.


Cerca de cuarenta horas a lo largo de cuatro días me llevó esto.

Cuando aprenda a [simular] supongo que será todo más fluido.

Hay que mirar permanentemente los warnings, sobre todo los critical warnings, varias veces me avisaron de cables no conectados.

Sin embargo, en la etapa de debugging del pipeline ocurrió algo muy interesante: por desviar hacia el display etapas intermedias y no usar la salida de pipeline para nada, lo quita por optimización:


Efecto de conectar el display al stage00 en lugar del stage63






Seguí con la parte 6

Forzando Brutalmente MD5 - parte 7 - caminos no tomados

¿Venís de leer la intro, la parte 1, la parte 2, la parte 3, la parte 4, la parte 5, la  implementación FPGA en nexys4ddr y la parte 6?

Dejo registradas acá todas las ideas y caminos no explorados, ya sea por falta de tiempo, ganas, dinero, interés o acceso.


No garantizo que sea la última, pues me falta usar la FPGA de la Parallella y la PYNQ y dejando de lado esto específico de md5, es una experiencia que me falta. La diferencia entre Parallella y PYNQ es el doble de FPGA.

 

Mainframe


Aunque tengo acceso parcial a un mainframe, se trata de un elemento crítico y debería programarlo en assembly por motivos de licencias. No sería la primera vez, en una materia de la facultad lo hice con un simulador, tendría que instalarme un hercules para hacer que funcione primero.

Tambien podría programarlo en cobol, pero estuve mirando y es una patada en los piés. No tengo acceso a la licencia para compilar en C, que sería lo más sencillo. Entiendo que hay oferta de acceso gratuito a mainframes para hacer pruebas, pero ya he perdido el impulso, quedará para otra reencarnación, si es que recuerdo la clave de acceso a este blog.


Se consigue acceso gratuito vía Master the Mainframe, pero parece que no tiene compilador C, habría que mirar. No vale la pena usar el emulador Hercules para la medición, pues queda desvirtualizada. Chiste nerd.

 

NEON


Otra prueba que no hice fue SIMD en ARM, que se llama NEON. Si buscás en ese lugar, al momento de escribir esto te lleva a una página que te ofrece:

 

Arm Architecture Reference Manual Armv8, for Armv8-A architecture profile

Contains reference documentation for all Advanced SIMD instructions.

 

pero al intentar ir por ahí, falla, no importa, con esas palabras claves se consigue un pdf con una versión beta del 2013 que tiene más de 5000 páginas. Tras mirar superficialmente, desistí y vía la descripción de instrinsics parece que soporta 4 x 32 bits, la mitad que AVX2, no logré encontrar rapido las instrucciones, justamente no tengo tiempo para esto. Hubiese servido para Raspberry Pi y celulares.


Cell Processor


Mencioné en la parte de GPGPU la existencia del Cell Processor, la verdad es que me quedé con la ganas. Algo que no dije, es que no es como una GPU, un conjunto de procesadores especializados que se agregan a un sistema, si no más bien como la Parallella o como los micros A de AMD, o sea un(os) cores llamados PPU (PowerPC Processing Element) tipo los ARM de zynq o los x86_64 de AMD más los SPE (Synergistic Processor Elements), como el multicore Epiphany de la Parallella o la GPU de AMD.

 

El problema era conseguir uno:

  • Playstation 3: hay un rango muy específico de modelos que permiten ejecutar linux y nadie lo tenía.
  • Servidor: había encontrado un server, lo vendían por ebay en Inglaterra
  • Placa PCI: tambien existe como una placa aceleradora.

 

Cell Processor
Cell Processor

Por suerte no tomé este camino, recientemente me enteré que aunque son increiblemente potentes al punto que se podrían seguir usando, son increiblemente difíciles de programar.

 

Sistemas Distribuido


No quiero dictar cátedra de sistemas distribuidos, más por que no la cursé, pero en mi mediano entender alcanzo a vislumbrar algunos escenarios.

 

Homogéneos

 

Hay múltiples técnicas para esto, mí única experiencia, académica, ha sido con MPI.

 

Agente en Javascript para el browser


No sé como andará la performance de webassembly, no apareció nada que no fuera youtube en google al buscar o que fuera una clara comparación fácil de leer e interpretar. Además está el problemita del multicore, no sé pero apuesto a que no se puede usar más de un core a la vez.

Todo eso no importa, por que bien aplica la frase "no somos machos pero somos muchos" y el agente en javascript para el browser se llama...

 

Botnet 

 

Del mismo modo que hay sitios que cuando entrás te dan un javascript para ponerte a minar bitcoin, se puede confeccionar un agente similar en Javascript o webassembly, si te conseguís muchos, todo bien.

 

Heterogéneo


Esto corresponde a un escenario más colaborativo y artesanal que el anterior,  donde podríamos distribuir la carga sobre CPUs con y sin SIMD, GPUs y FPGAs en una red no necesariamente local. Por ejemplo:


  • Mi laptop soporta AVX2 y GPU
  • La Parallella soporta FPGA, los 16 cores del Epiphany y los dos del PS, que no sé si soportan SIMD
  • Nexys4 soporta FPGA

 Como podrás apreciar, nos movemos en varias dimensiones

 

¿Cómo distribuir la carga?
¿Cómo distribuir la carga?

Estas deben estar coordinadas entre sí, fijate que para la nexys4 deberías contar con una computadora que le configure los rangos y esté atenta a los hallazgos, todo un subproyecto de por sí.

 

Y ahí empiezan las preguntas, ahora no estoy hablando de armar un sistema de cero, ahi sin duda hay diseñar para usar GPU y/o FPGA, digo a partir de lo uno (yo en este caso) tiene.

 

Si la FPGA y/o GPU es XXX veces más rápida, ¿vale la pena molestarse en usar las CPUs asociadas de ese dispositvio?

Otra, ¿y si ya tenemos las CPUs como puede ser un montón de netbooks o celulares? ¿alcanzará SIMD para justificar?


Luego hay que pensar en la distribución de carga entre todos los nodos, evidentemente hay que hacer lotes de distinto tamaño según la potencia del nodo. 

También hay que implementar un mecanismo de corte generalizado ante el primer hallazgo. Pero si en lugar de estar buscando estuviésemos calculando para almacenar, ¿Cómo hacemos para sacar toda esa información, sobre todo en FPGA?

Para trabajar más cómodo y aprovechar varias máquinas

Tengo una máquina que es muy cómoda pero no debo usarla para el trabajo. La del trabajo es más potente pero inusable, ¿qué hago?

Pues uso las dos, tomando lo mejor de cada una.

Objetivos


Ejecutar las aplicaciones sensibles y/o de alto consumo de CPU en la Máquina Remota operando desde la Máquina Local para aprovechar sus múltiples monitores y mejores teclado y mouse.

Mantener toda la información de trabajo a la Máquina Remota.

 

Detalles

  • Máquina Remota
    • más segura
    • más procesador
    • bastante memoria
    • dificultad para usabilidad
      • display
        • 1920x1080
        • casi 14 pulgadas (35 cm) diagonal
      • mousepad
      • teclado membrana
  • Máquina Local
    • no necesariamente segura
    • con menos procesador
    • el doble de bastante memoria
    • usabilidad óptima
      • display
        • tres monitores
        • 1920x1080
        • 23.5 pulgadas (60 cm) diagonal
      • mouse común
      • teclado IBM Model M 1987



Las aplicaciones son un browser y varias máquinas virtuales. Dentro de esas virtuales, un completo zoológico de browsers, terminales, dockers, mongos...

Estoy usando Linux Mint tanto en una como otra máquina, no deberías necesitar cambiar mucho con otras distribuciones. Las virtuales son agnósticas siempre que puedas controlar la resolución.


Comienzo confesando que lo del browser ni probé mucho pues se achanca mucho el display y además necesito hacer video conferencia, lo que implica lidiar con la cámara, micrófono y audio, quedará para otra ocasión, en esta entrada sólo desarrollaré la configuración de las virtuales y un mínimo soporte para el intercambio de archivos con sftp  y otro mínimo nivel de interacción con ssh -X, centrándome en los displays y las virtuales.


Memoria


Aunque es verdad que la Máquina Local tiene el doble de memoria, lo que siempre me termina matando es el browser, no las virtuales.


Red


Esto no lo hice hace meses pues estaba sin switch, mi hub de 10 no es suficiente para la conexión necesaria. No probé si por WiFi alcanza el ancho de banda.

A cada máquina virtual hay que ponerle la interfaz en modo "bridge" para que tenga una IP alcanzable por la Máquina Local por si querés hacer ssh/sftp. Además, en View hay que activar "Remote Display". Recordá que la IP es la de la Máquina Remota, no la de la virtual, cada virtual está en un puerto distinto que se debe setear al habilitar el Remote Display.

 

Lo más prolijo sería fijar la dirección IP de la Máquina Remota para no tener que estar pescándola todos los días... veré, igual es extremadamente fácil. 

Si tuviera una red de 1000...

Display



Acordemos algunos nombres:

Una pantalla es... una pantalla.

Un workspace es como una extensión virtual del escritorio, un duplicador, triplicador, multiplicador de pantallas. Se puede pasar de uno a otro mediante una combinación de teclas o con el "Workspace Switcher"

La configuración de los workspaces es muy personal, esta es la mía:

 
En la Máquina Local tengo seis workspaces, en uno de ellos Remmina con los RDPs a las virtuales.

En la Máquina Remota y en cada virtual cuatro workspaces por costumbre.

Esto hace que tenga hasta 18 + 4 + 4n workspaces, no me va a hacer muy bien


Resoluciones


Tras bastante pelear llegué a este procedimiento para hallar la configuración óptima:

  • Medir la pantalla local (1920x1080)
  • Darle a la virtual en la Máquina Remota esa resolución, aunque sobre o falte, si no la vas a usar ahí, no hace diferencia.
  • Le pedís a Remmina "Full Screen" y "Resize the window to fit in remote resolution"
  • Eso me ocupa una pantalla entera, ok


Problemas, siempre hay problemas, como uso el mejor workspace y es donde está la barra de comandos, no puedo pasar a otro workspace sin usar

Control-Alt-(left/right) Arrow


Si necesitás salir de Full Screen y no encontrás el panelcito, la combinación de teclas en Remmina es:

Right-Control-f

 

Si tenés varias conexiones a varias virtuales, podés pasar de una a otra con:

 

Right-Control-(left/right) Arrow


Navegación
Navegación


Me molesta que no he logrado que Remina me muestre dos conexiones en paralelo, lo cuál es útil cuando una operación abarca varias virtuales.


Power Management


En la Máquina Remota el display se puede ir a dormir sin problemas, a menos que quieras tener esa pantalla extra para ver notificaciones. Mejor no dejés que la CPU se duerma.


Virtual Box

Te conviene arrancar en modo headless, así podés arrancarla vía ssh -X desde la Máquina Local, lo que sea para no mover el trasero.



Topología
Topología

 

Intercambio de información



Es un poco tedioso, hay que hacer una carpeta compartida a las virtuales, probablemente siempre la misma. Esto implica instalar las "Guest Additions". Entonces si recibo por mail un archivo al cual tengo que hacerle un proceso, el caminito es:

mail con datos
     ( Bajar a )
Máquina Local / Downloads
      (copiar a)
Máquina Remota / Shared
      (Abrir desde)
la virtual apropiada
      (salvar a)
Máquina Remota / Shared
      (copiar a)
Máquina Local / Downloads
      (enviar como)
mail


Lo voy a usar un tiempo y veré si hay alguna mejora para compartir.


Deudas

  • Ver como marcha la memoria.
  • Usar el browser remoto.
  • Aumentar los colores de 256 a algo mejorcito.
  • Probar WiFi.
  • Fijar IP.
  • Ver comportamiento ante CPU sleep.
  • Investigar como separar sesiones de Remmina o cambiar de cliente.

2020/12/27

Hardware Malware: bit supervisor

 

 

La idea de esta demo está basada en un paper que no recuerdo si he leido en su completitud o no. Si no lo he leido ha sido a propósito, pues una vez comprendida la idea central, no quería spoilearme cómo hacerlo.

Repasemos: hay que instalar subrepticiamente en el proceso de diseño y  construcción de un chip antes de que llegue al silicio, un mínima lógica activada por las órdenes legítimas o por un capacitor que se carga cuando hay mucho tráfico en una pista donde habitualmente hay poco.

 

Activación
Activación


O sea, normalmente el capacitor se está descargando, pero si hay una sucesión suficientemente sostenida en el tiempo tal que la carga supere  a la descarga y llegue al punto tal que su valor represente un 1 lógico, la mínima lógica prenderá el bit supervisor.

¿Qué es el bit supervisor? El que permite proteger a nivel de hardware recursos como la memoria, IO y ciertas instrucciones y separar los procesos del usuario común del sistema operativo

Esto va desde el simple deseo de que las cosas funcionen bien, como que un programa no pise la memoria de otro hasta la seguridad del sistema, donde un programa no puede ver la memoria de otro.

 

Tenía varios caminos, del cual implementar el ataque como en el paper con un ASIC quedaba completamente fuera de mi alcance.

La siguiente posibilidad era obtener el VHDL o Verilog de una CPU, por ejemplo 6809 o 68000, teniendo que cumplir con las siguiente condiciones:

  • implemente bit supervisor: obvio.
  • la pueda hacer funcionar con sencillez: para mi nada es sencillo.
  • entienda yo cómo se interactúa con el bit supervisor
  • pudiera yo encontrar el punto donde colocar el capacitor

Comprenderás que el capacitor debe ser externo, con VHDL o Verilog lo único que puedo hacer es agregar un contador, lo cual pierde toda la gracia.

A esto se le suma que tengo que aprender una parte del lenguaje de máquina de esa CPU y como hacerla arrancar, probablemente canibalizando un programa existente... demasiado. Esas son todas super capacidades que no tengo o no puedo adquirir en un tiempo razonable y, ¿quién quiere dedicar meses de su vida para aprender a usar una arquitectura obsoleta hace décadas?

No voy a mentir, yo querría, pero prefiero desperdiciar mis recursos en otras cosas igualmente improductivas pero más interesantes.


Hasta acá es lo que expuse en la charla de H4CK3D 2020, pero por falta de tiempo no entré en algunos detalles jugosos del diseño de la demo.

El camino más fácil y bastante productivo en términos educativos es hacerme mi propia CPU, tal que implemente lo mínimo necesario para la POC. Tuve que pensar el programa más corto posible que sirva y sólo implementar esas instrucciones.

Necesito:

  • Una operación que Output que sólo funcione cuando está el bit supervisor prendido (out).
  • Una operación tipo SVC (Super Visor Call), para pasar al modo supervisor (svc).
  • Una operación de retorno de SVC, para retomar el programa y salir del modo supervisor (ret)
  • Una operación para cargar un valor en el único registro (set)
  • Una operación de salto condicional para poder hacer un loop. (jnz)
  • Una operación de incremento para poder hacer un loop (inc)

Para logra la máxima sencillez, en los MSBits puse el opcode y en los LSBbits el operando de haberlo. Todas instrucciones de un byte. El Program Counter arranca en 16 debido a una evolución que no vale la pena que muestre.

Tanto el inc (1000xxxx) como el nop (1001xxxx), tienen el MSB observado por el capacitor.

La SVC tiene hardcodeada una dirección a la cual saltar, donde reside el código con priviliegios, no se si ha existido alguna arquitectura tan primitiva como la mía en ese aspecto, pero no olvidemos que esto tiene otro objetivo, no es el estudio de arquitecturas de microprocesadores.

El programa de ejemplo, en verde el funcionamiento legítimo, en rojo se bloquea la operación por falta de privilegios, en amarillo el ataque y en aqua la explotación.

Código usuario

  16: h90;  // nopC 17: h90;  // nop  
  18: h90;  // nop
  19: h90;  // nop
  20: h90;  // nop
  21: h90;  // nop
  22: h25;  // set   0101 en registro
  23: h40;  // svc   0101 en leds
  24: h2A;  // set   1010 en registro
  25: h40;  // svc   1010 en leds
  26: h2F;  // set   1111 en registro
  27: h40;  // svc   1111 en leds
  28: h25;  // set   0101 en registro
  29: h30;  // out   falla
  30: h2A;  // set   1010 en registro
  31: h30;  // out   falla
  32: h2F;  // set   1111 en registro
  33: h30;  // out   falla
  34: h20;  // set   Este es setup del loop
  35: h80;  // inc   incremento del registro
                    
inicio del loop
  36: h90;  // nop   nada
  37: h1F;  // jnz   salta al inicio del loop
  38: h25;  // set   0101 en registro
  39: h30;  // out   0101 en leds
  40: h2A;  // set   1010 en registro
  41: h30;  // out   1010 en leds
  42: h2F;  // set   1111 en registro
  43: h30;  // out   1111 en leds
  44: h90;  // nop
  45: h70;  // hlt

código privilegiado


  46: data = 8'h30;  // out legítimo
  47: data = 8'h00;  // ret


Si tuvieras ganas de mirar el repo  en la carpeta javascript podrías apreciar la evolución desde una simulación más abstracta a una más concreta considerando la microarquitectura, completamente en vano pues a la hora de implementar en Verilog usé la primera.

Si tuvieras ganas de mirar el Verilog verías el comportamiento legítimo del bit supervisor en svc y ret como se prende y apaga:

OPCODE_SVC: begin
  supervisor = 1;
  error= 0;
end

OPCODE_RET: begin
  supervisor = 0;
end

Luego, en out, si el bit está prendido transfiere el registro al puerto de salida, si está apagado tirar error:

OPCODE_OUT: begin
  if (supervisor) begin
    gpio = A[3:0];
  end else begin
    error = 1;   
  end
end

 

El malware lo podemos ver  en la interfaz de board.v

  output malware_activation_signal_out
  input  malware_activation_signal_in

que son los cables que van y vienen del capactor.

Luego en la implementación:

   assign malware_activation_signal_out =
           cpu.opcode[3] ? 1 : 1'bz;

dice que si el MSB del opcode es 1 ponga un 1 y si no ponga en alta impedancia para que no se descargue tan rápido el capacitor. Sabiendo más electrónica seguramente se puede reemplazar la condición por un diodo.

Finalmente, en cpu.v

OPCODE_NOP: begin
  if ( board.malware_switch &&
      (  board.malware_input ||
         board.malware_activation_signal_in
      ) )
     supervisor = 1;
end

Lo que dice es que si está habilitado el malware y ya sea porque está activado por un switch o por el capacitor, prenda el bit supervisor.

Mi conocimiento de electrónica analógica es ínfimo, así que prefiero no explicar mucho, en parte por vergüenza, en parte para no brindar conocimiento erróneo.

 



El capacitor que usé es gigante por los tiempos de un clock tal que se pueda apreciar en una demo. En la realidad sería minúsculo.

 

El PMOD con los leds y el bichito
El PMOD con los leds y el bichito

 

El potenciómetro está para calibrar los tiempos de descarga. Con respecto al PMOD explico un poquito en otra entrada.



 





2020/12/16

Curso Security AWS

Nuevamente, gracias al trabajo, he recibido capacitación de AWS, en este caso Seguridad.

Cloudshell
El lunes esto no estaba


Estas son unas notas un tanto inconexas tomadas y deducidas durante el curso que me pueden servir en el futuro para intentar certificar una vez haya ganado alguna experiencia práctica. Claramente una certificación no debería obtenerse por estudiar, eso es un curso o materia, una certificación es la medición de tu conocimiento por lo que has hecho, prefiero no repetirme.

Tené en cuenta que lo que sigue es mi visión, no necesariamente la de AWS así que no lo tomes como referencia para tu certificación.

Me resisto a hacer una enumeración de los servicios tratados y sus relaciones, en cierto modo sería un leak pues parece no estar publicado y no tengo ganas de estar pidiendo permiso a AWS.
 

La previa

No había visto que entre las precondiciones, además de Architecting on AWS que ya había hecho, estaba AWS Security Fundamentals o AWS Security Essentials, así que entré un poco rengo.

Es más, tenía un plan de tomar algunos cursitos tanto de AWS como de qwiklabs como de LinkedIn Formation pero no los hice para llegar sabiendo lo justo, dada la duración del curso cuando menos supiera previamente mejor, pues en las partes que ya sé me puedo dispersar, por ejemplo CIA y STRIDE, con el riesgo de perderme el momento en el cual sale de lo que ya sé.

El sonido


En el curso anterior tras un ratito dejaba de funcionarme el mic, que se arregló actualizando el chrome, no me había dado cuenta de que estaba con una versión muy vieja.

El docente



El docente muy ok, pobre, entre la interfaz y lo que tenía preparado habían pequeñas diferencias, es que AWS cambia bastante rápido, incluso en el medio del curso apareció una nueva funcionalidad o al menos el acceso, CloudShell, abrir una consola desde el menu.


Sólo tuve un desacuerdo, que intentaré desarrollar en otra entrada pues me requiere bastante pensamiento, investigación y pruebas.

El curso


El curso no es de técnicas, como puede ser pentesting, si no comprender las herramientas y servicios relacionados, sus configuraciones y buenas prácticas.

Al igual que con los cursos de Akamai Site Defender y Bot Defender, hay una buena parte del aprendizaje que consiste en traducir lo que ya sabés de la vida al lenguaje local.

Los talleres son copiar y pegar, yo intenté escribir los comandos para ir fijándolos.


Las notas



Responsabilidad


AWS tiene un modelo que llaman "shared responsability", responsabilidad compartida, que básicamente se reduce a que si el servicio es gestionado es responsabilidad de AWS, si no es tuya


Por ejemplo, para una base de datos, en todos los casos, la seguridad del dato es tuya, pero respecto a la infraestructura:

  • Usar un servidor instalado en una EC2
    • toda tuya
  • Usar RDS
    • la actualización y parcheo queda a tu cargo
    • la infraestructura subyacente AWS
  • Usar DynamoDB
    • todo (menos los datos ya dije) es AWS

 

Pentesting


Hay servicios que no requieren autorización de AWS para hacerles pentesting.

Sobre cualquier otro, hay que abrir un ticket, en caso contrario se considera un ataque y aws reacciona acordemente.

Este ticket incluso puede otorgarte ayuda de soporte para hacer la prueba.

Cualquier incidente puede generar un contacto desde el soporte de AWS el cual es fundamental responder y reaccionar a la brevedad pues puede llegar a generar un bloqueo de la cuenta y acciones sobre los servicios afectados y puede llegar a generar incluso problemas legales.


Forense


Para análisis forense se debe "desconectar" el equipo, tomar una imagen, no vimos el detalle, conectar a una VPC ya preparada para forense. O bajar la imagen y procesarla on-premise


Temas sueltos llamativos


Me resultó muy simpático un indicador de anomalía, billing activity, sigue el rastro del dinero.


Interesante, el tema de multifactor con acceso programático, me enteré que algunos proveedores tienen una API, yo pondría un cámara con OCR a un token físico, jaja.

2020/11/23

Forzando Brutalmente MD5 - parte 6 - FPGA

¿Venís de leer la intro, la parte 1, la parte 2, la parte 3 la parte 4, la parte 5 y la implementación FPGA en nexys4ddr?

El tema

Habiendo agotado en lo que a mi respecta las maneras de calcular MD5 usando una o varias CPU, ya sean sus instrucciones básicas o extendidas, habiendo aplicado una optimización llamada "loop unroll", que consiste en tomar un loop, quitarle el contador y escribir su cuerpo tantas veces como hubiese sido ejecutado, adaptando cada iteración a los valores que hubiese recibido del contador, llegó el momento de no usar más CPU.


Fijate que más arriba le dediqué mucho al loop unroll. Es que desde el primer día que decidí encarar este proyecto, sabía que era lo que en última instancia iba a utilizar.

Todo el caminito que recorrí por las CPUs, aunque muy divertido e instructivo, realmente aprendí mucho, asenté, fundamenté y completé mucho conocimiento, no era para mi, era para vos.

Lo que yo quería hacer desde el comienzo era esto, implementar el forzador de MD5 en una FPGA, pero si vos no sabés nada de técnicas digitales, ni cómo funcionan la computadoras, ni assembly, ni C, ni programar quizás, te muestro esto primero y te mato.

En el trabajo fui mostrando cada etapa en una charlas a gente de diverso conocimiento técnico y apuesto que de no haber seguido este camino, a la mayoría ahora le costaría asimilar algo de todo esto, no habría ninguna conexión con su conocimiento.

 

FPGA

Ni instrucciones básicas, ni extendidas, ni multithread/multiprocess, ni optimizaciones del compilador, nada.

Había comentado antes que la velocidad del clock se había convertido en un limitante y eso había impulsado el paralelismo del multicore.

Tambien que en el caso de supercomputadoras como Epiphany y GPGPU, que esos cores fueran lo más sencillos posibles para ahorra silicio y poner más cores.

Aondando en esa tendencia, pensá que un core es una CPU de propósito más o menos general y aunque sea de propósito muy específico, cada problema que resuelvas no va a utilizar buena parte de los recursos que ofrezca.

Si además, es muy especifica y el problema cambia, no la vas a poder utilizar.

Si pudieras reconfigurar el hardware para que el silicio existente esté íntegramente dedicado a la resolución del problema que estás encarando, alcanzarías el máximo rendimiento.


El hardware reconfigurable se llama FPGA y se programa principalmente en VHDL como en este caso y Verilog.


Pipeline
Pipeline

La idea es que con un contador vas generando las claves candidatas y le vas a aplicando algo así como el loop unroll que habíamos visto antes, pero con la diferencia que cada etapa, cada ronda es un circuito que está ejecutando las operaciones en simultáneo con las demas. 

Durante los primeros 63 clicks del reloj el comparador recibe basura, de ahí en más lo que había en el contador hace 64 ticks.

De esta manera tenemos un paralelismo de 64, así como con AVX2 8, con GPU varios centenares y con multicore x 32.

La ventaja abismal, es que en cada tick se obtiene un hash entero, a diferencia de CPU/GPU que lleva muchísimimos ticks, al punto de que el clock de la FPGA que tengo es de sólo 100Mhz y aún así, como tengo espacio suficiente en la FPGA para instanciar hasta 10 pipelines, alcanza a la GPGPU, consumiendo mucho menos.

Si además este diseño lo ajustar para poder pasarlo a un ASIC, esto es un chip no reconfigurable, carísimo para un sólo ejemplar pero baratísimo por millón, podría aumentar la velocidad de clock y agregar instancias del pipeline, pues FPGA ocupa mucho espacio por ser reconfigurable.

Según he leido, ese cambio lo haría 10 veces más rápido por el clock y supongo que otras 10 veces más rápido por poner más instancias. De hecho, para minar bitcoins existen ASICs.

El camino


Tuve que tomar diversos caminos, divergente, simultáneos e incluso superpuestos debido en parte a mi desorden mental, en parte a mis conocimientos limitados, al tiempo disponible, al hardware disponible y a las dificultades de los entornos de desarrollo.

Una vez que tuve una versión que malamente funcionaba, le quité todo lo superfluo y lo instancié varias veces en mi hardware para ver cual era el rendimiento máximo.

Utilicé la placa Nexys4-DDR que entre que la pedí y antes de llegar ya me quedó obsoleta, mala suerte. Es una FPGA de las más caras de las baratas o más baratas de las caras, tiene VGA, switches, botones, 7 segmentos, audio, usb, de todos.

Más arriba mencioné el loop unroll como gran protagonista. Es que de no utilizarlo, tendría que diseñar una circuitería de control que comenzaría a parecerse a una CPU, perdiendo las ventajas ganadas.

De todos modos, esa proto CPU tendría sólo las instrucciones necesarias para este problema.






cpucpu
unroll
avx2
+ unroll
threads
x 4
+ avx2
threads
x 32
gpu
fpga
x 1
fpga
x 8
fpga
x 10
velocidad5.79.647.9153.41791090.11008001000
rendimiento watt0.861.447.1923.013.1106.6445360450
rendimiento dolar2.38419.9663.9213.16454.2178.13625781.25






cpucpu
unroll
avx2
+ unroll
threads
x 4
+ avx2
threads
x 32
gpu
fpga
x 1
fpga
x 8
fpga
x 10


5.79.647.9153.41791090.11008001000
cpu5.71.001.688.4026.9131.40191.2517.54140.35175.44
cpu
unroll
9.6
1.004.9915.9818.65113.5510.4283.33104.17
avx2
+ unroll
47.9

1.003.203.7422.762.0916.7020.88
threads
x 4
+ avx2
153.4


1.001.177.110.655.226.52
threads
x 32
179



1.006.090.564.475.59
gpu
1090.1




1.000.090.730.92
fpga
x 1
100





1.008.0010.00
fpga
x 8
800






1.001.25

 

Con 8 pipelines, como corre a 100Mhz, tenemos 800 de velocidad, no muy lejos de los 1090 de la GPU. Aunque no lo hice funcionar pues se me complica la lógica, podría tener 10 pipelines y estoy seguro que de tener un poco más de praćtica y aprovechando los DSPs podria llega a meter 11 o incluso 12.



nexys4ddrparallellaPYNQ-Z2


artix-7zynq 7010zynq 7020

luts15k25k85k

dsp24080220
pipelines
implementados
o implementables
81345
máximo
estimado
111447


Utilizando sólo los luts y dsp disponibles, proyecto los números para las otras dos placas que tengo. No estoy considerando que quizás podría subir la velocidad del clock por encima de 100Mhz. Para ello tendría que usar los PLLs disponibles y evaluar los timings a ver si llegan a hacerse las operaciones a tiempo.

Con respecto a los DSP, supongo que no haría un pipeline de DSPs si no que una etapa de cada pipeline estaría implementada así, futuro improbable.

Si juntara todo, tendría entonces entre 6600M y 7200M hashes por segundo y 1090 con la GPU. Luego, tendría que pedirle a alguien que tenga una GPU decente que ejecute mi programa, pues mi GPU es GeForce 940MX, al momento de hacer este análisis, 2019, un GeForce GTX 1080 Ti era casi 9 veces más veloz según algún benchmark que no registré.


Al momento de escribir esto, GeForce RTX 2080 Ti sale u$s 1000, el doble que las tres FPGA que tengo y consume 250 Watts vs los menos de 15 Watts que consumen las tres juntas, pero, si se puede proyectar la comparación de mi GPU, tendría una velocidad de 15000M, así que el rendimiento dolar sería apenas mejor para GPU y el energético 15 veces mejor para las FPGA, pero tomalo con pinzas.

No sé cuántos LUTs se consiguen por u$s 1000.

De todos modos, todo esto es para MD5, habría que ver que pasa con algoritmos modernos tipo SHAx.

 

Código

  • https://github.com/cpantel/Forzando-Brutalmente-MD5/tree/master/v8_fpga

Seguí en la parte 7