[C] 纯文本查看 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <intrin.h>
static uint32_t g_anti_flags = 0;
static uint32_t g_self_crc = 0;
static uint32_t g_self_fnv = 0;
static unsigned char g_decrypt_buf[256];
static const unsigned char enc_banner[] = {
0x50,0x4c,0x71,0x6e,0x16,0x4e,0xa5,0x57,0x47,0x7b,0x34,0x2c,0x6b,0x74,0xfa,0x8b,
0xbf,0xd5,0xac,0xf0,0xc4,0x1c,0x13,0x0c,0x8f,0x8c,0xd4,0x36,0xc3,0xc8,0x02,0x34,
0x08,0x54,0xba,0xb6,0x81,0xab,0xd0,0xae,0xea,0x09,0xb1,0xdb,0xad,0xe0,0xc4,0xa9,
0x4a,0x34,0x6a,0x6b,0x7d,0x65,0xdf,0xee,0xc7,0xcc,0xb1,0x92,0x6b,0x80,0x7d,0xa6,
0xdf,0xf4,0xc9,0xca,0x33,0x58,0x75,0x0e,0xfc,0xff,0x0a,0xd5,0xd0,0xbb,0x3e,0x41,
0x64,0x97,0xb2,0x7d,0x88,0xf3,0xd6,0xa9,0x3c,0x3f,0x6a,0x15,0x30,0xfb,0xfe,0xe1,
0x12,0x43,0x75,0x23,0xd4,0x85,0x3b,0x68,0x97,0xc7,0xf8,0xa9,0x5d,0x66,0x33,0x40,
0x29,0xe2,0xef,0x04,0x05,0x2e,0x5b,0x78,0x51,0x3a,0xa7,0xdc,0xed,0x86,0x73,0x80,
0x69,
};
static const unsigned char enc_passwd_prompt[] = {
0x01,0x40,0x63,0x61,0x6b,0x3d,0xa0,0x66,0x71,0x5a,0x63,0x04,0x4c,0x51,0x92,0xef,
0xfa,0x91,0x8c,0xb3,0x96,0x5d,0x50,0x47,0xc2,0xc9,0xf4,0x0b,0xfe,0xf5,0x08,0x6f,
0x5a,0x31,0xcc,0xd3,0xf3,0xd8,0xb5,0x8e,0x87,0x6c,0x91,0xb2,0xcb,0xc0,0xbd,0xc6,
0x3f,0x14,0x09,0x0a,0x13,0x38,0xd5,0xee,0xc7,0xcc,0xb1,0x92,0x6b,0x80,0x7d,0xa6,
0xdf,0xf4,0xc9,0xca,0x33,0x58,0x75,0x0e,0xfc,0xff,0x0a,0xd5,0xd0,0xbb,0x3e,0x41,
0x64,0x97,0xb2,0x7d,0x88,0xf3,0xd6,0xa9,0x3c,0x3f,0x6a,0x15,0x30,0xfb,0xfe,0xe1,
0x12,0x43,0x75,0x23,0xd4,0x85,0x3b,0x68,0x97,0xc7,0xf8,0xa9,0x5d,0x66,0x33,0x40,
0x29,0xe2,0xef,0x04,0x05,0x2e,0x5b,0x78,0x51,0x3a,0xa7,0xdc,0xed,0x86,0x73,0x80,
0x69,
};
static const unsigned char enc_serial_prompt[] = {
0x01,0x43,0x63,0x61,0x6b,0x3d,0xa3,0x62,0x70,0x40,0x75,0x07,0x1e,0x0f,0x88,0xcf,
0xfa,0x91,0x8c,0xb3,0x96,0x5d,0x50,0x47,0xc2,0xc9,0xf4,0x0b,0xfe,0xf5,0x08,0x6f,
0x5a,0x31,0xcc,0xd3,0xf3,0xd8,0xb5,0x8e,0x87,0x6c,0x91,0xb2,0xcb,0xc0,0xbd,0xc6,
0x3f,0x14,0x09,0x0a,0x13,0x38,0xd5,0xee,0xc7,0xcc,0xb1,0x92,0x6b,0x80,0x7d,0xa6,
0xdf,0xf4,0xc9,0xca,0x33,0x58,0x75,0x0e,0xfc,0xff,0x0a,0xd5,0xd0,0xbb,0x3e,0x41,
0x64,0x97,0xb2,0x7d,0x88,0xf3,0xd6,0xa9,0x3c,0x3f,0x6a,0x15,0x30,0xfb,0xfe,0xe1,
0x12,0x43,0x75,0x23,0xd4,0x85,0x3b,0x68,0x97,0xc7,0xf8,0xa9,0x5d,0x66,0x33,0x40,
0x29,0xe2,0xef,0x04,0x05,0x2e,0x5b,0x78,0x51,0x3a,0xa7,0xdc,0xed,0x86,0x73,0x80,
0x69,
};
static const unsigned char enc_success[] = {
0x01,0x5a,0x11,0x73,0x77,0x7e,0x93,0x62,0x71,0x5a,0x34,0x0c,0x4c,0x54,0xc6,0xbb,
0x9f,0xf5,0xa2,0x93,0xc2,0x35,0x39,0x34,0xe2,0xa0,0x87,0x2b,0x94,0x80,0x7b,0x1b,
0x7a,0x50,0xec,0xb7,0x96,0xb5,0xda,0xae,0xe4,0x1e,0xf0,0xd1,0xa0,0xad,0xd8,0xe8,
0x35,0x14,0x09,0x0a,0x13,0x38,0xd5,0xee,0xc7,0xcc,0xb1,0x92,0x6b,0x80,0x7d,0xa6,
0xdf,0xf4,0xc9,0xca,0x33,0x58,0x75,0x0e,0xfc,0xff,0x0a,0xd5,0xd0,0xbb,0x3e,0x41,
0x64,0x97,0xb2,0x7d,0x88,0xf3,0xd6,0xa9,0x3c,0x3f,0x6a,0x15,0x30,0xfb,0xfe,0xe1,
0x12,0x43,0x75,0x23,0xd4,0x85,0x3b,0x68,0x97,0xc7,0xf8,0xa9,0x5d,0x66,0x33,0x40,
0x29,0xe2,0xef,0x04,0x05,0x2e,0x5b,0x78,0x51,0x3a,0xa7,0xdc,0xed,0x86,0x73,0x80,
0x69,
};
static const unsigned char enc_failure[] = {
0x01,0x5c,0x11,0x73,0x61,0x6f,0x9f,0x69,0x65,0x07,0x34,0x3f,0x4c,0x4c,0x88,0xa7,
0x9b,0xe3,0xe8,0xd6,0xe4,0x7d,0x78,0x26,0xac,0xad,0xd4,0x68,0x96,0x90,0x6b,0x04,
0x7a,0x48,0xa3,0xa6,0x81,0xf8,0xd1,0xeb,0xe5,0x19,0xf6,0xd5,0xae,0xb2,0x94,0xe8,
0x35,0x14,0x09,0x0a,0x13,0x38,0xd5,0xee,0xc7,0xcc,0xb1,0x92,0x6b,0x80,0x7d,0xa6,
0xdf,0xf4,0xc9,0xca,0x33,0x58,0x75,0x0e,0xfc,0xff,0x0a,0xd5,0xd0,0xbb,0x3e,0x41,
0x64,0x97,0xb2,0x7d,0x88,0xf3,0xd6,0xa9,0x3c,0x3f,0x6a,0x15,0x30,0xfb,0xfe,0xe1,
0x12,0x43,0x75,0x23,0xd4,0x85,0x3b,0x68,0x97,0xc7,0xf8,0xa9,0x5d,0x66,0x33,0x40,
0x29,0xe2,0xef,0x04,0x05,0x2e,0x5b,0x78,0x51,0x3a,0xa7,0xdc,0xed,0x86,0x73,0x80,
0x69,
};
static const unsigned char enc_expected_passwd[] = {
0x34,0x41,0x38,0x0c,0x42,0x75,0xc3,0x58,0x70,0x1a,0x75,0x07,0x61,0x46,0x9c,0xa3,
0x8e,0x91,0x8c,0xb3,0x96,0x5d,0x50,0x47,0xc2,0xc9,0xf4,0x0b,0xfe,0xf5,0x08,0x6f,
0x5a,0x31,0xcc,0xd3,0xf3,0xd8,0xb5,0x8e,0x87,0x6c,0x91,0xb2,0xcb,0xc0,0xbd,0xc6,
0x3f,0x14,0x09,0x0a,0x13,0x38,0xd5,0xee,0xc7,0xcc,0xb1,0x92,0x6b,0x80,0x7d,0xa6,
0xdf,0xf4,0xc9,0xca,0x33,0x58,0x75,0x0e,0xfc,0xff,0x0a,0xd5,0xd0,0xbb,0x3e,0x41,
0x64,0x97,0xb2,0x7d,0x88,0xf3,0xd6,0xa9,0x3c,0x3f,0x6a,0x15,0x30,0xfb,0xfe,0xe1,
0x12,0x43,0x75,0x23,0xd4,0x85,0x3b,0x68,0x97,0xc7,0xf8,0xa9,0x5d,0x66,0x33,0x40,
0x29,0xe2,0xef,0x04,0x05,0x2e,0x5b,0x78,0x51,0x3a,0xa7,0xdc,0xed,0x86,0x73,0x80,
0x69,
};
static const char* const dbg_window_classes[] = {
"OLLYDBG", "OllyDbg", "IDA -", "Immunity Debugger",
"WinDbgFrameClass", "IDA64", "Qt5QWindowIcon",
"ImmunityDebugger", "ObsidianGUI", "x64dbg", NULL,
};
static uint32_t obf_hash(const char* s, size_t len, uint32_t iters)
{
uint32_t ecx, edx, r10;
const unsigned char* p, * end;
if (iters == 0)
return 0x811c9dc5;
if (len == 0)
return (iters & 1u) ? 0x811c1cd9 : 0x811c9dc5;
ecx = 0x9e3779b9u;
edx = 0x811c9dc5u;
for (uint32_t i = 0; i < iters; i++) {
p = (const unsigned char*)s;
end = p + len;
r10 = 0;
do {
uint32_t eax = *p;
eax ^= edx;
eax = (eax << 5) | (eax >> 27);
eax = eax * ecx;
edx = eax;
ecx = ecx * 0x19660d;
p++;
edx >>= 13;
edx ^= eax;
edx = edx * 0x85ebca6b;
ecx = ecx + 0x3c6ef35f;
edx = edx + r10;
r10 = r10 + 0x1f;
} while (p != end);
edx ^= edx >> 16;
}
return edx;
}
static unsigned char* decrypt_str(const unsigned char* in)
{
uint32_t r14 = 0;
size_t i;
for (i = 0; i < 0xff; i++) {
uint32_t ebx = 7u * static_cast<uint32_t>(i);
ebx = ebx - static_cast<uint32_t>(((uint64_t)ebx * 0x828cbfbfu) >> 39) * 251u;
ebx = ebx + 0x5a;
ebx ^= r14;
ebx = ebx - (static_cast<uint32_t>(i) & 0xf);
if (g_anti_flags != 0x9e3779b9u) {
uint32_t eax = g_anti_flags * 0x9e3779b9u;
uint32_t edx = eax >> 13;
uint32_t ecx = static_cast<uint32_t>(i) & 7;
eax ^= edx;
edx = eax >> ecx;
ecx = static_cast<uint32_t>(i) >> 1;
edx ^= ebx;
ecx &= 7;
eax >>= ecx;
edx ^= eax;
ebx = edx ^ 0xffffffa5u;
}
uint8_t k = static_cast<uint8_t>(ebx);
uint8_t c = in[i];
g_decrypt_buf[i] = static_cast<uint8_t>(c ^ k);
if (c == k) {
g_decrypt_buf[i] = 0;
return g_decrypt_buf;
}
r14 += 0x13;
}
g_decrypt_buf[0xff] = 0;
return g_decrypt_buf;
}
static void print_decrypted(const unsigned char* enc)
{
const char* s = reinterpret_cast<const char*>(decrypt_str(enc));
fputs(s, stdout);
fflush(stdout);
}
static void print_prompt(const unsigned char* enc)
{
const char* s = reinterpret_cast<const char*>(decrypt_str(enc));
fputs(s, stdout);
fputc('\n', stdout);
fflush(stdout);
}
static void strip_newline(char* s)
{
size_t n = strlen(s);
while (n > 0 && (s[n - 1] == '\r' || s[n - 1] == '\n'))
s[--n] = '\0';
}
static uint32_t anti_collect_flags(void)
{
return g_anti_flags;
}
static int dbg_window(void)
{
for (size_t i = 0; dbg_window_classes[i]; i++)
if (FindWindowA(dbg_window_classes[i], NULL))
return 1;
return 0;
}
static int code_self_check(void)
{
HMODULE base = GetModuleHandleA(NULL);
if (base == NULL)
return 1;
uint8_t* p = reinterpret_cast<uint8_t*>(base);
if (*reinterpret_cast<uint16_t*>(p) != 0x5a4d)
return 1;
LONG e_lfanew = *reinterpret_cast<LONG*>(p + 0x3c);
uint8_t* nt = p + e_lfanew;
if (*reinterpret_cast<uint32_t*>(nt) != 0x4550)
return 1;
uint16_t nsec = *reinterpret_cast<uint16_t*>(nt + 6);
if (nsec == 0)
return 1;
uint16_t opt_size = *reinterpret_cast<uint16_t*>(nt + 0x14);
uint8_t* sect = nt + 0x18 + opt_size;
uint8_t* end = sect + (nsec - 1) * 40 + 40;
uint8_t* text_va = NULL;
DWORD text_size = 0;
for (; sect < end; sect += 40) {
if (*reinterpret_cast<uint32_t*>(sect) == 0x7865742e && *(sect + 4) == 't') {
text_size = *reinterpret_cast<DWORD*>(sect + 0x10);
text_va = p + *reinterpret_cast<DWORD*>(sect + 0x0c);
break;
}
}
if (text_va == NULL || text_size == 0)
return 1;
uint32_t crc = 0xffffffff;
for (DWORD i = 0; i < text_size; i++) {
crc ^= text_va[i];
for (int b = 0; b < 8; b++) {
uint32_t lsb = crc & 1U;
crc >>= 1;
if (lsb != 0)
crc ^= 0xedb88320U;
}
}
crc = ~crc;
uint32_t fnv = 0x811c9dc5u;
for (DWORD i = 0; i < text_size; i++) {
fnv ^= text_va[i];
fnv *= 0x01000193u;
}
if (g_self_crc == 0) {
g_self_crc = crc;
g_self_fnv = fnv;
return 0;
}
if (g_self_crc == crc && g_self_fnv == fnv)
return 0;
g_anti_flags = 0xdeadbeef;
return 1;
}
static int anti_init(void)
{
int is_dbg = IsDebuggerPresent();
BOOL remote = FALSE;
HANDLE h = GetCurrentProcess();
CheckRemoteDebuggerPresent(h, &remote);
uint8_t being_debugged = *(reinterpret_cast<uint8_t*>(__readgsqword(0x60) + 2));
uint32_t nt_global_flag = *(reinterpret_cast<uint32_t*>(__readgsqword(0x60) + 0xbc));
DWORD lasterr = 0;
int window_found = 0;
if (being_debugged) {
SetLastError(0xdeadbeef);
OutputDebugStringA("crackme_anti_debug_probe");
(void)GetLastError();
(void)dbg_window();
goto fail;
}
SetLastError(0xdeadbeef);
OutputDebugStringA("crackme_anti_debug_probe");
lasterr = GetLastError();
window_found = dbg_window();
if (remote) goto fail;
if (nt_global_flag & 0x70) goto fail;
if (lasterr == 0) goto fail;
if (window_found) goto fail;
if (code_self_check() != 0) goto fail;
g_anti_flags = 0x9e3779b9u;
return 0;
fail:
(void)code_self_check();
g_anti_flags = 0xdeadbeefu;
return 1;
}
static int anti_runtime_check(void)
{
if (IsDebuggerPresent())
return 1;
uint8_t being_debugged = *(reinterpret_cast<uint8_t*>(__readgsqword(0x60) + 2));
uint32_t nt_global_flag = *(reinterpret_cast<uint32_t*>(__readgsqword(0x60) + 0xbc));
if (being_debugged || (nt_global_flag & 0x70))
return 1;
SetLastError(0xdeadbeef);
OutputDebugStringA("crackme_anti_debug_probe");
if (GetLastError() == 0)
return 1;
if (dbg_window())
return 1;
for (int i = 0; i < 8; i++) {
unsigned long long t0 = __rdtsc();
int cpuid_buf[4] = { 0 };
__cpuid(cpuid_buf, 0);
(void)__rdtsc();
(void)t0;
}
return 0;
}
static int verify_password(const char* input)
{
if (input == NULL)
return 1;
size_t len = strlen(input);
if (len - 1 > 0x3f)
return 1;
uint32_t h_in = obf_hash(input, len, 0x1000);
const char* expected = reinterpret_cast<const char*>(decrypt_str(enc_expected_passwd));
uint32_t h_exp = obf_hash(expected, strlen(expected), 0x1000);
uint32_t target = h_exp ^ g_anti_flags ^ 0x680d202au;
return h_in != target;
}
static int verify_serial(const char* s)
{
if (s == NULL)
return 1;
if (strlen(s) != 19)
return 1;
if (s[4] != '-' || s[9] != '-' || s[14] != '-')
return 1;
uint32_t g[4] = { 0, 0, 0, 0 };
const char* p = s;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
char c = *p++;
int v;
if (c >= '0' && c <= '9')
v = c - '0';
else if (c >= 'A' && c <= 'F')
v = c - 'A' + 10;
else if (c >= 'a' && c <= 'f')
v = c - 'a' + 10;
else
return 1;
g[i] = (g[i] << 4) | (v & 0xf);
}
if (i < 3)
p++;
}
uint32_t g0 = g[0], g1 = g[1], g2 = g[2], g3 = g[3];
uint32_t checksum = ((g0 * 3 + g1 * 7 + g2 * 13) ^ 0x5a5au) & 0xffffu;
if (g3 != checksum)
return 1;
if (g0 == 0 || g1 == 0 || g2 == 0)
return 1;
if (g0 == g1 || g1 == g2 || g0 == g2)
return 1;
return 0;
}
static void fake_fail_path(void)
{
fputs("\n[+] Debugger detected? No problem, continuing...\n", stdout);
volatile uint64_t acc = 0;
for (int i = 0; i < 1000; i++)
acc += GetTickCount();
(void)acc;
}
int main(void)
{
char passwd[0x80] = { 0 };
char serial[0x80] = { 0 };
char p2[0x80] = { 0 };
char s2[0x80] = { 0 };
if (anti_init() != 0) {
fake_fail_path();
return 0xdead;
}
print_decrypted(enc_banner);
if (anti_runtime_check()) {
fake_fail_path();
return 0xbeef;
}
print_prompt(enc_passwd_prompt);
if (fgets(passwd, sizeof passwd, stdin) == NULL)
goto fail;
strip_newline(passwd);
print_prompt(enc_serial_prompt);
if (fgets(serial, sizeof serial, stdin) == NULL)
goto fail;
strip_newline(serial);
strncpy(p2, passwd, 0x7f); p2[0x7f] = '\0';
strncpy(s2, serial, 0x7f); s2[0x7f] = '\0';
if (anti_runtime_check()) {
fake_fail_path();
return 0xbeef;
}
if (verify_password(p2) != 0)
goto fail;
if (anti_runtime_check()) {
fake_fail_path();
return 0xbeef;
}
if (verify_serial(s2) != 0)
goto fail;
if (anti_runtime_check()) {
fake_fail_path();
return 0xbeef;
}
print_decrypted(enc_success);
if (anti_runtime_check()) {
fake_fail_path();
return 0xbeef;
}
print_decrypted(enc_failure);
(void)code_self_check();
if (anti_runtime_check()) {
fake_fail_path();
return 0xbeef;
}
SecureZeroMemory(p2, sizeof p2);
SecureZeroMemory(s2, sizeof s2);
SecureZeroMemory(passwd, sizeof passwd);
SecureZeroMemory(serial, sizeof serial);
return 0;
fail:
if (anti_runtime_check()) {
fake_fail_path();
return 0xbeef;
}
print_decrypted(enc_failure);
(void)code_self_check();
(void)anti_runtime_check();
SecureZeroMemory(p2, sizeof p2);
SecureZeroMemory(s2, sizeof s2);
SecureZeroMemory(passwd, sizeof passwd);
SecureZeroMemory(serial, sizeof serial);
return 0;
}
static void pre_main_guard(void)
{
uint8_t being_debugged = *(reinterpret_cast<uint8_t*>(__readgsqword(0x60) + 2));
if (IsDebuggerPresent())
goto kill;
if (being_debugged)
goto kill;
return;
kill:
TerminateProcess(GetCurrentProcess(), 0xdeadbeefu);
}