Sichere Speicherzuordnung in C ++

8

Ich möchte einen Zuordner erstellen, der Speicher mit den folgenden Attributen zur Verfügung stellt:

  • kann nicht auf die Festplatte ausgelagert werden.
  • ist unglaublich schwer über einen angehängten Debugger
  • zu erreichen

Die Idee ist, dass dies vertrauliche Informationen (wie Lizenzinformationen) enthält, auf die der Benutzer keinen Zugriff haben sollte. Ich habe die üblichen Recherchen online durchgeführt und ein paar andere Leute dazu befragt, aber ich kann keinen guten Startpunkt für dieses Problem finden.

Aktualisierungen

Josh erwähnt, dass VirtualAlloc verwendet wird, um den Schutz für den Speicherplatz festzulegen . Ich habe einen benutzerdefinierten Zuordner erstellt (siehe unten). Ich habe festgestellt, dass die Funktion VirtualLock die Speichermenge begrenzt, die ich zuweisen kann. Dies scheint jedoch von Entwurf zu sein. Da ich es für kleine Objekte verwende, ist das kein Problem.

%Vor%

und wird verwendet

%Vor%

Ted Percival erwähnt mlock, aber ich habe noch keine Implementierung davon .

Ich fand Practical Cryptography von Neil Furguson und Bruce Schneier auch sehr hilfreich.

    
roo 12.08.2008, 04:18
quelle

13 Antworten

18

Sie können nicht wirklich vor dem Speicherzugriff schützen. Sie können das Paging wahrscheinlich verhindern, wenn Sie als Administrator oder als System arbeiten, aber Sie können nicht verhindern, dass der Administrator oder das System Ihren Speicher liest. Selbst wenn Sie andere Prozesse irgendwie daran hindern könnten, Ihren Speicher zu lesen (was Sie nicht können), könnte ein anderer Prozess tatsächlich einen neuen Thread in Ihren Prozess einfügen und den Speicher auf diese Weise lesen.

Auch wenn Sie Ihren Prozess irgendwie vollständig sperren und sicherstellen könnten, dass das Betriebssystem niemals anderen Personen den Zugriff auf Ihren Prozess ermöglicht, haben Sie immer noch keinen vollständigen Schutz. Das gesamte Betriebssystem könnte auf einer virtuellen Maschine ausgeführt werden, die jederzeit angehalten und überprüft werden kann.

Sie können Speicherinhalte nicht vom Eigentümer des Systems schützen. Hollywood und die Musikindustrie haben seit Jahren dafür gesorgt. Wenn es möglich wäre, würden sie es schon tun.

    
Derek Park 12.08.2008, 05:17
quelle
5

Wenn Sie für Windows entwickeln, gibt es Möglichkeiten, den Zugriff auf den Arbeitsspeicher zu beschränken, aber das vollständige Blockieren anderer ist nicht möglich. Wenn Sie hoffen, ein geheimes Geheimnis zu bewahren, lesen Sie Secure Code schreiben - die dieses Problem einigermaßen anspricht, aber beachten Sie, dass Sie nicht wissen können, ob Ihr Code auf einem echten Computer oder einer virtuellen Maschine ausgeführt wird. Es gibt eine Menge Win32-API-Kram, der sich mit solchen Dingen beschäftigt, einschließlich der sicheren Aufbewahrung von Geheimnissen - das Buch spricht darüber. Sie können sich die Microsoft CyproAPI Details anzeigen lassen. Die OS-Designer erkennen genau dieses Problem und die Notwendigkeit, den Klartext sicher zu halten (lesen Sie erneut Sicherer Code schreiben ).

Die Win32-API-Funktion VirtualAlloc ist der Speicher auf Betriebssystemebene Zuweiser. Damit können Sie den Zugriffsschutz einstellen. Sie können den Zugriff auf PAGE_GUARD oder PAGE_NOACCESS ändern und den Zugriff auf etwas freundlicheres ändern, während Ihr Programm liest und danach zurücksetzt, aber das ist nur ein schneller Höcker, wenn jemand wirklich versucht, Ihr Geheimnis zu sehen .

Zusammenfassend können Sie sich die Crypto-APIs auf Ihrer Plattform ansehen, die das Problem besser angehen als etwas, das Sie selbst hacken.

    
Josh 26.08.2008 01:16
quelle
5

Nehmen wir das Stück für Stück:

  

Ich möchte einen Allokator erstellen, der   bietet Speicher mit folgenden   Attribute:

Das ist fair genug.

%Vor%

Das wird schwer werden. Soweit mir bekannt ist, können Sie Virtual Paging nicht so deaktivieren, wie es vom Betriebssystem gehandhabt wird. Wenn es einen Weg gibt, dann wirst du in den Tiefen des OS speln.

%Vor%

Sie können es über PGP ausführen und es verschlüsselt im Speicher speichern und es bei Bedarf entschlüsseln. Massive Leistung getroffen.

  

