
컴파일 타임 C 난독화용 매크로 헤더 (tcc, win x86/x64)

obfus.h 은 C 애플리케이션을 컴파일 시점에 난독화하기 위한 매크로 전용 라이브러리로, 특히 Tiny C (tcc) 을 위해 설계되었습니다 (여기서 다운로드할 수 있습니다 -> Tiny-C-Compiler/releases). Windows x86 및 x64 플랫폼에 맞춰져 있으며 거의 모든 버전의 컴파일러를 지원합니다. C 프로그램을 위한 매우 신뢰할 수 있는 갑옷입니다!
obfus.h 을 프로젝트에 통합하는 것은 간단한 과정입니다. 코드에 다음 줄을 포함하기만 하면 됩니다:
#include "obfus.h"
이렇게 하면 컴파일 중에 코드가 자동으로 난독화되어 지적 재산의 보호와 기밀성이 보장됩니다.
보호 기능 구성에 사용할 수 있는 옵션:
// 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 protection또는 컴파일러 인수와 함께 사용하세요:
tcc "app.c" -w -D NO_CFLOW -D ANTIDEBUG_V2 -D FAKE_SIGNS -D VIRT
[!WARNING] 난독화를 적용해 애플리케이션을 컴파일할 때는 경고를 억제하기 위해
-w인수를 사용하세요. 그렇지 않으면 콘솔에 최종 결과에는 영향을 미치지 않는 수많은 위협적으로 보이는 로그가 표시됩니다. 이를 보고 놀라실 필요는 없습니다.
🔐 디버깅 보호는 많은 기본 MSVCRT 함수 호출에 의해 트리거됩니다.
코드의 중요 위치에서는 ANTI_DEBUG; 구문을 사용할 수 있습니다. 예를 들어:
ANTI_DEBUG;
if (!licenseExpired()) {
// ...
}
HIDE_STRING(str) 은 문자열을 변형하여 난독화하고 시각적으로 숨김으로써 소스 코드에서 해당 문자열을 발견하고 패치하는 것을 상당히 어렵게 만듭니다. 이러한 방식으로 선언하면 문자열은 한 번에 모두 로드되는 대신 mov 명령을 통해 스택에 조립됩니다. 이 방법은 문자열이 정적으로 선언되지 않고 런타임에 구성되도록 하여 정적 분석에 덜 취약하게 만듭니다. 단, 이 기능은 함수 호출을 수반하므로 정적 필드를 선언하는 동안 이를 숨기는 데에는 사용할 수 없다는 점에 유의해야 합니다.
[!IMPORTANT] 일부 디컴파일러는 정적 최적화로 인해 여전히 이를 드러낼 수 있습니다. 디스어셈블러 출력에서 코드는 복잡하고 난해하게 보여 단순한 분석을 막을 수 있지만, 단호한 리버스 엔지니어링 시도를 완전히 차단하지는 못할 수 있습니다.
메시지를 정적으로 숨기고 스택에서 복호화하면서 표준 라이브러리의 printf 함수를 호출하는 예:
char *hidden_message = HIDE_STRING("Hello, world!");
// ...
printf(hidden_message);
이것은 특정 계산이 명령에 따라 내장된 가상 머신을 통해 수행되는 보호 기법입니다. 수학 연산의 분석을 매우 어렵게 만듭니다! VIRT 옵션이 활성화된 경우에만(그리고 오직 그 경우에만!) 작동합니다. 그렇지 않으면 모든 가상 머신 명령이 일반 수학 연산자로 대체됩니다.
[!WARNING] 중요 위치에서의 가상화는 최적화에 영향을 줄 수 있습니다. 정말 필요한 영역에서만 주의해서 사용하세요.
가상 머신은 일부 기본
double비교 연산을 지원하지 않습니다.
가상 머신 호출을 사용하는 논리 연산자를 사용하여 코드 이해를 더욱 복잡하게 만들 수 있습니다:
| 연산자 | 설명 |
|---|---|
VM_IF | if 대신 사용 |
이것은 if/else를 완전히 대체하는 것은 아니며, 단지 표준 연산자를 복잡하게 만드는 것일 뿐입니다.
가상화 사용의 간단한 예:
// ...
#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
}
가상 머신의 모든 함수 사용 예제는 tests/virtualmachine.c 파일에서 찾을 수 있습니다.
숙련된 리버서로부터 고급 보호가 필요하다면 CFLOW_V2 및 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");
}
}
최신 버전의 Tiny C(0.9.27) 사용을 권장합니다. 안타깝게도 일부 컴파일러 버전은 완전한 난독화에 필요한 기능을 지원하지 않습니다. Visual C, GCC 및 Clang은 지원되지 않으며 앞으로도 지원될 가능성이 낮습니다.
Windows용 특수 스크립트를 사용하여 공식 저장소에서 패키지를 다운로드함으로써 최신 버전의 obfus.h를 얻을 수 있습니다. git을 사용하지 않고 보안 업데이트를 자동화해야 하는 경우 유용합니다.
예를 들어, 프로젝트를 빌드하기 전에 사용할 수 있습니다:
+ C:\...> call obfh-update C:\...> tcc app.c -w이 스크립트는 (지정된 구성에 따라) 현재 디렉터리에 있는 obfus.h 파일의 내용을 업데이트합니다.
obfus.h 을 사용하여 보호된 프로그램의 코드(및 원래의 로직)는 거의 복구(역난독화)가 불가능합니다. 그러나 이 난독화 도구를 사용한다고 해서 모든 유형의 위협으로부터 완전한 보호가 보장되는 것은 아닙니다. 프로그램 내부 보안 시스템을 개발하고 유지 관리하는 것이 중요합니다.
난독화 후 코드가 어떻게 보이는지:
리버서가 디컴파일러를 사용하려고 하면 이런 모습을 보게 됩니다:
HIDE_STRING기능을 통해 숨겨진 모든 문자열이 디스어셈블러(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 . . . ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
이 프로젝트 개발에 도움을 주신 모든 분들께 감사드립니다. 정말 감사합니다! ❤️
그리고 이 프로젝트에 관심을 가져주신 여러분께 감사드립니다 🤝!
| 함수 | 형식 | 연산 | 설명 | 예 |
|---|
VM_ADD | long | + | 두 수를 더합니다 | VM_ADD(5, 3) = 8 |
VM_SUB | long | - | 두 수를 뺍니다 | VM_SUB(5, 3) = 2 |
VM_MUL | long | * | 두 수를 곱합니다 | VM_MUL(5, 3) = 15 |
VM_DIV | long | / | 두 수를 나눕니다 | VM_DIV(6, 3) = 2 |
VM_MOD | long | % | 두 수의 나머지를 계산합니다 | VM_MOD(5, 3) = 2 |
VM_EQU | BOOL | == | 두 수가 같은지 확인합니다 | VM_EQU(5, 5) = true |
VM_NEQ | BOOL | != | 두 수가 다른지 확인합니다 | VM_NEQ(5, 3) = true |
VM_LSS | BOOL | < | 첫 번째 수가 두 번째 수보다 작은지 확인합니다 | VM_LSS(3, 5) = true |
VM_GTR | BOOL | > | 첫 번째 수가 두 번째 수보다 큰지 확인합니다 | VM_GTR(5, 3) = true |
VM_LEQ | BOOL | <= | 첫 번째 수가 두 번째 수보다 작거나 같은지 확인합니다 | VM_LEQ(3, 5) = true |
VM_GEQ | BOOL | >= | 첫 번째 수가 두 번째 수보다 크거나 같은지 확인합니다 | VM_GEQ(5, 3) = true |
VM_ADD_DBL | long double | + | 두 double 수를 더합니다 | VM_ADD_DBL(5.5, 3.2) = ≈8.7 |
VM_SUB_DBL | long double | - | 두 double 수를 뺍니다 | VM_SUB_DBL(5.5, 3.2) = ≈2.3 |
VM_MUL_DBL | long double | * | 두 double 수를 곱합니다 | VM_MUL_DBL(5.5, 3.2) = ≈17.6 |
VM_DIV_DBL | long double | / | 두 double 수를 나눕니다 | VM_DIV_DBL(6.0, 3.0) = ≈2.0 |
VM_LSS_DBL | BOOL | < | 첫 번째 double 수가 두 번째 double 수보다 작은지 확인합니다 | VM_LSS_DBL(3.5, 5.2) = true |
VM_GTR_DBL | BOOL | > | 첫 번째 double 수가 두 번째 double 수보다 큰지 확인합니다 | VM_GTR_DBL(5.5, 3.2) = true |
VM_ELSE_IF | else if 대신 사용 |
VM_ELSE | else 대신 사용 |