The main function (address 0x140001200 ) implements a simple console UI:
# ------------------------------------------------------------ # 2. Reverse the custom transform def invert_transform(b): """Given transformed byte b = ROL8(c ^ 0x5A, 3), recover original c.""" # Inverse of ROL8 by 3 is ROR8 by 3 r = ((b >> 3) | (b << 5)) & 0xFF c = r ^ 0x5A return c
// 2. Compute a 32‑bit “hash” of the transformed buffer uint32_t h = 0xFFFFFFFF; for (int i = 0; i < 9; ++i) h ^= buf[i]; for (int j = 0; j < 8; ++j) if (h & 1) h = (h >> 1) ^ 0xEDB88320; // CRC‑32 (polynomial 0xEDB88320) else h >>= 1;
The program uses the insecure gets_s but limits to 63 characters – no overflow. The real work is in check_serial . 3.3. The serial‑checking routine In Ghidra the function is named check_serial (address 0x140001560 ). Its decompiled pseudo‑code (after some renaming) looks like this: Adeko 9 Crack 56
# ------------------------------------------------------------ # 1. CRC‑32 parameters (same as the binary) POLY = 0xEDB88320 INIT = 0xFFFFFFFF XOROUT = 0x00000000
# Instead of a complicated generic reverse, we exploit the fact that # CRC‑32 with polynomial 0xEDB88320 is reversible byte‑by‑byte. # The following tiny routine does it: def reverse_crc_bytes(target, nbytes): crc = target out = [] for _ in range(nbytes): # The low byte of the CRC is the byte that was processed last, # after the forward step it becomes (crc ^ byte) & 0xFF. # So to reverse, we take the low byte as the original data byte. b = crc & 0xFF out.append(b) crc = (crc ^ TABLE[b]) >> 8 return list(reversed(out))
Find an input string s (9 bytes) such that CRC32( b_0 … b_8 ) == 0x56C9A4F2 . 4.2. CRC‑32 is linear over GF(2) CRC‑32 with a fixed polynomial is a linear operation: The main function (address 0x140001200 ) implements a
int main(int argc, char **argv) char input[64]; puts("Enter your serial: "); gets_s(input, sizeof(input)); if (check_serial(input) == 0) puts("Invalid serial! Try again."); return 1; puts("Correct! Welcome, Adeko."); return 0;
If we denote the post‑transform byte as b_i = t(i) , the CRC algorithm is applied to the sequence b_0 … b_8 .
int __cdecl mainCRTStartup(void) ... return main(__argc, __argv); The real work is in check_serial
def crc32_step_rev(crc, b): """Reverse one CRC‑32 step (process byte b at the *end* of the stream).""" # The forward step is: crc = (crc >> 8) ^ TABLE[(crc ^ b) & 0xFF] # Reversing: idx = (crc ^ b) & 0xFF prev_crc = (crc ^ TABLE[idx]) << 8 prev_crc |= idx return prev_crc & 0xFFFFFFFF
(A classic “crack‑me” style reverse‑engineering challenge) 1. Overview | Item | Description | |------|-------------| | Challenge name | Adeko 9 Crack 56 | | Category | Reverse Engineering / Binary Cracking | | Platform | Windows 10 (x86‑64) – compiled with Visual Studio 2019 | | File size | ≈ 82 KB (PE32+ executable) | | Protection | No packer, but includes basic anti‑debug tricks and a custom serial‑check routine | | Goal | Produce a valid serial key that makes the program display “Correct!” (or the equivalent success message). | 2. Setup # Create a clean analysis environment mkdir adeko9-crack56 && cd adeko9-crack56 cp /path/to/Adeko9Crack56.exe . Tools used
transformed = reverse_crc_bytes(TARGET, 9) print("[+] Transformed bytes (b_i):", transformed)