MD5 Binary-SelfTest

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Hier eine Denksportaufgabe. Ich bin der Meinung, dass sie theoretisch (also rein mathematisch) lösbar ist, aber wie man das praktisch umsetzen soll, ist mir ein Rätsel.

Stellt euch vor ihr schreibt ein Programm, das ihr als Binary ausliefert. Um es vor Änderungen (Cracks etc.) zu schützen, soll es sich beim Aufruf selbst überprüfen. Mir ist klar, dass es keinen 100%igen Schutz gibt, aber es geht mir um eine möglichst einfache und relativ sinnvolle Methode, so etwas umzusetzen. Am besten geht es wohl mit einer MD5-Prüfsumme. Das Programm erstellt also eine MD5-Prüfsumme von sich selbst. Kein Problem bis hier hin.

Nun aber muss die MD5-Prüfsumme mit einem Wert verglichen werden. Die Schwierigkeit besteht darin, dass dieser Wert keine extern liegende .md5 Datei (Textdatei) sein soll, sondern dass sich dieser Wert im Binary selbst befinden muss. Wenn beide Summen übereinstimmen, wurde die Datei nicht verändert.

Bei einer externen .md5-Datei könnte man das Binary verändern und die .md5-Datei dahingehend manipulieren, dass beide Werte wieder übereinstimmen. Das ist zu einfach.

Wenn der Wert der korrekten MD5-Prüfsumme aber im Binary selbst liegt und dieses verändert wird, stimmt anschließend das Ergebnis des vom Binary durchgeführten "SelfTests" nicht mehr mit dem Wert überein und eine Änderung kann sofort festgestellt werden.

Die große Frage: Wie krieg ich die korrekte MD5-Prüfsumme in das Binary. Ich kann ja schlecht einen Platzhalter benutzen, die MD5-Summe des Binaries berechnen und die dann anstelle des Platzhalters einsetzen, weil sich der Wert anschließend verändern würde. Wie also dann?

Also rein theoretisch könnte man das über einen BruteForce-Test lösen :twisted: Man setzt anstelle des Platzhalters eine generierte MD5-Summe ein, erstellt das Binary und seine MD5-Summe. Wenn diese mit der generierten übereinstimmt, hat man die Lösung. Das ist mir allerdings etwas zu umständlich und könnte auch ein Weilchen dauern 8)
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Dh, du gehst davon aus, dass dein Programm nur als py2exe "binary" ausgeliefert wird?
TUFKAB – the user formerly known as blackbird
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Cryptographische Hashfunktionen sind ja gerade so gestrickt, dass dir nur die Brute-Force-Methode übrigbleibt, wenn die MD5 bestimmt Bedingungen erfüllen soll.

Was man im Allgemeinen macht ist, die Prüfsumme über alles außer dem Bereich, in dem die MD5 liegt, zu bilden.

Z.B. kannst du an EXE-Dateien einfach beliebige Daten hängen, da im Header steht, wie lang die Datei ist. Auslesen kannst du sie dann ganz einfach, indem du die EXE-Datei selbst öffnest, und die letzten 16 Bytes ausliest.

Außerdem sehe ich das Problem nicht; ein Cracker würde einfach die Berechnung der Prüfsumme rausnehmen.
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Ich gehe davon aus, dass ich mein Programm nicht mit Quellcode ausliefere, sondern entweder als .exe oder .pyc. Python 2.4 .pyc Dateien sollen derzeit noch nicht decompilierbar sein (bis Version 2.3 war das wohl fast problemlos möglich). Für UNIXe soll es doch wohl auch ne Möglichkeit geben, ein Binary zu erstellen. Die ersten Python-Compiler sind doch auch in der Entstehung... in diese Richtung dachte ich auch (für später).

Das mit dem Anhängen von beliebigen Daten an eine .exe Datei hab ich nicht ganz verstanden. Ich denke, sobald ich Daten anhänge, verändert sich auch die MD5-Prüfsumme. Gilt dieses Anhängen für jede Art von Binary (auf jedem System)? Es nützt ja auch nix, wenn jeder Idiot was an die .exe anhängen kann. Dann kann er ja beliebige Änderungen durchführen und die angehangenen Daten wieder so anpassen, dass die Prüfung wieder stimmt.

Kann man denn "so einfach" das Prüfverfahren aus dem Binary entfernen, ohne was anderes mit zu erwischen?

Nebenbei: Ich dachte an dieses Prüfverfahren auch als eine Art Sicherheit, wenn sich das Programm selbst updatet oder wenn man es aus dem Netz herunter geladen hat. Das Programm sollte sich selbst überprüfen, damit das dem Benutzer erspart bleibt. Das stellt sicher, dass beim Download alles gut gegangen ist. Später kam ich auf die Idee, das gleichzeitig als Crack-Schutz einzusetzen.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

