2019/05/19

OWASP Latam Tour 2019


Me perdí el comienzo y el final por logística laboral y familiar, pero pude asistir a tres charlas aparte de dar la mía.

Soy un tanto reacio a estar contando lo que los mismos autores pueden contar, así que sólo cuento lo mínimo y alguna opinión de haberla. 
Muchas gracias a  Andrés, Martín y la nueva organización por confiarme ese rato.

La primera charla fue la de Miguel Summer Elias (http://www.informaticalegal.com.ar/) que suele dar explicaciones claras y amenas y esta vez no fue la excepción. Tuvo la innovación de usar una tela touch, con la cual podía controlar con la mano y el audio la presentación ;-)

Luego la mía, "Forzando brutalmente MD5...", que originalmente eran cuatro de cinco charlas, tratándose de calcular MD5 con CPU, SIMD, multicore, supercomputadora y GPGPU.
La última, de un modo radicalmente distinto y que es la que realmente me interesa, la tengo elaborada, me falta implementar el código y trata de hacer lo mismo con FPGA.
Había presentado CPU y SIMD en H4CK3D 2018 pero ahora se le ha hecho largo en nombre, "Forzando brutalmente MD5 con CPU, SIMD, threads, forks, supercomputadora y GPU". Dos días antes caí en cuenta que debió llamarse "Forzando brutalmente MD5 con computadoras" y la última "Forzando brutalmente MD5 sin computadoras".

Primero hice un breve resumen de hashing, para que sirve, la implementación de MD5, optimizaciones como las que menciono más abajo como "mías", la descripción de cada caso, caminos fallidos y teniendo 40 minutos medio que algunas cosas quedaron muy superficiales, otras se cayeron y alguna me la olvidé.

Lo que me han dado ganas de hacer y lo intentaré, es un análisis cuantitivo en tres dimensiones:

  • pasar de CPU a SIMD que son dos casos
  • optimización de compilador que son dos casos
  • optimizaciones mías, como padding fijo, hardcodeo de constantes y loop unroll

Esto último podría ser considerando las ocho combinaciones o quizas cinco asi:

  • padding fijo
  • padding fijo + constantes
  • padding fijo + loop unroll
  • padding fijo + constantes + loop unroll 

Me quedarian entonces 32 o 16 combinaciones, tedioso pero factible.

Para el año pasado cuando estaba por mostrar en el trabajo la parte de GPGPU,  Andrés me había ofrecido acceso a su minador pero se fué de vacaciones y no llegó a configurarme el acceso, lo cual fué una suerte para mí, pues no mucho después, mientras él monitoreaba remotamente el consumo halló 0 Watts. Fué a fijarse y los aislantes de los cables de alimentación se habían fundido, si hubiera ocurrido mientras yo la usaba... Más suerte para Andrés que no tuvo un incendio.


Luego Leandro Mantovani nos contó como utilizar unos logs de certificados TLS como alerta temprana para detectar sitios vulnerables, muy ingenioso

Finalmente, nuevamente suerte en relación a Andrés, su charla la dió en el slot previo, si no me la hubiese perdido. Fue una muy buen ensayo para... BlackHat! ¡qué capo!



La agenda y los links, ...


https://www.owasp.org/index.php/LatamTour2019#tab=ARGENTINA_-_Buenos_Aires


...la presentación, ...


https://www.owasp.org/images/d/d5/Forzando_Brutalmente_MD5_con_computadoras_-_OWASP_2019_-_Carlos_Pantelides.pdf


...las cifras a medio cocinar, ...


https://www.owasp.org/images/5/53/Forzando_Brutalmente_MD5_con_computadoras_-_Cifras_-_OWASP_2019_-_Carlos_Pantelides.pdf


...las entradas en este blog y ...


https://seguridad-agile.blogspot.com/p/indice.html#md5


...el código.

https://github.com/cpantel/Forzando-Brutalmente-MD5

 

Forzando Brutalmente MD5 - parte 5 - GPGPU

Forzando Brutalmente MD5 - parte 5 - GPGPU


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



El tema


Finalemente, dentro del terreno de usar computadoras para calcular MD5, llegamos si no a lo último en términos tecnológicos a lo más potente.

En la misma linea de la supercomputadora, se usan CPUs sencillas, casi ni califican, optimizadas para cálculo. Y son muchas, centenares o miles.

Código

  • https://github.com/cpantel/Forzando-Brutalmente-MD5/tree/master/v7_cuda
Seguí con la parte 6, uno de estos días

Forzando Brutalmente MD5 - parte 4 - supercomputadora

Forzando Brutalmente MD5 - parte 4 - supercomputadora


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


El tema


Lo que veníamos viendo es como aprovechar mejor una CPU cada vez más compleja y luego varias pero con la ilusión de usar una sola.

Existe un enfoque que consiste en usar muchas CPUs genéricas simples y nosotros debemos administrar su uso.

La que uso es la parallella, que es una mini supercomputadora. Mini en términos de que tiene muy pocas CPUs, por ende, bajo rendimiento. Super en la arquitectura, son CPUs simples con un bus de interconexión que no he usado.



Código

  • https://github.com/cpantel/Forzando-Brutalmente-MD5/tree/master/v6_ebsp
Seguí con la parte 5

Forzando Brutalmente MD5 - parte 3 - threads, forks


Forzando Brutalmente MD5 - parte 3 - multicore


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

El tema


Hace años, tantos que ni es argumento de venta, tenemos computadoras multicore, esto es, que tienen varias CPUs.

Dos maneras de ejecutar simultáneamente tareas es por medio de disparar programas a la vez (forks) o a un programa pedirle que ejecute una función en un hilo (thread) distinto.

Algunas diferencias son que los forks se comunican mediante llamadas interprocesos, red, memoria compartida, archivos y los threads, como son parte de un mismo programa, por variables compartidas.

En este caso, como no hay comunicación, da lo mismo y de hecho la performance es la misma.

Se puede combinar con AVX2 y aumentar mucho el rendimiento.


Código

  • https://github.com/cpantel/Forzando-Brutalmente-MD5/tree/master/v4_threads
  • https://github.com/cpantel/Forzando-Brutalmente-MD5/tree/master/v4_threads_32cores
  • https://github.com/cpantel/Forzando-Brutalmente-MD5/tree/master/v4_threads_avx2
  • https://github.com/cpantel/Forzando-Brutalmente-MD5/tree/master/v5_fork
Seguí con la parte 4

2019/04/26

FLISOL 2019

He tenido la oportunidad asistir a medias a dos flisoles y de dar una charla en ambas, paso a compartir la experiencia y las notas de la charla.



Avellaneda

Sólo pude asistir a la de Marcos Russo de centrux de Docker, me hubiera gustado que fuera más demo que presentación, entendiendo que habiendo conectividad dudosa se complica preparar el entorno para hacerla off-line.


CABA

Sólo pude asistir a la de Tor, que se convirtió más en meetup que la exposición planeada por que ocurrió una turbia circunstancia que impidió que quienes iban a exponer pudieran hacerlo. Pese a que no tengo información completa de lo que ocurrió, por lo cual no voy a decir nada más que lo que voy a decir, mi intuición me dice que fué un acto de malicia intencional.

Charla de ponderación y clasificación de vulnerabilidades


El objetivo como siempre es estimular el pensamiento atacante/defensor propio de la seguridad de la información, con la variedad de tener herramientas no tan subjetivas para evaluar como lidiar con la vulnerabilidades.

No voy a transcribir el contenido completo, ni pegar la presentación, es más bien un machete con las ideas principales y los links, útil para quien asistió y no tomó nota o por si la diera otra vez (lo dudo, la dí seis veces en el trabajo, ya me aburrió y creo que ya asistieron todas las personas a las que les podía interesar) tengas elementos para evaluar si te interesa asistir.


Dado el tiempo disponible de sólo la mitad no pude hacer los ejercicios que hago en el trabajo pero mejor, no creo que quienes están buena parte del día en el evento se aguanten dos horas de este tema.

Algunas definiciones



Falla: comportamiento no previsto

Amenaza: algo que puede dañar

Vulnerabilidad: defecto en un sistema que lo deja expuesto ante una amenaza

Vulnerabilidad: es una falla explotable




Riesgo: probabilidad de que el daño se produzca

Y esta es el primer acercamiento a medir una Vulnerabilidad:

Riesgo = Amenaza * Vulnerabilidad

Gestión de riesgo


  • Mitigar
  • Asumir
  • Transferir
  • Evitar
  • Ignorar (*)
  • No gestionar (*)

Las dos últimas no figuran en los libros pero si en la realidad y se las suele confundir con "Asumir".

Una pisca de teoría de Seguridad de la Información


  • Confidencialidad
  • Integridad
  • Disponibilidad
Esas tres palabrìtas son la base de la S.I., como armonìa, melodía y ritmo para la música y nos llevan al segundo acercamiento a medir algo:

Riesgo = consecuencia * probabilidad

Riesgo = (C + I + D) *(amenaza * exposición)

Se le da un valor entre 0 y 1 a cada aspecto.


Algunos métodos útiles para reflexionar

 

DREAD

Damage – how bad would an attack be?
Reproducibility – how easy is it to reproduce the attack?
Exploitability – how much work is it to launch the attack?
Affected users – how many people will be impacted?
Discoverability – how easy is it to discover the threat?



Se le pone a cada item un valor de 1 a 10.

Lo usó Microsoft hasta 2008.


Más detalles:  https://en.wikipedia.org/wiki/DREAD_(risk_assessment_model)

STRIDE

Threat Desired property
Spoofing Authenticity
Tampering Integrity
Repudiation Non-repudiability
Information disclosure Confidentiality
Denial of Service Availability
Elevation of Privilege Authorization



Fijage que en la columna de atributos deseados aparecen Confidencialidad, Integridad y Disponibilidad, sumándose autenticación, autorización y no repudio, que forman los seis conceptos básicos de la S.I.


Mas detalles: https://en.wikipedia.org/wiki/STRIDE_(security)

Detección de vulnerabilidades

  • Modelado
    • attack tree, data flow, stride, que pasa si...
  • Pentesting
    • white vs gray vs black box
    • perimetral (automática, infraestructura)
  • Análisis estático de código
  • in the wild
  • reportes ajenos


 CVSS V3


Y por fín, la medición actual, a leer:

https://www.first.org/cvss/calculator/3.0


Esta dividido en tres regiones:

Base: es la calificación de la vulnerabilidad "en el aire", sin relación con lo que la rodea, es atemporal, una vez definida no debería cambiar salvo se descubra un error.

Temporal: es una modificación introducida por la evolución en el tiempo de los exploits que hayan, la confirmación y corrección oficial

Entorno: es la aplicación en un entorno particular y considerando los requerimientos relativos a CID.

La clave de este tema es entender que el nucleo está conformado por el impacto en la Confidencialidad, Integridad y Disponibilidad.


Clasificación

 

Para mi hay distintas categorías de clasificación:

"Muertas", o sea, es un amontonamiento de información histórica y "Vivas", se van adaptando al momento, priorizan según algún criterio de frecuencia y éxito.


2019/04/17

Rehacer una imagen live

El otro día el ProfMatías preguntó en el chat de CaFeLUG como no montar los discos rígidos en una máquina arrancada con puppy linux pues tenía el requerimiento institucional de que los alumnos no puedan tocar el windows presente.

Una idea propuesta fue virtualizar, pero también tenía la restricción de hardware incapaz.

Otra usar una distro de tipo forense, que no monta por default los discos.

Otra modifar la imagen, desde poner un script al arranque que desmonte hasta que ni siquiera pueda montarlos, pasando por que no los monte.


Esto es lo que hice para preparar el terreno para lo último. Asumo que algo sabés de administración linux y que tenés mucha curiosidad e iniciativa, así que no entro en detalles menores como por ejemplo cómo y qué editar de syslinux.conf, ni explico nada que puedas hallar en man xxx y entiendo que cuando ejecutes unsquashfs y te diga que no está, llames a tu gestor de software y te lo instales.

Si incluyo los pasos concretos obvios como el wget, es para que esto sirva como base para un script genérico que en algún momento githubearé.


Los programas necesarios

  • wget
  • mount
  • mkisofs
  • unsquashfs
  • mksquashfs
  • editor de texto preferido

La estructura de directorios

  • old/
  • rebuild/
    • puppy_xenialpup64_7.5/
    • zdrv_xenialpup64_7.5/
  • new/
  • xenialpup64-7.5-uefi.iso
  • xenialpup64-7.5-uefi-new.iso

Los pasos a seguir

  • Copiar todos los archivos de la imagen original a la nueva imagen
  • Descomprimir los squashfs presentes
  • Modificar los archivos deseados
  • Reconstruir los squashfs
  • Rehacer la imagen

Manos a la obra


Crear estructura de directorios

Una carpetita para el live original, otra para el que queremos como resultado

mkdir old new

Obtener imagen


wget  \
http://distro.ibiblio.org/puppylinux/puppy-xenial/64/xenialpup64-7.5-uefi.iso \
-o xenialpup64-7.5-uefi.iso

Montar la imagen


Para poder acceder a los elementos de la imagen.

sudo mount -t iso9660 -o loop xenialpup64-7.5-uefi.iso old


Terminar de crear los directorios faltantes

Es que hasta este momento no los conocíamo, son los que hay en old/*.sfs sin la extensión.


mkdir -p rebuild/puppy_xenialpup64_7.5 rebuild/zdrv_xenialpup64_7.5



Copiar todo de la iso a la nueva imagen


Para tener lo mismo que tiene la live original

sudo cp -a old/* new

Luego los *.sfs serán actualizados.


Desplegar los squashsfs


Hay que tomar cada *.sfs y descomprimirlo para poder hacer modificaciones en el sistema de archivo que será montado cuando inicie la live.


cd rebuild

cd puppy_xenialpup64_7.5/
unsquashfs ../../old/puppy_xenialpup64_7.5.sfs 


cd ..

cd zdrv_xenialpup64_7.5/
unsquashfs ../../old/zdrv_xenialpup64_7.5.sfs 

cd ..




Acciones incrementales




Primera iteración


Modifiqué syslinux.conf para que ofrezca una sola opción de boot. Los squashfs se rehacen sin modificarlos, en este momento sólo nos interesa que funcione el proceso.

Antes...

...despues


Segunda iteración


Recomprimí los squashfs agregando un archivito testigo con touch.



Tercera iteración


Poniendo en isolinux.cfg:

prompt 0
NOESCAPE 1


desactiva el acceso al boot prompt, lo que permitiría arrancar en single mode y nos jodería todas la demás medidas que tomemos.

De todos modos puppy arranca con el usuario root, haría falta un poco de hardening, quizas sea más fácil usar otra distro.


Pendiente


Lo que dejo sin hacer es:

  • Desactivar automount
    • Hallar y desactivar el automount, obvio.
    • Poner el driver de los discos en /etc/modprobe.d/blacklist.conf, mmmh, puede llevarse algo que haga falta.
    • un script al incio desmontando todo, mmh, sucio, sucio, ProfMatías.
  • Poner los permisos correctos
    • La verdad es que ni me fijé, quizás haciendo todo como root.
    • Sigo sin fijarme, hice todo como root.
  • Ver por que mi  puppy_xenialpup64_7.5.sfs queda tanto más grande que la original.
    • Me imagino que debe ser alguna opción de compresión.
Quizás lo haga uno de estos días.


Reconstruir imagen

 

Borrar y reconstruir los squashfs, pero sólo los que hayan sido modificados.



rm new/puppy_xenialpup64_7.5.sfs

mksquashfs \
    rebuild/puppy_xenialpup64_7.5/squashfs-root \
    new/puppy_xenialpup64_7.5.sfs

rm new/zdrv_xenialpup64_7.5.sfs

mksquashfs \
    rebuild/zdrv_xenialpup64_7.5/squashfs-root \
    new/zdrv_xenialpup64_7.5.sfs


cd new

sudo mkisofs -o ../xenialpup64-7.5-uefi-new.iso \
        -r -J -no-emul-boot -boot-load-size 4 \
        -b isolinux.bin -c boot.catalog \
        -boot-info-table .

sudo umount mnt

Y listo, arrancar con la vm y repetir todo hasta que salga lo que queremos.

 

2019/04/11

Python Productivity for Zynq tutorial@SPL2019

SPL2019 es una conferencia de lógica programable, de la cual me enteré en la lista de embebidos.

Me hubiese gustado asistir pero tiene poco y nada que ver con mi trabajo, así que no tengo punto de negociación para ausentarme tantos días.

Además tengo una alta ignoracia en el tema y aunque seguro que iba a aprender mucho si asistía, al no ponerlo rápidamente en práctica pronto se me iba a disipar.

Pero, habían varios workshops, uno de los cuales aposté estuviera al alcance de mis limitadas facultades.

  • WS1 (Xilinx, English):
    FPGA-based Accelerated Cloud Computing with AWS EC2 F1 and SDAccel 
  • WS2 (Xilinx, English):
    PYNQ: Python Productivity for Zynq
  • WS3 (UAM, Spanish):
    FPGA SoC design from a higher level of abstraction: SDSoC and HLS 
  • WS4 (Satellogic, Spanish):
    Testbenchs in Python: COCOTB

Lo dictó un señor, Parimal Patel que la tiene muy clara y explica muy bien, además de participar del proyecto activamente.

La placa utilizada para las prácticas fue la PYNQ-Z2 que obviamente, es rosa.


Se parece a la Parallella de la que tanto vengo hablando en que tiene un Zynq 70x0, pero un poquito más power, un 7020 en lugar de un 7010. Además no tiene el chip característico de la Parallella, que son los 16 cores del chip Epiphany. Extra tiene... mejor pongo una tabla comparativa:


 

PYNQ-Z2 Parallella
 Características     

Zynq 7020 7010
RAM [MB] 512 1024
Flash [MB] 16 (*)
SDCard si si
Ethernet 1Gb si si
USB 2.0 host si si
Audio si hdmi?
HDMI out si si
HDMI in si no
Epiphany no si
Power [v] 7-12 5 (**)
Raspberry Pi si

Arduino shield si
Porcupine (***)
si
PMOD 2 1 (***)
JTAG ? si (***)
Raspberry Pi Camera
si
Switches, botones y leds 2+4+4
Status proyecto Vivo Muerto


(*) No me queda claro por la documentación, tiene entre 32 y 128 Mb dice, pero no sé si se adhieren a que Mb es Mbit.
(**) La Parallella es excepcionalmente fastidiosa con la alimentación.
(***) Lo que tiene la Parallella es el Porcupine, que provee además de un PMOD, un JTAG y la interfaz para la cámara de la Raspberry Pi, "240 backside pins and a peak bandwidth of 50 Gbps". Entiendo que las interfaces de la PYNQ son todas lentas, o sea si quisiera sacar video en tiempo real o sería por ethernet o USB.



Volviendo a la PYNQ-Z2, como se puede ver, tiene los conectores de Arduino y Raspberry, lo que sumando a los PMOD+Grove o Arduino+Grove, permite adosarle una cantidad infernal de accesorios con gran sencillez.

Tambien es la más barata (u$s120) de las otras placas soportadas oficialmente por PYNQ. Nos chismorreó Patel que en unos tres meses (agosto 2019) sale una ZCU no tan cara como la ZCU104 u$s800 (y ni te digo la ZCU111 u$s8000), pero no sé si más que esta.



¿Y cómo funciona esto?




Yo entiendo que entendí, pero por la dudas no voy a entrar en mucho detalles por si me he confundido no esparcir errores. Intentaré ser breve y preciso y para la información posta RTFM. Si alguien que sabe encuentra algún error, me avisa por favor.

Tenemos los overlays, que proveen en la PL una serie de componentes comunes. Por ejemplo el overlay "base.bit" tiene los conectores para PMOD, Arduino Shield, Raspberry Pi y video HDMI.

Lo que tienen en común es que usan IOP (Input Output Processors), en este caso son MicroBlazes para parametrizar en tiempo de pre-ejecución que hay en los pines en lugar de que estén hardcodeado en el bitstream. Luego, durante la ejecución lo implementan.

Los IOPs son "soft processors", se implementan en la PL si hacen falta, en contraste con los cores ARM que están al costadito y que siempre están.



Dicho de otra manera, entre los buses SPI, UART o GPIO y el componente externo en sí, en lugar de ya estar configurado, tiene una capa que se adapta programáticamente. Entiendo que esto sólo debe funcionar con interfaces de baja velocidad, pues el IOP no deja de ser una CPU y siempre va a ser más lenta que un circuito combinacional y unos pocos flip-flops.

El modo de trabajar es en cierto modo como usar un Arduino con Firmata, usado por Processing o algo parecido, Scratch. El micro Arduino en un caso, el MicroBlaze en este, no hace procesamiento, sólo el pasaje de señales de los pines físicos al procesador "real", en el caso de Firmata la PC donde tenés Processing, en este los cores de la Zynq 7020.

Concretamente, si leo un termómetro en PMODA y quiero mostrar en un OLED en PMODB, el valor pasa por el core ARM, mientras que con VHDL se podría pasar directamente, pero perdiendo la flexibilidad y implicando mayor conocimiento por parte de quien implemente.

Está claro que esto está orientado a la gente que sabe programar y tiene una idea no muy profunda de hardware, que el lo que dice el proyecto, ningún engaño.

Un ejercicio que hicimos con Facundo, que fué el que dictó en SASE 2017 el workshop de EDU-CIAA-NXP multicore y me tocó de compañerito es este:


from pynq.overlays.base import BaseOverlay
from pynq.lib.pmod import Pmod_OLED
from pynq.lib.pmod import Grove
from pynq.lib.pmod import PMOD_GROVE_G4

from time import sleep

base = BaseOverlay(“base.bit”)

oled = Pmod_OLED(base.PMODA)
oled.clear()

temp = Grove_TMP(base.PMODB, PMOD_GROVE_G4)

while 1:
    temperature = temp.read()
    oled.write(temperature)
    sleep(1)






Ojo, puede ser que en el dibujito estén invertidos PMODA y PMODB y sin duda en oled.write() había algo más, probablemente un format() cerquita de temperature.

Por otro lado, en contraposición y recuperando la independiencia del FPGA, está otro overlay, "logictools.bit" que implementa varios "generadores". El procesamiento está en la FPGA, pero el core ARM le dice que va a hacer mediante una magia que no me atrevo a describir y que entiendo modifica las LUTs sueltas, no reenviando el bitstream completo. En cierto modo es como si vía Firmata se le enviara un programa a un módulo wifi ESP8266 para que lo ejecute independientemente.






No lo practicamos, así que cuento así nomas los generadores:

Boolean generator


es para armar circuitos combinacionales. Se le provee una o más funciones lógicas tipo

LD2 = PB3 ^ PB0

y mágicamente LD2 será una salida función de las entradas PB0 y PB3

Pattern generator


es para armar patrones, se le provee con un json parecido a esto:

up_counter = {
  ‘signal’ : [
    [‘stimulus’,
        {‘name’: ‘bit0’, ‘pin’:’D0’, ‘wave’: ‘lh’ * 8 },
        {‘name’: ‘bit1’, ‘pin’:’D1’, ‘wave’: ‘l.h.’ * 4 },
        {‘name’: ‘bit2’, ‘pin’:’D2’, ‘wave’: ‘l...h...’ * 2},
        etc
    ]
  ]
}


FSM generator


Se determinan unas entradas, unas salidas y la tabla de transiciones y... ocurre.

Trace analyzer


Se utiliza para capturar las entradas y salidas. En los ejemplos vistos se usa para ver lo que hacen los generadores.


En el caso de PYNQ hay una capa extra, que es Jupyter que permite que la interfaz sea web, usando un concepto llamado "notebooks", cuando sepa más, si lo llega a ocurrir, contaré.



Seguro que se debe poder usar desde una terminal pero no lo puedo afirmar hasta que le eche mano otra vez a una placa y haga las pruebas pertinentes o lo lea accidentalmente en la sección "Running from the command line".



La idea es que uno hace o consigue un overlay, implementa o consigue los c-drivers, implementa o consigue los wrappers, arma un cuaderno y tiene así un proyecto.

Si uno no agrega nada nuevo, usando uno de los overlays base.bit o logictools.bit puede hacer un montón de cosas sin bajarse de IPython.

 

¿Por qué me interesa?



Esta placa me interesa particularmente por el HDMI in, pues se puede tomar la salida de la computadora, pasarla por la placa, hacerle algún proceso y volcarla en la pantalla, para aprender a hacer cosas como:
  • Prender leds de colores detrás del monitor dependiendo de la imagen que haya, se lo llama ....
  • Agregar cosas a la imagen, como pueden ser letras.
  • Botón de pausa, pero perdiendo los frames mientras dure ésta.
  • Sacar fotos a la imagen.
  • Grabar el video.


Tambien, a mi backlog de proyectos inalcanzables le agrego el port de PYNQ a la Parallella, que sorprendentemente se llamará... ¡ParaPYNQ! y sin ninguna sorpresa me llevará mucho tiempo iniciar, si es que lo hago. Patel está al tanto de mi propósito y me ha ofrecido apoyo, así que... tengo que hacerlo.

Dos sitios con mucha info y código:

http://www.pynq.io/

https://github.com/xilinx/pynq




2019/04/05

Jugando con los rayos 3: sacándole el alma al cadáver

Habíamos quedado en que no podía leer confiablemente el firmware con la pinza soic8, que tras soldar implementando SPI con GPIO algo se leía, que son la interfaz SPI no sólo nada se leía sino que entiendo no era posible operar, que al estar independizando la alimentación a la flash y emprolijando el router terminó de morir sin poder diagnosticar los motivos. A todo eso se llega por el índice.

Trasca, al extraer el chip se cortó el pin de Vcc.

Corrección del pin

La idea es comer el encapsulado con un torno de mano hasta exponer lo suficiente del pin para soldar algo.

Resultado


Debí haber usado en lugar de la fresa más chica que tenía, la mecha más chica, durante un instante estuvo expuesto el pin, casi casi lo suficiente, pero quise aumentar levemente la superficie y puff, casi desapareció, no le pude soldar nada.

Por este lado no voy a poder responder la pregunta motivadora de todo esto:



¿Por qué no tengo el password del firmware oficial si yo no cambié el firmware?

2019/03/24

Jugando con los rayos 2: obteniendo el firmware via spi


Circunstancias

Un rayo me ha dejado afuera de un router, más detalles en [1] o el índice.

Motivación y objetivos

La lectura por serial usando el monitor de U-boot además de ser lenta, quizás no sea fidedigna, pueden haber partes no accesibles o que estén en un orden distinto [2].

Para la escritura la situación es peor.

Lo que deseo es leer el firmware que hay en la memoria flash por medio de la interfaz SPI, preferentemente usando una EDU-CIAA-NXP [3] y/o CIAA-NXP [4] ya que no quiero gastar plata en un programador ni seguir juntando cosas de uso poco frecuente ni tener que usar programas ajenos.

Tambien ejercitar el ingenio y adiestrarme en hardware hacking.

La síntesis de todo esto sería desarrollar o adaptar el software y la configuración para poder leer y escribir mediante la EDU-CIAA-NXP o CIAA-NXP y poder repetirlo con sencillez en otras placas.

Arriba a la izquierda, EDU-CIAA-NXP haciendo de conversor USB-serial.

Eso azul abajo a la derecha es un pela naranjas, muy muy bueno para abrir los gabinetes.


Identificación de componentes y pines

Se trata de un chip winbond 25q64f




Verificación de conexión a soic8


Que haya contacto y que no hayan cortos. Para lo último hay que probar que no haya continuidad entre pines adyacentes.

Para ello primero hay que buscar pistas de referencia:

A la derecha el conector serial: Vcc, GND, Rx, Tx.




Resultado:


Cuesta bastante que haga el contacto correcto, hubiese sido más fácil soldar en las pistas de referencia, quizás cuando llegue el momento de escribir sea buena idea.


Pinza soic8 a protoboard

Verificación de actividad y voltaje



Prender y ver que traza deja en el analizador lógico y/u osciloscopio.

Resultado:





Hay actividad en
  • /CS: SI
  • DO (IO1): SI
  • WP (IO2): SI
  • /Hold (IO3): SI
  • DI (IO0): SI
  • CLK: SI
Desde mi profundo desconocimiento pero habiendo leido la datasheet, intuyo que está usando el modo en el cual ejecuta código directo desde la flash, pues está usando todos los pines, probablement Quad SPI.


Planificación de acceso

 


Si no va a ser desoldado el chip, el resto de la placa va a ser energizada, ya sea normalmente o por alimentar el chip.

En el segundo caso hay que ver que no deje la misma traza que en la verificación anterior.

Si la hubiera, o sea, si se estuviera activando la CPU, habría que ver la manera de activarle el reset, que obviamente no es el botón de reset, si así fuera no diría cosas como "press and hold WPS/Reset Button during powering on until WPS LED turns on" [5].

Resultado:


Al alimentar no parece arrancar la CPU pues no hay actividad en el puerto serial y aunque /CS se va para arriba, no tiene actividad posterior.


Al centro a la derecha, con el cable blanco se puede apreciar el adaptar 5v -> 3.3 v de un protoboard.



Reflexión


Habiendo llegado tan lejos, en este momento debería retroceder un poco e intentar capturar el comando de cambio de modo, pero me supera.

Prueba de concepto: Implementación lectura con GPIO

Enviar el comando SPI Read Data (03h) y una dirección de 24 bits. Leer 7 bytes para ver si coinciden con el texot "TP-LINK" esperado. La escritura del comando mediante la placa, detectar la lectura con el analizador lógico u osciloscopio.

La dirección debe ser 0x000000000004 para saltear valores menores a 32 en las posiciones 0 a 3 que no se pueden ver en la terminal.




Dificultad elegida a fines didácticos: no puedo usar código ajeno.

Segunda dificultad con los mismos fines: no puedo usar la interfaz SPI que tiene la EDU-CIAA-NXP.



Para leer datos:

The Standard/Dual/Quad SPI instruction set of the W25Q64FV consists of thirty six basic instructions that are fully controlled through the SPI bus. Instructions are initiated with the falling edge of Chip Select (/CS). The first byte of data clocked into the DI input provides the instruction code. Data on the DI input is sampled on the rising edge of clock with most significant bit (MSB) first.

Data on all four IO pins are sampled on the rising edge of clock with most significant bit (MSB) first.

Instructions are completed with the rising edge of edge /CS.

En particular:

The Read Data instruction allows one or more data bytes to be sequentially read from the memory. The instruction is initiated by driving the /CS pin low and then shifting the instruction code “03h” followed by a 24-bit address (A23-A0) into the DI pin. The code and address bits are latched on the rising edge of the CLK pin. After the address is received, the data byte of the addressed memory location will be shifted out on the DO pin at the falling edge of CLK with most significant bit (MSB) first. The address is automatically incremented to the next higher address after each byte of data is shifted out allowing for a continuous stream of data. This means that the entire memory can be accessed with a single instruction as long as the clock continues. The instruction is completed by driving /CS high.



Necesito que mi programa adaptador USB<->serial crezca, que entienda si le envío una orden y la ejecute utilizando GPIO.



Resultado:


Conecté desde GPIO00 a GPIO06  pares a /CS, CLK, DO y DI respectivamente, modifiqué el programa adaptador para que interprete los caracteres '#' y '$' como órdenes y tras muchas idas y vueltas revisando el mapeo en el programa, ajustando que los cambios y lecturas en DI y DO fueran entre flancos de CLK y ajustando la pinza (ya dije por ahí que voy a soldarle cables, no?) en el osciloscopio se vé bastante bien.


Se vé en amarillo /CS que baja y sube, en cyan está CLK, en azul DI y en magenta DO, la respuesta.

Se pueden ver el 0x03 del read y el 0x000000000004 de la dirección en DI del comando '#'.



Traza completa para dirección 0x000000000004


En DO (magenta) se ve la respuesta



Traza completa para dirección 0x000000000006

El comando '$' es la dirección 0x000000000006, fijate que hay dos pulsitos azules en el segundo grupo.

En otras muestras CLK no tiene esos escalones, sospecho que tienen que ver un problema eléctrico, de hecho si no está conectado el osciloscopio

Y acá está la ejecución de '#$$'

Feedback por terminal USB a la PC

Se puede apreciar que hay un desplazamiento de dos, coherente con que pedimos la 0x6 ( que es igual a 0x4 + 2). Tambien que el mismo comando dá la misma respuesta.

Lo que no me cierra es que yo esperaba algo como lo amarillo.


xxd -b "wdr3600v1_en_3_14_3_up_boot(150518).bin"

Lo que tampoco me cierra es que a veces aparece eso, otras todo FFFF, otras todo 0000, es muy inestable, tengo dos caminos, usar la interfaz SPI o reemplazar la pinza por alguna intervención más permanente.



Prueba de concepto, implementación lectura con SPI


Voy a basarme en el ejemplo de escritura de SD de la sAPI, estoy usando Firmware_V2 [6], copio acá el diagrama de conexión:

Gracias Éric

 

Puedo empezar a morder del ejemplo de escritura de SD de la sAPI, que llama a spiConfig(). Tras un git grep spiConfig llegamos a modules/lpc4337_m4/sapi/inc/sapi_spi.h que es tan sencillo como:


bool_t spiConfig( spiMap_t spi );
bool_t spiRead( spiMap_t spi, uint8_t* buffer, uint32_t bufferSize );
bool_t spiWrite( spiMap_t spi, uint8_t* buffer, uint32_t bufferSize);



No sé para qué me metí a hacerlo con GPIO. Igual le desconfío, por lo que tengo entendido hasta ahora, ¿qué pasa si uno no llama inmediatamente spiWrite() tras spiRead()? Es que según el dibujito:

A la izquierda arriba se vé lo del Mode 0/3
en el flanco ascendente del pulso 31 de CLK  se lee el LSB del último byte de dirección y en el descendente ya empieza a transmitir por DO.

Me imagino que lo que hace spiWrite()es dejar CLK arriba, pues en las tablas de valores la frecuencia mínima es DC:

...y los tiempos mínimos están en ns, mil veces más rápido que lo que estoy manejando


y no es así, los bloques de la derecha supuestamente son los de lectura.

Se puede apreciar que hay bloques de 8 pulsos




Cancelación prematura


Intentando eliminar el factor pinza soic8 berreta, mientras soldaba y probaba hallé una elevada conductividad entre Vcc y GND. Buscando el calor, llegué al chip atheros ar8327 7 port low power managed/layer3 gigabit switch with hardware nat, que supera los 100°c. Puede ser que terminara de morir por si mismo, no olvidemos que por ahí pasó un rayo o que hay algún corto en otro lado producto de mi intervención, nunca lo sabré.

Quizás, quizás no fui yo, pues antes de intervenir dejé de recibir el patrón que aunque no era el que esperaba, era siempre el mismo.

Es una pena el momento, pues he puesto unos cables muy bonito.

El paso siguiente era calar el costado del gabinete y asomar el conector por ahí para poder seguir jugando con aquel armado.


Le puedo poner un jumper para elegir alimentar la flash desde el router o externamente.

Conectando 14-16, es la alimentación externa, 15-16 interna.






Planes de contingencia




Supongo que la memoria está ok aún, pero no la estoy pudiendo leer onboard probablemente por la falla del chip del switch. Tengo dos caminos:

Desoldar el chip de memoria


Pros

  • Es muy fácil y disminuyen los factores desconocidos sobre las fallas de acceso.

Contras

  • Lo leo, lo escribo, fin del camino, tiro el router al cajón del futuro.

Desoldar el chip del switch

 

Contras

  • Veo bastante difícil que pueda desoldar el chip sin hacer un desastre.

Pros

  • Si fallara, puedo ir por el otro plan.
  • Si lo hiciera bien y no hubiera otra falla, probablemente podría seguir usando el router.

Como se puede ver de como estructuré el texto previo, espero que no hayan dudas acerca del camino.

Extracción del chip del switch

En otro experimiento relacionado a reemplazar el lpc4337 del la EDU-CIAA-NXP por un lpc43s37, que tiene en lugar de un M0 como dual core un "acelerador criptográfico", extraje el chip de la placa, con resultados no muy buenos, me llevé algunas pistas conmigo debido a falta de paciencia.

Esta es una segunda oportunidad, por un lado un poco más difícil pues los pines son más chicos. Por el otro mejor, pues sólo estoy arriesgando componentes que ya doy por perdidos.


Resultado

Falla monumental no catastrófica, la EDU-CIAA-NXP sigue funcionando y he descubierto varias cosas:

Es imposible con mis herramientas sacar el chip del switch, al menos en una sola pieza, con daños colaterales de efectos imprevisibles.

No había contado antes que al desoldar la patita de Vcc de la flash había arrancado la pista, evidentemente tiré antes de tiempo. Luego, ya en retirada, cuando desoldé mis lindos cables, la patita terminó de cortarse, con lo cual se me dificulta inmensamente poder conectar la flash al entorno planeado.

Doy por terminada esta parte de la experiencia, luego pensaré como retomar, ya sea leyendo esta FLASH u otra en otro dispositivo y la posterior transferencia, por serial o vía una memoria SD.

El router yace en el cajón del futuro.



Todo el código, en github, https://github.com/cpantel/Flash-via-SPI



[1] https://seguridad-agile.blogspot.com/2019/03/jugando-con-los-rayos-0-intro.html
[2] https://seguridad-agile.blogspot.com/2019/03/jugando-con-los-rayos-1-obteniendo-el.html
[3] http://www.proyecto-ciaa.com.ar/index_comprar_educiaanxp.html
[4] http://www.proyecto-ciaa.com.ar/index_comprar_ciaanxp.html
[5] https://openwrt.org/toh/tp-link/tl-wdr3600#tftp_auto_recovery_in_revision_15
[6] https://github.com/ciaa/firmware_v2/tree/master/sapi_examples/edu-ciaa-nxp/bare_metal/spi_01_sdCard_fatFileSystem/



2019/03/20

Jugando con los rayos 1: obteniendo el firmware via serial


Al contexto de esto se llega por el índice.

Los pasos son escribir "tpl" para acceder al monitor y con

md offset length

ir bajando la memoria. Si oprimís enter tiene autoincremento.

Comencé poniendo un peso en la tecla pero no escala, no no. Así que a recordar expect:

#!/usr/bin/expect --
spawn /usr/bin/miniterm.py /dev/ttyUSB1 115200
expect {
  "Autobooting in 1 seconds*" {
    send "tpl\n"
    expect {
      "db12x> " {
         send "md
9f020000 20\n"
         while 1 {
           expect "db12x> " {
             send "\n"
           }
         }
      }
    }
  }
}



y su invocación:

expect capture.tcl > 9f020000.hex

Tras limpiar un poquito con grep, lo convertimos a binario:

grep ":" 9f020000.hex | xxd -r > 9f020000.bin

y ese binario le corremos binwalk:

binwalk -e 9f020000.bin





Te preguntarás de dónde salió la elección de la dirección 9f020000.

db12x> printenv
 

bootargs=console=ttyS0,115200 root=31:02 rootfstype=squashfs init=/sbin/init mtdparts=ath-nor0:256k(u-boot),64k(u-boot-env),6336k(rootfs),1408k(uImage),64k(mib0),64k(ART)
 

bootcmd=bootm 0x9f020000

De paso nos queda este muy útil script, para no tener que estar tipeando "tpl" a gran velocidad:

#!/usr/bin/expect --
spawn /usr/bin/miniterm.py /dev/ttyUSB1 115200
expect {
  "Autobooting in 1 seconds*" {
    send "tpl\n"
    expect {
      "db12x> " {
         interact
         }
      }
    }
  }
}


binwalk obtiene todo excelentemente de las imágenes de firwmare bajadas de tplink, pero de estos volcados no.

La idea seguiente es buscar el firmware.bin en los volcados:

sudo apt install yara



yara es una herramienta para investigar malware, que tiene la capacidad de buscar patrones de datos en archivos, lo cual me viene muy bien para lo que necesito que es hallar el firmware en el dump de memoria de un router dañado por un rayo, si es que es posible.


Mediante acceso al puerto serial del router puedo hacer dumps de la memoria si arranco el monitor que tiene. El router es un TP-LINK WDR3600n.

Tengo la esperanza de que parte de ese dump corresponda a la memoria flash así no tengo que conseguir o armar la pinza soic8 y programar la lectura de la flash, otra nota aparte.

Por el otro tengo varios firmwares, asi que la idea es buscar en dump los firmwares hasta ver si coinciden.


¿Qué hay que buscar? 



Las letritas en hexadecimal.

¿Cómo buscarlo?



sudo apt install yara

ok?

Y crear las reglas, por ejemplo, en yara/rule-firmware.yara

rule Firmware
{
  strings:
    $hex_string = {

      01 00 00 00 54 50 2d 4c  49 4e 4b 20 54 65 63 68
    }

  condition:
    $hex_string
}


Luego ejecutar

yara yara/rule-firmware.yara capture

Sería conveniente que en la carpeta capture sólo estén los binarios, pues yara busca en todo.

Ah, antes, para controlar que todo esté funcionando, podemos buscar algo que sabemos que vamos a encontrar, no olvidemos que nunca antes hemos usado yara y no tenemos idea de que trae ni vamos a leer el manual hasta que nos trabemos:




Acá hemos obtenido unos hexa () que hemos puesto en la regla yara/rule-control.yara y buscado en capture/00000000.bin


Volviendo, tras ejecutar la búsqueda, lo hemos hallado en capture/9f020000.bin, pero no sabemos cual de los tres firmwares es y nos sería útil saber en que punto difieren los firmwares, un poco de bash y listo:




tenemos que hacer una regla para cada firmware tal que llegue hasta un poco más hallá de la diferencia, tipo hasta 0x4f, ok?

Tenemos entonces un archivo de reglas para los tres firmwares que bajamos:


rule Firmware_1
{
  strings:
    $hex_string = {
      01 00 00 00 54 50 2d 4c  49 4e 4b 20 54 65 63 68
      6e 6f 6c 6f 67 69 65 73  00 00 00 00 76 65 72 2e
      20 31 2e 30 00 00 00 00  00 00 00 00 00 00 00 00
      00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
      36 00 00 01 00 00 00 01  00 00 00 00 f1 63 1c 98
    }
 

  condition:
    $hex_string
}
rule Firmware_2
{
  strings:
    $hex_string = {
      01 00 00 00 54 50 2d 4c  49 4e 4b 20 54 65 63 68
      6e 6f 6c 6f 67 69 65 73  00 00 00 00 76 65 72 2e
      20 31 2e 30 00 00 00 00  00 00 00 00 00 00 00 00
      00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
      36 00 00 01 00 00 00 01  00 00 00 00 fd 6a 69 c2
    }

  condition:
    $hex_string
}
rule Firmware_3
{
  strings:
    $hex_string = {
      01 00 00 00 54 50 2d 4c  49 4e 4b 20 54 65 63 68
      6e 6f 6c 6f 67 69 65 73  00 00 00 00 76 65 72 2e
      20 31 2e 30 00 00 00 00  00 00 00 00 00 00 00 00
      00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
      36 00 00 01 00 00 00 01  00 00 00 00 19 2d 99 29
    }

  condition:
    $hex_string
}


Ufa!! no encuentra ninguno, achiquemos... quitándole la quinta linea coincide, eso significa que el firmware que tenemos no es el que bajamos. Vamos a tener que tomar otro camino mientras.

Si recordamos que el objetivo es bajar el firmware en el router, tendríamos que verificar tomando entre el match de la regla y la longitud del firmware si es un firmware.




Si en capture/9f020000.bin, antes de 9F7F0200 (9f020000 + 7d0200) tenemos unos pocos bytes distintos de cero y luego todos ceros y luego todos 0xff, podríamos sospechar que es lo que buscamos. De un modo un otro, tomando el segmento 9f020000 .. 9F7F0200 como si fuera un firmware y ejecutándole binwalk, deberíamos obtener algo parecido a lo que se obtiene de cualquier otro firmware.

Mirando para atras, nos pudimos haber arreglado sin yara. De hecho, no he podido obtener el desplazamiento del match en el archivo y tuve que buscar con grep en el .hex. Pero claro, eso lo sé ahora.

Procedimiento completo


  1. expect capture.tcl | tee 9f020000.hexdump.noisy
  2. grep -P \
    '^[0-9a-f]{8}:( [0-9a-f]{8}){4}    .{16}' \ 9f020000.hexdump.noisy > 9f020000.hexdump
  3. dos2unix 9f020000.hexdump
  4. cut -b 11-45 9f020000.hexdump > 9f020000.hex
  5. xxd 9f020000.hex -r -p > 9f020000.bin
  6. binwalk -e  9f020000.bin

 

Explicaciones


  1. El script capture.tcl invoca el monitor y le pide que haga dump indefinidamente, hasta que uno decida cortar. Para eso está el tee, que va salvando en el archivo mientras muestra en pantalla.
  2. El grep limpia el ruido de todo el diálogo, sólo deja el volcado.
  3. El dos2unix arregla los saltos de linea.
  4. El cut quita las direcciones y el render para que no le molesta a...
  5. El xxd convierte de notación hexadecimal a binario.
  6. El binwalk extrae lo que haya dentro del binario.

Y luego hacemos

cat _9f020000.bin.extracted/squashfs-root/etc/shadow 

que nos da...

root:$1$GTN.gpri$DlSyKvZKMR9A9Uj9e9wR3/:15502:0:99999:7:::

que es lo mismo que teníamos en los otros firmwares, fallamos, no hemos podido ingresar al linux funcionando

Solo nos resta averiguar que firmware es, ¿no?

Un recurso sería buscar el md5 del volcado y los firmwares, pero aunque los archivos comprimidos están, los descomprimidos no. Comprimir el volcado no debería servir, pues debería haberse aplicado exactamente la misma compresión, mmhhh, probemos igual.

for level in {1..9} ; do
   zip firmware$level.zip -"$level" ../capture3/9f020000.bin
done

Lástima que no puedo saber cual es el nombre del archivo original, que forma parte del .zip o sea que influye al hash, dead end.

Dejo acá los hashes de los firmares que tengo...


768584458745f2a5e2ed24cb77ba3d8c  wdr3600v1_en_3_14_1_up_boot(141022).bin
25f0d01aaa74a00a929330d75887a200  wdr3600v1_en_3_14_1_up_boot(150302).bin
faf0c2b2128141c587f06a27d7fabe6a  wdr3600v1_en_3_14_3_up_boot(150518).bin


y del que obtuve:



20b3566386a50ea3afb7fb8330736edb  9f020000.bin


Estos son los que se obtienen en el sitio oficial


7e21d127116d48d0a05e54fc78636ebc  TL-WDR3600_V1_141022.zip
56cf77919b60c32cc6bb49b991881baa  TL-WDR3600_v1_150302.zip
efbdeebd5c85fdb857d23e17d22c4970  TL-WDR3600_V1_150518.zip


No me alcanza, quiero saber que está pasando... dirdiff es mi nueva esperanza.

Esto es dirdiff contra el último oficial, TL-WDR3600_V1_150518:


Primero no veia nada, cuando activé "options -> show files that are identical" me apareció así. Lo comparé con los anteriores y se mantuvo idéntico, sólo cambiando la fecha de modificación. Quedan dos archivos más:


200.7z
7E3C60.7z

que en el los firmwares oficiales tienen otro nombre:

20400.7z
3E60.7z

0328325baa82949c0c063df84b8b6718 _wdr3600v1_en_3_14_3_up_boot(150518)/20400.7z
9f92aa0eaa3d4ebe53660aba5d1d78e5 _wdr3600v1_en_3_14_3_up_boot(150518)/3E60.7z


3d1b44907feb914380a05eb4ccdd2d13 _wdr3600v1_en_3_14_1_up_boot(141022)/20400.7z
f6c55acfa5a2beacf86bccea88ef7be7 _wdr3600v1_en_3_14_1_up_boot(141022)/3E60.7z


c4220429117cbd64cb4372fed422c858 _wdr3600v1_en_3_14_1_up_boot(150302)/20400.7z
ea8a66b8071a63b5ab04bc649b09f8ba _wdr3600v1_en_3_14_1_up_boot(150302)/3E60.7z


348c14f63d8947f43c8d11d6afd0ed38  _wdr3600v1_en_3_14_3_up_boot(150518)/20400
eef72299e5c46f3796cb4c6ce63cf936  _9f020000/7E3C60



Los filesystems son idénticos:

da91975154424bd4e088a8a3f5b808d6 v1_en_3_14_3_up_boot(150518)/120200.squashfs
da91975154424bd4e088a8a3f5b808d6 _9f020000.bin.extracted/100000.squashfs

Esto amerita mucho más investigación, pero como se rompió el router, por ahora no puedo avanzar más.