Programm aus PIC12F508 laden und verstehen

OP #7531229
Lesenswert?

Ich habe in einem anderen Beitrag hier (Beitrag "Funktion Reifendruckanlerngerät EL-50448; OEC-T5; Welches Bauelement ist das?") zu einem RDSK-Trigger Gerät Fragen zum darauf befindlichen PIC Mikrocontroller. Das RDSK-Thema ist aber vermutlich zu speziell, daher frage ich hier nochmal allgemein.

Herzstück hier ist ein PIC12F508I auf dem Board. Den habe ich runtergelötet und mit einem Flash-Programmer ausgelesen.

Laut Datenblatt hat dieser PIC einen Flash-Speicher von 512 words, also 1024 Bytes (0x400) und 25 Bytes RAM. Das BIN und HEX davon habe ich ins ZIP eingefügt. Ebenso ein Disassembly (mit PICDisasm erzeugt).

Wenn jetzt hier keine speziellen Protections greifen, dann dürfte das wirklich der komplette Code sein.

Vom Board her konnte ich ermitteln das folgende IO-Pins belegt sind:

  • OSC1/OSC2 gehen direkt zu einem 4MHz Oszillator.
  • GP0 konnte ich noch nicht ermitteln, wüsste auch grad nicht wozu es gut sein sollte da das Gerät nicht mehr Funktionen hat.
  • GP1 geht über einen Transistor auf ein LCR, bestehend aus Antenne, Kondensator und Widerstand, nach Masse. Hierüber wird gesendet (125 kHz LF-Band)
  • GP2 geht über einen 220 Ohm auf die Kathode einer grünen LED, welche den Sendebetrieb anzeigt (flackert beim drücken von T1)
  • GP3 kommt über einen 4,7k von einem Taster T1 welcher auf (+) gelegt ist, er erzeugt also eine steigende Flanke.

Nun versuche ich aus der Software schlau zu werden und da könnte ich was Hilfe gebrauchen da ich mich mit den PICs überhaupt nicht auskenne.

Das FSR-Register sollte hier wohl keine Rolle spielen, da der 12F508 nur eine Speicherbank hat? Der Reset-Vector ist immer 0x0000, hier startet die Softwareausführung also. Auf Adresse 0x1FF soll beim 12F508 ein MOVLW Kommando mit dem Wert für die interne Oszillator-Kalibration liegen. Dieser liegt in meinem Dump jedoch auf 0x3FF und hat den Wert 0x2A.