droptix hat geschrieben:Ich gehe davon aus, dass ich mein Programm nicht mit Quellcode ausliefere, sondern entweder als .exe oder .pyc. Python 2.4 .pyc Dateien sollen derzeit noch nicht decompilierbar sein (bis Version 2.3 war das wohl fast problemlos möglich).
My Support ends here :roll:
TUFKAB – the user formerly known as blackbird
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

So viel hat sich im Bytecode zwischen 2.3 und 2.4 nicht geändert. Kann höchstens sein, dass irgendein kommerzielles Tool die neuen Opcodes noch nicht unterstützt. In jedem Falle gilt, dass Pythons Bytecode genauso wie Java-Bytecode high-level und damit leicht dekompilierbar ist.

Natürlich kann man Daten an die exe-Datei anhängen, da wie Joghurt schrieb die Länge im Header steht und Windows nicht weiter liest. Die MD5-Summe lässt sich dadurch trotzdem nicht so einfach austricksen, da man erstens sinnvollerweise auch die Dateigröße prüfen ließe und du zweitens nicht wüsstest, was genau du jetzt anhängen musst.

Das Ausbauen der Überprüfung ist mit etwas Übung recht einfach, vor allem wenn es sich um Python-Bytecode handelt (was anderes ist in deiner exe-Datei auch nicht drin).

Sprich: Der Einsatz von Hashes zur Verifikation von Downloads ist sehr sinnvoll. Als Schutz vor Cracking taugen sie nichts.
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Schade eigentlich. Ich kenne das noch von früher als man einen Patch über eine .exe geschoben hat und hinterher meldete das Programm, dass es verändert worden sei und nun nicht starten wird.

Ich dachte, das ist cool und mache ich auch. Mich hat es jedenfalls in manchen Fällen abgehalten, das gepatchte Programm zu nutzen. Aber richtig: Früher oder später kam ein Patch der funktionierte.

Aber mal abgesehen von der Sinnhaftigkeit für einen wirksamen Crack-Schutz, als Überprüfung würde es sich trotzdem eignen. Die Frage nach der Lösung bleibt: Wie kriege ich die korrekte .md5 in das Binary?
BlackJack

Na das hatten wir doch schon: An die EXE anhängen. Und bei der Überprüfung natürlich die Prüfsumme am Ende nicht mit in die Berechnung einbeziehen.
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

1) Das wie habe ich nicht verstanden bzw. wusste es bis vor Kurzem ja gar nicht. Wie hänge ich was an eine .exe? Und wie verändere ich den Header der Datei so, dass die angehängten Daten beim Einlesen nicht mit ausgewertet werden?

2) Was ich bereits fragte: Geht das Anhängen zusätzlicher Informationen bei allen Binaries auf jedem Betriebssystem? Oder ist das eine .exe-spezifische Geschichte? Falls ja, kann ich das nur eingeschränkt anwenden bzw. der MD5-SelfTest müsste intern ja auf sys.platform = "win32" beschränkt werden.

Danke!
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

ich versuchs nochma.
du öffnest eine binary. den inhalt liest du ein. nun kannst du am ende etwas hinzufügen: den md5-hash!
die binary wird immer noch funktionieren!
nur bei der berechnung musst du jetzt einmal die dateilänge herausfinden und dann die letzten 16(?) Zeichen als md5-hash einlesen und danach ignorieren. ohne den angehängten md5-hash jetzt den md5-hash kreieren und nun vergleichen.
http://www.cs.unm.edu/~dlchao/flake/doom/
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Entschuldige meine unerfahrenen Fragen: Kann ich denn einfach Plaintext (den MD5-Hash) an ein Binary (kein Plaintext) anhängen?

Ich hab mir mal einen MD5-FileTester geschrieben. Damit jede Art von Datei eingelesen werden kann, hab ich das über einen Puffer gelöst. Damit wird also die Datei schrittweise eingelesen, damit es den RAM bei großen Dateien nicht sprengt.

> Angenommen, ich lese nun die .exe in 512kB-Blöcken ein. Die .exe ist 550kB groß. Dann brauch ich zwei Schritte zum Einlesen. Der erste geht klar. Beim zweiten Schritt sind nur noch 38kB einzulesen. Wie verhindere ich denn, dass ich nun genau die angehängten Daten nicht mit einlese? Ich kann sie ja nicht abschneiden... :?:

Sorry, ich steig da noch nicht dahinter. V.a. nicht hinter die Idee, dass wenn ich was an die .exe anhänge das nicht beim MD5-Hash der Datei beachtet werden soll.

Hmmm, vielleicht kannste mal nen Dreizeiler dazu posten, wie man

