Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Hola a tots

Avui, Victor Antipov i Ilya Aleshin, parlarem de la nostra experiència treballant amb dispositius USB mitjançant Python PyUSB i una mica d'enginyeria inversa.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

prehistòria

El 2019, el Decret del Govern de la Federació de Rússia núm. 224 "Sobre l'aprovació de les normes per a l'etiquetatge dels productes del tabac amb mitjans d'identificació i característiques de la implementació d'un sistema d'informació estatal per controlar la circulació de mercaderies subjectes a etiquetatge obligatori amb mitjans d'identificació. en relació amb els productes del tabac”.
El document explica que a partir de l'1 de juliol de 2019, els fabricants estan obligats a etiquetar cada paquet de tabac. I els distribuïdors directes han de rebre aquests productes amb l'execució d'un document de transferència universal (UDD). Les botigues, al seu torn, han de registrar la venda de productes etiquetats a través de la caixa registradora.

Així mateix, a partir de l'1 de juliol de 2020 està prohibida la circulació de productes de tabac sense etiquetar. Això vol dir que tots els paquets de cigarrets han d'estar marcats amb un codi de barres Datamatrix especial. A més, un punt important, va resultar que el Datamatrix no serà normal, sinó invers. És a dir, no codi negre sobre blanc, sinó viceversa.

Vam provar els nostres escàners i va resultar que la majoria d'ells s'han de tornar a entrenar/reformar, en cas contrari, simplement no poden funcionar normalment amb aquest codi de barres. Aquest gir dels esdeveniments ens va garantir un fort maldecap, perquè la nostra empresa compta amb un munt de botigues repartides per un extens territori. Diverses desenes de milers de caixes registradores, i molt poc temps.

Què s'havia de fer? Hi ha dues opcions. Primer: els enginyers del lloc actualitzen i ajusten manualment els escàners. Segon: treballem de forma remota i, preferiblement, cobrim molts escàners alhora en una iteració.

La primera opció, òbviament, no ens era adequada: hauríem de gastar diners en enginyers visitants, i en aquest cas seria difícil controlar i coordinar el procés. Però el més important és que la gent treballés, és a dir, potencialment ens trobaríem molts errors i, molt probablement, no compliríem el termini.

La segona opció és bona per a tothom, si no per una cosa. Alguns venedors no tenien les eines de flasheig remot que necessitàvem per a tots els sistemes operatius necessaris. I com que els terminis s'acabaven, vaig haver de pensar amb el meu propi cap.

A continuació, us explicarem com hem desenvolupat eines per a escàners de mà per al sistema operatiu Debian 9.x (totes les nostres caixes registradores estan a Debian).

Resoldre l'enigma: com flashejar un escàner

Víctor Antipov informa.

La utilitat oficial proporcionada pel venedor funciona amb Windows i només amb IE. La utilitat pot flashejar i configurar l'escàner.

Com que el nostre sistema objectiu és Debian, hem instal·lat un servidor de redirector USB a Debian i un client de redirector USB a Windows. Utilitzant utilitats de redirector USB, vam reenviar l'escàner des d'una màquina Linux a una màquina Windows.

Una utilitat d'un proveïdor de Windows va veure l'escàner i fins i tot l'ha mostrat amb normalitat. Així, vam fer la primera conclusió: res depèn del sistema operatiu, és qüestió del protocol de parpelleig.

D'ACORD. Vam executar el parpelleig a la màquina Windows i vam eliminar l'abocament a la màquina Linux.

Vam posar l'abocador a WireShark i... ens vam entristir (ometré alguns detalls de l'abocador, no tenen cap interès).

Què ens va mostrar l'abocador:

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Les adreces 0000-0030, a jutjar per Wireshark, són informació de servei USB.

Ens interessava la part 0040-0070.

Res no estava clar d'un marc de transmissió, excepte els caràcters MOCFT. Aquests caràcters van resultar ser caràcters del fitxer del microprogramari, així com els caràcters restants fins al final del marc (el fitxer del microprogramari està ressaltat):

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

El que significaven els símbols fd 3e 02 01 fe, jo personalment, com Ilya, no en tenia ni idea.

Vaig mirar el marc següent (la informació del servei s'ha eliminat aquí, el fitxer de microprogramari s'ha ressaltat):

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Què va quedar clar? Que els dos primers bytes són una mena de constant. Tots els blocs posteriors ho van confirmar, però abans del final del bloc de transmissió:

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Aquest marc també era estupefactori, ja que la constant havia canviat (ressaltat) i, curiosament, hi havia part del fitxer. La mida dels bytes transferits del fitxer mostrava que s'han transferit 1024 bytes. De nou no sabia què volien dir els bytes restants.

