| MCM 6.0 - Project Mayhem |
I started by listing all the functions in IDA and immediately noticed that the binary had zero imports, which told me everything was resolved dynamically. The function list showed a huge "start" function at 0x140007C70 spanning about 2 megabytes, along with around 40 smaller helper functions. I also noticed section names like .vmp0, .vmp1, .themida, .enigma1 which were clearly fake, put there to scare off beginners into thinking multiple protectors were applied. My first move was to search for readable strings in the binary. The regex search only returned "CrackMeByPwn.pdb" and "rMKey", nothing useful like "password" or "correct". So I shifted to decompiling the smaller functions one by one. I quickly identified the function at 0x140007BD0 as an FNV-1a hash function because of the characteristic constants 0x811C9DC5 (initial value) and 0x01000193 (prime multiplier), with a case-insensitive comparison that converts lowercase letters to uppercase before hashing. Another function at 0x140007900 turned out to be a PEB-walking API resolver that uses the FNV-1a hash to find exports by name hash instead of by string. I then computed FNV-1a hashes for common Windows API names using a Python script inside IDA. This let me map each helper function to the API it resolves. For example, I found that 0x4FF7FB75 is GetTickCount, 0x6D3D9A28 is Sleep, 0xD1AFE3BC is GetComputerNameA, 0xAC392D5A is ExitProcess, 0x38E87001 is VirtualAlloc, and so on. Some functions didn't have a hardcoded hash in their cmp instructions, so I had to look deeper into their code to find the actual comparison value. With the API map in hand, I went back to the start function and disassembled it from the beginning. The first hundred instructions showed it reading bytes from fake sections, storing the initial key 0x64FA4D94, and calling the anti-debug memory scanner. I traced the key variable through each check. After the anti-debug call, if it returns 0 (clean), no XOR happens. Then GetTickCount is called, Sleep(50) executes, GetTickCount is called again, and the delta is checked against 30ms and 5000ms bounds. In a normal run, the delta is around 50-60ms, so no XOR. GetComputerNameA succeeds on any real machine, and the function table lookup always picks index 1 which returns 0. So the key stays at 0x64FA4D94 throughout. The breakthrough came when I looked for cross-references to the HMAC-SHA256 function (0x1400068A0). I found it was called from 0x1401B3A85 inside the start function. I disassembled backwards from that address and found the decryption loop starting at 0x1401B3313. The code was straightforward despite the CFF obfuscation around it because the decryption itself wasn't flattened, it was inline. I could read the three decryption stages directly from the disassembly: first a subtract-and-XOR pass, then a Fisher-Yates shuffle seeded with the key via MSVC's LCG, and finally a 4-byte repeating XOR. To actually decrypt the embedded PE, I wrote a Python script inside IDA's scripting console. It read all 0x69600 bytes from 0x1402C7000, applied the three decryption stages using the key 0x64FA4D94, and checked if the result started with "MZ". It did. The first 16 bytes came out as 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00, a perfectly valid DOS header. I saved the decrypted PE to disk and then extracted all ASCII strings from it. The string dump revealed everything. Among the standard C++ runtime strings and Windows API names, I found the crackme-specific strings: anti-debug taunts like "MCM v5.0 | Your breakpoints are cute", a fake flag format "[+] SUCCESS BUT NOT! Flag: MCM6{%08X}", and most importantly the password candidates "S4CaqeCret20MCM6" and "PwEedPasswordOtsosiPenis" sitting right next to each other in the .rdata section. The decrypted PE also imports ws2_32.dll and wininet.dll, confirming it does network-based validation. The whole process from opening the binary to finding the passwords took about 30 minutes of guided analysis using IDA's MCP tools. |
2026-03-10 23:45 |
| MCM 6.0 - Project Mayhem |
Try the password "aaaaaaaaaadsssssa" in the decrypted exe I sent. |
2026-03-10 23:39 |