Die Register liegen im RAM (Register File Map). Ich habe mit dann einen PIC-Simulator runtergeladen (https://gputils.sourceforge.io/) und versucht das alles nachzuvollziehen und hier ergeben sich die ersten Fragen:

Der erste Befehl ist laut Datenblatt die letzte Speicheradresse der ersten Page, dort wird das einzige Register "W" mit dem Wert 0x2A geladen. Danach geht der Programm-Counter automatisch auf 0x0000 und fängt an dort den Code auszuführen. Gleich die erste Anweisung ist ein NOP (warum nur?). Zunächst wird dann das OSCCAL-Register mit dem Wert aus W aus 0x2A beladen. Das kann ich im Simulator gut nachvollziehen.

Dann überspringt der Code einige Stellen die eher nach Daten als nach Programmcode aussehen um an Postion 0x0014 weiter zu machen. Dort ruft er eine Subroutine auf (LADR_0x0016) aus der er irgendwann mit einem return zurückkehren wird um dann anschließend an die Adresse LADR_0x0148 zu springen. Ab dieser Adresse stehen aber nur noch NOPs im Programmcode. Die führt er bis zuende aus um dann vermutlich wieder auf 0x0000 zu gehen und das Programm von vorn zu starten?

Der Code ab 0x0016 sieht aus wie eine Initialisierung der GPIOs. Hier wird das GPIO-Register (RAM Adresse 0x06) zunächst auf 0b00000100 eingestellt, was zur Folge hat das GP2 auf HIGH geht. Dadurch ist die grüne LED erstmal aus. Das nachfolgende MOVLW 0x08 und TRIS GPIO setzt wohl den GP3 (Taster-Eingang) auf Tri-State.

Nun wird der zuvor in W geladene Wert 0b01001111 mit dem "OPTION" Befehl in das gleichnamige Register geschrieben. Das bedeutet:

  • setze den Prescaler des WDT auf 1:128
  • setzte Wakeup auf Pin-Änderung von GP0, GP1 oder GP3 (hier sitzt der Taster)

Laut Datenblatt liest der Chip nach dem RESET das Configuration Word von der Speicheradresse 0x3FF. Hier steht im Dump ein 0b00001100 was soviel bedeutet wie "Use GP3 as input", "Use LP oscillator (200 kHz)", "Copy Protection OFF" und "Watchdog-Timer enabled". Das bedeutet das nach 18 ms nach dem POR der Watchdog auslöst. Ein solcher Auslöser ist immer ein RESET, es gibt also keine speziellen Watchdog-Vectoren/Code.

Soweit glaube ich noch mit zu kommen... aber jetzt geht es mit dieser ominösen Schleife los:

1
    MOVLW 0x07           ;   b'00000111'  d'007'
2
    MOVWF FSR
3
    CLRF INDF
4
LADR_0x001F
5
    INCF FSR,F
6
    CLRF INDF
7
    MOVLW 0xFF           ;   b'11111111'  d'255'
8
    SUBWF FSR,W
9
    BTFSS STATUS,Z
10
    GOTO LADR_0x001F
11
    RETLW 0x00           ;   b'00000000'  d'000'
12
    MOVWF LRAM_0x09

Was genau macht dieser Code? Und sehe ich das richtig das nach der Schleife ein einfacher Return "RETLW 0x00" steht welcher die Subroutine und damit dann das Programm faktisch beendet? Das kann es ja nicht gewesen sein. Wie wird der code danach ausgeführt?

Angehängte Dateien:
Gast #7531508
Lesenswert?

Olli Z. schrieb:

Soweit glaube ich noch mit zu kommen... aber jetzt geht es mit dieser ominösen Schleife los: MOVLW 0x07 ; b'00000111' d'007' MOVWF FSR CLRF INDF LADR_0x001F INCF FSR,F CLRF INDF MOVLW 0xFF ; b'11111111' d'255' SUBWF FSR,W BTFSS STATUS,Z GOTO LADR_0x001F RETLW 0x00 ; b'00000000' d'000' MOVWF LRAM_0x09

Was genau macht dieser Code?

Der löscht die GPRs.

Und sehe ich das richtig das nach der Schleife ein einfacher Return "RETLW 0x00" steht welcher die Subroutine und damit dann das Programm faktisch beendet? Das kann es ja nicht gewesen sein. Wie wird der code danach ausgeführt?

Es geht danach einfach im Hauptprogamm weiter.

#7531547
Lesenswert?

H. H. schrieb:

Nach 1ffh kommt 0h.

Ja klar. So hat man damals die Osszicaltor Trimmungswerte übergeben. Ich glaube bei einigen PICs war der Resetvector nicht 0 sondern 0x1FFF. Damit wurde W mit den Trimmwerten geladen, und man musste das abspeichern. Egal, das sind jetzt Detail Sachen.

Wenn ich mir den Code angucke, macht der meist garnix. Hälfte sind einfach NOPs und bisschen hin und her springen. Habe bestimmte etwas übersehen, aber so wie ich es verstanden habe, macht der etwas am Anfang, dann kommen irgendwie viele NOPs, dann überrollt der PC wieder auf 0 und fängt von vorne wieder an.

Hier bin ich unsicher: BTFSS STATUS,Z GOTO LADR_0x001F RETLW 0x00 ; b'00000000' d'000' MOVWF LRAM_0x09

Sprint der RETLW wieder auf GOTO LADR_0x0148 , richtig? Es gibt hier noch keinen Stack wo man die Rücksprungadressen gespeichert hat. Das Ding meine ich hatte einen Hardcoded Stack von 3 und man konnte nur da für den CALL verwenden.

Wenn das so der Fall ist, lässt sich der Code so vereinfachen: ; Reset-Vector NOP MOVWF OSCCAL GOTO LADR_0x0014

LADR_0x0014 CALL LADR_0x0016 GOTO DelayShort

LADR_0x0016 MOVLW 0x04 ; b'00000100' d'004' MOVWF GPIO MOVLW 0x08 ; b'00001000' d'008' TRIS GPIO MOVLW 0x4F ; b'01001111' d'079' "O" OPTION MOVLW 0x07 ; b'00000111' d'007' MOVWF FSR CLRF INDF LADR_0x001F INCF FSR,F CLRF INDF MOVLW 0xFF ; b'11111111' d'255' SUBWF FSR,W BTFSS STATUS,Z GOTO LADR_0x001F RETLW 0x00 ; b'00000000' d'000'

DelayShort NOP MOVLW 0x2A ; b'00101010' d'042' "*"

1
End
#7531561
Lesenswert?

Bist Du Dir sicher dass das Auslesen ohne Fehler funktioniert hat? Womit hast Du ausgelesen, der PICkit ist nach meinen bisherigen Erfahrungen zuverlässig.

Ich frage weil der Code meiner Meinung nach wenig Sinn ergibt. Es gibt bei dem Code auch nichts zu verschleiern was eine eventuell absichtlich unsinnige Struktur erkären würde. Die erzeugte Modulation kann man ja einfach mit einem Logic-Analyzer abgreifen und damit weiss man bereits alles, wie genau das im Code gemacht wird spielt keine Rolle.

#7531639
Lesenswert?

H. H. schrieb:

Und hier eben ganz normaler Code, kein Kalibrierwert.

Also ja ist halt normaler Code. Aber der PIC kommt so aus dem Werk vorprogrammiert, dass da ein movlw Befehl liegt der einen Wert in W lädt. Der Wärt wird ja im Werk ermittelt. Beim flashen, muss der Flasher den Wert auslesen, und wieder reinschreiben. Sonst ist der wer, und man muss noch einmal den irgendwie (wie?) ermitteln. Ist nicht so schlimm.

OP #7531682
Lesenswert?

Der Code erzeugt aber das Signal an der Antenne und am GP gemessen. Ausgelesen habe ich mit einem hochwertigen RT809H Flash Programmer, mehrmals, kam immer das gleiche Ergebnis. Habe noch einen anderen Trigger, kleinerer Buart, hat das gleiche PIC und die gleiche Software.

Einen partiellen Kopierschutz für den Code gibt es ja nicht. Es wäre jetzt noch eine Option für mich einen neuen PIC mit dem Code zu programmieren und zu schauen ob dieser die gleiche Funktion erfüllt.

#7532244
Lesenswert?

Leider fehlt das Configuration Word im Hexfile. Aber der Prozessor ist vermutlich einfach Code Protected, deshalb stehen nach dem Auslesen von 0x040 bis 0x01fe nur Nullen (Kapitel 7.10 im Datenblatt).

7.10 Program Verification/Code Protection

If the code protection bit has not been programmed, the on-chip program memory can be read out for verification purposes.

The first 64 locations and the last location (OSCCAL) can be read, regardless of the code protection bit setting.

The last memory location can be read regardless of the code protection bit setting on the PIC12F508/509/16F505 devices.

#7532270
Lesenswert?

Oliver F. schrieb:

Leider fehlt das Configuration Word im Hexfile. Aber der Prozessor ist vermutlich einfach Code Protected, deshalb stehen nach dem Auslesen von 0x040 bis 0x01fe nur Nullen (Kapitel 7.10 im Datenblatt).

Das erklärt warum der Code keinen Sinn macht. Allerdings frage ich mich warum das verwendete Tool zum Auslesen des PIC die Code Protection nicht anzeigt, Zugriff auf das Configuration Word hat es ja.

Ist das Code Protection Word eventuell die letzten Bytes E5 0F im Binary von hier (tpms-trigger-tool_small.zip) ?

Beitrag "Re: Funktion Reifendruckanlerngerät EL-50448; OEC-T5; Welches Bauelement ist das?"

OP #7532579
Lesenswert?

Laut diesem Datenblatt http://ww1.microchip.com/downloads/en/DeviceDoc/41227B.pdf ist das im "Configuration Word" enthalten. Dieses liegt beim 12F508 an der statischen Adresse 0x3FF und ist nachdem einschalten vorhanden bis der erste PC increment stattfindet. Zuständig ist Bit 3. Im Dump ist das der Teil wo dieser als MOVLW 0x2A interpretierte Befehl.

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 000003F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2A 0C ..............*.

Ich meine 0x2A wäre das OSCCAL Byte und 0x0C müsste das Configuration word sein. 0x0C wäre 0b0000 1100 und somit wäre das CP-Bit gesetzt, was bedeuten würde der Chip hätte keine Copy protection.

Aber die Ausführungen meines Namensvetters sind absolut schlüssig und die einzige Erklärung für den merkwürdig funktionslosen Code mit den vielen NOPs.

Jetzt zu fragen ob man diesen alten PIC evtl. knacken kann spare ich mir, das wäre die Mühe nicht wert. Ich werde wohl meinen eigenen Code schreiben müssen und ihn dann in dem Tool zum laufen bringen.

Angehängte Dateien:
#7532677
Lesenswert?

Der Befehl an Adresse 0x01FF (= Adresse 0x03FE im Hexfile) - MOVLW 0x2A - ist der Kalibrierwert für den Oszillator.

Das Config Word steht im Flash an Adresse 0x03FF.

Ist das Code Protection Word eventuell die letzten Bytes E5 0F im Binary von hier (tpms-trigger-tool_small.zip) ?

Beitrag "Re: Funktion Reifendruckanlerngerät EL-50448; OEC-T5; Welches Bauelement ist das?"

Das könnte durchaus sein. Wenn man es entsprechend interpretiert, kommt etwas sinnvolles heraus:

0x0FE5 = 1111 1110 0101

1111 111 unbenutzte Bits

0 MCLRE GP3 ist digitaler Eingang, Reset intern erzeugt

0 CP Code Protection on

1 WDTE Watchdog Timer enabled

01 FOSC XT Oscillator

OP #7533632
Lesenswert?

So, nun mal mit einem PICKit2 (Clone) - Guess what: "Protected"

Davon ab das es natürlich nicht lohnen wird, gäbe es nun zwei Möglichkeiten doch an den Code zu kommen:

Hack-Methode 1) Decap vom Chip, Fuses localisieren, den Flash-Bereich mit Tonband abdecken und UV-Licht schräg auf die Fuses geben um diese zurück zu setzen. Aufwand ist sehr hoch, Decap benötigt spezielle Chemikalien (einige davon dienen auch zum Bau von Sprengstoffen, also nicht einfach erhältlich) und man kann den Chip dabei schnell komplett ruinieren.

