
Macro-header per l'offuscamento C in fase di compilazione (tcc, win x86/x64)

obfus.h è una libreria composta solo da macro per l'offuscamento in fase di compilazione di applicazioni C, progettata specificamente per Tiny C (tcc) (puoi scaricarlo qui -> Tiny-C-Compiler/releases). È pensata per piattaforme Windows x86 e x64 e supporta quasi tutte le versioni del compilatore. Un'armatura molto affidabile per i tuoi programmi C!
Integrare obfus.h nel tuo progetto è un processo semplice. È sufficiente includere la seguente riga nel tuo codice:
#include "obfus.h"
Questo offuscherà automaticamente il tuo codice durante la compilazione, garantendo protezione e riservatezza della tua proprietà intellettuale.
Opzioni disponibili per la configurazione della protezione:
// Advanced code protection (see the "Virtualization" part of the documentation!) #define VIRT 1 // Allows you to use the functions of a math VM // Additional options #define CFLOW_V2 1 // More powerful Control Flow obfuscation (slowly!) #define ANTIDEBUG_V2 1 // Use better dynamic anti-debugging protection #define FAKE_SIGNS 1 // Adds fake signatures of various protectors or packers // Disabling default features #define NO_OBF 1 // Don't obfuscate (for debugging) #define NO_CFLOW 1 // Don't use Control-Flow obfuscation #define NO_ANTIDEBUG 1 // Don't build in debugging protectionoppure usalo con gli argomenti del compilatore:
tcc "app.c" -w -D NO_CFLOW -D ANTIDEBUG_V2 -D FAKE_SIGNS -D VIRT
[!WARNING] Quando compili un'applicazione con l'offuscamento, usa l'argomento
-wper sopprimere gli avvisi. In caso contrario, la console mostrerà numerosi log intimidatori che non hanno alcun impatto sul risultato finale. Non c'è bisogno di allarmarsi.
🔐 La protezione anti-debug viene attivata dalle chiamate a molte funzioni di base della MSVCRT.
Nei punti critici del codice puoi usare il costrutto ANTI_DEBUG;. Per esempio:
ANTI_DEBUG;
if (!licenseExpired()) {
// ...
}
La macro HIDE_STRING(str) offusca e nasconde visivamente le stringhe mutandole, complicando notevolmente la loro individuazione e la loro modifica nel codice sorgente. Quando vengono dichiarate in questo modo, le stringhe vengono assemblate sullo stack tramite istruzioni mov invece di essere caricate tutte in una volta. Questo metodo garantisce che le stringhe non siano dichiarate staticamente, ma vengano costruite a runtime, rendendole meno suscettibili all'analisi statica. Tuttavia, è importante notare che questa funzionalità non può essere usata per nascondere campi statici durante la loro dichiarazione, poiché comporta una chiamata di funzione.
[!IMPORTANT] Alcuni decompilatori potrebbero comunque rivelarle a causa di ottimizzazioni statiche. Nell'output del disassembler, il codice apparirà complesso e macchinoso, il che può scoraggiare l'analisi immediata ma potrebbe non impedire del tutto sforzi determinati di reverse engineering.
Un esempio di chiamata alla funzione printf della libreria standard con occultamento statico del messaggio e la sua decifratura sullo stack:
char *hidden_message = HIDE_STRING("Hello, world!");
// ...
printf(hidden_message);
Questa è una tecnica di protezione in cui determinati calcoli vengono eseguiti tramite una macchina virtuale integrata a comando. Rende l'analisi delle operazioni matematiche molto difficile! Funziona con l'opzione VIRT abilitata (e solo con quella!). In caso contrario, tutti i comandi della macchina virtuale verranno sostituiti da normali operatori matematici.
[!WARNING] La virtualizzazione nei punti critici può influire sull'ottimizzazione. Usala con cautela solo nelle aree in cui è realmente necessaria.
La macchina virtuale non supporta alcune operazioni di confronto di base per i
double.
Puoi usare operatori logici che utilizzano chiamate alla macchina virtuale per complicare ulteriormente la comprensione del tuo codice:
| Operatore | Descrizione |
|---|---|
VM_IF |
Questa non è una sostituzione completa di if/else, ma solo una complicazione degli operatori standard.
Un semplice esempio di utilizzo della virtualizzazione:
// ...
#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
}
Puoi trovare esempi di utilizzo di tutte le funzioni della macchina virtuale nel file tests/virtualmachine.c
Se hai bisogno di una protezione avanzata contro reverse engineer esperti, usa le opzioni CFLOW_V2 e 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");
}
}
Si consiglia di usare l'ultima versione di Tiny C (0.9.27). Purtroppo, alcune versioni del compilatore non supportano le funzionalità necessarie per un offuscamento completo. Visual C, GCC e Clang non sono supportati ed è improbabile che vengano supportati.
Puoi usare lo script speciale per Windows per ottenere le ultime versioni di obfus.h scaricando il pacchetto dal repository ufficiale. È utile se devi automatizzare gli aggiornamenti di sicurezza senza usare git.
Per esempio, puoi usarlo prima di compilare il tuo progetto:
+ C:\...> call obfh-update C:\...> tcc app.c -wLo script aggiornerà il contenuto del file obfus.h nella directory corrente (secondo la configurazione specificata)
Il codice di un programma (e la sua logica originale) protetto usando obfus.h è quasi impossibile da recuperare (deoffuscare). Tuttavia, l'uso di questo offuscatore non garantisce una protezione completa contro tutti i tipi di minacce. È importante sviluppare e mantenere sistemi di sicurezza interni al programma.
Ecco come apparirà il codice schematico dopo l'offuscamento:
Il reverse engineer vedrà qualcosa del genere se tenta di usare un decompilatore:
Ecco come appaiono tutte le stringhe nascoste tramite la funzionalità
HIDE_STRINGnel disassembler (architettura x86-64):; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 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 . . . ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
Grazie a tutti coloro che hanno aiutato nello sviluppo di questo progetto. Lo apprezzo molto! ❤️
E grazie a te 🤝 per aver prestato attenzione a questo progetto!
| Funzione | Tipo | Op | Descrizione | Esempio |
|---|
VM_ADD | long | + | Somma due numeri | VM_ADD(5, 3) = 8 |
VM_SUB | long | - | Sottrae due numeri | VM_SUB(5, 3) = 2 |
VM_MUL | long | * | Moltiplica due numeri | VM_MUL(5, 3) = 15 |
VM_DIV | long | / | Divide due numeri | VM_DIV(6, 3) = 2 |
VM_MOD | long | % | Calcola il modulo di due numeri | VM_MOD(5, 3) = 2 |
VM_EQU | BOOL | == | Verifica se due numeri sono uguali | VM_EQU(5, 5) = true |
VM_NEQ | BOOL | != | Verifica se due numeri sono diversi | VM_NEQ(5, 3) = true |
VM_LSS | BOOL | < | Verifica se il primo numero è minore del secondo | VM_LSS(3, 5) = true |
VM_GTR | BOOL | > | Verifica se il primo numero è maggiore del secondo | VM_GTR(5, 3) = true |
VM_LEQ | BOOL | <= | Verifica se il primo numero è minore o uguale al secondo | VM_LEQ(3, 5) = true |
VM_GEQ | BOOL | >= | Verifica se il primo numero è maggiore o uguale al secondo | VM_GEQ(5, 3) = true |
VM_ADD_DBL | long double | + | Somma due numeri double | VM_ADD_DBL(5.5, 3.2) = ≈8.7 |
VM_SUB_DBL | long double | - | Sottrae due numeri double | VM_SUB_DBL(5.5, 3.2) = ≈2.3 |
VM_MUL_DBL | long double | * | Moltiplica due numeri double | VM_MUL_DBL(5.5, 3.2) = ≈17.6 |
VM_DIV_DBL | long double | / | Divide due numeri double | VM_DIV_DBL(6.0, 3.0) = ≈2.0 |
VM_LSS_DBL | BOOL | < | Verifica se il primo numero double è minore del secondo numero double | VM_LSS_DBL(3.5, 5.2) = true |
VM_GTR_DBL | BOOL | > | Verifica se il primo numero double è maggiore del secondo numero double | VM_GTR_DBL(5.5, 3.2) = true |
Da usare al posto di if |
VM_ELSE_IF | Da usare al posto di else if |
VM_ELSE | Da usare al posto di else |