Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Hola a todos.

Nosotros, Viktor Antipov e Ilya Aleshin, hablaremos hoy sobre nuestra experiencia trabajando con dispositivos USB a través de Python PyUSB y un poco sobre ingeniería inversa.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Prehistoria

En 2019, el Decreto del Gobierno de la Federación de Rusia N° 224 “Sobre la aprobación de las Reglas para el etiquetado de productos de tabaco con medios de identificación y las características de la implementación de un sistema de información estatal para monitorear la circulación de mercancías sujetas a etiquetado obligatorio con medios de identificación en relación con los productos del tabaco”.
El documento explica que a partir del 1 de julio de 2019 los fabricantes deberán etiquetar cada paquete de tabaco. Y los distribuidores directos deberán recibir estos productos con la formalización de un documento de transferencia universal (UDD). Las tiendas, a su vez, deben registrar la venta de productos etiquetados a través de la caja registradora.

Asimismo, a partir del 1 de julio de 2020, queda prohibida la circulación de productos del tabaco sin etiquetar. Esto significa que todas las cajetillas de cigarrillos deben estar marcadas con un código de barras especial Datamatrix. Además, un punto importante, resultó que Datamatrix no será normal, sino inverso. Es decir, no código negro sobre blanco, sino viceversa.

Probamos nuestros escáneres y resultó que la mayoría de ellos necesitan ser actualizados/reentrenados; de lo contrario, simplemente no pueden funcionar normalmente con este código de barras. Este giro de los acontecimientos nos garantizó un fuerte dolor de cabeza, porque nuestra empresa tiene muchas tiendas repartidas en un vasto territorio. Varias decenas de miles de cajas registradoras y muy poco tiempo.

Cual era la tarea asignada? Hay dos opciones. Primero: los ingenieros en el sitio actualizan y ajustan manualmente los escáneres. Segundo: trabajamos de forma remota y, preferiblemente, cubrimos muchos escáneres a la vez en una sola iteración.

La primera opción, obviamente, no nos convenía: tendríamos que gastar dinero en ingenieros visitantes y, en este caso, sería difícil controlar y coordinar el proceso. Pero lo más importante es que la gente trabajaría, es decir, potencialmente cometeríamos muchos errores y, muy probablemente, no cumpliríamos el plazo.

La segunda opción es buena para todos, aunque no sea por algo. Algunos proveedores no tenían las herramientas de actualización remota que necesitábamos para todos los sistemas operativos necesarios. Y como los plazos se estaban acabando, tuve que pensar con mi propia cabeza.

A continuación, le contaremos cómo desarrollamos herramientas para escáneres portátiles para el sistema operativo Debian 9.x (todas nuestras cajas registradoras están en Debian).

Resuelve el acertijo: cómo flashear un escáner

Informa Víctor Antipov.

La utilidad oficial proporcionada por el proveedor funciona en Windows y sólo en IE. La utilidad puede actualizar y configurar el escáner.

Dado que nuestro sistema de destino es Debian, instalamos un servidor redirector USB en Debian y un cliente redirector USB en Windows. Utilizando las utilidades de redirector USB, reenviamos el escáner desde una máquina Linux a una máquina con Windows.

Una utilidad de un proveedor de Windows vio el escáner e incluso lo actualizó normalmente. Así, llegamos a la primera conclusión: nada depende del sistema operativo, se trata del protocolo de actualización.

DE ACUERDO. Ejecutamos el flasheo en la máquina con Windows y eliminamos el volcado en la máquina con Linux.

Metimos el volcado en WireShark y... nos pusimos tristes (omitiré algunos de los detalles del volcado, no son de ningún interés).

Lo que nos mostró el vertedero:

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Las direcciones 0000-0030, a juzgar por Wireshark, son información del servicio USB.

Estábamos interesados ​​en la pieza 0040-0070.

No quedó claro nada en una trama de transmisión, excepto los caracteres MOCFT. Estos caracteres resultaron ser caracteres del archivo de firmware, así como los caracteres restantes hasta el final del cuadro (el archivo de firmware está resaltado):

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Lo que significaban los símbolos fd 3e 02 01 fe, yo personalmente, al igual que Ilya, no tenía idea.

Miré el siguiente cuadro (aquí se eliminó la información del servicio, se resaltó el archivo de firmware):

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

¿Qué quedó claro? Que los dos primeros bytes son una especie de constante. Todos los bloques posteriores lo confirmaron, pero antes del final del bloque de transmisión:

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Este fotograma también resultaba sorprendente, ya que la constante había cambiado (resaltada) y, curiosamente, allí estaba parte del archivo. El tamaño de los bytes transferidos del archivo mostró que se transfirieron 1024 bytes. Nuevamente no sabía qué significaban los bytes restantes.