1. Plaintext-Infos an die .exe hängt
2. den MD5-Hash ohne die angehängten Infos bestimmt

Vielleicht kapier ich's dann.
BlackJack

Daten an Dateien anhängen geht einfach indem man sie mit 'a' wie "append" als Modus öffnet und dann die Daten schreibt.

Man kann auch einfach die Bytes in die Datei schreiben ohne sie in Plain-Text umzuwandeln. MD5 ergibt genau 16 Bytes, die man mit der `digest()` Methode bekommt.

Und das mit dem Einlesen löst man am einfachsten in dem man die ganze Datei minus der letzten 16 Bytes in den Speicher liesst. EXEn die den Hauptspeicher sprengen sind äusserst selten.

Und natürlich ist das nicht plattformunabhängig. Da würde ich die Prüfsumme einfach in eine eigene Datei schreiben.
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Hum. Schade, ich suche was plattformunabhängiges, weil die meisten meiner Python-Programme ja auch cross-platform funktionieren.

Den MD5-Hash in eine separate Datei zu schreiben ist nicht mein Ziel, weil bei einem Update via Download z.B. die separate .md5 Datei beschädigt worden sein könnte. Falls sowas auftritt, wird die .exe denken, sie sei beschädigt, obwohl die .md5 Datei beschädigt ist. Teufelskreis.

Oder andere Frage: Gibt es unter UNIX was Äquivalentes zu der Methode "MD5-Hash an .exe anhängen"?
BlackJack

Warum macht das einen Unterschied, ob der Hash in einer separaten Datei steht, die beschädigt wurde, oder in der EXE und die gerade bei dem Teil beschädigt wurde in dem der Hash steht? Das ist doch genau das gleiche!?

Wenn der Hash nicht stimmt kannst Du nie sagen was kaputt ist, der Hash oder die Daten über die der Hash gebildet wurde. Jedenfalls nicht wenn beide den gleichen Übertragungsweg genommen haben.

Es gibt unter "UNIX" kein einheitliches EXE Format. Warum willst Du das unbedingt mit aller Gewalt zusammen packen wenn es anders viel plattformunabhängiger geht!?
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

BlackJack hat geschrieben:Warum macht das einen Unterschied, ob der Hash in einer separaten Datei steht, die beschädigt wurde, oder in der EXE und die gerade bei dem Teil beschädigt wurde in dem der Hash steht? Das ist doch genau das gleiche!?
Nicht ganz. Angenommen die .exe wurde einwandfrei heruntergeladen, aber bei der .md5 Datei trat ein Fehler auf. Obwohl die .exe okay ist, meint sie bei der Überprüfung sie sei falsch.
BlackJack hat geschrieben:Wenn der Hash nicht stimmt kannst Du nie sagen was kaputt ist, der Hash oder die Daten über die der Hash gebildet wurde. Jedenfalls nicht wenn beide den gleichen Übertragungsweg genommen haben.
Ja richtig. Deshalb fände ich es auch besser, wenn sich der Hash gleich in der zu prüfenden Datei selbst befindet. Falls diese fehlerhaft herunter geladen wurde, stimmt der Hash sowieso nicht mehr. Dann kann man zu 100% sagen, dass diese Datei kaputt ist und nicht eventuell auch eine externe Quelle.
BlackJack hat geschrieben:Es gibt unter "UNIX" kein einheitliches EXE Format.
Ich weiß. Aber es gibt auf jedem OS ein Binary-Format. Ich möchte mein Programm auf jeden Fall für Windows, Mac OS X, Linux, FreeBSD und Symbian (Nokia) ausliefern. Das sind fünf verschiedene Binary-Formate. Für Windows gibt's py2exe – kein Problem also. Für Linux hab ich mal was ähnliches gelesen, habe mich aber noch nie richtig intensiv damit befasst. Was es für Linux gibt, wird meistens auch für andere Unixe portiert. Für alle anderen Systeme ohne Binary-Möglichkeit setze ich eine Python-Installation voraus und liefere die .pyc Datei.
BlackJack hat geschrieben:Warum willst Du das unbedingt mit aller Gewalt zusammen packen wenn es anders viel plattformunabhängiger geht!?
Weil das die meisten Endanwender einfach lieber mögen und das Ganze sehr einfach zu handhaben ist. Was spricht denn dagegen?
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

droptix hat geschrieben:Nicht ganz. Angenommen die .exe wurde einwandfrei heruntergeladen, aber bei der .md5 Datei trat ein Fehler auf. Obwohl die .exe okay ist, meint sie bei der Überprüfung sie sei falsch.
Wenn der MD5 an der exe dranhängt, kann doch genau der gleiche Fall auftreten: nur die paar Bytes am Schluss sind falsch übertragen worden. Dann ist die exe ebenfalls okay, d.h. fehlerfrei ausführbar.
BlackJack

