Number of crackmes:
Number of writeups:
Comments:
| Name | Author | Language | Arch | Difficulty | Quality | Platform | Date | Downloads | Writeups | Comments |
|---|
| Crackme | Date | Infos |
|---|
| Crackme | Comment | Date |
|---|---|---|
| Paladium VM | import ctypes import ctypes.wintypes as wt import struct import sys import os # Windows constants DEBUG_PROCESS = 0x1 CREATE_NEW_CONSOLE = 0x10 INFINITE = 0xFFFFFFFF EXCEPTION_DEBUG_EVENT = 1 CREATE_THREAD_DEBUG_EVENT = 2 CREATE_PROCESS_DEBUG_EVENT = 3 EXIT_PROCESS_DEBUG_EVENT = 5 LOAD_DLL_DEBUG_EVENT = 6 EXCEPTION_BREAKPOINT = 0x80000003 EXCEPTION_ACCESS_VIOLATION = 0xC0000005 EXCEPTION_SINGLE_STEP = 0x80000004 DBG_CONTINUE = 0x00010002 DBG_EXCEPTION_NOT_HANDLED = 0x80010001 PAGE_EXECUTE_READWRITE = 0x40 CONTEXT_FULL = 0x10000B CONTEXT_ALL = 0x10001F MEM_COMMIT = 0x1000 MEM_RESERVE = 0x2000 PROCESS_ALL_ACCESS = 0x1F0FFF THREAD_ALL_ACCESS = 0x1F03FF k32 = ctypes.windll.kernel32 class EXCEPTION_RECORD(ctypes.Structure): pass EXCEPTION_RECORD._fields_ = [ ("ExceptionCode", wt.DWORD), ("ExceptionFlags", wt.DWORD), ("ExceptionRecord", ctypes.POINTER(EXCEPTION_RECORD)), ("ExceptionAddress", ctypes.c_void_p), ("NumberParameters", wt.DWORD), ("ExceptionInformation", ctypes.c_uint64 * 15), ] class EXCEPTION_DEBUG_INFO(ctypes.Structure): _fields_ = [ ("ExceptionRecord", EXCEPTION_RECORD), ("dwFirstChance", wt.DWORD), ] class CREATE_PROCESS_DEBUG_INFO(ctypes.Structure): _fields_ = [ ("hFile", wt.HANDLE), ("hProcess", wt.HANDLE), ("hThread", wt.HANDLE), ("lpBaseOfImage", ctypes.c_void_p), ("dwDebugInfoFileOffset", wt.DWORD), ("nDebugInfoSize", wt.DWORD), ("lpThreadLocalBase", ctypes.c_void_p), ("lpStartAddress", ctypes.c_void_p), ("lpImageName", ctypes.c_void_p), ("fUnicode", wt.WORD), ] class DEBUG_EVENT_UNION(ctypes.Union): _fields_ = [ ("Exception", EXCEPTION_DEBUG_INFO), ("CreateProcessInfo", CREATE_PROCESS_DEBUG_INFO), ("_padding", ctypes.c_byte * 160), ] class DEBUG_EVENT(ctypes.Structure): _fields_ = [ ("dwDebugEventCode", wt.DWORD), ("dwProcessId", wt.DWORD), ("dwThreadId", wt.DWORD), ("u", DEBUG_EVENT_UNION), ] class STARTUPINFOW(ctypes.Structure): _fields_ = [ ("cb", wt.DWORD), ("lpReserved", wt.LPWSTR), ("lpDesktop", wt.LPWSTR), ("lpTitle", wt.LPWSTR), ("dwX", wt.DWORD), ("dwY", wt.DWORD), ("dwXSize", wt.DWORD), ("dwYSize", wt.DWORD), ("dwXCountChars", wt.DWORD), ("dwYCountChars", wt.DWORD), ("dwFillAttribute", wt.DWORD), ("dwFlags", wt.DWORD), ("wShowWindow", wt.WORD), ("cbReserved2", wt.WORD), ("lpReserved2", ctypes.c_void_p), ("hStdInput", wt.HANDLE), ("hStdOutput", wt.HANDLE), ("hStdError", wt.HANDLE), ] class PROCESS_INFORMATION(ctypes.Structure): _fields_ = [ ("hProcess", wt.HANDLE), ("hThread", wt.HANDLE), ("dwProcessId", wt.DWORD), ("dwThreadId", wt.DWORD), ] class M128A(ctypes.Structure): _fields_ = [("Low", ctypes.c_uint64), ("High", ctypes.c_int64)] class CONTEXT(ctypes.Structure): _fields_ = [ ("P1Home", ctypes.c_uint64), ("P2Home", ctypes.c_uint64), ("P3Home", ctypes.c_uint64), ("P4Home", ctypes.c_uint64), ("P5Home", ctypes.c_uint64), ("P6Home", ctypes.c_uint64), ("ContextFlags", wt.DWORD), ("MxCsr", wt.DWORD), ("SegCs", wt.WORD), ("SegDs", wt.WORD), ("SegEs", wt.WORD), ("SegFs", wt.WORD), ("SegGs", wt.WORD), ("SegSs", wt.WORD), ("EFlags", wt.DWORD), ("Dr0", ctypes.c_uint64), ("Dr1", ctypes.c_uint64), ("Dr2", ctypes.c_uint64), ("Dr3", ctypes.c_uint64), ("Dr6", ctypes.c_uint64), ("Dr7", ctypes.c_uint64), ("Rax", ctypes.c_uint64), ("Rcx", ctypes.c_uint64), ("Rdx", ctypes.c_uint64), ("Rbx", ctypes.c_uint64), ("Rsp", ctypes.c_uint64), ("Rbp", ctypes.c_uint64), ("Rsi", ctypes.c_uint64), ("Rdi", ctypes.c_uint64), ("R8", ctypes.c_uint64), ("R9", ctypes.c_uint64), ("R10", ctypes.c_uint64), ("R11", ctypes.c_uint64), ("R12", ctypes.c_uint64), ("R13", ctypes.c_uint64), ("R14", ctypes.c_uint64), ("R15", ctypes.c_uint64), ("Rip", ctypes.c_uint64), ("FltSave", ctypes.c_byte * 512), ("VectorRegister", M128A * 26), ("VectorControl", ctypes.c_uint64), ("DebugControl", ctypes.c_uint64), ("LastBranchToRip", ctypes.c_uint64), ("LastBranchFromRip", ctypes.c_uint64), ("LastExceptionToRip", ctypes.c_uint64), ("LastExceptionFromRip", ctypes.c_uint64), ] def read_mem(hProcess, addr, size): buf = ctypes.create_string_buffer(size) n = ctypes.c_size_t() k32.ReadProcessMemory(hProcess, ctypes.c_void_p(addr), buf, size, ctypes.byref(n)) return buf.raw[:n.value] def write_mem(hProcess, addr, data): n = ctypes.c_size_t() k32.WriteProcessMemory(hProcess, ctypes.c_void_p(addr), data, len(data), ctypes.byref(n)) return n.value def read_std_string(hProcess, addr): """Read MSVC std::string from memory. Layout: [ptr_or_buf(16)] [size(8)] [capacity(8)] If capacity <= 15 (SSO): data is inline at addr Else: data is at the pointer stored at addr """ raw = read_mem(hProcess, addr, 32) if len(raw) < 32: return b"" size = struct.unpack_from("<Q", raw, 16)[0] cap = struct.unpack_from("<Q", raw, 24)[0] if cap <= 15: # SSO: data inline return raw[:size] else: # Heap allocated: first 8 bytes = pointer to data data_ptr = struct.unpack_from("<Q", raw, 0)[0] return read_mem(hProcess, data_ptr, size) def main(): exe_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "anan.exe") if not os.path.exists(exe_path): print(f"[!] {exe_path} not found") sys.exit(1) # Breakpoint address: right after CALL FUN_14011bb20 (password generation) BP_VA = 0x140198FE1 # RSP offset for the password std::string PASSWORD_RSP_OFFSET = 0xA8 print(f"[*] Launching {exe_path} under debugger...") si = STARTUPINFOW() si.cb = ctypes.sizeof(si) pi = PROCESS_INFORMATION() ok = k32.CreateProcessW( exe_path, None, None, None, False, DEBUG_PROCESS | CREATE_NEW_CONSOLE, None, None, ctypes.byref(si), ctypes.byref(pi) ) if not ok: print(f"[!] CreateProcess failed: {k32.GetLastError()}") sys.exit(1) hProcess = pi.hProcess hThread = pi.hThread pid = pi.dwProcessId main_tid = pi.dwThreadId print(f"[+] Process created: PID={pid}, TID={main_tid}") bp_set = False bp_original_byte = None password_found = False password = "" av_count = 0 evt = DEBUG_EVENT() while True: if not k32.WaitForDebugEvent(ctypes.byref(evt), INFINITE): break continue_status = DBG_CONTINUE if evt.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT: info = evt.u.CreateProcessInfo base = info.lpBaseOfImage print(f"[+] Process loaded at base: 0x{base:X}") # Calculate actual BP address (in case of ASLR, use base) # For PE64 with preferred base 0x140000000, check if relocated bp_addr = BP_VA - 0x140000000 + base print(f"[*] Setting breakpoint at VA 0x{bp_addr:X}") # Read original byte and write INT3 orig = read_mem(hProcess, bp_addr, 1) if orig: bp_original_byte = orig[0:1] write_mem(hProcess, bp_addr, b'\xCC') bp_set = True print(f"[+] Breakpoint set (original byte: 0x{bp_original_byte[0]:02X})") else: print("[!] Failed to read memory at breakpoint address") # Try without ASLR adjustment bp_addr = BP_VA orig = read_mem(hProcess, bp_addr, 1) if orig: bp_original_byte = orig[0:1] write_mem(hProcess, bp_addr, b'\xCC') bp_set = True print(f"[+] Breakpoint set at fixed VA (original byte: 0x{bp_original_byte[0]:02X})") if info.hFile: k32.CloseHandle(info.hFile) elif evt.dwDebugEventCode == EXCEPTION_DEBUG_EVENT: exc = evt.u.Exception.ExceptionRecord code = exc.ExceptionCode addr = exc.ExceptionAddress if code == EXCEPTION_BREAKPOINT and bp_set and addr == bp_addr: print(f"\n[!!!] BREAKPOINT HIT at 0x{addr:X}") # Get thread context to read RSP ctx = CONTEXT() ctx.ContextFlags = CONTEXT_ALL th = k32.OpenThread(THREAD_ALL_ACCESS, False, evt.dwThreadId) if th: k32.GetThreadContext(th, ctypes.byref(ctx)) rsp = ctx.Rsp print(f"[*] RSP = 0x{rsp:X}") # Read password string at [RSP + 0xA8] str_addr = rsp + PASSWORD_RSP_OFFSET password_bytes = read_std_string(hProcess, str_addr) if password_bytes and len(password_bytes) == 22: password = password_bytes.decode('ascii', errors='replace') password_found = True print(f"\n{'='*50}") print(f" PASSWORD FOUND: {password}") print(f" (length: {len(password)})") print(f"{'='*50}\n") else: print(f"[*] String at RSP+0xA8: {password_bytes!r} (len={len(password_bytes)})") # Try other offsets for off in [0xA0, 0xA8, 0xB0, 0xB8, 0x98, 0x90, 0xC0, 0xC8, 0x80, 0x88]: s = read_std_string(hProcess, rsp + off) if s and len(s) >= 10 and all(33 <= b <= 126 for b in s): password = s.decode('ascii', errors='replace') password_found = True print(f" [+] Found at RSP+0x{off:X}: {password} (len={len(s)})") break # Restore original byte and fix RIP write_mem(hProcess, bp_addr, bp_original_byte) ctx.Rip = bp_addr # re-execute original instruction k32.SetThreadContext(th, ctypes.byref(ctx)) k32.CloseHandle(th) bp_set = False # don't break again else: print("[!] Failed to open thread") elif code == EXCEPTION_ACCESS_VIOLATION: # Anti-debug null-call trap: pass exception to VEH av_count += 1 if av_count <= 3 or av_count % 10 == 0: print(f"[*] Access violation #{av_count} at 0x{addr:X} (anti-debug trap, passing to VEH)") continue_status = DBG_EXCEPTION_NOT_HANDLED elif code == EXCEPTION_BREAKPOINT: # System breakpoint (initial), just continue pass elif code == EXCEPTION_SINGLE_STEP: pass else: continue_status = DBG_EXCEPTION_NOT_HANDLED elif evt.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT: print(f"\n[*] Process exited") break elif evt.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT: pass k32.ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, continue_status) k32.CloseHandle(hProcess) k32.CloseHandle(hThread) if password_found: print(f"\n[RESULT] Password for this run: {password}") print(f"[HINT] Run: anan.exe then enter the password above") print(f"[NOTE] Password changes every run! This script extracts it fresh each time.") else: print("\n[!] Password not found. The breakpoint may need offset adjustment.") return 0 if __name__ == "__main__": main() | 2026-02-18 00:36 |