En primer lugar, como antiguo apodo de BBS, revisé los protocolos de transmisión estándar. Ningún protocolo transmitió 1024 bytes. Comencé a estudiar el hardware y encontré el protocolo 1K Xmodem. Permitía transmitir 1024, pero con una salvedad: al principio sólo 128, y sólo si no había errores, el protocolo aumentaba el número de bytes transmitidos. Inmediatamente tuve una transferencia de 1024 bytes. Decidí estudiar los protocolos de transmisión, y concretamente el X-modem.

Había dos variaciones del módem.

Primero, el formato del paquete XMODEM con soporte CRC8 (el XMODEM original):

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

En segundo lugar, el formato de paquete XMODEM con soporte CRC16 (XmodemCRC):

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Tiene un aspecto similar, excepto SOH, número de paquete, CRC y longitud del paquete.

Miré el comienzo del segundo bloque de transmisión (y nuevamente vi el archivo de firmware, pero ya con una sangría de 1024 bytes):

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Vi el encabezado familiar fd 3e 02, pero los dos bytes siguientes ya habían cambiado: era 01 fe y se convirtió en 02 fd. Entonces me di cuenta de que el segundo bloque ahora tenía el número 02 y así lo entendí: frente a mí estaba la numeración del bloque de transmisión. La primera marcha 1024 es 01, la segunda es 02, la tercera es 03 y así sucesivamente (pero en hexadecimal, por supuesto). Pero ¿qué significa el cambio de fe a fd? Los ojos vieron una disminución de 1, el cerebro recordó que los programadores cuentan desde 0, no desde 1. Pero entonces, ¿por qué el primer bloque es 1 y no 0? Todavía no he encontrado la respuesta a esta pregunta. Pero entendí cómo se cuenta el segundo bloque. El segundo bloque no es más que FF – (menos) el número del primer bloque. Así, el segundo bloque fue designado como = 02 (FF-02) = 02 FD. La lectura posterior del vertedero confirmó mi suposición.

Entonces comenzó a surgir la siguiente imagen de la transmisión:

Inicio de la transmisión
fd 3e 02 – Inicio
01 FE – contador de transmisión
Transferencia (34 bloques, 1024 bytes transferidos)
fd 3e 1024 bytes de datos (divididos en bloques de 30 bytes).
Fin de la transmisión
fd25

Los datos restantes se alinearán en 1024 bytes.

¿Cómo se ve el marco final de la transmisión del bloque?

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

fd 25 – señal para finalizar la transmisión del bloque. Siguiente 2f 52: el resto del archivo con un tamaño de hasta 1024 bytes. 2f 52, a juzgar por el protocolo, es una suma de comprobación CRC de 16 bits.

Para recordar los viejos tiempos, creé un programa en C que extraía 1024 bytes de un archivo y calculaba un CRC de 16 bits. El lanzamiento del programa demostró que este no es un CRC de 16 bits. Estupor nuevamente, durante unos tres días. Todo este tiempo estuve tratando de entender qué podría ser, si no una suma de verificación. Mientras estudiaba sitios en inglés, descubrí que el X-modem utiliza su propio cálculo de suma de verificación: CRC-CCITT (XModem). No encontré ninguna implementación en C de este cálculo, pero encontré un sitio que calcula esta suma de verificación en línea. Después de transferir 1024 bytes de mi archivo a la página web, el sitio me mostró una suma de verificación que coincidía completamente con la suma de verificación del archivo.

¡Hurra! El último enigma estaba resuelto, ahora necesitaba crear mi propio firmware. Luego, le transmití mis conocimientos (y quedaron solo en mi cabeza) a Ilya, quien está familiarizado con el poderoso conjunto de herramientas Python.

Creando un programa

Ilya Aleshin informa.

Habiendo recibido las instrucciones apropiadas, me sentí muy “feliz”.

¿Dónde empezar? Así es, desde el principio.  De realizar un volcado desde el puerto USB.

Iniciar USB-pcap https://desowin.org/usbpcap/tour.html

Seleccionamos el puerto al que está conectado el dispositivo y el archivo donde guardaremos el volcado.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Conectamos el escáner a una máquina donde esté instalado el software nativo EZConfigScanning para Windows.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

En él encontramos el elemento para enviar comandos al dispositivo. Pero ¿qué pasa con los equipos? ¿Dónde puedo conseguirlos?
Cuando se inicia el programa, el equipo es sondeado automáticamente (esto lo veremos un poco más adelante). Y había códigos de barras de entrenamiento de documentos oficiales del equipo. DEFECTO. Este es nuestro equipo.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Se han recibido los datos necesarios. Abra dump.pcap mediante Wirehark.

Bloquear al iniciar EZConfigScanning. Los lugares a los que debes prestar atención están marcados en rojo.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Al ver todo esto por primera vez, me desanimé. No está claro dónde excavar a continuación.