Die Idee ist, dass dies enthalten wird   sensible Informationen (wie Lizenz   Informationen), die sein sollten   für den Benutzer nicht zugänglich. Ich habe es getan   die übliche Recherche online und fragte a   wenige andere Leute darüber, aber ich   Ich kann keinen guten Platz finden   Problem.

Halten Sie alle vertraulichen Informationen vom Gerät fern. Ernst. Speichern Sie keine vertraulichen Informationen im Speicher. Schreiben Sie eine benutzerdefinierte Löschroutine, die automatisch alle Daten aus den von Ihnen ausgeführten Zuordnungen löscht. Niemals den allgemeinen Zugang zu einer Maschine mit empfindlichem Material erlauben. Wenn Sie den Datenbankzugriff ausführen, stellen Sie sicher, dass der gesamte Zugriff vor dem Brennen bereinigt wurde. Nur Personen mit bestimmten Anmeldedaten dürfen zugreifen. Kein allgemeiner Gruppenzugriff.

  

Nebenbei bemerkt, welche anderen Methoden sind   dort auf den Speicher eines zugreifen   Prozess anders als das Anfügen eines   Debugger?

Einen Speicherauszug machen.

    
graham.reeds 12.08.2008 05:13
quelle
4

Auf Unix-Systemen können Sie mlock (2) verwenden, um Speicherseiten im RAM zu sperren und so zu verhindern, dass sie ausgelagert werden .

  

mlock () und mlockall () sperren jeweils einen Teil oder alle Anrufe   den virtuellen Adressraum des Prozesses in den RAM-Speicher und verhindert, dass der Speicher   in den Swap-Bereich ausgelagert werden.

Es gibt eine Grenze dafür, wie viel Speicher jeder Prozess sperren kann, er kann mit ulimit -l angezeigt werden und wird in Kilobyte gemessen. Auf meinem System beträgt das Standardlimit 32 kB pro Prozess.

    
Ted Percival 02.09.2008 02:25
quelle
3

Installieren Sie Libsodium, verwenden Sie Zuweisungsmechanismen durch # include <sodium.h>

Bewachte Heapzuweisungen

Langsamer als malloc () und Freunde benötigen sie 3 oder 4 zusätzliche Seiten virtuellen Speichers.

%Vor%

Weisen Sie Speicher zu, um vertrauliche Daten mit sodium_malloc() und sodium_allocarray() zu speichern. Sie müssen zuerst sodium_init() aufrufen, bevor Sie diese Heap-Wächter verwenden.

%Vor%

Die sodium_allocarray() -Funktion gibt einen Zeiger zurück, von dem jeweils auf Zählobjekte zugegriffen werden kann, die die Größe von Bytes des Speichers haben. Es bietet dieselben Garantien wie sodium_malloc() , schützt aber auch vor arithmetischen Überläufen, wenn count * size SIZE_MAX überschreitet.

Diese Funktionen fügen Schutzseiten um die geschützten Daten hinzu, um sie in einem Heartbleed-ähnlichen Szenario weniger zugänglich zu machen.

Darüber hinaus kann der Schutz für Speicherbereiche, die auf diese Weise zugeordnet sind, mit den sperrenden Speicheroperationen geändert werden: sodium_mprotect_noaccess() , sodium_mprotect_readonly() und sodium_mprotect_readwrite() .

Nach sodium_malloc können Sie sodium_free() zum Entsperren und Freigeben von Speicher verwenden. An diesem Punkt in Ihrer Implementierung sollten Sie den Speicher nach der Verwendung auf Null setzen.

Zerlege den Speicher nach der Verwendung

%Vor%

Nach der Verwendung sollten sensible Daten überschrieben werden, aber memset () und handgeschriebener Code können automatisch durch einen optimierenden Compiler oder den Linker entfernt werden.

Die Funktion sodium_memzero () versucht, len Bytes beginnend mit pnt effektiv zu zerlegen, selbst wenn Optimierungen auf den Code angewendet werden.

Sperrt die Speicherbelegung

%Vor%

Die Funktion sodium_mlock() sperrt mindestens len Bytes des Speichers ab addr. Auf diese Weise können Sie verhindern, dass vertrauliche Daten auf die Festplatte ausgelagert werden.

%Vor%

Die Funktion sodium_mprotect_noaccess () macht eine Region unzugänglich, die mithilfe von sodium_malloc () oder sodium_allocarray () zugewiesen wurde. Es kann nicht gelesen oder geschrieben werden, aber die Daten bleiben erhalten. Diese Funktion kann verwendet werden, um vertrauliche Daten unzugänglich zu machen, außer wenn sie tatsächlich für eine bestimmte Operation benötigt werden.

%Vor%

Die Funktion sodium_mprotect_readonly () markiert eine Region, die mit natrium_malloc () oder natrium_allocarray () als schreibgeschützt zugewiesen wurde. Wenn Sie versuchen, die Daten zu ändern, wird der Prozess beendet.

%Vor%

