Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Bonghjornu.

Avemu, Viktor Antipov è Ilya Aleshin, oghje parlemu di a nostra sperienza di travaglià cù i dispositi USB via Python PyUSB è un pocu di l'ingegneria inversa.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Pristoria

In u 2019, u Decretu di u Guvernu di a Federazione Russa N ° 224 "In appruvazioni di e regule per l'etichettatura di i prudutti di tabacco cù i mezi d'identificazione è e caratteristiche di l'implementazione di un sistema d'infurmazione statale per u seguimentu di a circulazione di e merchenzie sottumessi à l'etichettatura obligatoria cù i mezi d'identificazione. in relazione à i prudutti di u tabacco » hè entrata in vigore.
U documentu spiega chì da u 1 di lugliu di u 2019, i pruduttori sò tenuti à etichettate ogni pacchettu di tabacco. È i distributori diretti devenu riceve sti prudutti cù l'esekzione di un documentu di trasferimentu universale (UDD). I magazzini, à u turnu, anu bisognu di registrà a vendita di prudutti etichettati attraversu u cash register.

Inoltre, da u 1 di lugliu di u 2020, a circulazione di prudutti di tabacco senza etichetta hè pruibita. Questu significa chì tutti i pacchetti di sigarette devenu esse marcati cù un codice a barre Datamatrix speciale. Inoltre - un puntu impurtante - hè risultatu chì u Datamatrix ùn serà micca ordinariu, ma inversu. Questu hè, micca codice neru nantu à biancu, ma vice versa.

Avemu pruvatu i nostri scanners, è hè risultatu chì a maiò parte di elli deve esse reflashed / retrained, altrimenti ùn sò micca solu capaci di travaglià nurmale cù stu codice à barre. Questa volta di l'avvenimenti ci hà garantitu un malu di testa severu, perchè a nostra cumpagnia hà assai magazzini chì sò spargugliati nantu à un vastu territoriu. Parechji decine di millaie di cash registers - è pocu tempu.

Chì avia da fà ? Ci sò dui ozzione. Prima: ingegneri in situ reflash manualmente è aghjustate i scanners. Siconda: avemu travagliatu remotamente è, preferibile, copre parechji scanners à una volta in una sola iterazione.

A prima opzione, ovviamente, ùn era micca adattatu per noi: averemu da spende soldi per visità ingegneri, è in questu casu, saria difficiule di cuntrullà è coordina u prucessu. Ma u più impurtante hè chì a ghjente hà da travaglià, vale à dì, averemu potenzalmentu assai errori è, assai prubabilmente, ùn rispettanu micca u termini.

A seconda opzione hè bona per tutti, se micca per una cosa. Certi venditori ùn avianu micca l'arnesi di lampeggiamentu remoti chì avemu bisognu per tutti i sistemi operativi richiesti. E siccomu i termini s'eranu, aghju avutu à pensà cù u mo propiu capu.

In seguitu, vi diceremu cumu avemu sviluppatu strumenti per scanners manuali per u Debian 9.x OS (tutti i nostri cash registers sò in Debian).

Risolve l'enigma: cumu lampà un scanner

Victor Antipov riporta.

L'utilità ufficiale furnita da u venditore travaglia sottu Windows, è solu cù IE. L'utilità pò lampà è cunfigurà u scanner.

Siccomu u nostru sistema di destinazione hè Debian, avemu installatu un servitore usb-redirector in Debian è un usb-redirector client in Windows. Utilizendu utilità di redirector usb, avemu trasmessu u scanner da una macchina Linux à una macchina Windows.

Una utilità da un venditore di Windows hà vistu u scanner è ancu lampatu normalmente. Cusì, avemu fattu a prima cunclusione: nunda dipende di u SO, hè una materia di u protokollu lampante.

OK. Eseguimu u lampeggiante nantu à a macchina Windows, è sguassate u dump in a macchina Linux.