Un poco de lluvia de ideas y-y-y... ¡Ajá! en el basurero salir - Es inY in это salir.

Busqué en Google qué es URB_INTERRUPT. Descubrí que este es un método de transferencia de datos. Y existen 4 métodos de este tipo: control, interrupción, isócrono, masivo. Puedes leer sobre ellos por separado.

Y las direcciones de los puntos finales en la interfaz del dispositivo USB se pueden obtener mediante el comando “lsusb –v” o usando pyusb.

Ahora necesitamos encontrar todos los dispositivos con este VID. Puede buscar específicamente por VID:PID.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Se ve así:

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Entonces, tenemos la información necesaria: los comandos P_INFO. o DEFALT, direcciones donde escribir comandos endpoint=03 y dónde obtener la respuesta endpoint=86. Todo lo que queda es convertir los comandos a hexadecimal.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Como ya hemos encontrado el dispositivo, desconectémoslo del kernel...

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

...y escribir en el punto final con la dirección 0x03,

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

... y luego lea la respuesta del punto final con la dirección 0x86.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Respuesta estructurada:

P_INFOfmt: 1
mode: app
app-present: 1
boot-present: 1
hw-sn: 18072B44CA
hw-rev: 0x20
cbl: 4
app-sw-rev: CP000116BBA
boot-sw-rev: CP000014BAD
flash: 3
app-m_name: Voyager 1450g
boot-m_name: Voyager 1450g
app-p_name: 1450g
boot-p_name: 1450g
boot-time: 16:56:02
boot-date: Oct 16 2014
app-time: 08:49:30
app-date: Mar 25 2019
app-compat: 289
boot-compat: 288
csum: 0x6986

Vemos estos datos en dump.pcap.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

¡Excelente! Convierta códigos de barras del sistema a hexadecimal. Eso es todo, la funcionalidad de entrenamiento está lista.

¿Qué pasa con el firmware? Todo parece igual, pero hay un matiz.

Habiendo realizado una descarga completa del proceso de actualización, entendimos aproximadamente a qué nos enfrentamos. Aquí hay un artículo sobre XMODEM, que fue muy útil para comprender cómo ocurre esta comunicación, aunque en términos generales: http://microsin.net/adminstuff/others/xmodem-protocol-overview.html Recomiendo leer

Al observar el volcado, puede ver que el tamaño del marco es 1024 y el tamaño de los datos URB es 64.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Por lo tanto – 1024/64 – obtenemos 16 líneas en un bloque, leemos el archivo de firmware 1 carácter a la vez y formamos un bloque. Complementando 1 línea en un bloque con caracteres especiales fd3e02 + número de bloque.
Las siguientes 14 líneas se complementan con fd25 +, usando XMODEM.calc_crc() calculamos la suma de verificación de todo el bloque (nos llevó mucho tiempo comprender que "FF – 1" es CSUM) y la última línea, 16, se complementa con fd3e.

Parece que eso es todo, lea el archivo de firmware, presione los bloques, desconecte el escáner del kernel y envíelo al dispositivo. Pero no es tan simple. El escáner debe cambiarse al modo firmware,
отправив ему NEWAPP = ‘\xfd\x0a\x16\x4e\x2c\x4e\x45\x57\x41\x50\x50\x0d’.
De donde es este equipo?? Del basurero.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Pero no podemos enviar un bloque completo al escáner debido al límite de 64:

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Bueno, el escáner en modo intermitente NEWAPP no acepta hexadecimal. Por lo tanto, tendrás que traducir cada línea bytes_array

[253, 10, 22, 78, 44, 78, 69, 87, 65, 80, 80, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Y luego envíe estos datos al escáner.

Obtenemos la respuesta:

[2, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Si consulta el artículo sobre XMODEM, quedará claro: los datos han sido aceptados.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

Una vez transferidos todos los bloques, completamos la transferencia END_TRANSFER = 'xfdx01x04'.

Bueno, dado que estos bloques no contienen ninguna información para la gente común, instalaremos el firmware en modo oculto de forma predeterminada. Y por si acaso, organizaremos una barra de progreso a través de tqdm.

Una tarea para un desarrollador o cómo presentamos escáneres portátiles sin proveedor

En realidad, entonces es una cuestión de pequeñas cosas. Todo lo que queda es envolver la solución en scripts para replicación masiva en un momento claramente definido, para no ralentizar el proceso de trabajo en las cajas, y agregar registros.

Total

Después de haber invertido mucho tiempo, esfuerzo y pelos de punta, pudimos desarrollar las soluciones que necesitábamos y además cumplimos el plazo. Al mismo tiempo, los escáneres ahora se actualizan y capacitan de forma centralizada, controlamos claramente todo el proceso. La empresa ahorró tiempo y dinero y adquirimos una experiencia invaluable en equipos de ingeniería inversa de este tipo.

Fuente: habr.com

Añadir un comentario