Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Ahoj všetci

My, Victor Antipov a Ilya Aleshin, dnes budeme hovoriť o našich skúsenostiach s prácou so zariadeniami USB cez Python PyUSB a trochu o reverznom inžinierstve.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

pravek

V roku 2019 bolo prijaté nariadenie vlády Ruskej federácie č. 224 „O schválení pravidiel označovania tabakových výrobkov identifikačnými prostriedkami a znakmi implementácie štátneho informačného systému na monitorovanie obehu tovaru podliehajúceho povinnému označovaniu identifikačnými prostriedkami vo vzťahu k tabakovým výrobkom“ nadobudol účinnosť.
Dokument vysvetľuje, že od 1. júla 2019 sú výrobcovia povinní označovať každé balenie tabaku. A priami distribútori musia dostať tieto produkty s vyhotovením univerzálneho transferového dokumentu (UDD). Predajne zase musia evidovať predaj označených produktov cez registračnú pokladňu.

Od 1. júla 2020 je tiež zakázaný obeh neoznačených tabakových výrobkov. To znamená, že všetky škatuľky cigariet musia byť označené špeciálnym čiarovým kódom Datamatrix. Navyše – dôležitý bod – sa ukázalo, že Datamatrix nebude obyčajný, ale inverzný. Teda nie čierny kód na bielom, ale naopak.

Testovali sme naše skenery a ukázalo sa, že väčšinu z nich treba preflashovať/preškoliť, inak jednoducho nedokážu s týmto čiarovým kódom normálne pracovať. Tento zvrat udalostí nám zaručil silnú bolesť hlavy, pretože naša spoločnosť má veľa obchodov, ktoré sú roztrúsené na obrovskom území. Niekoľko desiatok tisíc pokladníc – a veľmi málo času.

Čo sa malo urobiť? Sú dve možnosti. Po prvé: technici na mieste manuálne preformátujú a upravia skenery. Po druhé: pracujeme na diaľku a pokiaľ možno, pokrývame veľa skenerov naraz v jednej iterácii.

Prvá možnosť pre nás zjavne nebola vhodná: museli by sme míňať peniaze na hosťujúcich inžinierov a v tomto prípade by bolo ťažké kontrolovať a koordinovať proces. Najdôležitejšie však je, že ľudia by pracovali, to znamená, že by sme potenciálne dostali veľa chýb a s najväčšou pravdepodobnosťou by sme nedodržali termín.

Druhá možnosť je dobrá pre všetkých, ak nie na jednu vec. Niektorí predajcovia nemali nástroje na vzdialené blikanie, ktoré sme potrebovali pre všetky požadované operačné systémy. A keďže sa termíny krátili, musel som myslieť vlastnou hlavou.

Ďalej vám povieme, ako sme vyvinuli nástroje pre ručné skenery pre OS Debian 9.x (všetky naše pokladne sú na Debiane).

Vyriešte hádanku: ako flashovať skener

Informuje o tom Victor Antipov.

Oficiálny nástroj poskytovaný predajcom funguje pod Windowsom a iba s IE. Pomôcka môže flashovať a konfigurovať skener.

Keďže naším cieľovým systémom je Debian, nainštalovali sme usb-redirector server na Debian a usb-redirector klienta na Windows. Pomocou nástrojov usb-redirector sme preposlali skener z počítača so systémom Linux na počítač so systémom Windows.

Pomôcka od predajcu systému Windows videla skener a dokonca ho normálne preblikla. Preto sme urobili prvý záver: nič nezávisí od operačného systému, je to záležitosť blikajúceho protokolu.

OK. Spustili sme blikanie na počítači so systémom Windows a odstránili sme výpis na počítači so systémom Linux.

Napchali sme skládku do WireShark a... zosmutneli (niektoré podrobnosti o skládke vynechám, nie sú zaujímavé).

Čo nám skládka ukázala:

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Adresy 0000-0030, súdiac podľa Wireshark, sú servisné informácie USB.

Zaujal nás diel 0040-0070.

Z jedného prenosového rámca nebolo jasné nič okrem znakov MOCFT. Ukázalo sa, že tieto znaky sú znaky zo súboru firmvéru, ako aj zostávajúce znaky do konca rámca (súbor firmvéru je zvýraznený):

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Čo znamenali symboly fd 3e 02 01 fe, som osobne, rovnako ako Ilya, netušil.

Pozrel som sa na nasledujúci rámec (tu boli odstránené servisné informácie, zvýraznený súbor firmvéru):

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Čo sa vyjasnilo? Že prvé dva bajty sú nejaké konštanty. Všetky nasledujúce bloky to potvrdili, ale pred koncom bloku prenosu:

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Tento rám bol tiež ohromujúci, pretože konštanta sa zmenila (zvýraznila) a napodiv tam bola časť súboru. Veľkosť prenesených bajtov súboru ukázala, že bolo prenesených 1024 bajtov. Opäť som nevedel, čo znamenajú zvyšné bajty.

