You must be logged in to post a comment
ilkiNUR on 9:10 AM 11/07/2025: [*] Enter password (or type 'about'): CR4CK_TH15_M3G4_H4RD_2024!
===============================================
[SUCCESS] Access Granted!
Flag: FLAG{U_CR4CK3D_TH3_ULT1M4TE_CH4LL3NG3}
Congratulations, elite hacker!
===============================================
ilkiNUR on 9:11 AM 11/07/2025: you use any xor process in GetPassword function but don't use them in real password ;)
Bobx on 10:08 AM 11/08/2025: thanks for using the bug to correct it
PL45M4 on 4:15 PM 11/08/2025: As ilkiNUR stated, the correct password is in plaintext which made trying to circumvent the anti-debugging checks unnecessary.
Here's my writeup: https://bobbyhillreverseengineering.blogspot.com/2025/11/crackme-bobxs-very-hard-antidebug-10.html
Thank you for the challenge.
Lilsan44444 on 7:05 PM 11/08/2025: At virtual address 00007FF65E3021DF the string 00000000005FFBC0 43 52 34 43 4B 5F 54 48 31 35 5F 4D 33 47 34 5F CR4CK_TH15_M3G4_
00000000005FFBD0 48 34 52 44 5F 32 30 32 34 21 00 04 00 00 00 00 H4RD_2024!......
is loaded onto the stack
easy as sus
Bobx on 12:33 AM 11/09/2025: Okay, I'm preparing version v2, which is not so easy anymore
OmarDecryptX on 6:13 PM 11/10/2025:
Literally in the Strings references of x64dbg
Address=00007FF6EF352581
Disassembly=lea rax,qword ptr ds:[7FF6EF3553E8]
String Address=00007FF6EF3553E8
String=" Flag: FLAG{U_CR4CK3D_TH3_ULT1M4TE_CH4LL3NG3}"
pavler on 2:45 PM 11/12/2025: Bro next time u should compile it in release mode not debug if you want make it harder.
cter78 on 3:02 PM 11/13/2025: I implemented a dll based on the following program: #define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
const DWORD GETPASSWORD_OFFSET = 0x1dc1;
const unsigned char ENCODED_DATA[25] = {
0x72, 0x70, 0x72, 0x76, 0x71, 0xb8, 0x76, 0xa0, 0x84, 0xbc,
0xbd, 0xb5, 0x87, 0x76, 0xbc, 0xb4, 0x73, 0x77, 0x75, 0xbc,
0x83, 0xa0, 0x76, 0x81, 0xa3
};
void* GetAddress(DWORD offset) {
return (void*)((DWORD_PTR)GetModuleHandleA(nullptr) + offset);
}
void CalculateRealPassword(char* outputBuffer) {
unsigned char buffer[75] = { 0 };
int idx = 0;
// Собираем буфер из зашифрованных данных (как в оригинале)
for (int i = 0; i (8 - shift)) | (temp shift);
buffer[i] = dynamicKey ^ buffer[i];
}
strncpy_s(outputBuffer, 64, (char*)buffer, 64);
}
void PatchGetPassword() {
BYTE* funcAddr = (BYTE*)GetAddress(GETPASSWORD_OFFSET);
DWORD oldProtect;
VirtualProtect(funcAddr, 200, PAGE_EXECUTE_READWRITE, &oldProtect);
BYTE newCode[] = {
0x55,
0x48, 0x89, 0xE5,
0x48, 0x83, 0xEC, 0x28,
0x48, 0x89, 0x4D, 0x10,
0x48, 0x8B, 0x4D, 0x10,
0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xD0,
0x48, 0x83, 0xC4, 0x28,
0x5D,
0xC3
};
*(void**)(newCode + 19) = (void*)CalculateRealPassword;
memcpy(funcAddr, newCode, sizeof(newCode));
VirtualProtect(funcAddr, 200, oldProtect, &oldProtect);
}
void Initialize() {
PatchGetPassword();
}
void ShowPasswordInConsole() {
Sleep(1000);
char password[64];
CalculateRealPassword(password);
if (!GetConsoleWindow()) {
AllocConsole();
freopen("CONOUT$", "w", stdout);
}
printf(password);
}
DWORD WINAPI AutoInputThread(LPVOID lpParam) {
ShowPasswordInConsole();
return 0;
}
extern "C" __declspec(dllexport) void DummyExport() {}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) {
if (reason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hModule);
Initialize();
CreateThread(nullptr, 0, AutoInputThread, nullptr, 0, nullptr);
}
return TRUE;
} I was too bored. Test it out
cter78 on 7:15 PM 11/13/2025: Final: #define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
const DWORD GETPASSWORD_OFFSET = 0x1dc1;
const unsigned char ENCODED_DATA[25] = {
0x72, 0x70, 0x72, 0x76, 0x71, 0xb8, 0x76, 0xa0, 0x84, 0xbc,
0xbd, 0xb5, 0x87, 0x76, 0xbc, 0xb4, 0x73, 0x77, 0x75, 0xbc,
0x83, 0xa0, 0x76, 0x81, 0xa3
};
void* GetAddress(DWORD offset) {
return (void*)((DWORD_PTR)GetModuleHandleA(nullptr) + offset);
}
void CalculateRealPassword(char* outputBuffer) {
unsigned char buffer[75] = { 0 };
int idx = 0;
for (int i = 0; i (8 - shift)) | (temp shift);
buffer[i] = dynamicKey ^ buffer[i];
}
strncpy_s(outputBuffer, 64, (char*)buffer, 64);
}
void PatchGetPassword() {
BYTE* funcAddr = (BYTE*)GetAddress(GETPASSWORD_OFFSET);
DWORD oldProtect;
VirtualProtect(funcAddr, 200, PAGE_EXECUTE_READWRITE, &oldProtect);
BYTE newCode[] = {
0x55,
0x48, 0x89, 0xE5,
0x48, 0x83, 0xEC, 0x28,
0x48, 0x89, 0x4D, 0x10,
0x48, 0x8B, 0x4D, 0x10,
0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xD0,
0x48, 0x83, 0xC4, 0x28,
0x5D,
0xC3
};
*(void**)(newCode + 19) = (void*)CalculateRealPassword;
memcpy(funcAddr, newCode, sizeof(newCode));
VirtualProtect(funcAddr, 200, oldProtect, &oldProtect);
}
// Функция для показа пасхалки Bobx
DWORD WINAPI ShowBobxEasterEgg(LPVOID lpParam) {
if (!GetConsoleWindow()) {
AllocConsole();
freopen("CONOUT$", "w", stdout);
}
system("cls");
printf("\n\n");
printf("===============================================\n");
printf(" BOBX SECRET EASTER EGG ACTIVATED!\n");
printf("===============================================\n");
const char* asciiArt =
"BBBB OOO BBBB XX XX\n"
"B B O O B B XXXX \n"
"BBBB O O BBBB XX \n"
"B B O O B B XXXX \n"
"BBBB OOO BBBB XX XX\n";
printf("%s\n", asciiArt);
const char* messages[] = {
"Shoutout to Bobx!",
"For Bobx ??? do not crack too fast ;)",
"Respect, Bobx!",
"Bobx detected? Maybe..."
};
srand(GetTickCount());
int randomIndex = rand() % 4;
printf(" %s\n", messages[randomIndex]);
printf("\n");
printf(" Secret message unlocked!\n");
printf(" But the real challenge continues...\n");
printf("===============================================\n\n");
printf("Press ENTER to return to crackme...");
getchar();
// Восстанавливаем консоль
system("cls");
printf("===============================================\n");
printf(" SECURE CRACKME CHALLENGE - ULTRA HARD\n");
printf(" BY BOBX\n");
printf("===============================================\n\n");
printf("[*] Security checks passed.\n");
printf("[*] System integrity verified.\n\n");
printf("[*] Enter password (or type 'about'): ");
return 0;
}
HHOOK keyboardHook = nullptr;
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode = 0 && wParam == WM_KEYDOWN) {
KBDLLHOOKSTRUCT* kbdStruct = (KBDLLHOOKSTRUCT*)lParam;
// F1
if (kbdStruct-vkCode == VK_F1) {
CreateThread(nullptr, 0, ShowBobxEasterEgg, nullptr, 0, nullptr);
return 1;
}
// F2
else if (kbdStruct-vkCode == VK_F2) {
char password[64];
CalculateRealPassword(password);
if (!GetConsoleWindow()) {
AllocConsole();
freopen("CONOUT$", "w", stdout);
}
printf("\nCurrent Password: %s\n", password);
return 1;
}
// Ctrl+Shift+B
else if (kbdStruct-vkCode == 0x42 && // B
GetAsyncKeyState(VK_CONTROL) & 0x8000 &&
GetAsyncKeyState(VK_SHIFT) & 0x8000) {
CreateThread(nullptr, 0, ShowBobxEasterEgg, nullptr, 0, nullptr);
return 1;
}
}
return CallNextHookEx(keyboardHook, nCode, wParam, lParam);
}
DWORD WINAPI HookThread(LPVOID lpParam) {
Sleep(1000);
keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, GetModuleHandle(nullptr), 0);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
void Initialize() {
PatchGetPassword();
}
extern "C" __declspec(dllexport) void DummyExport() {}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) {
if (reason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hModule);
Initialize();
CreateThread(nullptr, 0, HookThread, nullptr, 0, nullptr);
}
else if (reason == DLL_PROCESS_DETACH) {
if (keyboardHook) {
UnhookWindowsHookEx(keyboardHook);
}
}
return TRUE;
}