Ich versuche, ein RAM-residentes Image dazu zu bringen, sich selbst zu prüfen, was leichter gesagt als getan ist.
Der Code wird zunächst auf einer Cross-Development-Plattform kompiliert, wodurch eine .elf-Ausgabe generiert wird. Ein Dienstprogramm wird verwendet, um das Binärbild zu entfernen, und dieses Bild wird zusammen mit der Bildgröße zum Flashen auf der Zielplattform gebrannt. Wenn das Ziel gestartet wird, kopiert es die Binärdatei in die richtige Region des RAM und springt dorthin. Das Dienstprogramm berechnet auch eine Prüfsumme aller Wörter im Elf, die für RAM bestimmt sind, und auch das wird in den Flash gebrannt. Mein Image könnte also theoretisch sein eigenes RAM-residentes Image anhand der a-priori-Startadresse und der im Flash gespeicherten Größe prüfen und mit der im Flash gespeicherten Summe vergleichen.
So jedenfalls die Theorie. Das Problem ist, dass, sobald das Bild mit der Ausführung beginnt, eine Änderung in der erfolgt .data
Abschnitt, wenn Variablen geändert werden. Wenn die Summe fertig ist, ist das summierte Bild nicht mehr das Bild, für das der Versorger die Summe berechnet hat.
Ich habe Änderungen aufgrund von Variablen, die von meiner Anwendung definiert wurden, eliminiert, indem ich die Prüfsummenroutine vor alle anderen Initialisierungen in der App verschoben habe (was sinnvoll ist, wenn eine Integritätsprüfung fehlschlägt, oder?), aber die Killer ist die C-Laufzeit selbst. Es scheint, dass es einige Elemente gibt, die sich darauf beziehen malloc
und Pointer-Casting und andere Dinge, die zuvor geändert wurden main()
sogar eingetragen ist.
Ist die ganze Idee der Selbstprüfsumme von C-Code lahm? Wenn es eine Möglichkeit gäbe, app und CRT .data in verschiedene Abschnitte zu zwingen, könnte ich den CRT-Thrash vermeiden, aber man könnte argumentieren, dass, wenn das Ziel darin besteht, das Image auf Integrität zu prüfen, bevor es (das meiste davon) ausgeführt wird, die initialisierten CRT-Daten sollten ein Teil davon sein. Gibt es überhaupt eine Möglichkeit, Code-Prüfsummen selbst im RAM zu erstellen?
FWIW, ich scheine mit einer Anforderung dafür festgefahren zu sein. Persönlich hätte ich gedacht, dass der richtige Weg darin besteht, die Binärdatei zu prüfen in dem Blitz, vor der Übergabe an den Stößel, und vertrauen Sie dem Lader und dem Stößel. Paranoia muss irgendwo enden, oder?
Verschiedene Details: Werkzeugkette ist GNU, Bild enthält .text
, .rodata
und .data
als ein zusammenhängend geladener Block. Es gibt kein Betriebssystem, dies ist Bare-Metal-Embedded. Hauptlader im Wesentlichen memcpy
ist meine Binärdatei in den RAM, an einer vorgegebenen Adresse. Es finden keine Umzüge statt. VM wird nicht verwendet. Die Prüfsumme muss nur einmal bei init getestet werden.
Aktualisiert
Habe das dadurch gefunden..
__attribute__((constructor)) void sumItUp(void) {
// sum it up
// leave result where it can be found
}
..dass ich vor der summe fast alles erledigen kann ausser der initialisierung der malloc
/sbrk
vars von der CRT-Init und einige vars, die “impure.o” und “locale.o” gehören. Jetzt die malloc
/sbrk
value ist etwas, das ich aus dem Projekt-Linker-Skript kenne. Wenn impure.o und locale.o entschärft werden könnten, könnten sie im Geschäft sein.
aktualisieren
Da ich den Einstiegspunkt steuern kann (durch das, was im Flash für den primären Lader angegeben ist), scheint es jetzt der beste Angriffswinkel zu sein, ein Stück benutzerdefinierten Assembler-Code zu verwenden, um Stack- und Sdata-Zeiger einzurichten, die Prüfsummenroutine aufzurufen und verzweigen Sie dann in den “normalen” _start-Code.
Haben Sie nicht die Möglichkeit, den Code in ein anderes Segment als .data einzufügen? Auf diese Weise können Sie Änderungen bei der Berechnung Ihrer Prüfsumme vollständig vermeiden.
– Oliver Charlesworth
31. Dezember 2012 um 15:01 Uhr
Ich könnte einfach die .text- und .rodata-Dateien summieren, aber dies würde Dinge wie initialisierte Tabellen usw. aus der Summe auslassen.
– Just Jeff
31. Dezember 2012 um 15:05 Uhr
Ja das stimmt. In diesem Fall haben Sie ein Problem. Vielleicht gibt es eine Möglichkeit, den CRT-Start vollständig zu untergraben und vorher Ihre Prüfsummenroutine auszuführen, aber das geht weit über mein Fachwissen hinaus! Um welche Plattform handelt es sich? Gibt es eine Möglichkeit, den Loader selbst zu ändern?
– Oliver Charlesworth
31. Dezember 2012 um 15:08 Uhr
Drat. Hatte auf so etwas wie -Wl,-weird_corner_case gehofft. Nun gut, „Requirements Pushback“ beginnt zu gefallen
– Just Jeff
31. Dezember 2012 um 15:16 Uhr
Warum übrigens das Datensegment in die Prüfsumme einbeziehen? Das Wesentliche in Bezug auf die Sicherheit ist sicherzustellen ausführbarer Code wurde nicht verändert.
– Benutzer529758
31. Dezember 2012 um 15:19 Uhr