In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Hi everyone

Wy, Viktor Antipov en Ilya Aleshin, sille hjoed prate oer ús ûnderfining mei it wurkjen mei USB-apparaten fia Python PyUSB en in bytsje oer reverse engineering.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

prehistoarje

Yn 2019, Beslút fan 'e regearing fan' e Russyske Federaasje No. yn relaasje ta tabaksprodukten” fan krêft kaam.
It dokumint leit út dat fan 1 july 2019 fabrikanten ferplicht binne elk pakje tabak te labeljen. En direkte distributeurs moatte dizze produkten ûntfange mei de útfiering fan in universele oerdrachtdokumint (UDD). Winkels moatte op har beurt de ferkeap fan labele produkten registrearje fia de kassa.

Ek is fan 1 july 2020 ôf de sirkulaasje fan net-labelde tabaksprodukten ferbean. Dit betsjut dat alle sigarettenpakjes moatte wurde markearre mei in spesjale Datamatrix barcode. Boppedat - in wichtich punt - it die bliken dat de Datamatrix sil net gewoan wêze, mar inverse. Dat is, gjin swarte koade op wyt, mar oarsom.

Wy hawwe ús scanners hifke, en it die bliken dat de measten fan harren moatte wurde opknapt/opnijd, oars kinne se gewoan net normaal wurkje mei dizze barcode. Dizze beurt garandearre ús in swiere hoofdpijn, om't ús bedriuw in protte winkels hat dy't ferspraat binne oer in grut territoarium. Ferskate tsientûzenen kassa registers - en hiel bytsje tiid.

Wat moast der dien wurde? Der binne twa opsjes. As earste: yngenieurs op it plak manuell opnij opnij en oanpasse de scanners. Twad: wy wurkje op ôfstân en, leafst, dekke in protte scanners tagelyk yn ien iteraasje.

De earste opsje, fansels, wie net geskikt foar ús: wy soene moatte besteegje jild op besite yngenieurs, en yn dit gefal soe it dreech wêze om it proses te kontrolearjen en te koördinearjen. Mar it wichtichste is dat minsken soene wurkje, dat is, wy soene potinsjeel in protte flaters krije en, nei alle gedachten, de deadline net foldwaan.

De twadde opsje is goed foar elkenien, as net foar ien ding. Guon leveransiers hiene net de bliksemynstruminten op ôfstân dy't wy nedich wiene foar alle fereaske bestjoeringssystemen. En om't de deadlines rûnen, moast ik mei myn eigen holle tinke.

Folgjende sille wy jo fertelle hoe't wy ark ûntwikkele hawwe foar handheld scanners foar it Debian 9.x OS (al ús kassaregisters binne op Debian).

Los it riedsel op: hoe't jo in scanner flashje

Victor Antipov meldt.

It offisjele hulpprogramma levere troch de ferkeaper wurket ûnder Windows, en allinich mei IE. It hulpprogramma kin de scanner flashje en konfigurearje.

Sûnt ús doelsysteem Debian is, hawwe wy in usb-redirector-tsjinner ynstalleare op Debian en in usb-redirector-client op Windows. Mei help fan usb-omliedingsprogramma's hawwe wy de scanner trochstjoerd fan in Linux-masine nei in Windows-masine.

In hulpprogramma fan in Windows-ferkeaper seach de scanner en flitse it sels normaal. Sa makken wy de earste konklúzje: neat hinget ôf fan it OS, it is in kwestje fan it bliksemprotokol.

OK. Wy rûnen it wjerljocht op 'e Windows-masine, en fuortsmiten de dump op' e Linux-masine.

Wy stuffen de dump yn WireShark en ... waard fertrietlik (ik sil wat fan 'e details fan' e dump weilitte, se binne net fan belang).

Wat de dump ús liet sjen:

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Adressen 0000-0030, beoardielje troch Wireshark, binne USB-tsjinstynformaasje.

Wy wiene ynteressearre yn diel 0040-0070.

Neat wie dúdlik út ien oerdracht frame útsein foar de MOCFT karakters. Dizze karakters die bliken tekens te wêzen fan 'e firmware-bestân, lykas de oerbleaune tekens oant it ein fan it frame (it firmware-bestân is markearre):

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Wat de symboalen fd 3e 02 01 fe betsjutte, hie ik persoanlik, lykas Ilya, gjin idee.

Ik seach nei it folgjende frame (tsjinstynformaasje is hjir fuortsmiten, it firmwarebestân is markearre):

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Wat waard dúdlik? Dat de earste twa bytes in soarte fan konstante binne. Alle folgjende blokken befêstige dit, mar foar it ein fan it oerdrachtblok:

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Dit frame wie ek stupefying, sûnt de konstante wie feroare (markearre) en, raar genôch, wie der in part fan de triem. De grutte fan de oerdroegen bytes fan it bestân liet sjen dat 1024 bytes waarden oerdroegen. Ik wist wer net wat de oerbleaune bytes betsjutte.

