Industrielles Reverse Engineering

Die Geschichte des Ausleihprozesses bei der Entwicklung der Elektronik an einem guten Beispiel.



Aufzeichnung des Aufzugsprotokolls des hausgemachten Schnüfflers


Einmal musste ich ein ziemlich einfaches Gerät kopieren. Das produzierende Unternehmen hörte auf zu existieren, aber im ganzen Land bestand immer noch eine Nachfrage nach dem Ersatz defekter oder gebrauchter Geräte.


Das Gerät selbst ist die Aufzugstaste auf dem Foto links. Für Experimente gaben sie mir zwei Exemplare, von denen eines vollständig zerlegt werden konnte.


Der Gesamtarbeitsplan sah ungefähr so ​​aus:


  1. Studieren der Leiterplatte;
  2. Untersuchung der Elementbasis der Platine selbst;
  3. Skizzieren ihres Stromkreises;
  4. Versuchen Sie, die Firmware-Datei vom Mikrocontroller zu lesen.
  5. Firmware zerlegen;
  6. Extrahieren des Operationsalgorithmus;
  7. Entwicklung eines neuen Boards;
  8. Neue Firmware schreiben.

Wenn Absatz 4 fehlschlägt, wäre der weitere Plan komplizierter gewesen, aber ich hatte Glück.


Wir studieren das Experiment



Hauptmikrocontroller



Ein Teil des Stromkreises des Aufzugs, auf dem unsere Bretter rot eingekreist sind


Die Karte ist auf einem 1997er Mikrocontroller, dem AT89C2051 , montiert , der auf der Intel MCS-51- Architektur basiert. Im Jahr 2020 feiert sie ihr 40-jähriges Bestehen auf dem Markt für eingebettete Systeme.


Eine kleine Erklärung: Ein Mikrocontroller ist eine solche Mikroschaltung, die einen Computerkern und einen Satz Peripheriegeräte zur Steuerung externer Geräte enthält. In einer modernen Waschmaschine fragt der Mikrocontroller beispielsweise die Steuertasten und Sensoren ab, zeigt Informationen auf dem Bildschirm an und steuert die Pumpen, die Heizung, die Ventile und den Trommelantrieb. Für die meisten dieser Funktionen sind keine Zwischengeräte erforderlich, sondern nur ein Satz passiver elektronischer Komponenten.


Wir zerlegen die Leiterplatte

Wenn Sie in Zukunft den ursprünglichen Schaltplan der Karte skizzieren, können Sie den Zweck der Pins des Mikrocontrollers ermitteln, der zum Parsen des Firmware-Codes erforderlich ist.


Das ursprüngliche Gerät wurde von einer chinesischen Firma entwickelt, und daher ist seine Schaltung äußerst verwirrt und mit vielen unnötigen Komponenten. Beispielsweise wurde das Relais durch eine Dreifachkaskade aus Bipolartransistor, Optokoppler und Feldregler (in dieser Reihenfolge) eingeschaltet.


Ein Bekannter, der mit chinesischen Herstellern zusammenarbeitet, sagte mir, dass die Chinesen ähnliche Komplikationen bei Programmen zur Erhöhung der Entwicklungs- und Produktionskosten haben, wenn nur eine Person dies tut. Danach neige ich dazu, ihm zu glauben:



Die gleiche Stelle auf dem chinesischen Zweischichtbrett auf beiden Seiten. Drei riesige Widerstände sind an nichts angeschlossen. Ich habe sogar das Board mit einer leistungsstarken Taschenlampe beleuchtet, um sicherzugehen.


Das Schema wird kopiert, mysteriöse Orte werden in einem Multisim modelliert, wir greifen die Firmware auf.


Ich versuche die Firmware zu lesen


Ich hatte großes Glück, dass der Leseschutz nicht auf beiden Karten der Controller aktiviert war, und habe die beiden Firmware-Optionen erfolgreich mit ähnlicher Pornografie zusammengeführt:



Foto aus dem persönlichen Blog eines amerikanischen Enthusiasten


Firmware zerlegen


Im nächsten Schritt müssen wir diesen Maschinencode in etwas Lesbareres konvertieren:



Wir nehmen das bekannte IDA Pro- Tool, das bereits über unseren Controller mit allen Peripherieregistern verfügt, und öffnen die HEX-Firmware-Datei:



Verarbeitung der vom Board empfangenen Daten in Assemblersprache


Danach ist es ein ziemlich langwieriger Prozess, den Befehlssatz unseres Rechenkerns zu studieren, den Assembler-Code zu kommentieren und zu decodieren.


Interrupt-Handler selbst wurden an den Adressen der Interrupt-Vektortabelle gefunden, Einträge in den Peripherieregistern gaben Auskunft über die Konfiguration der Kommunikationsschnittstelle. Schritt für Schritt hat sich der unbenannte Assembler-Code in etwas verwandelt, das gelesen werden kann.


Extraktion des Arbeitsalgorithmus


Da ich ein neues Gerät auf einer anderen Elementbasis entwickeln musste, musste ein Algorithmus aus dem Code extrahiert werden. Einige Zeit später wurde ein solcher Pseudocode geboren:


void UartISR (void) { counter500ms = 0; //ClearFlag(isrFlags, ISR_FLAG_3); ProcessUart(recievedByte); } void ProcessUart(uint8_t recievedData) { static uint8_t uartPacketsToRxLeft, uartRecievedCmd, uartCurrPacketCRC; static uint8_t i, carryFlag; static uint16_t uartIsrPointer; static uint8_t uartBuffer1[8], uartBuffer2[6]; static uint8_t uartBuffer1Pos, uartBuffer2Pos; // 0 - // 1 - // 2 - // 3 - led state, 0x0F // 4 - // 5 - // 6 - // 7 - // 8 - buttons time static uint8_t dataRegisters[9]; // RAM:0050 uint8_t tmpVal, i; uint8_t dataToSend; if (GetFlag(UartISRFlags, UART_RECIEVED_FLAG)) { ClearFlag(UartISRFlags, UART_RECIEVED_FLAG); if (recieved9thBit) { switch (recievedData) { case 0xC1: uartPacketsToRxLeft = 8; uartRecievedCmd = 1; uartBuffer1Pos = 0; uartBuffer1[uartBuffer1Pos] = recievedData; //uartIsrPointer = 0x0037; //tmpVal_0037 = recievedData; uartCurrPacketCRC = recievedData; UartRxOn(); return; break; case 0xC2: uartPacketsToRxLeft = 3; uartRecievedCmd = 2; 

Die gleiche Verarbeitung der empfangenen Daten in C.


Wen interessiert das Übertragungsprotokoll:


Die Aufzugskontrollstation kommunizierte mit den Ruftasten über eine 24-Volt-Vollduplex-Schnittstelle. Im normalen Modus lauschten die Tastenkarten der Leitung und warteten auf ein 9-Bit-Datenpaket. Wenn die Adresse unserer Karte in diesem Paket enthalten war (sie wurde durch den DIP-Schalter auf der Karte festgelegt), wurde die Karte in den 8-Bit-Empfangsmodus geschaltet, und alle nachfolgenden Pakete wurden von den übrigen Karten in der Hardware ignoriert.

Das erste nach der Adresse war ein Paket mit einem Steuerbefehlscode. Insbesondere nahm dieses Board nur 3 Teams:
  1. Schreiben in Datenregister. Zum Beispiel die Häufigkeit und Dauer der blinkenden Taste bei einem Anruf;
  2. Einschalten der Hintergrundbeleuchtung der Taste;
  3. Fragen Sie den Status der Tasten ab (gedrückt oder nicht).


Das letzte Byte war die Prüfsumme, die ein einfaches XOR aller Bytes nach der Adresse ist.
Nach der Prüfsumme ging die Karte für ihre Adresse erneut in den Standby-Modus.

Neue Board-Entwicklung


Für die Entwicklung eines neuen Schaltplans und einer Leiterplatte habe ich keine Bilder, aber es war ungefähr so:


Die Verkabelung und Verkabelung erfolgte in Altium Designer . Die Herstellung der Leiterplatte wurde in Zelenograd „ Resonite “ bestellt.


Neue Firmware schreiben


Während unser neues Board in Produktion ist, gehen wir zu dem Objekt, in dem solche Ruftasten installiert sind, und überprüfen die Richtigkeit des zerlegten Übertragungsprotokolls mit dem auf dem Arduino montierten Sniffer:

Eine Senderschaltung, die dem Original elektrisch entspricht. Der Empfänger ist nur ein Optokoppler.


 //UART1 initialize // desired baud rate:19200 // actual baud rate:19231 (0,2%) // char size: 9 bit // parity: Disabled void uart1_init(void) { UCSR1B = 0x00; //disable while setting baud rate UCSR1A = 0x00; UCSR1C = 0x06; UBRR1L = 0x33; //set baud rate lo UBRR1H = 0x00; //set baud rate hi UCSR1B = 0x94; } #pragma interrupt_handler uart1_rx_isr:iv_USART1_RXC void uart1_rx_isr(void) { unsigned char tmp; unsigned int rcv = 0; if (UCSR1B & 0x02) { rcv = 0x100; } rcv |= UDR1; tmp = (rcv >> 4) & 0x0F; if (rcv & 0x100) { tmp |= 0xC0; } else { tmp |= 0x80; } txBuf12 = (rcv & 0x0F); txBuf11 = tmp; txState1 = 0; TX_ON(); msCounter0 = 5000; } 

Sprechen Sie über unseren Schnüffler in ICC AVR


Als nächstes musste äußerst vorsichtig vorgegangen werden, um nichts im Aufzug zu verbrennen und ein Anhalten zu verhindern.



Wir klettern in die Ruftaste. Dicke gelbe Drähte - Stromversorgungs- und Übertragungsschnittstelle der Platine. Weiß am 4-poligen Stecker - verbindet den Knopf und seine Hintergrundbeleuchtung.


Wir überprüfen, ob alles ordnungsgemäß funktioniert, beheben die Pfosten und schreiben eine neue Firmware für unser Gerät:


 //ICC-AVR application builder : 11.02.2015 12:25:51 // Target : M328p // Crystal: 16.000Mhz #include <macros.h> #include <iccioavr.h> #include <avrdef.h> #include "types.h" #include "gpio.h" #define TX_OFF() UCSR0B &= 0b11011111; #define TX_ON() UCSR0B |= 0b00100000; #define TX_STATE() (UCSR0B & 0b00100000) #define MAX_TIMEOUT 3000 //#define SNIFFER_MODE 1 //#define MASTER_MODE 1 // #pragma avr_fuse (fuses0, fuses1, fuses2, fuses3, fuses4, fuses5) #pragma avr_fuse (0xFF, 0xD1, 0xFC) #pragma avr_lockbits (0xFC) // AVR signature is always three bytes. Signature0 is always the Atmel // manufacturer code of 0x1E. The other two bytes are device dependent. #pragma avr_signature (0x1E, 0x95, 0x0F) // atmega32 static GPIOx errorLed, rcvLed, butUp, butDn, ledUp, ledDn, butLedUp, butLedDn, ledButUp, ledButDn; static uint8_t msFlag = 0; static uint8_t ledState = 0, buttonsState = 0; static uint16_t rcvLedLitTime = 0, butMaskCalcTime = 0, timeoutTimer = 0; typedef struct { uint16_t buffer[10]; uint8_t dataLength; } UartPacket; static UartPacket txPacket, rxPacket; #ifdef SNIFFER_MODE static uint8_t txBuffer[64], txBufferLength = 0, bufferMutex = 0; #endif static uint8_t GetPacketCRC(UartPacket* packet); static void SendLedState(void); uint8_t GetAddress(void) { return (PINC & 0x3F); } 

C-Code für die neue Karte basierend auf dem AVR ATmega328P- Mikrocontroller


Die Einfachheit des Geräts und der Firmware lässt sich anhand der Codemenge abschätzen. Sie enthält nur etwa 600 Zeilen in C-Sprache.


Der Erstellungsprozess sah folgendermaßen aus:



Die Gebühr ist unterschiedlich, aber das Prinzip ist das gleiche


Ich kann kein Foto des fertigen Geräts anhängen, glaube nur, dass es noch produziert und verkauft wird.


Lyrische Schlussfolgerung


In Bezug auf die Aufzugsknöpfe "hoch" und "runter" auf dem Boden. Mir ist aufgefallen, dass viele Menschen ihren Zweck überhaupt nicht verstehen und beide gleichzeitig schütteln.



Von hier aus


Der Aufzug verfügt über zwei Tastensätze: In der Kabine befindet sich eine Bestelltafel und auf der Etage eine Ruftafel. Sie können bereits anhand des Namens erraten, dass das Bestellfeld eine höhere Kontrollpriorität hat.


Alle Aufzüge mit Ruftafeln mit Auf- und Ab-Tasten arbeiten mit einer Art Reiseoptimierungsalgorithmus, dessen Zweck darin besteht, die maximale Anzahl von Passagieren in der minimalen Zeit und eine separate Bedingung für die maximale Wartezeit auf dem Boden (gemäß staatlichem Standard) zu transportieren.


Ein solcher Algorithmus beinhaltet normalerweise die Auswahl von Passagieren auf Etagen, wenn sie in die gleiche Richtung fahren, wie durch Drücken der Ruftaste „nach oben“ oder „nach unten“ angezeigt.


Stellen Sie sich eine Situation vor, in der ein Aufzug mit Passagieren nach unten fährt und von einem Stockwerk darunter einen Anruf nach unten erhält. Der Aufzug hält an, um den Passagier abzuholen (ja, die Beladung der Kabine durch den Gewichtssensor wird noch berücksichtigt, aber wir werden sie senken).


Der Aufzug fährt weiter und erhält einen Anruf von der unteren Etage. Es ist logisch, dass der Aufzug nicht anhält, um einen Passagier aufzunehmen, da er die Fahrtrichtung nicht ändert (dies ist auch in der Norm geregelt), und einen Passagier aufnimmt, um hinunter und dann hinauf zu fahren - nutzloser Energie- und Platzverbrauch im Aufzug.


Der Aufzug fährt weiter und erhält zwei Anrufe „auf und ab“ aus dem unteren Stockwerk, die von einem ungeduldigen Passagier gedrückt wurden, der aufsteigen muss. Es ist logisch, dass der Aufzug auf dieser Etage anhält, der Passagier ihn jedoch nicht betritt. Es dauert jedoch einige Zeit, bis die Personen in der Kabine den Aufzug verlangsamen und anhalten, die Türen öffnen, warten, die Türen schließen und auf die Nenngeschwindigkeit beschleunigen.


Wenn der Aufzug nur einen Knopf auf dem Boden hat, funktioniert er in 99% der Fälle nach dem Algorithmus „Kollektives Herunterfahren“. Wenn sich Befehle in der Kabine befinden, stoppt er nur beim Herunterfahren.


Wenn Sie Programmierkenntnisse in JS haben, können Sie versuchen, einen ähnlichen Steuerungsalgorithmus im Online-Spiel Elevator Saga zu implementieren. Es bietet alle Aspekte der Optimierung von Fahrten, ohne sich eingehend mit dem Betrieb von Aufzugssicherheitskreisen zu befassen.



In meinem Telegrammkanal poste ich ähnliche Materialien. Dort können Sie jetzt die Entwicklung des nächsten Geräts verfolgen.

Source: https://habr.com/ru/post/de459492/


All Articles