Hack-Methode 2) Ein interessanter Ansatz bei dem nicht der ganze Flash gelöscht wird, sondern nur ein Teil, eine Bank. Dabei werden die Fuses mit zurückgesetzt und man kann den Chip auslesen. Eine erweiterte Option davon ist, in die erste Bank, in der sich normalerweise ein Bootloader befindet, ein kleines Stück Dump-Software zu programmieren, welches dann beim Reset den Inhalt des Flash auf einen IO-Port (bei größeren Chips ein UART) pumpt. Hat man dann noch einen zweiten Chip programmiert man alles bis auf den Bootloader (1st Bank) mit NOP und schreibt den Dump-Code ans Ende des Flash. Der Bootloader wird irgendwann an eine Speicherstelle springen wo er normalerweise den Main-Code ausführt, dort führen ihn die NOPs dann unweigerlich zum eigenen Trojaner-Code. Durchführen kann man diesen partiellen Erase/Program nicht aus einem MPLAB o.ä. sondern nur mit Big-Banging der Signale.

Methode 2 wäre nicht schlecht, aber der kleine 12F508 hat keine Banks und keinen Bootloader, wird also vermutlich nicht funktionieren. Toll wäre ja wenn man genau die ersten Bytes die man ohnehin frei auslesen kann überschreiben könnte um an den Rest zu kommen. Laut Datenblatt hat der PIC12F508 nur zwei Bulk-Erase Modes, die jeweils angestoßen, den gesamten Chip leeren.

OP #7533907
Lesenswert?

Ich habe mir das Timing mal etwas näher angesehen und folgendes daraus ermittelt: Modulationsverfahren: ASK 1 Impuls = 1 µS + 7 µS Pause (=125 kHz) Symbole K = 16 Pulse (120 µS) + 134 µS Pause K' = 16 Pulse (120 µS) + 262 µS Pause M = 32 Pulse (248 µS) + 262 µS Pause M' = 32 Pulse (248 µS) + 138 µS Pause L = 48 Pulse (376 µS) + 376 µS Pause

Sendefolge = Sync + Data Sync = 17 x K Data = L K M M K K' M K M M' K' M K M M M M M K K M M M M

Das entspricht dem was Dieter schon vor langer Zeit in dem anderen Thread mitteilte:

Schau Dir mal im Datenblatt des SP40T (Infineon-SP400-15-11-DataSheet-v01_01-EN.pdf) auf Seite 54 "Figure 5-17 LF telegram modulated on a 125 kHz carrier" an. Das passt ganz gut:

  • 17 Bits Preamble
  • Synchronization pattern (laut Datenblatt fest vorgegeben)
  • 32 Bits Daten (Manchester codiert)

Ein "K" entspricht also einem Bit.

Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren