Number of crackmes:
Number of writeups:
Comments:
| Name | Author | Language | Arch | Difficulty | Quality | Platform | Date | Downloads | Writeups | Comments |
|---|
| Crackme | Date | Infos | Actions |
|---|
| Crackme | Comment | Date |
|---|---|---|
| hard crack me | Really elegant crackme. Defeated the anti-debug checks, then dumped the custom hashing routine at 0x140001540. Because the 20-byte input is split and hashed with derived seeds (seed2 = eax1 ^ 0xC001D00D), I wrote a parallel C# brute-forcer to target the 0x60FAF8E6 collision check. Crushed the search space in seconds. The fact that the success state executes a classic process injection directly into explorer.exe (and spikes the CPU) was a fantastic touch. Excellent work on this one. writeup submitted | 2026-07-31 17:33 |
| Ultimate Ultimate Boss Crackme | The author compiled this one with Profile-Guided Optimization (PGO), which completely scattered the basic blocks of the functions and made the std::cin C++ STL code look like an absolute nightmare to trace through. But once you find the true checking function, the core logic is revealed: Instead of 2 parts, this version loops and asks for 152 Parts. Part 1 must equal the mathematical sum of the Username's ASCII characters multiplied by 31. Every subsequent part is mathematically chained to the previous one using the formula: Part[i] = ((i + 0x1337) XOR Part[i-1]) + (i * 123). The final twist is that the lowest byte of the very last part (Part 152) is used as the XOR key to decrypt the final success message! If you use a random valid username, you'll pass the check but get a garbage text flag. To get the true message, your Username's characters must sum to exactly 297 (for example, the word ace). Since no one wants to type 152 numbers by hand, I generated the full mathematical sequence for ace and pasted it as a single space-separated string, letting std::cin auto-fill all 152 prompts instantly. Decrypted Flag: Wow you did it! What an amazing finale to the series! | 2026-07-29 12:30 |
| Ultimate Boss Level - Final | What an absolutely incredible finish to this series! The author threw everything at us for this final crackme. Here is a breakdown of all the protections and how the algorithm works: 1. The Distractions & Anti-Debugging Maze If you look for strings, you'll only find standard C++ exception messages (like "bad allocation") left behind as a distraction. The program uses std::cin and std::cout and dynamically decrypts its strings on the fly. Before you even get to the password check, you have to survive a gauntlet of anti-debugging traps: IsDebuggerPresent & CheckRemoteDebuggerPresent GetThreadContext: Checks your CPU's debug registers to see if you placed any Hardware Breakpoints. Memory Check: Checks if the first byte of the password function is 0xCC, meaning it detects if you placed a software breakpoint (F2) on it! GetTickCount64 Timing Check: Measures how long the password check takes. If it takes longer than 500ms, it assumes you are single-stepping in a debugger and fails you! 2. Control Flow Flattening The actual license check is hidden inside a function that uses a technique called Control Flow Flattening. The code is chopped up into blocks and scrambled using a giant state machine (jmp rcx), making the assembly look like a complete mess. 3. The Algorithm Once you piece the flattened blocks back together, you'll find the author used advanced Intel SIMD/Vector instructions (paddd xmm) to add up the ASCII characters of your Username 16 bytes at a time! The math boils down to this: Part 1 must exactly equal Username_Sum * 31 (hex 1F) Part 2 must exactly equal (Part 1 XOR 0x1337) + 123 (hex 7B) 4. The Final Troll If you write a Keygen for the above math, the program unlocks, but the success message prints as scrambled garbage (┤îö├Üîû├...)! Why? Because the decryption key for the success message is mathematically tied to your Part 2! Any valid pair of numbers bypasses the check, but only a Username whose ASCII characters sum to exactly 246, 502, or 758 generates the correct key to properly decrypt the final flag. Valid License: Username: Zackm (Sum = 502) Part 1: 15562 Part 2: 12408 Decrypted Flag: Wow you did it! This was a 10/10 crackme series. Thanks for the amazing challenge! | 2026-07-29 00:14 |
| Level 10 | The author pulled out all the stops for the final boss and used a classic anti-analysis technique: Multithreading. If you look at the main assembly dump, the password check isn't actually there! The main program uses the C++ std::thread library to spawn a background thread, waits for it to finish using _Thrd_join, and then checks a global variable at 7FF617BD6278 to see if the thread set it exactly to 0x3D17141A. If you step into the hidden thread function (1300), you'll find a loop containing this math: assembly imul ebx, ebx, 1F ; Multiply running hash by 31 add ebx, eax ; Add the current character This is the standard polynomial string hashing algorithm, better known as the exact formula used for String.hashCode() in Java! Because this is a 32-bit hash, there isn't just one correct password—there are millions of string collisions that mathematically satisfy the check. By writing a quick brute-force script, you can generate a valid collision. Entering the password tvhcfqdrp mathematically hashes to exactly 0x3D17141A and unlocks the program! The Flag: Unlike Levels 6, 8, and 9, the author finally got the flag encryption right on the boss level! The program takes the lowest byte of the target hash (0x1A) and XORs it with 0xAA to generate the decryption key 0xB0. If you decrypt the garbage string (+▲ ↔▲↑☼Z) with 0xB0, it reveals the true final flag: Perfect! | 2026-07-28 23:24 |
| Level 9 | Level 9 completely ditches the Virtual Machines and loops, and instead hits you with a pure algebraic system of equations! The program takes your 8-letter password and splits it into two 32-bit (4-byte) chunks. Let's call them X (the first 4 letters) and Y (the last 4 letters). It then runs them through this exact sequence of math: eax = X + Y edx = Y ^ eax ecx = (edx + 0x1337) ^ eax Assert: ecx == 0x656D4278 Assert: edx + ecx == 0x22F8D52C Because we have two hardcoded targets, we can mathematically solve for X and Y by just working backwards: We know ecx MUST be 0x656D4278 to pass Step 4. Plug that into Step 5 to find edx: edx + 0x656D4278 = 0x22F8D52C, which means edx = 0xBD8B92B4. Plug edx into Step 3 to find eax: (0xBD8B92B4 + 0x1337) ^ eax = 0x656D4278, which means eax = 0xD8E6E793. Plug edx and eax into Step 2 to find Y: Y = 0xBD8B92B4 ^ 0xD8E6E793 = 0x656D7527. Plug Y and eax into Step 1 to find X: X = 0xD8E6E793 - 0x656D7527 = 0x7379726C. Converting those hex values back into ASCII characters: X = lrys Y = 'ume So the exact mathematically required password is lrys'ume. | 2026-07-28 23:03 |
| Level 8 | The 54 encrypted values in memory are actually instructions for a custom Virtual Machine the dev built just to check the password! Basically, every 3 bytes act as [Command] [Argument] [Padding]. So 01 loads a character from your input, 02 XORs it, and 03 asserts it matches the expected value. Since the final check is a hardcoded assert, matrix is mathematically the only password that can pass the VM. Don't drive yourself crazy trying to find a second password to fix the flag output lol. The dev just messed up the encryption for the success string. The program takes the sum of your password and uses it to make an XOR key (which ends up being 0x6A for matrix). If you XOR the hidden flag array with 0x6A, it just spits out total garbage. The author spent so much time building an awesome VM that they forgot to properly encrypt the flag (just like they did back in Level 6). @Lover1500 you were totally on the right track with your analysis of the 18 groups and values. You nailed it! Awesome crackme series overall. | 2026-07-28 22:57 |
| Level 7 | This level hides a "Secret Menu" behind a perfectly designed XOR check! Here is the breakdown: The Check: The program takes your input and explicitly checks it character-by-character against a hidden string in memory. However, the hidden string is XORed with 0x5A. By dumping the memory at the pointer 7FF675E37230, we find the raw bytes: 36 33 39 3F 34 29 3F. Reversing the XOR (0x36 ^ 0x5A, etc.), we get the exact password: license The Easter Egg: The program also calculates an XOR key by taking the sum of the password characters modulo 256 (0xE3), and XORing that with 0xA5 (which equals 0x46). It uses this key to decrypt the garbage header. If you enter license, it perfectly decrypts the header to say: Welcome to the Secret Menu! | 2026-07-28 22:38 |
| Level 6 | After the intense math of Levels 4 and 5, the author of Level 6 actually just hardcoded the password directly into the executable! The Distraction: There is a massive block of scary-looking SIMD assembly (paddd, psrad, etc.) designed to look like a complex cipher. However, there is a length check right above it (cmp r12, 5). Since the password must be exactly 5 letters long, the program skips the SIMD loop entirely! The Password: The program simply compares the letters of your input against hardcoded hex values in a scrambled order (checking index 0 for 'c', index 4 for 'k', index 1 for 'r', etc.). If you put them in order, the password is literally just crack. The Typo / Easter Egg: When you enter crack, the program generates the XOR key 0x51 and decrypts the flag. But because the author made a typo when they originally encrypted the hidden array in the source code, the flag decrypts into garbage: Pj``ffg". You can actually fix the developer's typo by patching the executable in memory! If you go to the data segment where the array is stored (01 3B 31 31 37 37 36 73), and patch those 8 bytes to 02 24 32 32 34 34 35 70, the program will perfectly decrypt the intended flag and output: [+] Correct! Decrypted flag: Succeed! | 2026-07-28 22:28 |
| Level 5 | this level has a great mathematical trap. The program uses two checks to validate your keys: Key Part 1 must be a multiple of 17. (The strange mul F0F0F0F1 instruction is actually compiler-optimized modulo division for 17). Key Part 2 must equal (Key Part 1 ^ 0x1337) + 0x2A. If you just find any valid pair (like 17 and 4944), you'll bypass the checks and get the "LICENSE VALIDATED!" message, but the flag will decrypt into complete garbage. This is because the XOR key used to decrypt the hidden array is strictly the lowest byte of Key Part 2. By taking the gibberish output and reverse-XORing it, you can figure out the encrypted array in memory. Brute-forcing that array reveals the correct XOR key must be 0xBD. So, we just need a multiple of 17 that produces a Key 2 ending in 0xBD. The Perfect Solution: Key Part 1: 1700 Key Part 2: 5565 This mathematically satisfies both license checks AND perfectly decrypts the flag to Victory!. | 2026-07-28 21:41 |
| Level 4 | This level is a brilliant mathematical trap! It separates the "Success" check from the decryption routine, meaning you can technically pass the check but get a garbage flag, or decrypt the flag perfectly but get "Access Denied". You have to thread the needle to get both. The Check: The program adds up the ASCII values of your Username, multiplies the sum by 123 (0x7B), and checks if it equals your Serial Key. The Decryption: It takes the lowest byte of your Serial Key and XORs it with 52 (0x34) to generate the key for the encrypted array. The Trap: If you want the flag to perfectly decrypt to "Solved!", the XOR key must be 103 (0x67). This means the lowest byte of your Serial Key must be 83 (since 83 ^ 52 = 103). To get the perfect ending, we need a Username whose ASCII sum, multiplied by 123, results in a Serial Key ending in 83. Using modular arithmetic (Sum * 123 ≡ 83 mod 256), the Username's sum must be exactly 265. The letters X, X, and Y (88 + 88 + 89) sum to 265. 265 * 123 = 32595. Perfect Solution: Username: XXY Serial Key: 32595 Beautiful crackme design! | 2026-07-28 00:45 |
| Level 3 | This level introduces a classic Keygen challenge. Instead of a hardcoded password, it mathematically generates a valid Serial Key based on your Username. By reading the assembly instructions, we can reverse the algorithm: add edx, ecx (Loop): Calculates the sum of all ASCII values in your Username. imul eax, edx, 539: Multiplies that sum by 0x539 (1337 in decimal). xor eax, 5A5A: XORs the result against 0x5A5A (23130 in decimal). The final result is compared against the Serial Key you entered. Since we know the math, we can write a simple Python Keygen to generate valid keys! python def generate_key(username): ascii_sum = sum(ord(c) for c in username) final_key = (ascii_sum * 0x539) ^ 0x5A5A print(f"Serial Key for {username}: {final_key}") # Example: AAAAAAA -> 594453 generate_key("AAAAAAA") | 2026-07-28 00:13 |
| Level 2 | [Click to reveal]This level encrypts your input and compares it against a secret array in memory. Find the Key: Inside the checking loop, look for xor cl, 5A. This means your input is encrypted using a single-byte XOR cipher with the key 0x5A. Find the Array: Right below the XOR, you'll see cmp ds:[r8+rax], cl. This compares your encrypted input against a secret array pointed to by R8. Look slightly above the loop to find where the R8 pointer is loaded. Decrypt: Follow the R8 pointer in the memory dump to find the encrypted hex bytes: 28 3F 2C 3F 28 29 3F. Because XOR is symmetric, just throw those bytes into CyberChef (XOR recipe, Key: 5A) to reverse the math and reveal the plain text. Password: reverse | 2026-07-27 23:59 |