As earste, as in âlde BBS-bynamme, haw ik de standert oerdrachtprotokollen besjoen. Gjin protokol oerdroegen 1024 bytes. Ik begon de hardware te studearjen en kaam it 1K Xmodem-protokol tsjin. It koe 1024 oerstjoere, mar mei in warskôging: earst mar 128, en allinich as d'r gjin flaters wiene, fergrutte it protokol it oantal ferstjoerde bytes. Ik hie fuortendaliks in oerdracht fan 1024 bytes. Ik besleat om oerdrachtprotokollen te studearjen, en spesifyk it X-modem.

D'r wiene twa farianten fan it modem.

Earst, it XMODEM-pakketformaat mei CRC8-stipe (de orizjinele XMODEM):

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Twad, it XMODEM-pakketformaat mei CRC16-stipe (XmodemCRC):

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

It liket gelyk, útsein foar SOH, pakket nûmer en CRC en pakket lingte.

Ik seach nei it begjin fan it twadde oerdrachtblok (en seach nochris it firmwarebestân, mar al ynkeard troch 1024 bytes):

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Ik seach de bekende koptekst fd 3e 02, mar de folgjende twa bytes wiene al feroare: it wie 01 fe, en waard 02 fd. Doe seach ik dat it twadde blok no nûmer 02 hie en begriep dus: foar my stie de nûmering fan it oerdrachtblok. De earste 1024 gear is 01, de twadde is 02, de tredde is 03 ensafuorthinne (mar yn hex, fansels). Mar wat betsjut de feroaring fan fe nei fd? De eagen seagen in fermindering fan 1, it brein herinnerde dat programmeurs telle fan 0, net 1. Mar wêrom is dan it earste blok 1, en net 0? Ik haw it antwurd op dizze fraach noch net fûn. Mar ik begriep hoe't it twadde blok teld wurdt. It twadde blok is neat mear as FF - (minus) it nûmer fan it earste blok. Sa waard it twadde blok oanwiisd as = 02 (FF-02) = 02 FD. It folgjende lêzen fan 'e dump befêstige myn ried.

Doe begon it folgjende byld fan 'e oerdracht te ferskinen:

Begjin fan oerdracht
fd 3e 02 - Start
01 FE - oerdracht teller
Oerdracht (34 blokken, 1024 bytes oerdroegen)
fd 3e 1024 bytes fan gegevens (ferdield yn 30 byte blokken).
Ein fan oerdracht
fd 25

De oerbleaune gegevens moatte wurde ôfstimd op 1024 bytes.

Hoe sjocht it einframe fan 'e bloktransmission der út:

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

fd 25 - sinjaal nei ein blok oerdracht. Folgjende 2f 52 - de rest fan it bestân oant 1024 bytes yn grutte. 2f 52, beoardielje troch it protokol, is in 16-bit CRC kontrôlesum.

Foar âlde tiden makke ik in programma yn C dat luts 1024 bytes út in triem en berekkene in 16-bit CRC. It starten fan it programma liet sjen dat dit gjin 16-bit CRC is. Stupor wer - foar likernôch trije dagen. Al dy tiid besocht ik te begripen wat it koe wêze, as net in kontrôlesum. Wylst ik Ingelsktalige siden studearre, ûntduts ik dat de X-modem syn eigen kontrôlesum-berekkening brûkt - CRC-CCITT (XModem). Ik fûn gjin C-ymplemintaasjes fan dizze berekkening, mar ik fûn in side dy't dizze kontrôlesum online berekkene. Nei't ik 1024 bytes fan myn bestân oerbrocht hie nei de webside, liet de side my in kontrôlesum sjen dy't folslein oerienkomt mei de kontrôlesum út it bestân.

Hoera! It lêste riedsel wie oplost, no moast ik myn eigen firmware meitsje. Dêrnei joech ik myn kennis (en it bleau allinich yn myn holle) troch oan Ilya, dy't bekend is mei de krêftige toolkit Python.

It meitsjen fan in programma

Ilya Aleshin meldt.

Neidat ik de passende ynstruksjes krige, wie ik heul "lokkich."

Wêr te begjinnen? Dat kloppet, fan it begjin ôf.  Fan it nimmen fan in dump fan 'e USB-poarte.

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

Selektearje de poarte wêrmei it apparaat is ferbûn en it bestân wêr't wy de dump sille bewarje.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Wy ferbine de scanner oan in masine wêr't de eigen EZConfigScanning-software foar Windows ynstalleare is.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Dêryn fine wy ​​it item foar it ferstjoeren fan kommando's nei it apparaat. Mar hoe sit it mei teams? Wêr kin ik se krije?
As it programma begjint, wurdt de apparatuer automatysk polled (wy sille dit in bytsje letter sjen). En der wiene training barcodes út offisjele apparatuer dokuminten. DEFALT. Dit is ús team.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

De nedige gegevens binne ûntfongen. Iepenje dump.pcap fia wireshark.