Die Funktion sodium_mprotect_readwrite() markiert eine Region, die mit sodium_malloc() oder sodium_allocarray() als lesbar und schreibbar zugewiesen wurde, nachdem sie mit sodium_mprotect_readonly() oder sodium_mprotect_noaccess() geschützt wurde.

    
Bent Cardan 06.11.2015 13:45
quelle
2

Was Sie fordern, wird auf Betriebssystemebene behandelt. Sobald die Daten in Ihrem Programm sind, wird es wahrscheinlich ausgelagert.

Für den Zugriff auf den Speicher kann eine motivierte Person einen Hardware-Debugger anhängen.

    
Mark Harrison 12.08.2008 05:07
quelle
1

@graham

  

Sie können es über PGP ausführen und es verschlüsselt im Speicher speichern und es bei Bedarf entschlüsseln. Massive Leistung getroffen.

Dann müssten Sie den Schlüssel im Speicher halten. Das würde es etwas schwieriger machen, aber definitiv nicht unmöglich. Jeder, der motiviert ist, wird es schaffen, die Daten aus dem Speicher zu holen.

    
Derek Park 12.08.2008 05:21
quelle
0

Am besten ist es, etwas Ähnliches wie die SecureString-Klasse von .NET zu implementieren und darauf zu achten, dass alle Klartextkopien Ihrer Daten sofort gelöscht werden (vergessen Sie nicht, das Programm zu bereinigen, auch wenn Ausnahmen ausgelöst werden). Eine gute Möglichkeit, dies mit std :: string zu tun, ist die Verwendung eines benutzerdefinierten Zuordners .

Wenn Sie unter Windows CryptProtectMemory (oder RtlEncryptMemory für ältere Systeme) verwenden, wird das Verschlüsselungskennwort in nicht umlagerbarem (Kernel?) Speicher gespeichert. In meinen Tests sind diese Funktionen ziemlich verdammt schnell, insb. unter Berücksichtigung des Schutzes, den sie Ihnen geben.

Auf anderen Systemen verwende ich gerne Blowfish, da es eine gute Mischung aus Geschwindigkeit und Stärke ist. In letzterem Fall müssen Sie beim Programmstart nach dem Zufallsprinzip Ihr ​​eigenes Passwort (16+ Byte Entropie für Blowfish) generieren. Leider gibt es nicht viel, was Sie tun können, um dieses Passwort ohne Betriebssystemunterstützung zu schützen, obwohl Sie allgemeine Verschleierungstechniken verwenden könnten, um einen hartcodierten Salt-Wert in Ihre ausführbare Datei einzubetten, den Sie mit dem Passwort kombinieren können (jedes bisschen hilft).

Insgesamt ist diese Strategie nur ein Teil eines breiter angelegten Defense-in-Depth-Ansatzes. Denken Sie auch daran, dass einfache Fehler wie Pufferüberläufe und das Bereinigen von Programmeingaben bei weitem die häufigsten Angriffsvektoren bleiben.

    
kgriffs 31.10.2011 22:05
quelle
0
  

Sie können den Speicherinhalt nicht vom Eigentümer des Systems schützen.   Hollywood und die Musikindustrie haben seit Jahren dafür gesorgt.   Wenn es möglich wäre, würden sie es schon tun.

Haben Sie sich Vista angesehen (und darüber) Geschützte Prozesse (direkt .doc herunterladen ). Ich glaube, dass der Schutz durch den Betriebssystem-Schutz der Unterhaltungsindustrie zu Gute kommt.

    
Jeffrey Walton 22.08.2010 16:38
quelle
-1

@Derek: Oh, aber mit Trusted Computing können Sie Memory Curtaining verwenden! : -P & lt; / devils-advocate & gt;

    
Chris Jester-Young 12.08.2008 06:03
quelle
-1

@roo

  

Ich habe wirklich gehofft, dass das möglich ist und ich es noch nicht gefunden habe. Ihr Beispiel hat mir gerade klar gemacht, dass wir genau das versuchen - nur Zugriff auf Dateien im Kontext unseres Programms erlauben und so die IP erhalten.

     

Ich glaube, ich muss akzeptieren, dass es keine wirklich sichere Möglichkeit gibt, Dateien von jemandem auf einem anderen Computer zu speichern, besonders wenn der Besitzer zu einem bestimmten Zeitpunkt Zugriff auf diese Datei hat.

Das ist definitiv das Problem. Sie können etwas sicher speichern, solange Sie niemals Zugriff gewähren, aber sobald Sie Zugriff gewähren, ist Ihre Kontrolle weg. Sie können es ein bisschen schwieriger machen, aber das ist alles.

    
Derek Park 12.08.2008 06:12
quelle
-1

@ Chris

  

Oh, aber mit Trusted Computing können Sie Memory Curtaining verwenden! :-P

Aber dann muss man tatsächlich bereit sein, für einen Computer zu bezahlen, den jemand anders besitzt. : p

    
Derek Park 12.08.2008 06:15
quelle
-1

@Derek Park

Er sagte nur härter, nicht unmöglich. PGP würde es schwieriger machen, nicht unmöglich.

    
graham.reeds 12.08.2008 08:10
quelle

Tags und Links