Ist dieses Programm hackbar?
-
Hallo, meine Frage ist, ob dieses Programm hackbar ist, natürlich wenn man den Quellcode nicht hat und man davon ausgeht, dass das Passwort zu gut ist?
#include <iostream> #include <string> int main(){ const std::string password = "BadPassword"; std::string input; std::cout<<"Password?"<<std::endl; std::cin>>input; if(input==password){ std::cout<<"Right Password, the cash is in the Apartment 44"; } else{ std::cout<<"False Password"; } return 0; }
Wenn man das Programm startet wird die Variable password irgendwo im RAM gespeichert. Wäre es nicht möglich, den Ram nach veränderungen nach dem Start zu suchen und somit das Passwort zu finden?
-
Das Passwort wird schon ganz simpel in deinen Binaries sichtbar sein. Einfach mal deine Exe-Datei mit einem Hex-Editor öffnen
-
Wenn das Programm auf meinem PC läuft oder ich die ausführbare Datei habe, dann ist das Programm natürlich hackbar. Man kann das richtige Passwort direkt aus der ausführbaren Datei auslesen, das Programm patchen, sodass jedes Passwort aktzeptiert wird usw...
Jedes Programm welches nicht auf irgendwelche externen Dienste angewiesen ist, ist hackbar. Ist nur die Frage mit wie viel Aufwand.
-
Wäre es also nicht möglich dieses Programm nicht hackbar zu machen oder mit extremen Zeitaufwand?
-
Prinzipiell ja.
Man muss das Programm nicht einmal starten, um deinen String darin zu finden.Als etwas erschwerend kann man hier betrachten,
dass BadPassword fälschlicherweise für einen Fehlermeldung gehalten werden könnte
(Security through obfuscation). Dann wiederum wird "False Password" ausgegeben, was man ebenfalls im Programm finden kann, weshalb man vermutlich dennoch einfach mal "BadPassword" ausprobieren würde :pDas ganze lässte sich auch im RAM feststellen mit einem Debugger (z.B. OllyDbg).
Ist hier allerdings unnötiger Aufwand.
Was man halt cooles mit OllyDbg machen kann ist:
* du suchst die Fehlermeldung bei falschem PW in der Stringtabelle
* du setzt einen Breakpoint auf alle Nutzungen dieses Strings
* du lässt das Programm im Debugger laufen, gibst ein PW ein und rennst in deinen Breakpoint
* jetzt gehst du im Assemblercode rückwärts bis zum VergleichJetzt hast du zwei Möglichkeiten:
1. den konditionalen Sprung so rauspatchen, dass jedes Passwort richtig ist
2. schauen, mit was verglichen wird, hier würdest du dann BadPassword wiederfinden.Ein kleines Manko hat dein Programm auch noch:
Ist die Nutzereingabe "BadPassword ... irgendwas whatever", dann bricht std::cin beim ersten whitespace ab, du erhältst BadPassword und die Einhabe ist plötzlich richtigstd::getline hilft hier weiter, aber Passwörter sollten ohnehin nicht mit Echo eingegeben werden, für den Fall das jemand hinter einem steht und guckt.
-
MISMR schrieb:
Wäre es also nicht möglich dieses Programm nicht hackbar zu machen oder mit extremen Zeitaufwand?
Es ist effektiv nicht möglich. Große Firmen investieren mehr Geld und Knowhow in Kopierschutz als du vermutlich zur Verfügung haben wirst und Kopierschütze werden dennoch geknackt.
Du kannst deine Software gegen Anfänger schützen, in dem du Passwörter verschlüsselst (was bei lokaler Software das Problem hat, dass der Schlüssel ja auch irgendwo liegen muss, und wenn der Schlüssel in der Nähe der verschlüsselten Daten liegt, sind diese effektiv nicht verschlüsselt).
Wenn du das Passwort später nicht mehr entschlüsseln können willst/musst, bietet sich ein Hash wie SHA3-512 an. Daraus lässt sich nur extrem schwer das eigentlich Passwort wieder herleiten.
Effektiv hast du damit aber deinen Schwachpunkt nur verschoben.
Letzten Endes kann ein Angreifer mit Debugger immer noch einfach die Stelle der Passwortprüfung suchen und so anpassen, dass das Passwort egal ist.
In erster Instanz ist hier sowas wie UPX empfehlenswert, das modifiziert den Programmcode und bastelt etwas Ladecode drumherum, der das eigentliche Programm beim Start in den RAM entpackt und dann ausführt.
Leider hat auch das zwei Schwachstellen:
1. UPX ist zu bekannt und kann (auch mit UPX) wieder umgekehrt werden (so weit ich mich erinnere xD)
2. da das Programm zur Laufzeit wieder normal im RAM liegt, kann man hier wieder mit dem Debugger ansetzen und dranrum manipulieren.Dann wäre noch der Ansatz Code obfuscation, was aber gegen Profis auch nur mäßig hilft.
Kurz:
sebi707 schrieb:
Wenn das Programm auf meinem PC läuft oder ich die ausführbare Datei habe, dann ist das Programm natürlich hackbar
Im Endeffekt kannst du also nur versuchen, es einem Angreifer so schwer wie möglich zu machen, aber absolute Sicherheit hast du nicht.
Aber im Falle von Passwörtern sind Verschlüsselung und Hashes schonmal ein ganz guter Ansatz.Ebenfalls ist es möglich, festzustellen, ob man gerade debuggt wird.
Allerdings wissen das auch Debugger und die fiesen versuchen auch wieder Tricks,
um zu verbergen, dass sie debuggen :p
-
Danke für deine Antwort
Könnte man das Passwort nicht auf einem Server speichern und die Eingabe mit dem
Passwort auf dem Server vergleichen oder könnte man beim Vergleichen wieder das Passwort auslesen ?
-
Natürlich kannst du die Passwörter auf einem Server haben,
die Nutzereingabe hinschicken und dann vom Server erfahren, ob die Eingaben cool waren.Das scheitert nur dummerweise an mehreren Stellen:
* Du bekommst als Antwort, ob die Daten okay waren und reagierst dann darauf...
vermutlich mit einem if... welches ein Angreifer umbiegen kann...
* Du kommunizierst per Socket... vllt über ein eigenes Protokoll, vllt über ein etabliertes... der Punkt ist, ein Angreifer kann die Kommunikation abgreifen, analysieren und einen eigenen Passwortserver nutzen, der eben in seinem Interesse antwortet (in gewisser Weise sehr vereinfacht das, was MMO Emulatoren tun)Dein erstes Problem lässt sich lösen, in dem du direkt Funktionalität auf den Server auslagerst. Damit ist dein Programm ohne gültige Zugangsdaten nutzlos, weil die ja zusammen mit der eigentlichen Logik auf dem Server liegen.
Das zweite Problem besteht dann immer noch, allerdings hat der Angreifer es wesentlich schwerer, da sein Emulator im Grunde dann auch deine Funktionalität nachbauen müsste. Dann braucht derjenige dein Programm auch nicht mehr xD
Kommen wir aber zum Punkt, dass die Nutzerdaten auf dem Server sind, und deine Anwendung generell mit dem Server für irgendwelches Zeug kommuniziert, weil er auf eine serverseitige Datenbank zugreifen muss, und die verschiedenen Nutzerdaten sind auch mit jeweiligen Berechtigungen auf dem Server gekoppelt.
Wie hackt man das Programm jetzt so, dass man sich als jemand mit mehr Rechten anmelden kann?
Das wiederum lässt sich nicht pauschal beantworten und hängt stark von der Unwissenheit des Entwicklers ab^^Grundsätzlich gilt "Never trust the user", also immer schön Eingaben checken (vor allem auf Serverseite, dein Client ist hier Teil des Users ;-)).
Im Ernstfall ist aber auch nicht dein Programm die Sicherheitslücke, sondern irgendein anderer Teil deiner Infrastruktur... Jetzt kommt der Angreifer auf deinen Server, fummelt an der Serverseite deiner Anwendung rum und schaut sich deine Datenbank an und du hast Spaß
-
Du sendest dem Server einen Hash.
Der Server entscheidet ob der Hash richtig ist.Aber auch da hast du eine Stelle im Programm, wo die Entscheidung fällt.
Und die kann man umgehen.
-
Die sicherste (und einfachste) Methode wäre den Text mit dem Passwort zu verschlüsseln und im Programm als bytearray abzulegen.
Dann kannst du den User um sein Passwort bitten, damit den Text wieder entschlüsseln und eventuell noch überprüfen ob alle Zeichen ASCII sind, anschließend den Text ausgeben.
So kann niemand das Programm "hacken".
-
Lösung in diesem Fall:
Programm schickt Passwort an Server, dieser prüft Korrektheit. Dann schickt der Server die Antwort "Right Password, the cash is in the Apartment 44" zurück. Das, was durch das Passwort geschützt werden soll, verlässt niemals den Server bevor man sich nicht authentifiziert hat.DirkB schrieb:
Du sendest dem Server einen Hash.
Der Server entscheidet ob der Hash richtig ist.Nein, du schickt dem Server das Passwort, dieser hasht es. Denn sonst ist der Hash nur ein Passwort, sprich: Man müsste nicht das Passwort kennen, sondern den richtige Hash.
Die Kommunikation sollte natürlich verschlüsselt erfolgen.
-
Ohne die Information wer an dem "Hack" interessiert ist kann man definitiv keine Aussage über "hackbarkeit" machen
Wenn sich jemand mit den gängigen Tools Olly/IDA/IDA+Hex-Rays usw. auskennt, dein Programm problemlos debuggbar ist, es nur eine Stelle im Code ist wo die Abfrage passiert und diese auch leicht/klar reproduzierbar ist sind die hier genannten Hürden (Hash, Server...) völlig wertlos - sobald die Vergleichs/PasswordValide-Stelle gefunden ist kann man ihn ausschalten, egal ob das per Netswerk, Hash, Server oder sonstwo herkommt - es geht nicht um die Komplexität der Validierung sondern NUR um die Stelle an der entschieden ist das dein Programm den Zugang verweigert
Was hilft dagegen:
Es schwer machen leicht die richtige Stelle zu finden
-Verhindern das es nur ein JMP in den jetzt-geht-es-Anteil ist
-Anti-Debug Tricks um das Debuggen zu verhindern/erschweren
-dein Algorithmus in einem eigenen Interpreter schreiben (pseudo VM) - damit
man nicht so einfach den ASM-Code lesen kann
-die Password-Abfrage an x Stellen in deinem Code verteilen, die x-mal anders Codiert ist
-Anti-Patch Tricks um das verändern der EXE zu erkennen (Signaturprüfungen an x Stellen im Code)
-viel "sinnlosen" Code um die Pruefstellen und auf dem Weg dorthin einstreuen - oder mit dem Algorithmus vermischenProduktbeispiel: http://www.oreans.com/winlicense_features.php unter Protection Features
wobei die Sicherheit durch Verwendung von häufig genutzten Tools nicht besser wird
alles andere ist nur ein Problem für Leute die kein Assembler können, Hex-Rays Ergebnisse nicht interpretieren koennen, den falschen Debugger verwenden oder einfach nicht genug Zeit haben
-
Gast3 schrieb:
alles andere ist nur ein Problem für Leute die kein Assembler können, Hex-Rays Ergebnisse nicht interpretieren koennen, den falschen Debugger verwenden oder einfach nicht genug Zeit haben
Sprich: Nicht-Hacker
-
SeppJ schrieb:
DirkB schrieb:
Du sendest dem Server einen Hash.
Der Server entscheidet ob der Hash richtig ist.Nein, du schickt dem Server das Passwort, dieser hasht es. Denn sonst ist der Hash nur ein Passwort, sprich: Man müsste nicht das Passwort kennen, sondern den richtige Hash.
Die Kommunikation sollte natürlich verschlüsselt erfolgen.
Noch besser wäre "salted challenge response" (SCRAM). Ist aber natürlich nicht mehr in 1-2 Sätzen zu erklären
https://en.wikipedia.org/wiki/Salted_Challenge_Response_Authentication_Mechanism----
Ich wundere mich aber gerade wieso der Vorschlag von DarkShadow44 ignoriert wurde, der ist nämlich gut. Ich persönlich würde noch ne Prüfsumme des Plaintext vergleichen statt nur zu prüfen ob alle Plaintext-Zeichen ASCII sind, aber das sind dann ja Details.
-
wenn ich das Programm verändere ist es völlig egal wie sicher der Passwort-Vergleich ist - also ist eher die Frage was man "hacken" möchte
-das Passwort (damit man als Fremder User das Programm/Account nutzen kann)
-die Kommunikation mit dem Server (das Protokoll)
(da noch: will man die Client-Kommunikation nachbauen können, oder die Kommunikation Hijacken - mitlesen/schreiben)-das Programm selbst (Ziel meines Tips)
wenn ich das richtig verstehe beziehen sich die meisten Tipps hier auf die Absicherung des Passwortes(oder der Kommunikation?) - was aber wie gesagt völlig bedeutungslos ist wenn man das Programm selbst veraendert