Hallo almal.
Ons, Viktor Antipov en Ilya Aleshin, sal vandag praat oor ons ervaring om met USB-toestelle via Python PyUSB te werk en 'n bietjie oor reverse engineering.
voorgeskiedenis
In 2019, Besluit van die regering van die Russiese Federasie No. 224 "By goedkeuring van die reëls vir die etikettering van tabakprodukte met identifikasiemiddele en kenmerke van die implementering van 'n staatsinligtingstelsel vir die monitering van die sirkulasie van goedere onderhewig aan verpligte etikettering met identifikasiemiddele met betrekking tot tabakprodukte” in werking getree het.
Die dokument verduidelik dat vervaardigers vanaf 1 Julie 2019 verplig word om elke pak tabak te etiketteer. En direkte verspreiders moet hierdie produkte ontvang met die uitvoering van 'n universele oordragdokument (UDD). Winkels moet op hul beurt die verkoop van gemerkte produkte deur die kasregister registreer.
Ook vanaf 1 Julie 2020 is die sirkulasie van ongemerkte tabakprodukte verbied. Dit beteken dat alle sigaretpakkies met 'n spesiale Datamatrix strepieskode gemerk moet word. Boonop - 'n belangrike punt - dit het geblyk dat die Datamatrix nie gewoon sal wees nie, maar omgekeerd. Dit wil sê, nie swart kode op wit nie, maar andersom.
Ons het ons skandeerders getoets, en dit het geblyk dat die meeste van hulle herflits/heropgelei moet word, anders kan hulle eenvoudig nie normaalweg met hierdie strepieskode werk nie. Hierdie wending het ons 'n erge hoofpyn gewaarborg, want ons maatskappy het baie winkels wat oor 'n uitgestrekte gebied versprei is. Etlike tienduisende kasregisters – en baie min tyd.
Wat moes gedoen word? Daar is twee opsies. Eerstens: ingenieurs op die terrein herlaai handmatig en pas die skandeerders aan. Tweedens: ons werk op afstand en dek verkieslik baie skandeerders gelyktydig in een iterasie.
Die eerste opsie was natuurlik nie vir ons geskik nie: ons sou geld op besoekende ingenieurs moes spandeer, en in hierdie geval sou dit moeilik wees om die proses te beheer en te koördineer. Maar die belangrikste ding is dat mense sal werk, dit wil sê, ons sal moontlik baie foute kry en heel waarskynlik nie die sperdatum haal nie.
Die tweede opsie is goed vir almal, indien nie vir een ding nie. Sommige verskaffers het nie die afgeleë flitsgereedskap gehad wat ons nodig gehad het vir al die vereiste bedryfstelsels nie. En aangesien die spertye besig was om uit te loop, moes ek met my eie kop dink.
Vervolgens sal ons jou vertel hoe ons gereedskap vir handskandeerders vir die Debian 9.x OS ontwikkel het (al ons kasregisters is op Debian).
Los die raaisel op: hoe om 'n skandeerder te flits
Victor Antipov berig.
Die amptelike hulpprogram wat deur die verkoper verskaf word, werk onder Windows, en slegs met IE. Die hulpprogram kan flits en die skandeerder konfigureer.
Aangesien ons teikenstelsel Debian is, het ons 'n usb-herleidingsbediener op Debian en 'n usb-herleidingskliënt op Windows geïnstalleer. Met behulp van usb-herleidingsprogramme het ons die skandeerder van 'n Linux-masjien na 'n Windows-masjien aangestuur.
'n Nut van 'n Windows-verskaffer het die skandeerder gesien en dit selfs normaal geflits. Ons het dus die eerste gevolgtrekking gemaak: niks hang van die bedryfstelsel af nie, dit is 'n kwessie van die flikkerprotokol.
OK. Ons het die flits op die Windows-masjien uitgevoer en die stortingsterrein op die Linux-masjien verwyder.
Ons het die stortplek in WireShark gestop en ... hartseer geraak (ek sal van die besonderhede van die storting weglaat, dit is nie van belang nie).
Wat die storting vir ons gewys het:
Adresse 0000-0030, te oordeel aan Wireshark, is USB-diensinligting.
Ons was geïnteresseerd in deel 0040-0070.
Niks was duidelik uit een transmissieraam nie, behalwe vir die MOCFT-karakters. Hierdie karakters blyk karakters uit die firmwarelêer te wees, sowel as die oorblywende karakters tot aan die einde van die raam (die firmwarelêer is uitgelig):
Wat die simbole fd 3e 02 01 fe beteken het, het ek persoonlik, soos Ilya, geen benul gehad nie.
Ek het na die volgende raam gekyk (diensinligting is hier verwyder, die firmwarelêer is uitgelig):
Wat het duidelik geword? Dat die eerste twee grepe 'n soort konstante is. Alle daaropvolgende blokke het dit bevestig, maar voor die einde van die transmissieblok:
Hierdie raam was ook verstommend, aangesien die konstante verander het (uitgelig) en, vreemd genoeg, was daar 'n deel van die lêer. Die grootte van die oorgeplaaste grepe van die lêer het getoon dat 1024 grepe oorgedra is. Ek het weer nie geweet wat die oorblywende grepe beteken nie.
Eerstens, as 'n ou BBS-bynaam, het ek die standaard transmissieprotokolle hersien. Geen protokol versend 1024 grepe. Ek het die hardeware begin bestudeer en op die 1K Xmodem-protokol afgekom. Dit het die oordrag van 1024 toegelaat, maar met 'n voorbehoud: eers net 128, en slegs as daar geen foute was nie, het die protokol die aantal grepe wat versend is, verhoog. Ek het dadelik 'n oordrag van 1024 grepe gehad. Ek het besluit om transmissieprotokolle te bestudeer, en spesifiek die X-modem.
Daar was twee variasies van die modem.
Eerstens, die XMODEM-pakketformaat met CRC8-ondersteuning (die oorspronklike XMODEM):
Tweedens, die XMODEM-pakketformaat met CRC16-ondersteuning (XmodemCRC):
Dit lyk soortgelyk, behalwe vir SOH, pakketnommer en CRC en pakketlengte.
Ek het na die begin van die tweede transmissieblok gekyk (en weer die firmware-lêer gesien, maar reeds met 1024 grepe ingekeep):
Ek het die bekende kopskrif fd 3e 02 gesien, maar die volgende twee grepe het reeds verander: dit was 01 fe, en het 02 fd geword. Toe merk ek op dat die tweede blokkie nou 02 genommer is en so verstaan: voor my was die nommering van die transmissieblok. Die eerste 1024-rat is 01, die tweede is 02, die derde is 03 en so aan (maar natuurlik in heks). Maar wat beteken die verandering van fe na fd? Die oë het 'n afname met 1 gesien, die brein het daaraan herinner dat programmeerders vanaf 0 tel, nie 1 nie. Maar hoekom is die eerste blok dan 1, en nie 0 nie? Ek het steeds nie die antwoord op hierdie vraag gekry nie. Maar ek het verstaan hoe die tweede blok getel word. Die tweede blokkie is niks meer as FF nie – (minus) die nommer van die eerste blokkie. Dus, die tweede blok is aangewys as = 02 (FF-02) = 02 FD. Die daaropvolgende lees van die stortingsterrein het my raaiskoot bevestig.
Toe begin die volgende prentjie van die oordrag na vore kom:
Begin van oordrag
fd 3e 02 – Begin
01 FE – transmissieteller
Oordrag (34 blokke, 1024 grepe oorgedra)
fd 3e 1024 grepe data (verdeel in 30 grepe blokke).
Einde van oordrag
fd 25
Oorblywende data moet in lyn gebring word met 1024 grepe.
Hoe lyk die bloktransmissie-eindraamwerk:
fd 25 – sein om blok transmissie te beëindig. Volgende 2f 52 – die res van die lêer tot 1024 grepe groot. 2f 52, te oordeel aan die protokol, is 'n 16-bis CRC kontrolesom.
Ter wille van ou tye het ek 'n program in C gemaak wat 1024 grepe uit 'n lêer getrek het en 'n 16-bis CRC bereken het. Die bekendstelling van die program het getoon dat dit nie 'n 16-bis CRC is nie. Weereens stupor - vir ongeveer drie dae. Al hierdie tyd het ek probeer verstaan wat dit kan wees, indien nie 'n kontrolesom nie. Terwyl ek Engelstalige webwerwe bestudeer het, het ek ontdek dat die X-modem sy eie kontrolesom-berekening gebruik - CRC-CCITT (XModem). Ek het geen C-implementerings van hierdie berekening gevind nie, maar ek het 'n webwerf gevind wat hierdie kontrolesom aanlyn bereken het. Nadat ek 1024 grepe van my lêer na die webblad oorgedra het, het die webwerf vir my 'n kontrolesom gewys wat heeltemal ooreenstem met die kontrolesom van die lêer.
Hoera! Die laaste raaisel is opgelos, nou moes ek my eie firmware maak. Vervolgens het ek my kennis oorgedra (en dit het net in my kop gebly) aan Ilya, wat vertroud is met die kragtige gereedskapstel Python.
Die skep van 'n program
Ilya Aleshin berig.
Nadat ek die toepaslike instruksies ontvang het, was ek baie "gelukkig".
Waar om te begin? Dis reg, van die begin af. Van die neem van 'n storting vanaf die USB-poort.
Begin USB-pcap
Kies die poort waaraan die toestel gekoppel is en die lêer waar ons die storting sal stoor.
Ons koppel die skandeerder aan 'n masjien waar die inheemse EZConfigScanning-sagteware vir Windows geïnstalleer is.
Daarin vind ons die item om opdragte na die toestel te stuur. Maar wat van spanne? Waar kan ek hulle kry?
Wanneer die program begin, word die toerusting outomaties gepols (ons sal dit 'n bietjie later sien). En daar was opleiding strepieskodes van amptelike toerusting dokumente. DEFALT. Dit is ons span.
Die nodige data is ontvang. Maak dump.pcap oop via wireshark.
Blokkeer wanneer EZConfigScanning begin word. Plekke waaraan jy moet aandag gee, is in rooi gemerk.
Toe ek dit alles vir die eerste keer sien, het ek moed verloor. Dit is nie duidelik waar om volgende te grawe nie.
'n Bietjie dinkskrum en-en-en... Aha! In die storting uit - hierdie inEn in hierdie uit.
Ek het gegoogle wat URB_INTERRUPT is. Ek het uitgevind dat dit 'n data-oordragmetode is. En daar is 4 sulke metodes: beheer, onderbreking, isochrone, grootmaat. Jy kan afsonderlik oor hulle lees.
En die eindpuntadresse in die USB-toestelkoppelvlak kan verkry word deur die "lsusb -v" opdrag of deur pyusb te gebruik.
Nou moet ons alle toestelle met hierdie VID vind. Jy kan spesifiek deur VID:PID soek.
Dit lyk so:
So, ons het die nodige inligting: die P_INFO opdragte. of DEFALT, spreek waar om opdragte eindpunt=03 te skryf en waar om die antwoordeindpunt=86 te kry. Al wat oorbly is om die opdragte om te skakel na hex.
Aangesien ons reeds die toestel gevind het, laat ons dit van die kern ontkoppel ...
...en skryf na die eindpunt met adres 0x03,
... en lees dan die antwoord vanaf die eindpunt met adres 0x86.
Gestruktureerde antwoord:
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
Ons sien hierdie data in dump.pcap.
Puik! Skakel stelsel strepieskodes om na hex. Dit is dit, die opleidingsfunksie is gereed.
Wat van die firmware? Alles blyk dieselfde te wees, maar daar is 'n nuanse.
Nadat ons 'n volledige dump van die flitsproses geneem het, het ons min of meer verstaan waarmee ons te doen het. Hier is 'n artikel oor XMODEM, wat baie nuttig was om te verstaan hoe hierdie kommunikasie plaasvind, al is dit in algemene terme:
As jy na die stortingsterrein kyk, kan jy sien dat die raamgrootte 1024 is, en die URB-datagrootte 64 is.
Daarom – 1024/64 – ons kry 16 reëls in 'n blok, lees die firmwarelêer 1 karakter op 'n slag en vorm 'n blok. Komplementering van 1 reël in 'n blok met spesiale karakters fd3e02 + bloknommer.
Die volgende 14 reëls word aangevul met fd25 +, deur gebruik te maak van XMODEM.calc_crc() bereken ons die kontrolesom van die hele blok (dit het baie tyd geneem om te verstaan dat “FF – 1” CSUM is) en die laaste, 16de reël word aangevul met fd3e.
Dit wil voorkom asof dit dit is, lees die firmware-lêer, druk die blokke, ontkoppel die skandeerder van die kern en stuur dit na die toestel. Maar dit is nie so eenvoudig nie. Die skandeerder moet na fermwaremodus oorgeskakel word,
отправив ему NEWAPP = ‘\xfd\x0a\x16\x4e\x2c\x4e\x45\x57\x41\x50\x50\x0d’.
Waar kom hierdie span vandaan?? Van die storting af.
Maar ons kan nie 'n hele blok na die skandeerder stuur nie as gevolg van die 64-limiet:
Wel, die skandeerder in NEWAPP-flitsmodus aanvaar nie hex nie. Daarom sal jy elke reël bytes_array moet vertaal
[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 stuur dan hierdie data na die skandeerder.
Ons kry die antwoord:
[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 jy die artikel oor XMODEM nagaan, sal dit duidelik word: die data is aanvaar.
Nadat alle blokke oorgedra is, voltooi ons die oordrag END_TRANSFER = 'xfdx01x04'.
Wel, aangesien hierdie blokke geen inligting vir gewone mense bevat nie, sal ons die firmware by verstek in versteekte modus installeer. En net vir ingeval, ons sal 'n vorderingsbalk deur tqdm organiseer.
Eintlik is dit dan 'n kwessie van klein dingetjies. Al wat oorbly, is om die oplossing in skrifte vir massareplikasie op 'n duidelik gedefinieerde tydstip toe te draai, om nie die proses van werk by die betaalpunte te vertraag nie, en aantekening by te voeg.
Totale
Nadat ons baie tyd en moeite en hare op ons koppe spandeer het, kon ons die oplossings ontwikkel wat ons nodig gehad het, en het ook die sperdatum gehaal. Terselfdertyd word die skandeerders nou herflits en sentraal opgelei, ons beheer duidelik die hele proses. Die maatskappy het tyd en geld gespaar, en ons het onskatbare ondervinding in omgekeerde ingenieurstoerusting van hierdie tipe opgedoen.
Bron: will.com