Avemu stuffed the dump in WireShark è... si sò tristi (Omitte some of the details of the dump, ùn sò micca d'interessu).

Ciò chì u dump ci hà dimustratu:

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

L'indirizzi 0000-0030, à ghjudicà da Wireshark, sò informazioni di serviziu USB.

Eramu interessatu in a parte 0040-0070.

Nunda era chjaru da un quadru di trasmissione eccettu per i caratteri MOCFT. Questi caratteri sò stati caratteri di u schedariu di firmware, è ancu di i caratteri rimanenti finu à a fine di u quadru (u schedariu di firmware hè evidenziatu):

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Chì significà i simboli fd 3e 02 01 fe, personalmente, cum'è Ilya, ùn avia micca idea.

Aghju guardatu u quadru seguente (l'infurmazione di serviziu hè stata sguassata quì, u schedariu di firmware hè statu evidenziatu):

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Chì hè diventatu chjaru? Chì i primi dui byte sò un tipu di custanti. Tutti i blocchi successivi anu cunfirmatu questu, ma prima di a fine di u bloccu di trasmissione:

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Stu quadru era ancu stupefiante, postu chì a custante era cambiata (saltata) è, curiosamente, ci era una parte di u schedariu. A dimensione di i bytes trasferiti di u schedariu dimustrava chì 1024 bytes sò stati trasferiti. I novu ùn sapia micca ciò chì i byte restante significavanu.

Prima di tuttu, cum'è un vechju soprannomu BBS, aghju rivedutu i protokolli di trasmissione standard. Nisun protokollu trasmessu 1024 bytes. Aghju cuminciatu à studià l'hardware è aghju scontru u protocolu 1K Xmodem. Hè permessu di trasmette 1024, ma cù una caveat: in prima solu 128, è solu s'ellu ùn ci era micca errore, u protocolu hà aumentatu u numeru di bytes trasmessi. Aghju subitu un trasferimentu di 1024 bytes. Aghju decisu di studià i protokolli di trasmissione, è in particulare u X-modem.

Ci era duie varianti di u modem.

Prima, u formatu di pacchettu XMODEM cù supportu CRC8 (u XMODEM originale):

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Siconda, u formatu di pacchettu XMODEM cù supportu CRC16 (XmodemCRC):

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Sembra simili, eccettu per SOH, numeru di pacchettu è CRC è lunghezza di pacchettu.

Aghju guardatu à u principiu di u sicondu bloccu di trasmissione (è novu vistu u schedariu di firmware, ma digià indentatu da 1024 bytes):

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Aghju vistu l'intestazione familiare fd 3e 02, ma i prossimi dui bytes avianu digià cambiatu: era 01 fe, è diventenu 02 fd. Allora aghju nutatu chì u sicondu bloccu era avà numeratu 02 è cusì capitu: davanti à mè era a numerazione di u bloccu di trasmissione. U primu gear 1024 hè 01, u sicondu hè 02, u terzu hè 03 è cusì (ma in hex, sicuru). Ma chì significa u cambiamentu da fe à fd ? L'ochji anu vistu una diminuzione di 1, u cervu hà ricurdatu chì i programatori contanu da 0, micca 1. Ma allora perchè u primu bloccu 1, è micca 0? Ùn aghju ancu micca trovu a risposta à sta quistione. Ma aghju capitu cumu u secondu bloccu hè cuntatu. U sicondu bloccu ùn hè nunda più cà FF - (minus) u numeru di u primu bloccu. Cusì, u sicondu bloccu hè statu designatu cum'è = 02 (FF-02) = 02 FD. A lettura successiva di u dump hà cunfirmatu a mo supposizione.

Allora a seguente stampa di a trasmissione cuminciò à emergere:

U principiu di a trasmissione
fd 3e 02 - Principià
01 FE - contatore di trasmissione
Trasferimentu (34 blocchi, 1024 bytes trasferiti)
fd 3e 1024 byte di dati (divisu in blocchi di 30 byte).
Fine di a trasmissione
fd 25

Dati rimanenti da esse allinati à 1024 bytes.

Cume hè u quadru di a fine di trasmissione di bloccu:

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

fd 25 - signale per finisce a trasmissione di bloccu. Next 2f 52 - u restu di u schedariu finu à 1024 bytes in size. 2f 52, à ghjudicà da u protocolu, hè un checksum CRC di 16 bit.

Per i vechji tempi, aghju fattu un prugramma in C chì tirava 1024 bytes da un schedariu è hà calculatu un CRC 16-bit. U lanciamentu di u prugramma hà dimustratu chì questu ùn hè micca un CRC 16-bit. Stupor again - per circa trè ghjorni. Tuttu stu tempu cercava di capisce ciò chì puderia esse, se micca un checksum. Mentre studiava siti in lingua inglese, aghju scupertu chì u X-modem usa u so propiu calculu di checksum - CRC-CCITT (XModem). Ùn aghju micca truvatu alcuna implementazione C di stu calculu, ma aghju trovu un situ chì hà calculatu questu checksum in linea. Dopu avè trasfirutu 1024 bytes di u mo schedariu à a pagina web, u situ m'hà mostratu un checksum chì currisponde cumpletamente à u checksum da u schedariu.

Eura! L'ultimu enigma hè statu risoltu, avà avia bisognu di fà u mo propiu firmware. In seguitu, aghju passatu a mo cunniscenza (è ferma solu in a mo testa) à Ilya, chì hè familiarizatu cù u putente toolkit Python.

Crià un prugramma

Ilya Aleshin informa.

Dopu avè ricevutu l'istruzzioni appropritate, eru assai "felice".

Induve principià ? Hè propiu, da u principiu.  Da piglià un dump da u portu USB.

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

Selezziunate u portu à quale hè cunnessu u dispusitivu è u schedariu induve salvemu u dump.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Cunnetteremu u scanner à una macchina induve u software nativu EZConfigScanning per Windows hè stallatu.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

In questu truvamu l'articulu per mandà cumandamenti à u dispusitivu. Ma chì ne di e squadre ? Induve li possu piglià ?
Quandu u prugramma principia, l'equipaggiu hè invucatu automaticamente (vedemu questu un pocu dopu). E ci eranu codici à barre di furmazione da documenti ufficiali di l'equipaggiu. DEFALT. Questu hè a nostra squadra.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

I dati necessarii sò stati ricevuti. Apertura dump.pcap via wireshark.

Bloccu quandu principia EZConfigScanning. I posti chì avete bisognu di attentu sò marcati in rossu.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Videndu tuttu questu per a prima volta, aghju persu u core. Ùn hè micca chjaru induve scavà dopu.

Un pocu di brainstorming è-è-è... Aha ! In u dump fora - questu ine in si fora.

Aghju cercatu in Google ciò chì hè URB_INTERRUPT. Aghju scupertu chì questu hè un metudu di trasferimentu di dati. È ci sò 4 tali metudi: cuntrollu, interruzzione, isochronous, bulk. Pudete leghje nantu à elli separatamente.

È l'indirizzi endpoint in l'interfaccia di u dispositivu USB ponu esse ottenuti sia per mezu di u cumandimu "lsusb -v" o cù pyusb.

Avà avemu bisognu di truvà tutti i dispositi cù questu VID. Pudete cercà specificamente per VID:PID.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Sembra cusì:

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Allora, avemu l'infurmazioni necessarii: i cumandamenti P_INFO. o DEFALT, indirizzi induve scrive cumandamenti endpoint = 03 è induve ottene u endpoint di risposta = 86. Tuttu ciò chì resta hè di cunvertisce i cumandamenti in hex.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Siccomu avemu digià trovu u dispusitivu, scunnettemu da u kernel...

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

... è scrivite à l'endpoint cù l'indirizzu 0x03,

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

... è poi leghje a risposta da l'endpoint cù l'indirizzu 0x86.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Risposta strutturata:

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

Avemu vede sta dati in dump.pcap.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Perfettu! Cunvertisce i codici a barre di u sistema in hex. Eccu, a funziunalità di furmazione hè pronta.

Chì ci hè di u firmware? Tuttu pare esse uguali, ma ci hè una sfumatura.

Dopu avè fattu un dump cumpletu di u prucessu lampante, avemu capitu à pocu pressu ciò chì avemu trattatu. Eccu un articulu nantu à XMODEM, chì era assai utile per capiscenu cumu si sta cumunicazione, ancu s'ellu in termini generale: http://microsin.net/adminstuff/others/xmodem-protocol-overview.html Vi cunsigliu di leghje.

Fighjendu u dump, pudete vede chì a dimensione di u quadru hè 1024, è a dimensione di i dati URB hè 64.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Dunque - 1024/64 - avemu 16 linee in un bloccu, leghje u schedariu di firmware 1 caratteru à tempu è formate un bloccu. Cumplementu 1 linea in un bloccu cù caratteri speciali fd3e02 + numeru di bloccu.
I prossimi 14 linii sò supplementati cù fd25 +, usendu XMODEM.calc_crc () avemu calculatu u checksum di tuttu u bloccu (hà pigliatu assai tempu per capisce chì "FF - 1" hè CSUM) è l'ultima, 16th line hè supplementata. cù fd3e.

Sembra chì hè questu, leghjite u schedariu di firmware, culpisce i blocchi, disconnect u scanner da u kernel è mandà à u dispusitivu. Ma ùn hè micca cusì simplice. U scanner deve esse cambiatu in modalità firmware,
отправив ему NEWAPP = ‘\xfd\x0a\x16\x4e\x2c\x4e\x45\x57\x41\x50\x50\x0d’.
Da induve hè sta squadra?? Da u dump.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Ma ùn pudemu micca mandà un bloccu sanu à u scanner per via di u limitu 64:

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Ebbè, u scanner in modalità lampeggiante NEWAPP ùn accetta micca hex. Dunque, avete da traduce ogni linea 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]

E poi mandà sti dati à u scanner.

Avemu a risposta:

[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]

Se verificate l'articulu di XMODEM, diventerà chjaru: i dati sò stati accettati.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

Dopu chì tutti i blocchi sò stati trasferiti, compie u trasferimentu END_TRANSFER = 'xfdx01x04'.

Ebbè, postu chì sti blocchi ùn portanu micca infurmazione per a ghjente ordinaria, stallà u firmware in modu oculatu per automaticamente. È solu in casu, urganizeremu una barra di prugressu attraversu tqdm.

Un compitu per un sviluppatore, o cumu avemu lampatu scanners manuali senza un venditore

In verità, allora hè una questione di picculi cose. Tuttu ciò chì resta hè di imbulighjà a suluzione in scripts per a replicazione di massa à un tempu chjaramente definitu, per ùn rallentà u prucessu di travaglià à i checkouts, è aghjunghje logging.

U risultatu

Dopu avè passatu assai tempu è sforzu è capelli nantu à a nostra testa, avemu pussutu sviluppà e suluzioni chì avemu bisognu, è ancu scontru u termini. À u listessu tempu, i scanners sò oghji rinfriscati è ricuperati cintrali, cuntrullemu chjaramente tuttu u prucessu. A cumpagnia hà risparmiatu tempu è soldi, è avemu acquistatu una sperienza inestimabile in l'equipaggiu di ingegneria inversa di stu tipu.

Source: www.habr.com

Add a comment