105 Stimmen

Techniken zur Verschleierung sensibler Zeichenketten in C++

Ich muss sensible Informationen (einen symmetrischen Verschlüsselungsschlüssel, den ich geheim halten möchte) in meiner C++-Anwendung speichern. Der einfache Ansatz ist dieser:

std::string myKey = "mysupersupersecretpasswordthatyouwillneverguess";

Wenn Sie die Anwendung jedoch über den strings Prozess (oder jeder andere, der Zeichenketten aus einer binären Anwendung extrahiert) wird die obige Zeichenkette aufdecken.

Welche Techniken sollten verwendet werden, um solche sensiblen Daten zu verbergen?

Edita:

OK, also haben so ziemlich alle von Ihnen gesagt "Ihre ausführbare Datei kann zurückentwickelt werden" - natürlich! Das ist eines meiner Lieblingsärgernisse, also werde ich hier ein bisschen schimpfen:

Warum werden 99% (OK, vielleicht übertreibe ich ein wenig) aller sicherheitsrelevanten Fragen auf dieser Website mit einem Schwall von "es gibt keine Möglichkeit, ein perfekt sicheres Programm zu erstellen" beantwortet - das ist keine hilfreiche Antwort! Sicherheit ist eine gleitende Skala zwischen perfekter Benutzerfreundlichkeit und keiner Sicherheit am einen Ende und perfekter Sicherheit aber keiner Benutzerfreundlichkeit am anderen Ende.

Der Punkt ist, dass Sie Ihre Position auf dieser gleitenden Skala wählen, je nachdem, was Sie zu tun versuchen und die Umgebung, in der Ihre Software laufen wird. Ich schreibe keine Anwendung für eine Militäreinrichtung, sondern eine Anwendung für einen Heim-PC. . Ich muss Daten über ein nicht vertrauenswürdiges Netz mit einem bekannten Verschlüsselungscode verschlüsseln. In diesen Fällen ist "Sicherheit durch Unklarheit" wahrscheinlich gut genug! Sicher, jemand mit genügend Zeit, Energie und Geschick könnte das Binärprogramm zurückentwickeln und das Passwort herausfinden, aber was soll's? Es ist mir egal:

Die Zeit, die ich benötige, um ein erstklassiges sicheres System zu implementieren, ist teurer als die Umsatzeinbußen durch die geknackten Versionen (nicht dass ich das tatsächlich verkaufen würde, aber Sie verstehen, worauf ich hinaus will). Dieser blauäugige "Wir machen es auf die absolut bestmögliche Art und Weise"-Trend in der Programmierung unter neuen Programmierern ist gelinde gesagt töricht.

Vielen Dank, dass Sie sich die Zeit genommen haben, diese Fragen zu beantworten - sie waren sehr hilfreich. Leider kann ich nur eine Antwort akzeptieren, aber ich habe alle nützlichen Antworten hochgestuft.

47voto

csl Punkte 10539

Im Grunde kann jeder, der Zugang zu Ihrem Programm und einem Debugger hat kann y wird den Schlüssel in der Anwendung finden, wenn sie das möchten.

Wenn Sie aber nur sicherstellen wollen, dass der Schlüssel nicht angezeigt wird, wenn Sie strings auf Ihrer Binärdatei können Sie zum Beispiel sicherstellen, dass der Schlüssel nicht im druckbaren Bereich liegt.

Schlüssel mit XOR verschlüsseln

Sie könnten zum Beispiel XOR verwenden, um den Schlüssel in zwei Byte-Arrays aufzuteilen:

key = key1 XOR key2

Wenn Sie Schlüssel1 mit der gleichen Bytelänge erstellen wie key können Sie (völlig) zufällige Byte-Werte verwenden und dann berechnen key2 :

key1[n] = crypto_grade_random_number(0..255)
key2[n] = key[n] XOR key1[n]

Sie können dies in Ihrer Build-Umgebung tun, und dann nur key1 y key2 in Ihrer Bewerbung.

Schutz des Binärcodes

Eine andere Möglichkeit ist der Einsatz eines Tools zum Schutz Ihrer Binärdateien. Es gibt zum Beispiel mehrere Sicherheitstools, die dafür sorgen, dass Ihre Binärdatei verschleiert wird und eine virtuelle Maschine startet, auf der sie läuft. Dies erschwert die Fehlersuche und ist auch die übliche Methode zum Schutz vieler kommerzieller sicherer Anwendungen (leider auch von Malware).

Eines der wichtigsten Instrumente ist Themida , das Ihre Binärdateien hervorragend schützt. Es wird oft von bekannten Programmen wie Spotify verwendet, um sich vor Reverse Engineering zu schützen. Es verfügt über Funktionen, die das Debuggen in Programmen wie OllyDbg und Ida Pro verhindern.

Es gibt auch eine größere, vielleicht etwas veraltete Liste von Tools zum Schutz Ihrer Binärdateien .
Einige von ihnen sind kostenlos.

Passwortabgleich

Jemand hat hier über das Hashing von Passwort+Salz diskutiert.

