Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Hallo.

Wir, Viktor Antipov und Ilya Aleshin, werden heute über unsere Erfahrungen bei der Arbeit mit USB-Geräten über Python PyUSB und ein wenig über Reverse Engineering sprechen.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Vorgeschichte

Im Jahr 2019 wurde das Dekret der Regierung der Russischen Föderation Nr. 224 „Über die Genehmigung der Regeln für die Kennzeichnung von Tabakerzeugnissen mit Identifizierungsmitteln und Merkmale der Umsetzung eines staatlichen Informationssystems zur Überwachung des Umlaufs von Waren, die einer obligatorischen Kennzeichnung mit Identifizierungsmitteln unterliegen“, erlassen in Bezug auf Tabakerzeugnisse“ in Kraft getreten.
In dem Dokument wird erläutert, dass Hersteller ab dem 1. Juli 2019 verpflichtet sind, jede Tabakpackung zu kennzeichnen. Und Direktvertriebshändler müssen diese Produkte mit der Ausstellung eines Universal Transfer Documents (UDD) erhalten. Geschäfte wiederum müssen den Verkauf gekennzeichneter Produkte über die Kasse registrieren.

Außerdem ist ab dem 1. Juli 2020 der Verkehr von nicht gekennzeichneten Tabakprodukten verboten. Das bedeutet, dass alle Zigarettenpackungen mit einem speziellen Datamatrix-Barcode gekennzeichnet sein müssen. Darüber hinaus – ein wichtiger Punkt – stellte sich heraus, dass die Datamatrix nicht gewöhnlich, sondern invers sein wird. Das heißt, nicht schwarzer Code auf weißem, sondern umgekehrt.

Wir haben unsere Scanner getestet und es stellte sich heraus, dass die meisten von ihnen neu geflasht/neu trainiert werden müssen, da sie sonst einfach nicht in der Lage sind, mit diesem Barcode normal zu arbeiten. Diese Wendung bereitete uns große Kopfschmerzen, da unser Unternehmen viele Geschäfte hat, die über ein riesiges Gebiet verstreut sind. Mehrere Zehntausend Kassen – und sehr wenig Zeit.

Was war zu tun? Es gibt zwei Möglichkeiten. Erstens: Die Ingenieure vor Ort flashen die Scanner manuell neu und justieren sie. Zweitens: Wir arbeiten remote und decken vorzugsweise viele Scanner gleichzeitig in einer Iteration ab.

Die erste Option war für uns offensichtlich nicht geeignet: Wir müssten Geld für den Besuch von Ingenieuren ausgeben, und in diesem Fall wäre es schwierig, den Prozess zu kontrollieren und zu koordinieren. Aber das Wichtigste ist, dass die Leute arbeiten würden, das heißt, wir würden möglicherweise viele Fehler machen und höchstwahrscheinlich die Frist nicht einhalten.

Die zweite Option ist für alle gut, wenn nicht für eine Sache. Einige Anbieter verfügten nicht über die Remote-Flashing-Tools, die wir für alle erforderlichen Betriebssysteme benötigten. Und da die Fristen abliefen, musste ich mit meinem eigenen Kopf nachdenken.

Als nächstes erzählen wir Ihnen, wie wir Tools für Handscanner für das Betriebssystem Debian 9.x entwickelt haben (alle unsere Registrierkassen laufen auf Debian).

Lösen Sie das Rätsel: So flashen Sie einen Scanner

Victor Antipov berichtet.

Das vom Hersteller bereitgestellte offizielle Dienstprogramm funktioniert unter Windows und nur mit IE. Das Dienstprogramm kann den Scanner flashen und konfigurieren.

Da unser Zielsystem Debian ist, haben wir einen USB-Redirector-Server unter Debian und einen USB-Redirector-Client unter Windows installiert. Mithilfe der USB-Redirector-Dienstprogramme haben wir den Scanner von einem Linux-Rechner auf einen Windows-Rechner weitergeleitet.

Ein Dienstprogramm eines Windows-Anbieters hat den Scanner erkannt und ihn sogar normal geflasht. Somit haben wir die erste Schlussfolgerung gezogen: Nichts hängt vom Betriebssystem ab, es ist eine Frage des Flash-Protokolls.

