Natives C++ wird in Maschinencode übersetzt, und man ist versucht zu glauben, dass kompiliert schon geschützt bedeutet. Das stimmt nicht. Eine Lizenzprüfung, die in einem einzigen if endet, ist nur einen gepatchten bedingten Sprung von einem funktionierenden Crack entfernt. Wer Software knackt, liest Ihren Quellcode selten. Er hängt Debugger an, hookt Funktionen, beobachtet den Netzwerkverkehr und patcht Befehle im Arbeitsspeicher. C++-Authentifizierung für lizenzierte Software muss davon ausgehen, dass all das passiert.
Dieser Leitfaden beschreibt einen Lizenzierungsablauf, der auf dieser Annahme aufbaut: wie die Sitzung entsteht, warum die Lizenzentscheidung auf dem Server liegen muss, was Integritätsprüfungen erkennen und wie Sie alles mit qPapel Auth in eine C++-Anwendung einbinden. Die Prinzipien gelten unabhängig davon, welches Lizenzsystem Sie einsetzen.
Wogegen sich C++-Authentifizierung wehren muss
Jedes brauchbare Design beginnt mit einem Bedrohungsmodell, und für Desktop-Software ist das ehrliche Modell schonungslos: Der Angreifer besitzt die Maschine. Er hat Ihr Binary, Administratorrechte, jedes öffentliche Reverse-Engineering-Werkzeug und so viel Zeit, wie er möchte. Innerhalb dieses Modells müssen fünf Angriffsarten scheitern.
| Angriff | Typische Werkzeuge | Was ihn stoppt |
|---|---|---|
| Statische Analyse | IDA, Ghidra, Binary Ninja | Keine Geheimnisse oder Entscheidungslogik, die sich zu finden lohnt |
| Dynamische Analyse | x64dbg, WinDbg | Debugger-Erkennung und Laufzeitanalyse |
| Abfangen des Datenverkehrs | Fiddler, Wireshark, mitmproxy | Verschlüsselter, signierter Datenverkehr mit Schlüsseln pro Sitzung |
| Speichermanipulation | Cheat Engine, ReClass | Speicherintegritätsprüfungen und Anti-Dumping |
| Binary-Patching | Hex-Editoren, Patch-Skripte | Serverseitige Entscheidungen und Integritätsprüfungen des Codes |
Keine einzelne Maßnahme deckt alle fünf ab. Deshalb wird ernsthafte C++-Lizenzierung als Kette aufgebaut: Wer ein Glied überwindet, hat trotzdem kein funktionierendes Produkt. Der Rest dieses Leitfadens folgt dieser Kette vom ersten Paket bis zur letzten Integritätsprüfung.
So funktioniert eine sichere C++-Lizenzierungssitzung
Eine geschützte Sitzung hat fünf Stufen. Jede schließt eine Lücke, die die vorherige offen lässt, und die Reihenfolge ist entscheidend: Nichts Wertvolles erreicht die Anwendung, bevor der Server seine Entscheidung getroffen hat.
01Schlüsselaustausch
Frische Sitzungsschlüssel, keiner im Binary gespeichert
02Signierte Handshake-Antwort
Ein gefälschter Server kann sie nicht erzeugen
03Lizenzschlüssel + HWID
Verschlüsselt und signiert übertragen
04Lizenzentscheidung
Ablauf, Sperren und HWID werden hier geprüft
05Strings und Dateien anfordern
Nur nach positiver Entscheidung
06Serverseitige Daten
Im Arbeitsspeicher, nie im Build
1. Schlüsselaustausch
Beim Start der Anwendung vereinbaren Client und Server über einen Schlüsselaustausch frische Sitzungsschlüssel. Moderne Verfahren nutzen meist einen ephemeren Schlüsselaustausch auf Basis elliptischer Kurven (ECDH), etwa X25519. So werden die Schlüssel zur Laufzeit abgeleitet und nie im Binary gespeichert. Wer jedes Byte Ihrer ausführbaren Datei extrahiert, besitzt sie trotzdem nicht. Eine aufgezeichnete Sitzung lässt sich außerdem nicht wiederholen, weil die nächste Sitzung andere Schlüssel nutzt.
qPapel Auth eröffnet jede Sitzung mit einem Schlüsselaustausch und rotiert für jede Sitzung die AES-256-Sitzungsschlüssel. Scheitert dieser Schritt, meldet das SDK einen konkreten Key-Exchange- oder Handshake-Fehler, getrennt von Fehlern wie Banned Computer oder Unverified Build. So unterscheiden Sie einen fehlgeschlagenen Handshake von einem Lizenzproblem.
2. Verschlüsselter, signierter Datenverkehr
Jede Anfrage und Antwort nach dem Handshake ist verschlüsselt und signiert. Die Verschlüsselung verbirgt den Inhalt vor Proxys wie Fiddler oder mitmproxy. Noch wichtiger ist die Signatur, denn sie erlaubt dem Client, eine echte Serverantwort von einer gefälschten zu unterscheiden. Ohne sie könnte ein Angreifer einen gefälschten Server aufstellen, der auf alles mit „Lizenz gültig“ antwortet. Das ist einer der ältesten Cracks überhaupt.
3. Lizenz- und HWID-Prüfung auf dem Server
Der Client sendet den Lizenzschlüssel und einen Hardware-Fingerabdruck innerhalb des geschützten Kanals und wartet dann. Er ermittelt nie selbst, ob die Lizenz gültig ist. Der Server prüft, ob der Schlüssel existiert, nicht abgelaufen oder gesperrt ist und an die Hardware-ID dieses Rechners gebunden ist. Da keine dieser Logiken im Binary ausgeliefert wird, gibt es lokal nichts, was man auf ein Ja patchen könnte.
4. Serverseitige Strings und Dateien
Dieser Schritt macht aus Lizenzierung echten Schutz. Nach einer positiven Entscheidung liefert der Server, was die Anwendung zum Laufen braucht: Konfigurationswerte, Endpunkte, Offsets, Konstanten und ganze Dateien. In qPapel Auth sind das serverseitige Strings und serverseitige Dateien. Sie werden an die authentifizierte Sitzung gestreamt und bleiben aus dem ausgelieferten Build heraus. Ein Build, dessen Lizenzprüfung herausgepatcht wurde, erhält sie nie.
5. Eine laufende Sitzung statt einer einmaligen Prüfung
Eine Prüfung, die nur beim Start stattfindet, lässt sich umgehen, indem man den Prozess nach dem Bestehen patcht. qPapel Auth bindet jeden Lauf über rollierende Sitzungsschlüssel an eine Serversitzung. Mit Session Token Enforcement in den Remote-Einstellungen legen Sie fest, wie lange eine aktive Sitzung höchstens dauern darf, und können Sitzungen an eine IP-Adresse binden. Wenn Sie einen Schlüssel im Dashboard ablaufen lassen oder sperren, erhält die Anwendung den neuen Status bei der nächsten Prüfung.
Warum die Lizenzentscheidung auf dem Server bleiben muss
Die wichtigste Regel der C++-Authentifizierung ist kurz: Der Client meldet, der Server entscheidet. Jede Prüfung, die komplett im Prozess läuft, lässt sich finden und ändern. Der klassische Crack wandelt einen bedingten Sprung von JE in JMP um oder überschreibt einen Aufruf mit NOP-Befehlen, und die Anwendung läuft weiter, als wäre die Lizenz gültig.
Mit der Entscheidung auf dem Server ändert sich, was ein Patch bewirkt. Der Angreifer kann Ihr lokales if weiterhin überspringen. Das Überspringen erzeugt aber keine gültige Sitzung, und ohne gültige Sitzung sendet der Server nichts. Dasselbe gilt für alles andere, was im Binary wertvoll ist.
| Bestandteil | Risiko, wenn er im Binary liegt | Wo er stattdessen liegen sollte |
|---|---|---|
| Lizenzentscheidung | Wird so gepatcht, dass sie immer erfolgreich ist | Serverurteil über einen signierten Kanal |
| Validierungsalgorithmus | Wird in einen Schlüsselgenerator kopiert | Nur auf dem Server |
| API-Schlüssel und Tokens | Werden mit einem Strings-Scan herausgezogen | Ihr eigenes Backend oder ein serverseitiger String |
| Konfiguration, Offsets, Konstanten | Werden verändert, um das Verhalten zu ändern | Serverseitige Strings nach dem Login |
| Premium-Module und DLLs | Werden ohne Lizenz kopiert und wiederverwendet | Serverseitige Dateien oder Laden im Arbeitsspeicher |
Natives Programm bietet für die letzte Zeile noch eine Option. Statt ein geschütztes Modul auf die Festplatte zu legen, kann qPapel Auth verschlüsselte DLLs in den Arbeitsspeicher streamen, ohne sie auf die Festplatte zu schreiben. Die Funktion Map Files bildet Ihre Dateien ähnlich wie ein PE-Loader in den Speicher ab. Laden von DLLs im Arbeitsspeicher erklärt, wie das funktioniert und wann sich der Aufwand lohnt.
Integritätsprüfungen: gepatchten Code und Speicher erkennen
Serverseitige Entscheidungen machen Patches weniger nützlich. Integritätsprüfungen machen sie sichtbar. Zwei Arten von Manipulation sind in einem laufenden C++-Prozess relevant.
- Änderungen am Code selbst. Ein Cracker bearbeitet Befehle in der ausführbaren Datei oder in ihrem Codebereich, nachdem sie geladen wurde, um eine Prüfung zu überspringen oder ein Ergebnis zu ändern.
- Änderungen am Speicher zur Laufzeit. Ein Debugger oder ein Speicherbearbeitungsprogramm schreibt in den laufenden Prozess und patcht einen Befehl oder einen Wert genau in dem Moment, in dem es darauf ankommt.
qPapel Auth stellt beides als Aufrufe bereit, die Sie in Ihren eigenen Code einfügen. auth.CheckTextIntegrity() führt CRC-Prüfungen, sitzungsbasierte Prüfungen und Prüfungen auf JMP- und NOP-Patches durch. auth.CheckMemoryIntegrity() prüft zur Laufzeit, ob der Speicher des Programms verändert wurde, einschließlich Befehls-Patches wie JMP- und NOP-Änderungen. Darüber hinaus bieten die Remote-Einstellungen die zuschaltbaren Schutzfunktionen Integrity Check und CRC32 Check. Build Control verhindert, dass Ihre Datei durch nicht autorisierte Werkzeuge verändert, gepatcht oder geöffnet wird.
// Illustrative: where qPapel Auth integrity checks fit in a C++ app.
// CheckTextIntegrity and CheckMemoryIntegrity are real SDK names.
// StartLicensedSession, RunMainLoop and ExportProject are your own code.
int main()
{
if (!StartLicensedSession()) // key exchange, license and HWID check
return 1; // fail closed: no session, no app
auth.CheckTextIntegrity(); // CRC, session and JMP/NOP checks
auth.CheckMemoryIntegrity(); // runtime memory modification
RunMainLoop();
}
void OnExportClicked()
{
auth.CheckMemoryIntegrity(); // check again before valuable work
ExportProject();
}So binden Sie qPapel Auth in eine C++-Anwendung ein
Die Integration gehört in Ihren Startpfad, bevor sensibler Code läuft. Hier sind die Schritte in der richtigen Reihenfolge, mit den Stellen, an denen die meisten ersten Integrationen scheitern.
- 01
Aktuelle SDK-Dateien beziehen
Übernehmen Sie die neuesten Dateien aus Lib und Include des offiziellen Beispielprojekts sowie
qPapelAuth64.dllvon der Downloads-Seite Ihres PapelShip-Dashboards. Ändern sich die Sicherheits- und Verschlüsselungsebenen, funktionieren alte Bibliotheken nicht mehr. Bauen Sie deshalb immer gegen die aktuelle Version. - 02
Default Library oder EasyAuth wählen
Die Default Library wird weiterhin vollständig unterstützt. EasyAuth ist die neuere Bibliothek mit C#-Unterstützung neben C++, besserer Fehlerbehandlung und Diagnosen zu Sicherheitsrichtlinien. PapelShip empfiehlt, Projekte nach und nach auf EasyAuth umzustellen.
- 03
Vor allem Wertvollen authentifizieren
Starten Sie die Sitzung ganz oben in
main, bevor Ihr Hauptfenster öffnet oder die Konfiguration geladen wird. Nichts Schützenswertes sollte in einer nicht authentifizierten Sitzung laufen. - 04
Benötigtes vom Server laden
Verlagern Sie Konfiguration, Endpunkte und sensible Konstanten in serverseitige Strings und Premium-Assets in serverseitige Dateien. Lesen Sie sie nach dem Login und halten Sie sie nur so lange im Arbeitsspeicher, wie Sie sie brauchen.
- 05
Integritätsprüfungen ergänzen und Schutz aktivieren
Platzieren Sie
auth.CheckTextIntegrity()undauth.CheckMemoryIntegrity()beim Start und vor wertvollen Operationen. Aktivieren Sie anschließend in den Remote-Einstellungen Anti VM, Ban on Debugger, das Sitzungssystem und HWID Lock. - 06
Bei Fehlern abbrechen
Kein Server, eine fehlerhafte Antwort oder eine fehlgeschlagene Prüfung bedeutet: Die Anwendung wird beendet. Ein Offline-Modus, der das komplette Produkt ausführt, ist eine Hintertür. Wenn Sie Offline-Nutzung unterstützen müssen, begrenzen Sie sie zeitlich und inhaltlich eng.
EasyAuth zeigt Nutzern außerdem an, warum eine Sitzung beendet wurde. Schließt eine Sicherheitsrichtlinie die Anwendung, erscheint die Meldung „Security Policy Closing..“ zusammen mit zusätzlichen Informationen zur Ursache. So bleiben Supportgespräche kurz, wenn echte Kunden versehentlich eine Regel auslösen. Produktdetails und Preise finden Sie auf der Seite zu qPapel Auth.
Anti-Debug, Anti-VM und Laufzeiterkennung für nativen Code
Lizenzierung entscheidet, wer Ihre Software ausführen darf. Laufzeitschutz entscheidet, ob die Umgebung, in der sie läuft, vertrauenswürdig ist. Debugger sind das wichtigste Werkzeug gegen nativen Code, gefolgt von Speicherbearbeitungsprogrammen und virtuellen Maschinen. Mit ihnen kann ein Angreifer eine Sitzung als Snapshot festhalten und so oft zurückspulen, wie er möchte.
Die Remote-Einstellungen von qPapel Auth erlauben es, Fenstertitel, Klassennamen, Prozesse und Debugging-Werkzeuge zu blockieren, virtuelle Maschinen zu erkennen und eine Lizenz zu sperren, sobald ein Debugger angehängt wird, und das alles ohne neuen Build. Anti-Dumping-Routinen, Speicherschutz und Anti-Tamper-Härtung schützen das Binary unabhängig von diesen Einstellungen. Da die Richtlinie remote ausgeliefert wird, können Sie den Schutz ohne Neuaufbau aktualisieren, sobald ein neues Werkzeug auftaucht.
Blacklists erfassen nur Werkzeuge, die Sie bereits kennen. Ein umbenannter oder neu kompilierter Debugger rutscht an einer Liste von Prozessnamen vorbei. Deshalb wertet qPAnalyzer stattdessen UI-Layoutmuster, Fenster-Handles und Speichersignaturen aus. Es erstellt einen Screenshot des markierten Fensters und erhöht einen Risikowert, für den Sie Schwellen für Warnung, Einschränkung, Beenden und Sperre festlegen. Reverse-Engineering-Schutz jenseits statischer Blacklists erklärt diesen Ansatz ausführlich.
Lizenz und HWID
Wer sie ausführen darf und auf welchem PC
Geschützte Sitzung
Schlüsselaustausch, verschlüsselter signierter Datenverkehr
Serverseitige Daten
Strings und Dateien erst nach dem Login
Integritätsprüfungen
Gepatchter Code und Speicher werden erkannt
Laufzeiterkennung
Blacklists, Anti-VM und qPAnalyzer
Typische Fehler bei C++-Lizenzprüfungen
Die meisten geknackten C++-Produkte wurden nicht durch etwas Raffiniertes besiegt. Sie fielen einer von einer Handvoll Abkürzungen im Design zum Opfer.
- Ein einziger Bool-Wert schützt alles. Ein einzelnes
isLicensed-Flag ist das Erste, wonach ein Cracker sucht. Lassen Sie Funktionen von Serverdaten abhängen statt von einem Flag. - Geheimnisse in String-Literalen. API-Schlüssel, Verschlüsselungsschlüssel und Download-URLs im Binary sind für jeden sichtbar, der einen Strings-Scan ausführt. Sie zu verschleiern verzögert nur den Moment, in dem sie im Speicher entschlüsselt werden.
- Vertrauen in die lokale Uhr. Ein Ablaufdatum, das aus der Systemzeit berechnet wird, lässt sich durch Umstellen des Datums umgehen. Lassen Sie den Server entscheiden, ob eine Lizenz abgelaufen ist.
- Einmalige Prüfung beim Start. Wer nach dem Start anhängt und mitten in der Sitzung patcht, umgeht einmalige Prüfungen. Halten Sie die Sitzung aufrecht und prüfen Sie erneut vor wertvollen Operationen.
- Großzügige Offline-Ausweichlösungen. Läuft die App vollständig, wenn der Server nicht erreichbar ist, ist das Blockieren des Servers der Crack.
- Veraltete SDKs. Alte Bibliotheken verpassen Protokoll- und Schutz-Updates. Bauen Sie neu, sobald sich das SDK ändert, und nicht Monate später.
Dieselben Fehler tauchen auch in verwaltetem Code auf, mit einem zusätzlichen Problem: .NET-Assemblys lassen sich zurück in lesbaren Quellcode dekompilieren. C#-Lizenzierung ohne fest hinterlegte Geheimnisse behandelt diese Seite.
Häufig gestellte Fragen
auth.CheckTextIntegrity() führt CRC-, sitzungsbasierte und JMP/NOP-Patch-Prüfungen durch. auth.CheckMemoryIntegrity() prüft zur Laufzeit, ob der Speicher des Programms verändert wurde, etwa durch gepatchte Befehle.Bauen Sie C++-Software, die bei einem Crack sicher fehlschlägt
Sichere C++-Authentifizierung ist nicht eine clevere Prüfung. Sie besteht aus einer geschützten Sitzung, einer Entscheidung auf dem Server, Daten, die erst nach dieser Entscheidung eintreffen, Integritätsprüfungen, die Patches bemerken, und einer Laufzeiterkennung, die die dahinterliegenden Werkzeuge erkennt. Jede Schicht ist für sich genommen nichts Außergewöhnliches. Zusammen bedeuten sie, dass das Umgehen einer einzigen den Angreifer mit einem Build zurücklässt, der nicht funktioniert.
Beginnen Sie mit der Entscheidung auf dem Server und den serverseitigen Daten, denn sie verändern die Rechnung beim Cracken am stärksten. Ergänzen Sie danach Integritätsprüfungen und Laufzeiterkennung, und halten Sie das SDK aktuell, damit der Schutz besser wird, ohne dass Sie etwas neu schreiben müssen.
qPapel-Security-Team
Lizenzierung und Softwareschutz