Wenn Sie den Schlüssel speichern müssen, um ihn mit einem vom Benutzer übermittelten Passwort abzugleichen, sollten Sie eine Einweg-Hash-Funktion verwenden, vorzugsweise durch Kombination von Benutzername, Passwort und einem Salt. Das Problem dabei ist jedoch, dass Ihre Anwendung das Salt kennen muss, um die Einweg-Hash-Funktion durchführen und die resultierenden Hashes vergleichen zu können. Sie müssen das Salt also immer noch irgendwo in Ihrer Anwendung speichern. Aber wie @Edward in den Kommentaren unten anmerkt, bietet dies einen wirksamen Schutz gegen einen Wörterbuchangriff, z. B. mit Rainbow-Tables.

Schließlich können Sie auch eine Kombination aller oben genannten Techniken anwenden.

13voto

Malick Punkte 5252

Es gibt ein (sehr leichtes) reines Header-Projekt vernebeln hergestellt von adamyaxley, das perfekt funktioniert. Es basiert auf Lambda-Funktionen und Makros und verschlüsselt Zeichenketten litteral mit einer XOR-Chiffre zur Kompilierungszeit. Bei Bedarf können wir den Seed für jede Zeichenkette ändern.

Der folgende Code speichert die Zeichenkette "hello world" nicht in der kompilierten Binärdatei.

#include "obfuscate.h"

int main()
{
  std::cout << AY_OBFUSCATE("Hello World") << std::endl;
  return 0;
}

Ich habe mit C++17 und Visual Studio 2019 getestet und über IDA überprüft und ich bestätige, dass die Zeichenfolge ausgeblendet ist. Ein wertvoller Vorteil im Vergleich zu ADVobfuscator ist, dass er in einen std::string konvertiert werden kann (während er in der kompilierten Binärdatei noch versteckt ist):

std::string var = AY_OBFUSCATE("string");

10voto

Chris Jefferson Punkte 7272

Zunächst einmal sollten Sie sich darüber im Klaren sein, dass Sie nichts tun können, um einen hinreichend entschlossenen Hacker aufzuhalten, und davon gibt es viele. Der Schutz jedes Spiels und jeder Konsole wird irgendwann geknackt, also ist dies nur eine vorübergehende Lösung.

Es gibt 4 Dinge, die Sie tun können, um Ihre Chancen zu erhöhen, eine Zeit lang unentdeckt zu bleiben.

1) Verstecken Sie die Elemente der Zeichenkette auf irgendeine Art und Weise - etwas Offensichtliches wie das Verknüpfen (der Operator ^) der Zeichenkette mit einer anderen Zeichenkette reicht aus, um die Suche nach der Zeichenkette unmöglich zu machen.

2) Teilen Sie die Zeichenkette in Stücke auf - teilen Sie Ihre Zeichenkette auf und packen Sie Teile davon in seltsam benannte Methoden in seltsamen Modulen. Machen Sie es nicht einfach, die Methode mit der Zeichenkette darin zu finden. Natürlich wird irgendeine Methode all diese Teile aufrufen müssen, aber das macht es immer noch ein wenig schwieriger.

3) Bauen Sie die Zeichenfolge niemals im Speicher auf - die meisten Hacker verwenden Tools, mit denen sie die Zeichenfolge im Speicher sehen können, nachdem Sie sie verschlüsselt haben. Vermeiden Sie dies nach Möglichkeit. Wenn Sie zum Beispiel den Schlüssel an einen Server senden, senden Sie ihn zeichenweise, so dass nie die gesamte Zeichenkette vorhanden ist. Wenn Sie den Schlüssel z. B. mit einer RSA-Verschlüsselung verwenden, ist dies natürlich schwieriger.

4) Führen Sie einen Ad-hoc-Algorithmus durch - und fügen Sie obendrein noch ein oder zwei einzigartige Elemente hinzu. Vielleicht addieren Sie einfach 1 zu allem, was Sie produzieren, oder führen jede Verschlüsselung zweimal durch, oder fügen einen Zucker hinzu. Das macht es dem Hacker etwas schwerer, der bereits weiß, worauf er achten muss, wenn jemand z. B. md5-Hashing oder RSA-Verschlüsselung verwendet.

Stellen Sie vor allem sicher, dass es nicht zu wichtig ist, wenn (und das wird es, wenn Ihre Anwendung populär genug wird) Ihr Schlüssel entdeckt wird!

7voto

Paul Sasik Punkte 76202

Eine Strategie, die ich in der Vergangenheit verwendet habe, besteht darin, eine Reihe von scheinbar zufälligen Zeichen zu erstellen. Man fügt es zunächst ein und findet dann die gewünschten Zeichen mit einem algebraischen Verfahren, bei dem jeder Schritt von 0 bis N eine Zahl < Größe des Arrays ergibt, die das nächste Zeichen in der 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)

0123456789
----------
ALFHNFELKD
LKFKFLEHGT
FLKRKLFRFK
FJFJJFJ!JL

Und eine Gleichung, deren erste sechs Ergebnisse sind: 3, 6, 7, 10, 21, 47

würde das Wort "HALLO!" aus dem obigen Array ergeben.

5voto

Nick Dandoulakis Punkte 41402

Ich stimme @Checkers zu, Ihre ausführbare Datei kann zurückentwickelt werden.

Ein etwas besserer Weg ist zum Beispiel, sie dynamisch zu erstellen:

std::string myKey = part1() + part2() + ... + partN();

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X