droptix hat geschrieben:
BlackJack hat geschrieben:Es gibt unter "UNIX" kein einheitliches EXE Format.
Ich weiß. Aber es gibt auf jedem OS ein Binary-Format. Ich möchte mein Programm auf jeden Fall für Windows, Mac OS X, Linux, FreeBSD und Symbian (Nokia) ausliefern. Das sind fünf verschiedene Binary-Formate.
Wenn man von einem Format pro Plattform ausgeht, dann ja.
Für Windows gibt's py2exe – kein Problem also. Für Linux hab ich mal was ähnliches gelesen, habe mich aber noch nie richtig intensiv damit befasst. Was es für Linux gibt, wird meistens auch für andere Unixe portiert. Für alle anderen Systeme ohne Binary-Möglichkeit setze ich eine Python-Installation voraus und liefere die .pyc Datei.
Du solltest auch unter Linux ein installiertes Python vorraussetzen. Bei den meisten Distributionen ist es sowieso schon installiert weil es von Programmen, manchmal sogar Systemprogrammen, schon benötigt wird. Auf jeden Fall sollte es per Paketsystem einfach nachzuinstallieren sein.

Software die einen eigenen Pythoninterpreter mitbringt fänd ich unter Linux ziemlich schräg.
BlackJack hat geschrieben:Warum willst Du das unbedingt mit aller Gewalt zusammen packen wenn es anders viel plattformunabhängiger geht!?
Weil das die meisten Endanwender einfach lieber mögen und das Ganze sehr einfach zu handhaben ist. Was spricht denn dagegen?
Einfach zu handhaben? Warum gibt's dann diese Diskussion? ;-)

Dagegen spricht die unnötige Komplexität. Wenn Du die Prüfsumme in einer eigenen Datei hast, dann funktioniert es ohne grosse Änderungen auf allen 5 Plattformen. Und auch auf solchen, an die Du gar nicht gedacht hast.
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

BlackJack hat geschrieben:Du solltest auch unter Linux ein installiertes Python vorraussetzen. Bei den meisten Distributionen ist es sowieso schon installiert […]
Nunja, da ich aktuell mit Python 2.4 arbeite, bereitet das manchmal Probleme: Debian Sarge (stable) oder Mac OS X haben standardmäßig nur Python 2.3 drauf. Der Endanwender hat in manchen Fällen nicht die nötigen Rechte zum Updaten der Version. Daher finde ich es gar nicht so schlecht, den Installer auszuliefern. Kann man ja optional gestalten -> einmal die .pyc für alle oder Binaries für Benutzer ohne Python.
BlackJack hat geschrieben:Einfach zu handhaben? Warum gibt's dann diese Diskussion? ;-)

Dagegen spricht die unnötige Komplexität. Wenn Du die Prüfsumme in einer eigenen Datei hast, dann funktioniert es ohne grosse Änderungen auf allen 5 Plattformen. Und auch auf solchen, an die Du gar nicht gedacht hast.
Das gilt aber nur, wenn ich für alle Systeme die selbe .py(c) ausliefere, was das Optimum darstellt. Ich fände es nett, wenn zumindest für die meist benutzten Systeme (Windows, Mac OS, Linux, FreeBSD) Binaries zum schnellen Ausprobieren exisiteren. Da kann man ein Programm mal eben schnell ohne Umwege starten und einfach testen.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

droptix hat geschrieben:Nicht ganz. Angenommen die .exe wurde einwandfrei heruntergeladen, aber bei der .md5 Datei trat ein Fehler auf. Obwohl die .exe okay ist, meint sie bei der Überprüfung sie sei falsch.
Ja, sie meint, dass beim Download ein Fehler passiert ist, was ja auch stimmt...
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Ich meine, dass der Fehler aber bei einer irrelevanten Datei aufgetreten ist. Das ließe sich vermeiden, wenn diese separate .md5-Datei nicht benutzt werden würde.

Hum. Also ich gebe euch ja recht, wenn's um das Thema "Einfachkeit" geht. Es wäre definitiv simpler und einfacher, den MD5-Hash auszulagern oder auf der Website anzugeben (zum selbst überprüfen).

Nur wenn man ein Update z.B. auf CD brennt, es mit nach Hause nimmt und dort drüber jagt… bei jeder Übertragung könnten Fehler entstehen. Ich empfinde es eben als das Optimum, den MD5-Hash direkt in der Datei zu haben. Nur dass dieser Weg meiner Meinung nach auch der Komplizierteste ist.

Übrigens: Wir haben immer noch keine Lösung, wie man das praktisch realisieren könnte (mal abgesehen vom Zweck). Hat jemand eine andere (effizientere) Idee als die Brute-Force-Methode?
Antworten