OK. Wir haben das Flashen auf dem Windows-Rechner ausgeführt und den Dump auf dem Linux-Rechner entfernt.

Wir haben den Dump in WireShark gestopft und ... wurden traurig (ich werde einige Details des Dumps weglassen, sie sind nicht von Interesse).

Was uns die Mülldeponie zeigte:

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Bei den Adressen 0000-0030 handelt es sich laut Wireshark um USB-Dienstinformationen.

Uns interessierte Teil 0040-0070.

Außer den MOCFT-Zeichen war aus einem Übertragungsrahmen nichts klar. Es stellte sich heraus, dass es sich bei diesen Zeichen um Zeichen aus der Firmware-Datei handelte, ebenso wie bei den restlichen Zeichen bis zum Ende des Frames (die Firmware-Datei ist hervorgehoben):

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Was die Symbole fd 3e 02 01 fe bedeuteten, hatte ich persönlich, wie auch Ilya, keine Ahnung.

Ich habe mir den folgenden Rahmen angesehen (Serviceinformationen wurden hier entfernt, die Firmware-Datei wurde hervorgehoben):

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Was wurde klar? Dass die ersten beiden Bytes eine Art Konstante sind. Alle nachfolgenden Blöcke bestätigten dies, jedoch vor dem Ende des Übertragungsblocks:

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Dieser Frame war ebenfalls verblüffend, da sich die Konstante geändert (hervorgehoben) hatte und seltsamerweise ein Teil der Datei vorhanden war. Die Größe der übertragenen Bytes der Datei ergab, dass 1024 Bytes übertragen wurden. Ich wusste wieder nicht, was die verbleibenden Bytes bedeuteten.

Als alter BBS-Spitzname habe ich zunächst die Standardübertragungsprotokolle überprüft. Kein Protokoll hat 1024 Byte übertragen. Ich begann, die Hardware zu studieren und stieß auf das 1K-Xmodem-Protokoll. Es erlaubte die Übertragung von 1024, allerdings mit einer Einschränkung: Zunächst nur 128, und nur wenn keine Fehler auftraten, erhöhte das Protokoll die Anzahl der übertragenen Bytes. Ich hatte sofort eine Übertragung von 1024 Bytes. Ich beschloss, Übertragungsprotokolle und insbesondere das X-Modem zu studieren.

Es gab zwei Varianten des Modems.

Zunächst das XMODEM-Paketformat mit CRC8-Unterstützung (das ursprüngliche XMODEM):

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Zweitens das XMODEM-Paketformat mit CRC16-Unterstützung (XmodemCRC):

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Es sieht ähnlich aus, bis auf SOH, Paketnummer und CRC sowie Paketlänge.

Ich habe mir den Anfang des zweiten Übertragungsblocks angeschaut (und wieder die Firmware-Datei gesehen, allerdings bereits um 1024 Bytes eingerückt):

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Ich sah den bekannten Header fd 3e 02, aber die nächsten beiden Bytes hatten sich bereits geändert: Es war 01 fe und wurde zu 02 fd. Dann bemerkte ich, dass der zweite Block nun die Nummer 02 hatte und verstand somit: Vor mir lag die Nummerierung des Übertragungsblocks. Der erste 1024-Gang ist 01, der zweite ist 02, der dritte ist 03 und so weiter (aber natürlich im Hexadezimalformat). Aber was bedeutet der Wechsel von fe zu fd? Die Augen sahen einen Rückgang um 1, das Gehirn erinnerte daran, dass Programmierer bei 0 und nicht bei 1 zählen. Aber warum ist dann der erste Block 1 und nicht 0? Ich habe immer noch keine Antwort auf diese Frage gefunden. Aber ich habe verstanden, wie der zweite Block gezählt wird. Der zweite Block ist nichts anderes als FF – (minus) die Nummer des ersten Blocks. Daher wurde der zweite Block als = 02 (FF-02) = 02 FD bezeichnet. Die anschließende Lektüre der Müllkippe bestätigte meine Vermutung.

Dann zeichnete sich folgendes Bild der Übertragung ab:

Beginn der Übertragung
fd 3e 02 – Start
01 FE – Übertragungszähler
Übertragung (34 Blöcke, 1024 Bytes übertragen)
fd 3e 1024 Byte Daten (aufgeteilt in 30-Byte-Blöcke).
Ende der Übertragung
FD25

Die verbleibenden Daten müssen auf 1024 Byte ausgerichtet werden.

Wie sieht der Endrahmen der Blockübertragung aus:

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

fd 25 – Signal zum Beenden der Blockübertragung. Next 2f 52 – der Rest der Datei ist bis zu 1024 Byte groß. 2f 52 ist, dem Protokoll nach zu urteilen, eine 16-Bit-CRC-Prüfsumme.

Der alten Zeit halber habe ich ein Programm in C erstellt, das 1024 Bytes aus einer Datei zog und einen 16-Bit-CRC berechnete. Beim Starten des Programms zeigte sich, dass es sich nicht um einen 16-Bit-CRC handelt. Wieder Stupor – etwa drei Tage lang. Die ganze Zeit über habe ich versucht zu verstehen, was es sein könnte, wenn nicht eine Prüfsumme. Beim Studium englischsprachiger Seiten habe ich herausgefunden, dass das X-Modem eine eigene Prüfsummenberechnung verwendet – CRC-CCITT (XModem). Ich habe keine C-Implementierungen dieser Berechnung gefunden, aber ich habe eine Website gefunden, die diese Prüfsumme online berechnet. Nachdem ich 1024 Bytes meiner Datei auf die Webseite übertragen hatte, zeigte mir die Site eine Prüfsumme an, die vollständig mit der Prüfsumme aus der Datei übereinstimmte.

Hurra! Das letzte Rätsel war gelöst, jetzt musste ich meine eigene Firmware erstellen. Als nächstes habe ich mein Wissen (und es blieb nur in meinem Kopf) an Ilya weitergegeben, der mit dem leistungsstarken Toolkit Python vertraut ist.

Erstellen eines Programms

Ilja Aljoschin berichtet.

Nachdem ich die entsprechenden Anweisungen erhalten hatte, war ich sehr „glücklich“.

Wo soll ich anfangen? Das stimmt, von Anfang an.  Vom Erstellen eines Dumps vom USB-Anschluss.

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

Wählen Sie den Port aus, an den das Gerät angeschlossen ist, und die Datei, in der der Dump gespeichert werden soll.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Wir verbinden den Scanner mit einem Computer, auf dem die native EZConfigScanning-Software für Windows installiert ist.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Darin finden wir den Punkt zum Senden von Befehlen an das Gerät. Aber was ist mit Teams? Wo kann ich sie bekommen?
Wenn das Programm startet, wird das Gerät automatisch abgefragt (wir werden dies etwas später sehen). Und es gab Trainingsbarcodes aus offiziellen Ausrüstungsdokumenten. STANDARD. Das ist unser Team.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Die notwendigen Daten sind eingegangen. Öffnen Sie dump.pcap über Wireshark.

Blockierung beim Starten von EZConfigScanning. Orte, auf die Sie achten müssen, sind rot markiert.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Als ich das alles zum ersten Mal sah, verlor ich den Mut. Es ist nicht klar, wo als nächstes gegraben werden soll.

Ein bisschen Brainstorming und-und-und... Aha! Auf der Müllkippe - Das inUnd in es .

Ich habe gegoogelt, was URB_INTERRUPT ist. Ich habe herausgefunden, dass dies eine Datenübertragungsmethode ist. Und es gibt 4 solcher Methoden: Kontrolle, Unterbrechung, Isochronität, Masse. Sie können sie separat lesen.

Und die Endpunktadressen in der USB-Geräteschnittstelle können entweder über den Befehl „lsusb –v“ oder mit pyusb abgerufen werden.

Jetzt müssen wir alle Geräte mit dieser VID finden. Sie können gezielt nach VID:PID suchen.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Es sieht so aus:

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Wir haben also die notwendigen Informationen: die P_INFO-Befehle. oder DEFALT, Adressen, wo Befehle geschrieben werden sollen, Endpunkt=03 und wo die Antwort abgerufen wird, Endpunkt=86. Es bleibt nur noch, die Befehle in Hex umzuwandeln.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Da wir das Gerät bereits gefunden haben, trennen wir es vom Kernel ...

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

...und zum Endpunkt mit der Adresse 0x03 schreiben,

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

... und dann die Antwort vom Endpunkt mit der Adresse 0x86 lesen.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Strukturierte Antwort:

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

Wir sehen diese Daten in dump.pcap.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Großartig! Konvertieren Sie Systembarcodes in Hex. Das war's, die Trainingsfunktionalität ist fertig.

Was ist mit der Firmware? Alles scheint gleich zu sein, aber es gibt eine Nuance.

Nachdem wir den Flash-Vorgang vollständig durchgesehen hatten, verstanden wir ungefähr, womit wir es zu tun hatten. Hier ist ein Artikel über XMODEM, der sehr hilfreich war, um zu verstehen, wie diese Kommunikation abläuft, wenn auch allgemein: http://microsin.net/adminstuff/others/xmodem-protocol-overview.html Ich empfehle es zu lesen.

Wenn Sie sich den Dump ansehen, können Sie sehen, dass die Framegröße 1024 und die URB-Datengröße 64 beträgt.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Daher – 1024/64 – Wir erhalten 16 Zeilen in einem Block, lesen die Firmware-Datei zeichenweise ein und bilden einen Block. Ergänzung einer Zeile in einem Block mit den Sonderzeichen fd1e1 + Blocknummer.
Die nächsten 14 Zeilen werden mit fd25 + ergänzt, mit XMODEM.calc_crc() berechnen wir die Prüfsumme des gesamten Blocks (es hat lange gedauert, um zu verstehen, dass „FF – 1“ CSUM ist) und die letzte, 16. Zeile wird ergänzt mit fd3e.

Es scheint, als wäre das alles: Lesen Sie die Firmware-Datei, klicken Sie auf die Blöcke, trennen Sie den Scanner vom Kernel und senden Sie ihn an das Gerät. Aber so einfach ist es nicht. Der Scanner muss in den Firmware-Modus geschaltet werden,
отправив ему NEWAPP = ‘\xfd\x0a\x16\x4e\x2c\x4e\x45\x57\x41\x50\x50\x0d’.
Woher kommt dieses Team?? Von der Müllkippe.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Aufgrund der Beschränkung auf 64 können wir jedoch keinen ganzen Block an den Scanner senden:

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Nun, der Scanner im NEWAPP-Blinkmodus akzeptiert kein Hex. Daher müssen Sie jede Zeile bytes_array übersetzen

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

Und dann senden Sie diese Daten an den Scanner.

Wir bekommen die Antwort:

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

Wenn Sie den Artikel über XMODEM lesen, wird klar: Die Daten wurden akzeptiert.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Nachdem alle Blöcke übertragen wurden, schließen wir die Übertragung ab END_TRANSFER = 'xfdx01x04'.

Da diese Blöcke für normale Menschen keine Informationen enthalten, installieren wir die Firmware standardmäßig im versteckten Modus. Und für alle Fälle organisieren wir über tqdm einen Fortschrittsbalken.

Eine Aufgabe für einen Entwickler oder wie wir Handscanner ohne Anbieter geflasht haben

Eigentlich geht es dann um Kleinigkeiten. Es bleibt nur noch, die Lösung in Skripte für die Massenreplikation zu einem klar definierten Zeitpunkt zu packen, um den Arbeitsprozess an den Kassen nicht zu verlangsamen, und eine Protokollierung hinzuzufügen.

Ergebnis

Mit viel Zeit, Mühe und Haaren auf dem Kopf konnten wir die Lösungen entwickeln, die wir brauchten, und auch den Termin einhalten. Gleichzeitig werden die Scanner nun zentral neu geflasht und neu trainiert, wir haben den gesamten Prozess klar im Griff. Das Unternehmen sparte Zeit und Geld und wir sammelten unschätzbare Erfahrungen beim Reverse Engineering von Geräten dieser Art.

Source: habr.com

Kommentar hinzufügen