En primer lloc, com a antic sobrenom de BBS, vaig revisar els protocols de transmissió estàndard. Cap protocol transmès 1024 bytes. Vaig començar a estudiar el maquinari i vaig trobar el protocol 1K Xmodem. Permetia transmetre 1024, però amb una advertència: al principi només 128, i només si no hi havia errors, el protocol augmentava el nombre de bytes transmesos. Immediatament vaig tenir una transferència de 1024 bytes. Vaig decidir estudiar els protocols de transmissió, i concretament el mòdem X.

Hi havia dues variacions del mòdem.

Primer, el format de paquet XMODEM amb suport CRC8 (el XMODEM original):

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

En segon lloc, el format de paquet XMODEM amb suport CRC16 (XmodemCRC):

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Sembla similar, excepte per SOH, número de paquet i CRC i longitud del paquet.

Vaig mirar l'inici del segon bloc de transmissió (i vaig tornar a veure el fitxer de microprogramari, però ja amb sagnat de 1024 bytes):

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Vaig veure la capçalera familiar fd 3e 02, però els dos bytes següents ja havien canviat: era 01 fe i es va convertir en 02 fd. Llavors em vaig adonar que el segon bloc estava numerat ara 02 i així ho vaig entendre: davant meu hi havia la numeració del bloc de transmissió. El primer engranatge 1024 és 01, el segon és 02, el tercer és 03 i així successivament (però en hexadecimal, és clar). Però què significa el canvi de fe a fd? Els ulls van veure una disminució d'1, el cervell va recordar que els programadors compten des de 0, no 1. Però llavors, per què el primer bloc és 1 i no 0? Encara no he trobat la resposta a aquesta pregunta. Però vaig entendre com es compta el segon bloc. El segon bloc no és més que FF: (menys) el número del primer bloc. Així, el segon bloc es va designar com a = 02 (FF-02) = 02 FD. La lectura posterior de l'abocador va confirmar la meva conjectura.

Aleshores va començar a sorgir la següent imatge de la transmissió:

Inici de la transmissió
fd 3e 02 – Inici
01 FE – comptador de transmissió
Transferència (34 blocs, 1024 bytes transferits)
fd 3e 1024 bytes de dades (dividits en blocs de 30 bytes).
Final de la transmissió
fd 25

Les dades restants s'han d'alinear amb 1024 bytes.

Quin aspecte té el marc final de transmissió del bloc:

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

fd 25 – senyal per acabar la transmissió del bloc. Següent 2f 52: la resta del fitxer fins a 1024 bytes de mida. 2f 52, a jutjar pel protocol, és una suma de verificació CRC de 16 bits.

Pel bé dels vells temps, vaig fer un programa en C que va treure 1024 bytes d'un fitxer i va calcular un CRC de 16 bits. El llançament del programa va demostrar que no es tracta d'un CRC de 16 bits. Estupor de nou - durant uns tres dies. Durant tot aquest temps vaig estar intentant entendre què podia ser, si no una suma de control. Mentre estudiava llocs en anglès, vaig descobrir que el mòdem X utilitza el seu propi càlcul de suma de verificació: CRC-CCITT (XModem). No he trobat cap implementació C d'aquest càlcul, però he trobat un lloc que calculava aquesta suma de comprovació en línia. Després d'haver transferit 1024 bytes del meu fitxer a la pàgina web, el lloc em va mostrar una suma de comprovació que coincideix completament amb la suma de comprovació del fitxer.

Hura! L'últim enigma estava resolt, ara necessitava fer el meu propi firmware. A continuació, vaig transmetre els meus coneixements (i només em van quedar al cap) a Ilya, que està familiaritzat amb el potent conjunt d'eines Python.

Creació d'un programa

Ilya Aleshin informa.

Després d'haver rebut les instruccions adequades, estava molt "feliç".

Per on començar? Així és, des del principi.  De fer un abocador des del port USB.

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

Seleccioneu el port al qual està connectat el dispositiu i el fitxer on guardarem el bolcat.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Connectem l'escàner a una màquina on està instal·lat el programari natiu EZConfigScanning per a Windows.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Hi trobem l'element per enviar ordres al dispositiu. Però què passa amb els equips? On els puc aconseguir?
Quan s'inicia el programa, l'equip es consulta automàticament (això ho veurem una mica més endavant). I hi havia codis de barres d'entrenament dels documents oficials de l'equip. DEFALT. Aquest és el nostre equip.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

