Ich muss vertrauliche Informationen (einen symmetrischen Verschlüsselungsschlüssel, den ich privat halten möchte) in meiner C ++ - Anwendung speichern. Der einfache Ansatz besteht darin, dies zu tun:
std::string myKey = "mysupersupersecretpasswordthatyouwillneverguess";
Wenn Sie die Anwendung jedoch durch den strings
Prozess ausführen (oder eine andere, die Zeichenfolgen aus einer binären App extrahiert), wird die obige Zeichenfolge angezeigt.
Welche Techniken sollten verwendet werden, um solche sensiblen Daten zu verschleiern?
Bearbeiten:
OK, so ziemlich alle von Ihnen haben gesagt "Ihre ausführbare Datei kann rückentwickelt werden" - natürlich! Dies ist ein Liebling von mir, also werde ich hier ein bisschen schimpfen:
Warum werden 99% (OK, vielleicht übertreibe ich ein wenig) aller sicherheitsrelevanten Fragen auf dieser Website mit dem Strom "Es gibt keine Möglichkeit, ein perfekt sicheres Programm zu erstellen" beantwortet - das ist nicht hilfreich Antworten! Sicherheit ist eine gleitende Skala zwischen perfekter Benutzerfreundlichkeit und keiner Sicherheit an einem Ende und perfekter Sicherheit, aber keiner Benutzerfreundlichkeit am anderen Ende.
Der Punkt ist, dass Sie Ihre Position auf dieser gleitenden Skala auswählen, je nachdem, was Sie versuchen und in welcher Umgebung Ihre Software ausgeführt wird. Ich schreibe keine App für eine militärische Installation, ich schreibe eine App für einen Heim-PC . Ich muss Daten über ein nicht vertrauenswürdiges Netzwerk mit einem bekannten Verschlüsselungsschlüssel verschlüsseln. In diesen Fällen ist "Sicherheit durch Dunkelheit" wahrscheinlich gut genug! Sicher, jemand mit genügend Zeit, Energie und Geschick könnte die Binärdatei rückentwickeln und das Passwort finden, aber wissen Sie was? Es ist mir egal:
Die Zeit, die ich für die Implementierung eines erstklassigen sicheren Systems benötige, ist teurer als der Umsatzverlust aufgrund der geknackten Versionen (nicht, dass ich das tatsächlich verkaufe, aber Sie verstehen, worum es geht). Dieser Trend des Programmierens unter den Programmierern unter neuen Programmierern ist, gelinde gesagt, dumm.
Vielen Dank, dass Sie sich die Zeit genommen haben, diese Frage zu beantworten - sie waren sehr hilfreich. Leider kann ich nur eine Antwort akzeptieren, aber ich habe alle nützlichen Antworten hochgestimmt.
Antworten:
Grundsätzlich kann und wird jeder, der Zugriff auf Ihr Programm und einen Debugger hat , den Schlüssel in der Anwendung finden, wenn er möchte.
Wenn Sie jedoch nur sicherstellen möchten, dass der Schlüssel beim Ausführen
strings
Ihrer Binärdatei nicht angezeigt wird, können Sie beispielsweise sicherstellen, dass der Schlüssel nicht im druckbaren Bereich liegt.Verdeckter Schlüssel mit XOR
Sie können beispielsweise XOR verwenden, um den Schlüssel in zwei Byte-Arrays aufzuteilen:
Wenn Sie key1 mit derselben Bytelänge erstellen, wie
key
Sie (vollständig) zufällige Bytewerte verwenden können, und dann Folgendes berechnenkey2
:Sie können in Ihrer Build - Umgebung tun dies, und auch nur dann speichern
key1
undkey2
in Ihrer Anwendung.Schützen Sie Ihre Binärdatei
Ein anderer Ansatz besteht darin, ein Tool zum Schutz Ihrer Binärdatei zu verwenden. Beispielsweise gibt es mehrere Sicherheitstools, mit denen sichergestellt werden kann, dass Ihre Binärdatei verschleiert ist und eine virtuelle Maschine gestartet wird, auf der sie ausgeführt wird. Dies erschwert das Debuggen und ist auch die übliche Art und Weise, wie viele kommerzielle sichere Anwendungen (leider auch Malware) geschützt werden.
Eines der wichtigsten Tools ist Themida , das Ihre Binärdateien hervorragend schützt. Es wird häufig von bekannten Programmen wie Spotify zum Schutz vor Reverse Engineering verwendet. Es verfügt über Funktionen zum Verhindern des Debuggens in Programmen wie OllyDbg und Ida Pro.
Es gibt auch eine größere, möglicherweise etwas veraltete Liste von Tools zum Schutz Ihrer Binärdatei .
Einige von ihnen sind kostenlos.
Passwortabgleich
Jemand hier hat über Hashing-Passwort + Salt gesprochen.
Wenn Sie den Schlüssel speichern müssen, um ihn mit einem vom Benutzer übermittelten Kennwort abzugleichen, sollten Sie eine Einweg-Hashing-Funktion verwenden, vorzugsweise durch Kombinieren von Benutzername, Kennwort und Salt. Das Problem dabei ist jedoch, dass Ihre Anwendung das Salz kennen muss, um die Einbahnstraße ausführen und die resultierenden Hashes vergleichen zu können. Daher müssen Sie das Salz immer noch irgendwo in Ihrer Anwendung aufbewahren. Wie @Edward in den Kommentaren unten ausführt, schützt dies jedoch effektiv vor einem Wörterbuchangriff, bei dem beispielsweise Regenbogentabellen verwendet werden.
Schließlich können Sie eine Kombination aller oben genannten Techniken verwenden.
quelle
Stellen Sie zunächst fest, dass Sie nichts tun können, was einen ausreichend entschlossenen Hacker aufhält, und es gibt viele davon. Der Schutz für jedes Spiel und jede Konsole ist irgendwann aufgehoben, daher ist dies nur eine vorübergehende Korrektur.
Es gibt 4 Dinge, die Sie tun können, um Ihre Chancen zu erhöhen, eine Weile verborgen zu bleiben.
1) Verstecken Sie die Elemente der Zeichenfolge auf irgendeine Weise - etwas Offensichtliches wie das Xoring (der Operator ^) der Zeichenfolge mit einer anderen Zeichenfolge ist gut genug, um die Suche nach der Zeichenfolge unmöglich zu machen.
2) Teilen Sie die Zeichenfolge in Teile auf - teilen Sie die Zeichenfolge auf und fügen Sie Teile davon in seltsam benannte Methoden in seltsamen Modulen ein. Machen Sie es sich nicht leicht, die Methode mit der Zeichenfolge zu durchsuchen und zu finden. Natürlich muss eine Methode alle diese Bits aufrufen, aber es macht es immer noch etwas schwieriger.
3) Erstellen Sie die Zeichenfolge niemals im Speicher - die meisten Hacker verwenden Tools, mit denen sie die Zeichenfolge im Speicher sehen können, nachdem Sie sie codiert haben. Wenn möglich, vermeiden Sie dies. Wenn Sie beispielsweise den Schlüssel an einen Server senden, senden Sie ihn zeichenweise, damit die gesamte Zeichenfolge nie vorhanden ist. Wenn Sie es mit einer RSA-Codierung verwenden, ist dies natürlich schwieriger.
4) Führen Sie einen Ad-hoc-Algorithmus durch - fügen Sie zusätzlich ein oder zwei eindeutige Wendungen hinzu. Fügen Sie einfach 1 zu allem hinzu, was Sie produzieren, oder führen Sie eine Verschlüsselung zweimal durch oder fügen Sie einen Zucker hinzu. Dies macht es für den Hacker, der bereits weiß, wonach er suchen muss, wenn jemand beispielsweise Vanilla MD5-Hashing oder RSA-Verschlüsselung verwendet, etwas schwieriger.
Stellen Sie vor allem sicher, dass es nicht zu wichtig ist, wann (und wenn Ihre Anwendung populär genug wird) Ihr Schlüssel entdeckt wird!
quelle
Eine Strategie, die ich in der Vergangenheit verwendet habe, besteht darin, eine Reihe von scheinbar zufälligen Zeichen zu erstellen. Sie fügen zunächst Ihre bestimmten Zeichen ein und suchen sie dann mit einem algebraischen Prozess, wobei jeder Schritt von 0 bis N eine Zahl <Größe des Arrays ergibt, das das nächste Zeichen in Ihrer verschleierten Zeichenfolge enthält. (Diese Antwort fühlt sich jetzt verschleiert an!)
Beispiel:
Bei einer Reihe von Zeichen (Zahlen und Bindestriche dienen nur als Referenz)
Und eine Gleichung, deren erste sechs Ergebnisse sind: 3, 6, 7, 10, 21, 47
Würde das Wort "HALLO!" aus dem Array oben.
quelle
Ich stimme @Checkers zu, Ihre ausführbare Datei kann rückentwickelt werden.
Ein bisschen besser ist es, es dynamisch zu erstellen, zum Beispiel:
quelle
Das Speichern privater Daten in Software, die an den Benutzer gesendet wird, ist natürlich immer ein Risiko. Jeder ausreichend ausgebildete (und engagierte) Ingenieur kann die Daten rückentwickeln.
Abgesehen davon können Sie häufig die Sicherheit erhöhen, indem Sie die Barriere erhöhen, die die Benutzer überwinden müssen, um Ihre privaten Daten preiszugeben. Das ist normalerweise ein guter Kompromiss.
In Ihrem Fall könnten Sie Ihre Zeichenfolgen mit nicht druckbaren Daten überladen und diese dann zur Laufzeit mithilfe einer einfachen Hilfsfunktion wie folgt dekodieren:
quelle
Ich habe ein einfaches Verschlüsselungswerkzeug für Zeichenfolgen erstellt. Es kann automatisch verschlüsselte Zeichenfolgen generieren und verfügt über einige zusätzliche Optionen, einige Beispiele:
Zeichenfolge als globale Variable:
Als Unicode-String mit Entschlüsselungsschleife:
Zeichenfolge als globale Variable:
quelle
Etwas abhängig von dem, was Sie schützen wollen, wie Joshperry hervorhebt. Aus Erfahrung würde ich sagen, wenn es Teil eines Lizenzierungsschemas zum Schutz Ihrer Software ist, dann stören Sie sich nicht. Sie werden es eventuell zurückentwickeln. Verwenden Sie einfach eine einfache Chiffre wie ROT-13, um sie vor einfachen Angriffen zu schützen (darüber laufende Strings). Wenn es darum geht, sensible Daten für Benutzer zu schützen, würde ich mich fragen, ob der Schutz dieser Daten mit einem lokal gespeicherten privaten Schlüssel sinnvoll ist. Wieder kommt es darauf an, was Sie schützen wollen.
EDIT: Wenn Sie es tun wollen, dann ist eine Kombination von Techniken, auf die Chris hinweist, weitaus besser als rot13.
quelle
Wie bereits gesagt, gibt es keine Möglichkeit, Ihre Saite vollständig zu schützen. Es gibt jedoch Möglichkeiten, es mit angemessener Sicherheit zu schützen.
Als ich dies tun musste, habe ich eine unschuldig aussehende Zeichenfolge in den Code eingefügt (z. B. einen Copyright-Hinweis oder eine gefälschte Benutzeraufforderung oder irgendetwas anderes, das nicht von jemandem geändert wird, der nicht verwandten Code repariert), und diese mit sich selbst verschlüsselt Als Schlüssel habe ich das gehasht (etwas Salz hinzugefügt) und das Ergebnis als Schlüssel verwendet, um das zu verschlüsseln, was ich eigentlich verschlüsseln wollte.
Natürlich könnte dies gehackt werden, aber es braucht einen entschlossenen Hacker, um dies zu tun.
quelle
Wenn Sie unter Windows-Benutzer DPAPI arbeiten, rufen Sie http://msdn.microsoft.com/en-us/library/ms995355.aspx auf
Wie bereits in einem früheren Beitrag erwähnt, verwenden Sie den Schlüsselbund, wenn Sie einen Mac verwenden.
Grundsätzlich sind all diese niedlichen Ideen, wie Sie Ihren privaten Schlüssel in Ihrer Binärdatei speichern können, aus Sicherheitsgründen so schlecht, dass Sie sie nicht tun sollten. Jeder, der Ihren privaten Schlüssel erhält, ist eine große Sache. Behalten Sie ihn nicht in Ihrem Programm. Abhängig davon, wie wichtig Ihre App ist, können Sie Ihre privaten Schlüssel auf einer Smartcard, auf einem Remotecomputer, mit dem Ihr Code kommuniziert, aufbewahren oder das tun, was die meisten Benutzer tun, und sie an einem sehr sicheren Ort auf dem lokalen Computer aufbewahren (den "Schlüssel" store "(das ist wie eine seltsame sichere Registrierung), die durch Berechtigungen und die ganze Stärke Ihres Betriebssystems geschützt ist.
Dies ist ein gelöstes Problem und die Antwort ist NICHT, den Schlüssel in Ihrem Programm zu behalten :)
quelle
Versuchen Sie dies . Im Quellcode wird erläutert, wie alle Zeichenfolgen in einem bestimmten Visual Studio c ++ - Projekt im laufenden Betrieb verschlüsselt und entschlüsselt werden.
quelle
Eine Methode, die ich kürzlich ausprobiert habe, ist:
part1
part2
part1
und verwendenpart2
part1
. Es wird die Integrität privater Daten überprüft.MAKRO zum Auffüllen von Daten:
Angenommen, private Daten bestehen aus 4 Bytes. Wir definieren dafür ein Makro, das die Daten mit Zuweisungsanweisungen in zufälliger Reihenfolge speichert.
Verwenden Sie dieses Makro nun in Code, in dem Sie speichern müssen,
part1
undpart2
wie folgt:quelle
Anstatt einen privaten Schlüssel in Ihrer ausführbaren Datei zu speichern, möchten Sie ihn möglicherweise vom Benutzer anfordern und über einen externen Kennwortmanager speichern , ähnlich wie bei Mac OS X Keychain Access.
quelle
Kontextabhängig, aber Sie können einfach den Hash des Schlüssels plus ein Salz speichern (konstante Zeichenfolge, leicht zu verdecken).
Wenn der Benutzer den Schlüssel eingibt, fügen Sie das Salz hinzu , berechnen den Hash und vergleichen.
Das Salz ist in diesem Fall wahrscheinlich nicht erforderlich. Es stoppt einen Brute-Force-Wörterbuchangriff, wenn der Hash isoliert werden kann (eine Google-Suche funktioniert ebenfalls).
Ein Hacker muss immer noch irgendwo eine jmp-Anweisung einfügen, um das ganze Los zu umgehen, aber das ist etwas komplizierter als eine einfache Textsuche.
quelle
Es gibt ein (sehr leicht) Kopf nur Projekt obfuscate von adamyaxley gefertigt, die perfekt funktioniert. Es basiert auf Lambda-Funktionen und Makros und verschlüsselt Zeichenfolgen zur Kompilierungszeit mit einer XOR-Verschlüsselung. Bei Bedarf können wir den Startwert für jede Zeichenfolge ändern.
Der folgende Code speichert die Zeichenfolge "Hallo Welt" nicht in der kompilierten Binärdatei.
Ich habe mit C ++ 17 und Visual Studio 2019 getestet und überprüfe über IDA, ob die Zeichenfolge ausgeblendet ist. Ein wertvoller Vorteil gegenüber ADVobfuscator ist, dass es in einen std :: string konvertierbar ist (während es immer noch in der kompilierten Binärdatei versteckt ist):
quelle