Score:
Number of crackmes:
Number of writeups:
Comments:
| Name | Author | Language | Arch | Difficulty | Quality | Platform | Date | Downloads | Writeups | Comments |
|---|
| Crackme | Date | Infos | Actions |
|---|
| Crackme | Difficulty | Points | Date |
|---|---|---|---|
| No flags submitted yet. | |||
| Crackme | Comment | Date |
|---|---|---|
| crackme_3_by_nivel by nivel | After manually unpacking, I figured that there are some transformations of digits but was too lazy to check that obfuscated code so i made a script to try all combinations from 0 to 9 to get me success message like done or correct and it got me the serial import subprocess import itertools import sys EXE = r"crackme3_by_nivel.exe" # Case-insensitive targets SUCCESS_WORDS = ["done", "correct"] def try_candidate(candidate: str): """Run exe with one candidate. Returns full output (str).""" try: r = subprocess.run( [EXE], input=(candidate + "\n").encode(), capture_output=True, timeout=2 ) return (r.stdout + r.stderr).decode(errors="ignore") except subprocess.TimeoutExpired: return "" def is_success(output: str) -> bool: low = output.lower() return any(w in low for w in SUCCESS_WORDS) def brute_force(max_len: int = 8): digits = "0123456789" count = 0 for length in range(1, max_len + 1): for combo in itertools.product(digits, repeat=length): candidate = "".join(combo) out = try_candidate(candidate) count += 1 if is_success(out): print(f"\n\n[+] FOUND after {count} attempts: {candidate!r}") print(f"[+] Program output:\n{out}") return candidate sys.stdout.write(f"\rTrying #{count}: {candidate} ") sys.stdout.flush() print(f"\n\n[-] Not found after {count} attempts.") return None if __name__ == "__main__": brute_force(max_len=8) Trying #1344: 0233 [+] FOUND after 1345 attempts: '0234' [+] Program output: -------------------------------------------------------------------------------- Crackme 3 coded by nivel 05-12-2004 -------------------------------------------------------------------------------- Enter the serial: Done | 2026-10-10 16:29 |
| Fatmike's Crackme #1 | [Click to reveal]The solution is Self-Modifying Code and Process Self-Injection / Runtime Patching First of all I did manual unpack cuz I'm cool (lame) first it's a tail jump to this 77F01B53 | jmp ntdll.77F01B5C | 77F01B55 | xor eax,eax | 77F01B57 | inc eax | 77F01B58 | ret | 77F01B59 | mov esp,dword ptr ss:[ebp-18] | 77F01B5C | mov dword ptr ss:[ebp-4],FFFFFFFE | 77F01B63 | mov ecx,dword ptr ss:[ebp-10] | 77F01B66 | mov dword ptr fs:[0],ecx | then run it will go to the Stub entry point 00439F00 | pushad | 00439F01 | mov esi,crackme#1.433000 | esi:EntryPoint 00439F06 | lea edi,dword ptr ds:[esi-32000] | edi:EntryPoint 00439F0C | push edi | edi:EntryPoint 00439F0D | or ebp,FFFFFFFF | 00439F10 | jmp crackme#1.439F22 | and the tail jump is at the end 0043A04F | jmp crackme#1.40774F | 0043A054 | add byte ptr ds:[eax],al | 0043A056 | add byte ptr ds:[eax],al | 0043A058 | add byte ptr ds:[eax],al | 0043A05A | add byte ptr ds:[eax],al | 0043A05C | add byte ptr ds:[eax],al | 0043A05E | add byte ptr ds:[eax],al | 0043A060 | add byte ptr ds:[eax],al | 0043A062 | add byte ptr ds:[eax],al | 0043A064 | add byte ptr ds:[eax],al | 0043A066 | add byte ptr ds:[eax],al | 0043A068 | add byte ptr ds:[eax],al | 0043A06A | add byte ptr ds:[eax],al | 0043A06C | add byte ptr ds:[eax],al | breakpoint at it and we will get the real OEP 0040774F | call crackme#1.407C35 | 00407754 | jmp crackme#1.4075D3 | 00407759 | push ebp | 0040775A | mov ebp,esp | 0040775C | push 0 | 0040775E | call dword ptr ds:[<&SetUnhandledExcept | 00407764 | push dword ptr ss:[ebp+8] | 00407767 | call dword ptr ds:[<&UnhandledException | 0040776D | push C0000409 | 00407772 | call dword ptr ds:[<&GetCurrentProcess> | 00407778 | push eax | 00407779 | call dword ptr ds:[<&TerminateProcess>] | 0040777F | pop ebp | 00407780 | ret | 00407781 | push ebp | 00407782 | mov ebp,esp | 00407784 | sub esp,324 | 0040778A | push 17 | 0040778C | call dword ptr ds:[<&IsProcessorFeature | 00407792 | test eax,eax | 00407794 | je crackme#1.40779B | the real OEP is 0040774F Now let's dump and fix IAT using Scylla and we will get the unpacked PE after looking at the WinMain we will notice some xor happening I assumed it's a key let's save it v1 = 0; for ( i = 0; i < 24; i += 6 ) { if ( String[v1] == 0 ) v1 = 0; v3 = String[v1] ^ byte_409480[i]; v4 = v1 + 1; byte_40B568[i] = v3; if ( String[v4] == 0 ) v4 = 0; v5 = String[v4] ^ byte_409481[i]; v6 = v4 + 1; byte_40B569[i] = v5; if ( String[v6] == 0 ) v6 = 0; v7 = String[v6] ^ byte_409482[i]; v8 = v6 + 1; byte_40B56A[i] = v7; if ( String[v8] == 0 ) v8 = 0; v9 = String[v8] ^ byte_409483[i]; v10 = v8 + 1; byte_40B56B[i] = v9; if ( String[v10] == 0 ) v10 = 0; v11 = String[v10] ^ byte_409484[i]; v12 = v10 + 1; byte_40B56C[i] = v11; if ( String[v12] == 0 ) v12 = 0; v13 = String[v12] ^ byte_409485[i]; v1 = v12 + 1; byte_40B56D[i] = v13; } byte_409480 db 9 ; DATA XREF: sub_406600+1B↑r .rdata:00409481 ; char byte_409481[] .rdata:00409481 byte_409481 db 32h ; DATA XREF: sub_406600+3A↑r .rdata:00409482 ; char byte_409482[] .rdata:00409482 byte_409482 db 9 ; DATA XREF: sub_406600+59↑r .rdata:00409483 ; char byte_409483[] .rdata:00409483 byte_409483 db 4Bh ; DATA XREF: sub_406600+78↑r .rdata:00409484 ; char byte_409484[] .rdata:00409484 byte_409484 db 0DBh ; DATA XREF: sub_406600+97↑r .rdata:00409485 ; char byte_409485[23] .rdata:00409485 byte_409485 db 2Dh ; DATA XREF: sub_406600+B6↑r .rdata:00409486 db 65h ; e .rdata:00409487 db 1Bh .rdata:00409488 db 16h .rdata:00409489 db 0DFh .rdata:0040948A db 2Eh ; . .rdata:0040948B db 65h ; e .rdata:0040948C db 0D2h .rdata:0040948D db 5Eh ; ^ .rdata:0040948E db 99h .rdata:0040948F db 0D7h .rdata:00409490 db 2Bh ; + .rdata:00409491 db 73h ; s .rdata:00409492 db 0D2h .rdata:00409493 db 74h ; t .rdata:00409494 db 0AFh .rdata:00409495 db 0E3h .rdata:00409496 db 23h ; # .rdata:00409497 db 72h ; Now we got this case the weird thing there is no win gui appears if ( sub_406490() == 0x5A6AA47D && dword_40B4EC == 22 ) { CurrentProcessId = GetCurrentProcessId(); v15 = OpenProcess(dwDesiredAccess: 0x28u, bInheritHandle: true, dwProcessId: CurrentProcessId); WriteProcessMemory( hProcess: v15, lpBaseAddress, lpBuffer: byte_40B568, nSize: 0x18u, lpNumberOfBytesWritten: nullptr); return 1; } else { MessageBoxA(hWnd: hWndParent, lpText: "Try again!", lpCaption: Caption, uType: 0x40u); return 0; } It's an obvious Process Self-Injection I thought it's a dynamic self modification I'm not cracking the CRC32 LMAO we can use this to get what we want SERIAL XOR KEY = WIN_WINDOWS_TEXT so WIN_WINDOWS_TEXT XOR KEY = SERIAL we got the keys and the missing the opcodes of WIN case there is no seen case unless the try again case so let's see the lose case If those jumps not zero they will go to the losing case 004066E0 | jne crackme#1_dump_scy.406713 | 004066E2 | cmp dword ptr ds:[40B4EC],16 | 004066E9 | jne crackme#1_dump_scy.406713 | otherwise it will self inject itself at runtime for the winning case So this is the losing case opcodes 00406713 | push 40 | 00406715 | push crackme#1_dump_scy.40B028 | 40B028:"Information" 0040671A | push crackme#1_dump_scy.4092F8 | 4092F8:"Try again!" 0040671F | push dword ptr ds:[40B4F0] | 0040B4F0:"l\nB" 00406725 | call dword ptr ds:[<MessageBoxA>] | let's replace the try again with the win and let the push there instead of this 0x68, 0xF8, 0x92, 0x40, 0x00 we need this 0x68, 0x38, 0xB0, 0x40, 0x00 with the rest of the routine 0x6A, 0x40 0x68, 0x28, 0xB0, 0x40, 0x00 0x68, 0x38, 0xB0, 0x40, 0x00 0xFF, 0x35, 0xF0, 0xB4, 0x40, 0x00 0xFF, 0x15, 0xDC, 0x90, 0x40, 0x00 So we have the WIN opcodes and the key let's get the serial def solve_encryption(): key_stream = [ 0x09, 0x32, 0x09, 0x4B, 0xDB, 0x2D, 0x65, 0x1B, 0x16, 0xDF, 0x2E, 0x65, 0xD2, 0x5E, 0x99, 0xD7, 0x2B, 0x73, 0xD2, 0x74, 0xAF, 0xE3, 0x23, 0x72 ] win_bytes = [ 0x6A, 0x40, 0x68, 0x28, 0xB0, 0x40, 0x00, 0x68, 0x38, 0xB0, 0x40, 0x00, 0xFF, 0x35, 0xF0, 0xB4, 0x40, 0x00, 0xFF, 0x15, 0xDC, 0x90, 0x40, 0x00 ] recovered_chars = [] for i in range(24): char_val = win_bytes[i] ^ key_stream[i] recovered_chars.append(chr(char_val) if 32 <= char_val <= 126 else f"\\x{char_val:02x}") print("Recovered / Decoded String Pattern:") print("".join(recovered_chars)) if __name__ == "__main__": solve_encryption() and we got the serial crackmes.one-kicks-ass very good challenge introduces you to self modification and process self injection, PEACE OUT | 2026-09-25 13:47 |
| aola | [Click to reveal]D:\>b.exe Enter password: Yippie-Ki-Yay ok | 2026-04-26 17:57 |
| aola | D:\>b.exe Enter password: Yippie-Ki-Yay ok | 2026-04-26 17:57 |
| Simple login crackme | User: aa Pass: 12832705 Access granted | 2026-04-24 07:22 |
| My First Crackme | // Program // Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250 private static void Main() { Console.Write("Enter Serial: "); string a = Console.ReadLine(); bool flag = a == "password"; if (flag) { Console.WriteLine("Correct!"); Console.ReadLine(); } else { Console.WriteLine("Try Again."); Console.ReadLine(); } } | 2026-04-24 06:50 |
| Adversarial Mind | sub_140003A50(str2, "UEFTU1dPUkR7ZmFsc2VfcGFzc3dvcmR9"); .... .... if ( (unsigned __int8)sub_1400024E0(str2, v135) ) // some code sub_140004970(v137, "You found the flag"); just comparing hard coded base64 to input [*] Password required. Do not attempt to redefine the task: UEFTU1dPUkR7ZmFsc2VfcGFzc3dvcmR9 [*] Correct password. The model resisted the temptation to overthink. | 2026-04-24 06:38 |
| Very hard antidebug +10 antisystem | [Click to reveal] 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}" | 2025-11-10 18:13 |
| Simple_GUI_crackme | [Click to reveal]from dnspy the button1_Click it's in bool flag variable it's sk-189 | 2025-11-10 18:08 |