S'han rebut les dades necessàries. Obriu dump.pcap mitjançant wireshark.

Bloqueja quan s'inicia EZConfigScanning. Els llocs als quals cal prestar atenció estan marcats en vermell.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

En veure tot això per primera vegada, em vaig desanimar. No està clar on excavar a continuació.

Una mica de pluja d'idees i-i-i... Aha! A l'abocador fora - ho és inI in aquest fora.

He buscat a Google què és URB_INTERRUPT. Vaig descobrir que aquest és un mètode de transferència de dades. I hi ha 4 mètodes d'aquest tipus: control, interrupció, isòcrona, a granel. Podeu llegir sobre ells per separat.

I les adreces de punt final a la interfície del dispositiu USB es poden obtenir mitjançant l'ordre "lsusb -v" o mitjançant pyusb.

Ara hem de trobar tots els dispositius amb aquest VID. Podeu cercar específicament per VID:PID.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Es veu així:

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Així doncs, tenim la informació necessària: les ordres P_INFO. o DEFALT, adreces on escriure les ordres endpoint=03 i on obtenir la resposta endpoint=86. Tot el que queda és convertir les ordres a hexadecimal.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Com que ja hem trobat el dispositiu, desconnectem-lo del nucli...

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

...i escriviu al punt final amb l'adreça 0x03,

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

... i després llegiu la resposta del punt final amb l'adreça 0x86.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Resposta 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

Veiem aquestes dades a dump.pcap.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Genial! Converteix els codis de barres del sistema a hexadecimal. Això és tot, la funcionalitat d'entrenament està llesta.

Què passa amb el firmware? Tot sembla ser igual, però hi ha un matís.

Després d'haver fet un abocament complet del procés de parpelleig, vam entendre aproximadament amb què estàvem tractant. Aquí teniu un article sobre XMODEM, que va ser molt útil per entendre com es produeix aquesta comunicació, encara que en termes generals: http://microsin.net/adminstuff/others/xmodem-protocol-overview.html Recomano llegir-lo.

Mirant l'abocament, podeu veure que la mida del marc és 1024 i la mida de les dades URB és de 64.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Per tant - 1024/64 – obtenim 16 línies en un bloc, llegim el fitxer del firmware 1 caràcter alhora i formem un bloc. Complementar 1 línia en un bloc amb caràcters especials fd3e02 + número de bloc.
Les 14 línies següents es complementen amb fd25 +, utilitzant XMODEM.calc_crc() calculem la suma de control de tot el bloc (va trigar molt de temps a entendre que "FF - 1" és CSUM) i es complementa la darrera línia 16. amb fd3e.

Sembla que això és tot, llegiu el fitxer del microprogramari, prem els blocs, desconnecteu l'escàner del nucli i envieu-lo al dispositiu. Però no és tan senzill. L'escàner s'ha de canviar al mode de microprogramari,
отправив ему NEWAPP = ‘\xfd\x0a\x16\x4e\x2c\x4e\x45\x57\x41\x50\x50\x0d’.
D'on és aquest equip?? De l'abocador.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Però no podem enviar un bloc sencer a l'escàner a causa del límit de 64:

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Bé, l'escàner en mode intermitent NEWAPP no accepta hexadecimals. Per tant, haureu de traduir cada línia 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]

I després envieu aquestes dades a l'escàner.

Obtenim la resposta:

[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 consulteu l'article sobre XMODEM, quedarà clar: les dades s'han acceptat.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

Després de transferir tots els blocs, completem la transferència END_TRANSFER = 'xfdx01x04'.

Bé, com que aquests blocs no porten cap informació per a la gent normal, instal·larem el firmware en mode ocult per defecte. I per si de cas, organitzarem una barra de progrés mitjançant tqdm.

Una tasca per a un desenvolupador, o com vam mostrar els escàners de mà sense un venedor

De fet, llavors és qüestió de petites coses. Només queda embolicar la solució en scripts per a la replicació massiva en un moment clarament definit, per no frenar el procés de treball a les caixes i afegir registre.

Total

Després d'haver dedicat molt de temps, esforços i cabells al cap, vam poder desenvolupar les solucions que necessitàvem i també vam complir el termini. Al mateix temps, els escàners s'actualitzen i es tornen a entrenar de manera centralitzada, controlem clarament tot el procés. L'empresa va estalviar temps i diners, i vam obtenir una experiència inestimable en equips d'enginyeria inversa d'aquest tipus.

Font: www.habr.com

Afegeix comentari