Blokkearje by it starten fan EZConfigScanning. Plakken wêrop jo oandacht moatte jaan, binne read markearre.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Doe't ik dit alles foar de earste kear seach, ferlear ik moed. It is net dúdlik wêr't te graven folgjende.

In bytsje brainstorming en-en-en... Aha! Yn 'e dump út - is inen in it út.

Ik haw googled wat URB_INTERRUPT is. Ik fûn út dat dit in metoade foar gegevensferfier is. En d'r binne 4 sokke metoaden: kontrôle, interrupt, isochronous, bulk. Jo kinne lêze oer harren apart.

En de einpuntadressen yn 'e USB-apparaatynterface kinne wurde krigen fia it kommando "lsusb -v" of mei pyusb.

No moatte wy alle apparaten fine mei dizze VID. Jo kinne spesifyk sykje troch VID: PID.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

It sjocht der sa út:

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Dat, wy hawwe de nedige ynformaasje: de P_INFO-kommando's. of DEFALT, adressen wêr't kommando's einpunt=03 skriuwe moatte en wêr't it antwurdeindpunt=86 te krijen is. Alles wat oerbliuwt is om de kommando's te konvertearjen nei hex.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Om't wy it apparaat al fûn hawwe, litte wy it losmeitsje fan 'e kernel ...

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

... en skriuw nei it einpunt mei adres 0x03,

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

... en lês dan it antwurd fan it einpunt mei adres 0x86.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Strukturearre antwurd:

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

Wy sjogge dizze gegevens yn dump.pcap.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Grut! Konvertearje systeembarcodes nei hex. Dat is it, de trainingsfunksjonaliteit is klear.

Wat oer de firmware? Alles liket itselde te wêzen, mar der is in nuânse.

Nei't wy in folsleine dump fan it flitsende proses hawwe nommen, begrepen wy rûchwei wêr't wy mei te meitsjen hiene. Hjir is in artikel oer XMODEM, dat heul nuttich wie om te begripen hoe't dizze kommunikaasje bart, hoewol yn algemiene termen: http://microsin.net/adminstuff/others/xmodem-protocol-overview.html Ik advisearje it te lêzen.

As jo ​​​​nei de dump sjogge, kinne jo sjen dat de framegrutte 1024 is, en de URB-gegevensgrutte is 64.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Dêrom - 1024/64 - wy krije 16 rigels yn in blok, lês de firmware triem 1 karakter tagelyk en foarmje in blok. Oanfolling fan 1 rigel yn in blok mei spesjale tekens fd3e02 + bloknûmer.
De folgjende 14 rigels wurde oanfolle mei fd25 +, mei help fan XMODEM.calc_crc () wy berekkenje de kontrôlesum fan it hiele blok (it naam in protte tiid om te begripen dat "FF - 1" is CSUM) en de lêste, 16e rigel wurdt oanfolle mei fd3e.

It soe lykje dat it it is, lês it firmware-bestân, slach op de blokken, ferbrekke de scanner fan 'e kernel en stjoer it nei it apparaat. Mar sa ienfâldich is it net. De scanner moat wurde oerskeakele nei firmware-modus,
отправив ему NEWAPP = ‘\xfd\x0a\x16\x4e\x2c\x4e\x45\x57\x41\x50\x50\x0d’.
Wêr komt dit team wei?? Fan de dump.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Mar wy kinne net in folslein blok nei de scanner stjoere fanwegen de limyt fan 64:

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

No, de scanner yn NEWAPP-flitsende modus akseptearret gjin hex. Dêrom moatte jo elke rigel bytes_array oersette

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

En dan stjoer dizze gegevens nei de scanner.

Wy krije it antwurd:

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

As jo ​​​​it artikel oer XMODEM kontrolearje, sil it dúdlik wurde: de gegevens binne akseptearre.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Nei't alle blokken oerdroegen binne, foltôgje wy de oerdracht END_TRANSFER = 'xfdx01x04'.

No, om't dizze blokken gjin ynformaasje drage foar gewoane minsken, sille wy standert de firmware yn ferburgen modus ynstallearje. En foar it gefal, sille wy in foarútgongsbalke organisearje fia tqdm.

In taak foar in ûntwikkelder, of hoe't wy flashed hand-held scanners sûnder in ferkeaper

Eins is it dan in kwestje fan lytse dingen. Alles wat oerbliuwt is de oplossing yn skripts foar massa-replikaasje op in dúdlik definieare tiid te wikkeljen, om it proses fan wurkjen by de kassa's net te fertrage en logging ta te foegjen.

It resultaat

Nei't wy in protte tiid en muoite en hier op 'e holle hawwe bestege, koenen wy de oplossingen ûntwikkelje dy't wy nedich wiene, en ek de deadline helle. Tagelyk wurde de scanners no sintraal opknapt en opnij oplaat, wy kontrolearje it heule proses dúdlik. It bedriuw besparre tiid en jild, en wy opdien ûnskatbere wearde ûnderfining yn reverse engineering apparatuer fan dit type.

Boarne: www.habr.com

Add a comment