
Makro-Header für Compilezeit-C-Verschleierung (tcc, win x86/x64)

obfus.h ist eine reine Makro-Bibliothek zur Verschleierung von C-Anwendungen zur Compile-Zeit, die speziell für den Tiny C (tcc) entwickelt wurde (du kannst ihn hier herunterladen -> Tiny-C-Compiler/releases). Sie ist auf Windows-x86- und x64-Plattformen zugeschnitten und unterstützt fast alle Versionen des Compilers. Sehr zuverlässige Rüstung für deine C-Programme!
Die Integration von obfus.h in dein Projekt ist ein einfacher Vorgang. Füge einfach die folgende Zeile in deinen Code ein:
#include "obfus.h"
Dadurch wird dein Code während der Kompilierung automatisch verschleiert, was den Schutz und die Vertraulichkeit deines geistigen Eigentums gewährleistet.
Verfügbare Optionen zur Konfiguration des Schutzes:
// Erweiterter Code-Schutz (siehe den Teil "Virtualisierung" der Dokumentation!) #define VIRT 1 // Ermöglicht die Verwendung der Funktionen einer Mathe-VM // Zusätzliche Optionen #define CFLOW_V2 1 // Leistungsfähigere Control-Flow-Verschleierung (langsam!) #define ANTIDEBUG_V2 1 // Verwende besseren dynamischen Anti-Debugging-Schutz #define FAKE_SIGNS 1 // Fügt gefälschte Signaturen verschiedener Protectors oder Packer hinzu // Standardfunktionen deaktivieren #define NO_OBF 1 // Nicht verschleiern (zum Debuggen) #define NO_CFLOW 1 // Keine Control-Flow-Verschleierung verwenden #define NO_ANTIDEBUG 1 // Keinen Debugging-Schutz einbauenoder verwende es mit Compiler-Argumenten:
tcc "app.c" -w -D NO_CFLOW -D ANTIDEBUG_V2 -D FAKE_SIGNS -D VIRT
[!WARNING] Wenn du eine Anwendung mit Verschleierung kompilierst, verwende das Argument
-w, um Warnungen zu unterdrücken. Andernfalls zeigt die Konsole zahlreiche einschüchternde Logs an, die keinerlei Auswirkung auf das Endergebnis haben. Es besteht kein Grund, sich davon beunruhigen zu lassen.
🔐 Der Debugging-Schutz wird durch Aufrufe vieler grundlegender MSVCRT-Funktionen ausgelöst.
An kritischen Stellen im Code kannst du das Konstrukt ANTI_DEBUG; verwenden. Zum Beispiel:
ANTI_DEBUG;
if (!licenseExpired()) {
// ...
}
HIDE_STRING(str) verschleiert Zeichenketten und verbirgt sie optisch, indem es sie mutiert, was ihre Auffindung und das Patchen im Quellcode erheblich erschwert. Bei dieser Art der Deklaration werden die Zeichenketten über mov-Anweisungen auf dem Stack zusammengesetzt, anstatt auf einmal geladen zu werden. Diese Methode stellt sicher, dass die Zeichenketten nicht statisch deklariert werden, sondern erst zur Laufzeit konstruiert werden, wodurch sie weniger anfällig für statische Analysen sind. Es ist jedoch wichtig zu beachten, dass diese Funktion nicht zum Verbergen statischer Felder während ihrer Deklaration verwendet werden kann, da sie einen Funktionsaufruf beinhaltet.
[!IMPORTANT] Einige Decompiler können sie aufgrund statischer Optimierungen dennoch offenlegen. In der Disassembler-Ausgabe erscheint der Code komplex und umständlich, was eine einfache Analyse abschrecken kann, aber entschlossene Reverse-Engineering-Bemühungen möglicherweise nicht vollständig verhindert.
Ein Beispiel für den Aufruf der printf-Funktion aus der Standardbibliothek mit statischem Verbergen der Nachricht und ihrer Entschlüsselung auf dem Stack:
char *hidden_message = HIDE_STRING("Hello, world!");
// ...
printf(hidden_message);
Dies ist eine Schutztechnik, bei der bestimmte Berechnungen auf Befehl über eine eingebettete virtuelle Maschine ausgeführt werden. Macht die Analyse mathematischer Operationen sehr schwierig! Sie funktioniert nur mit aktivierter VIRT-Option (und nur dann!). Andernfalls werden alle Virtual-Machine-Befehle durch gewöhnliche mathematische Operatoren ersetzt.
[!WARNING] Virtualisierung an kritischen Stellen kann die Optimierung beeinträchtigen. Verwende sie mit Vorsicht nur dort, wo sie wirklich benötigt wird.
Die virtuelle Maschine unterstützt einige grundlegende
double-Vergleichsoperationen nicht.
Du kannst logische Operatoren verwenden, die Virtual-Machine-Aufrufe nutzen, um das Verständnis deines Codes weiter zu erschweren:
| Operator | Beschreibung |
|---|---|
Dies ist kein vollständiger Ersatz für if/else, sondern lediglich eine Verkomplizierung der Standardoperatoren.
Ein einfaches Beispiel für die Verwendung der Virtualisierung:
// ...
#define VIRT 1
// ...
// if ((2 + 2) == 4) { ... }
VM_IF (VM_EQU(VM_ADD(2, 2), 4)) {
printf("2 + 2 == 4!");
}
// if (condition1) { ... }
// else if (condition2) { ... }
// else { ... }
VM_IF (condition1) {
// if
} VM_ELSE_IF (condition2) {
// else if
} VM_ELSE {
// else
}
Beispiele für die Verwendung aller Funktionen einer virtuellen Maschine findest du in der Datei tests/virtualmachine.c
Wenn du erweiterten Schutz gegen versierte Reverse Engineers benötigst, verwende die Optionen CFLOW_V2 und ANTIDEBUG_V2.
// Let's obfuscate your code!
#include <stdio.h>
#define VIRT 1 // [+] Use math virtual machine
#define CFLOW_V2 1 // [+] ControlFlow v2
#define FAKE_SIGNS 1 // [+] Fake signatures
#define ANTIDEBUG_V2 1 // [+] AntiDebug v2
#define NO_OBF 0 // [-] Don't obfuscate (disable all)
#define NO_CFLOW 0 // [-] Disable ControlFlow
#define NO_ANTIDEBUG 0 // [-] Disable AntiDebug
#include "obfus.h"
void main() {
char *out = malloc(256);
strcpy(out, HIDE_STRING("Hello, world!\n"));
if (out) {
printf(out);
} else {
printf("Error!\n");
}
free(out);
int result = VM_ADD(5, 7); // 5 + 7
VM_IF (VM_EQU(result, 12)) { // (5 + 7) == 12
printf("5 + 7 == 12");
}
}
Die neueste Version von Tiny C (0.9.27) wird zur Verwendung empfohlen. Leider unterstützen einige Versionen des Compilers die für eine vollständige Verschleierung benötigte Funktionalität nicht. Visual C, GCC und Clang werden nicht unterstützt und werden wahrscheinlich auch künftig nicht unterstützt.
Du kannst das spezielle Skript für Windows verwenden, um die neuesten Versionen von obfus.h zu erhalten, indem du das Paket aus dem offiziellen Repository herunterlädst. Dies ist nützlich, wenn du Sicherheitsupdates ohne git automatisieren musst.
Du kannst es zum Beispiel vor dem Build deines Projekts verwenden:
+ C:\...> call obfh-update C:\...> tcc app.c -wDas Skript aktualisiert den Inhalt der obfus.h-Datei im aktuellen Verzeichnis (entsprechend der angegebenen Konfiguration)
Der Code eines Programms (und seine ursprüngliche Originallogik), das mit obfus.h geschützt wurde, ist nahezu unmöglich wiederherzustellen (zu deobfuskatoren). Die Verwendung dieses Obfuscators garantiert jedoch keinen vollständigen Schutz gegen alle Arten von Bedrohungen. Es ist wichtig, interne Sicherheitssysteme des Programms zu entwickeln und zu pflegen.
So sieht der Code nach der Verschleierung aus:
So etwas sieht ein Reverse Engineer, wenn er versucht, einen Decompiler zu verwenden:
So sehen alle über die
HIDE_STRING-Funktion verborgenen Zeichenketten im Disassembler aus (x86-64-Architektur):; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; PROTECTED STRING: ; ORIGINAL STRING: ; mov eax, 48h lea rax, aHelloWorld ; mov [rbp-0Fh], al mov r11, rax ; mov eax, 65h ; . . . ; mov [rbp-0Eh], al ; mov eax, 6Ch ; mov [rbp-0Dh], al ; mov eax, 6Ch ; mov [rbp-0Ch], al ; mov eax, 6Fh ; mov [rbp-0Bh], al ; mov eax, 2Ch ; ; etc . . . ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
Danke an alle, die bei der Entwicklung dieses Projekts geholfen haben. Ich weiß das zu schätzen! ❤️
Und danke an dich 🤝, dass du diesem Projekt Aufmerksamkeit schenkst!
| Funktion | Typ | Op | Beschreibung | Beispiel |
|---|
VM_ADD | long | + | Addiert zwei Zahlen | VM_ADD(5, 3) = 8 |
VM_SUB | long | - | Subtrahiert zwei Zahlen | VM_SUB(5, 3) = 2 |
VM_MUL | long | * | Multipliziert zwei Zahlen | VM_MUL(5, 3) = 15 |
VM_DIV | long | / | Dividiert zwei Zahlen | VM_DIV(6, 3) = 2 |
VM_MOD | long | % | Berechnet den Modulo zweier Zahlen | VM_MOD(5, 3) = 2 |
VM_EQU | BOOL | == | Prüft, ob zwei Zahlen gleich sind | VM_EQU(5, 5) = true |
VM_NEQ | BOOL | != | Prüft, ob zwei Zahlen ungleich sind | VM_NEQ(5, 3) = true |
VM_LSS | BOOL | < | Prüft, ob die erste Zahl kleiner als die zweite Zahl ist | VM_LSS(3, 5) = true |
VM_GTR | BOOL | > | Prüft, ob die erste Zahl größer als die zweite Zahl ist | VM_GTR(5, 3) = true |
VM_LEQ | BOOL | <= | Prüft, ob die erste Zahl kleiner oder gleich der zweiten Zahl ist | VM_LEQ(3, 5) = true |
VM_GEQ | BOOL | >= | Prüft, ob die erste Zahl größer oder gleich der zweiten Zahl ist | VM_GEQ(5, 3) = true |
VM_ADD_DBL | long double | + | Addiert zwei Double-Zahlen | VM_ADD_DBL(5.5, 3.2) = ≈8.7 |
VM_SUB_DBL | long double | - | Subtrahiert zwei Double-Zahlen | VM_SUB_DBL(5.5, 3.2) = ≈2.3 |
VM_MUL_DBL | long double | * | Multipliziert zwei Double-Zahlen | VM_MUL_DBL(5.5, 3.2) = ≈17.6 |
VM_DIV_DBL | long double | / | Dividiert zwei Double-Zahlen | VM_DIV_DBL(6.0, 3.0) = ≈2.0 |
VM_LSS_DBL | BOOL | < | Prüft, ob die erste Double-Zahl kleiner als die zweite Double-Zahl ist | VM_LSS_DBL(3.5, 5.2) = true |
VM_GTR_DBL | BOOL | > | Prüft, ob die erste Double-Zahl größer als die zweite Double-Zahl ist | VM_GTR_DBL(5.5, 3.2) = true |
VM_IFVerwende es anstelle von if |
VM_ELSE_IF | Verwende es anstelle von else if |
VM_ELSE | Verwende es anstelle von else |