V prvom rade som si ako stará prezývka BBS prezrel štandardné prenosové protokoly. Žiadny protokol nepreniesol 1024 bajtov. Začal som študovať hardvér a narazil som na protokol 1K Xmodem. Umožnil prenos 1024, ale s upozornením: najprv iba 128 a iba ak neboli žiadne chyby, protokol zvýšil počet prenášaných bajtov. Okamžite som mal prevod 1024 bajtov. Rozhodol som sa študovať prenosové protokoly a konkrétne X-modem.

Existovali dve varianty modemu.

Po prvé, formát balíka XMODEM s podporou CRC8 (pôvodný XMODEM):

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Po druhé, formát paketov XMODEM s podporou CRC16 (XmodemCRC):

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Vyzerá podobne, až na SOH, číslo balenia a CRC a dĺžku balenia.

Pozrel som sa na začiatok druhého bloku prenosu (a znova som videl súbor firmvéru, ale už odsadený o 1024 bajtov):

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Videl som známu hlavičku fd 3e 02, ale ďalšie dva bajty sa už zmenili: bolo to 01 fe a stalo sa 02 fd. Potom som si všimol, že druhý blok bol teraz očíslovaný 02, a tak som pochopil: predo mnou bolo číslovanie bloku prenosu. Prvý prevodový stupeň 1024 je 01, druhý je 02, tretí je 03 a tak ďalej (ale samozrejme v hex). Čo však znamená zmena z fe na fd? Oči videli pokles o 1, mozog si pripomenul, že programátori počítajú od 0, nie od 1. Ale prečo je potom prvý blok 1 a nie 0? Stále som nenašiel odpoveď na túto otázku. Ale pochopil som, ako sa počíta druhý blok. Druhý blok nie je nič iné ako FF – (mínus) číslo prvého bloku. Druhý blok bol teda označený ako = 02 (FF-02) = 02 FD. Následné čítanie výpisu potvrdilo môj odhad.

Potom sa začal objavovať nasledujúci obrázok prenosu:

Začiatok prenosu
fd 3e 02 – Štart
01 FE – počítadlo prenosov
Prenos (34 blokov, 1024 prenesených bajtov)
fd 3e 1024 bajtov dát (rozdelených do 30 bajtových blokov).
Koniec prenosu
fd 25

Zostávajúce údaje na zarovnanie na 1024 bajtov.

Ako vyzerá koncový rámec blokového prenosu:

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

fd 25 – signál na ukončenie prenosu bloku. Ďalej 2f 52 – zvyšok súboru do veľkosti 1024 bajtov. 2f 52, súdiac podľa protokolu, je 16-bitový kontrolný súčet CRC.

Kvôli starým časom som vytvoril program v C, ktorý vytiahol 1024 bajtov zo súboru a vypočítal 16-bitový CRC. Spustenie programu ukázalo, že nejde o 16-bitový CRC. Opäť stupor - asi tri dni. Celý ten čas som sa snažil pochopiť, čo to môže byť, ak nie kontrolný súčet. Pri štúdiu stránok v anglickom jazyku som zistil, že X-modem používa vlastný výpočet kontrolného súčtu – CRC-CCITT (XModem). Nenašiel som žiadne C implementácie tohto výpočtu, ale našiel som web, ktorý vypočítal tento kontrolný súčet online. Po prenesení 1024 bajtov môjho súboru na webovú stránku mi stránka ukázala kontrolný súčet, ktorý sa úplne zhodoval s kontrolným súčtom zo súboru.

Hurá! Posledná hádanka bola vyriešená, teraz som potreboval urobiť vlastný firmvér. Ďalej som svoje vedomosti (a zostali len v mojej hlave) odovzdal Iljovi, ktorý pozná mocnú sadu nástrojov Python.

Vytvorenie programu

Informuje o tom Ilya Aleshin.

Keď som dostal príslušné pokyny, bol som veľmi „šťastný“.

kde začať? Presne tak, od začiatku.  Z vyberania výpisu z portu USB.

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

Vyberieme port, ku ktorému je zariadenie pripojené a súbor, do ktorého budeme ukladať výpis.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Skener pripojíme k stroju, kde je nainštalovaný natívny softvér EZConfigScanning pre Windows.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

V ňom nájdeme položku na odosielanie príkazov do zariadenia. Ale čo tímy? Kde ich môžem získať?
Keď sa program spustí, zariadenie sa automaticky vyvolá (uvidíme o niečo neskôr). A boli tam cvičné čiarové kódy z oficiálnych dokumentov o výstroji. DEFALT. Toto je náš tím.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Boli prijaté potrebné údaje. Otvorte dump.pcap cez wireshark.

Blokovať pri spustení EZConfigScanning. Miesta, ktorým je potrebné venovať pozornosť, sú označené červenou farbou.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Keď som to všetko videl prvýkrát, stratil som srdce. Nie je jasné, kam ďalej kopať.

Trochu brainstormingu a-a-a... Aha! Na smetisku von - Je inA in это von.

Vygooglil som, čo je URB_INTERRUPT. Zistil som, že ide o spôsob prenosu údajov. A existujú 4 také metódy: kontrola, prerušenie, izochrónna, hromadná. Môžete si o nich prečítať samostatne.

A adresy koncových bodov v rozhraní USB zariadenia je možné získať buď pomocou príkazu „lsusb –v“ alebo pomocou pyusb.

Teraz musíme nájsť všetky zariadenia s týmto VID. Môžete vyhľadávať konkrétne podľa VID:PID.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Vyzerá to takto:

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Takže máme potrebné informácie: príkazy P_INFO. alebo DEFALT, adresy, kde sa majú zapisovať príkazy endpoint=03 a kde získať odpoveď endpoint=86. Zostáva len previesť príkazy na hex.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Keďže sme už zariadenie našli, odpojme ho od jadra...

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

...a napíšte do koncového bodu s adresou 0x03,

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

... a potom si prečítajte odpoveď z koncového bodu s adresou 0x86.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Štruktúrovaná odpoveď:

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

Tieto údaje vidíme v dump.pcap.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Skvelé! Prevod systémových čiarových kódov na hex. To je všetko, funkcia tréningu je pripravená.

A čo firmware? Zdá sa, že všetko je rovnaké, ale existuje nuansa.

Po kompletnom výpise procesu blikania sme zhruba pochopili, s čím máme do činenia. Tu je článok o XMODEM, ktorý veľmi pomohol pochopiť, ako táto komunikácia prebieha, aj keď vo všeobecnosti: http://microsin.net/adminstuff/others/xmodem-protocol-overview.html Odporúčam prečítať.

Pri pohľade na výpis môžete vidieť, že veľkosť rámca je 1024 a veľkosť údajov URB je 64.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Preto - 1024/64 – dostaneme 16 riadkov v bloku, prečítame súbor firmvéru po 1 znaku a vytvoríme blok. Doplnenie 1 riadku v bloku špeciálnymi znakmi fd3e02 + číslo bloku.
Ďalších 14 riadkov je doplnených o fd25 +, pomocou XMODEM.calc_crc() vypočítame kontrolný súčet celého bloku (trvalo dlho, kým sme pochopili, že „FF – 1“ je CSUM) a doplní sa posledný, 16. riadok s fd3e.

Zdalo by sa, že je to tak, prečítajte si súbor firmvéru, stlačte bloky, odpojte skener od jadra a pošlite ho do zariadenia. Ale také jednoduché to nie je. Skener je potrebné prepnúť do režimu firmvéru,
отправив ему NEWAPP = ‘\xfd\x0a\x16\x4e\x2c\x4e\x45\x57\x41\x50\x50\x0d’.
Odkiaľ je tento tím?? Zo smetiska.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Ale nemôžeme poslať celý blok do skenera kvôli limitu 64:

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Skener v režime blikania NEWAPP neakceptuje hex. Preto budete musieť preložiť každý riadok 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]

A potom odošlite tieto údaje do skenera.

Dostávame odpoveď:

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

Ak skontrolujete článok o XMODEM, bude jasné: údaje boli prijaté.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

Po prenose všetkých blokov dokončíme prenos END_TRANSFER = 'xfdx01x04'.

Keďže tieto bloky nenesú žiadne informácie pre bežných ľudí, predvolene nainštalujeme firmvér v skrytom režime. A pre každý prípad zorganizujeme indikátor priebehu prostredníctvom tqdm.

Úloha pre vývojára, alebo ako sme flashovali ručné skenery bez predajcu

V skutočnosti ide potom o maličkosti. Ostáva už len zabaliť riešenie do skriptov na hromadnú replikáciu v jasne definovanom čase, aby sa nespomalil proces práce na pokladniach a pridať logovanie.

Celkový

Keďže sme strávili veľa času a úsilia a vlasov na hlave, boli sme schopní vyvinúť riešenia, ktoré sme potrebovali, a tiež sme dodržali termín. Zároveň sú skenery teraz centrálne preflashované a preškolené, celý proces jasne kontrolujeme. Spoločnosť ušetrila čas a peniaze a získali sme neoceniteľné skúsenosti so zariadeniami reverzného inžinierstva tohto typu.

Zdroj: hab.com