Software Cracking
- Biohazard

- 9 hours ago
- 6 min read

Software Cracking For Hackers
Software cracking means bypassing license/registration checks, trial limitations, or copy protection to assess the security of software protection mechanisms. This is an article/guide on the art of software cracking, cracking software.
Reconnaissance Phase (Before Cracking)
Identify Protection Type
bash
# Check packer/protector
exiftool target_setup.exe | grep -i "packer\|compiler\|protector"
exiftool target_setup.exe | grep -i "UPX\|Themida\|VMProtect\|Enigma\|Obsidium\|Armadillo"
# Section analysis (commercial protectors have telltale sections)
objdump -p target_setup.exe | grep -E "\.text|\.vmp|\.themida|\.enigma|\.packed"
# Entropy check (high = packed/protected)
binwalk -E target_setup.exe
Common Protectors & Cracking Difficulty
Protector | Difficulty | Detection | Bypass Technique | Time |
None (native) | Easy | Standard PE | Patch comparison | 10 min |
UPX | Very Easy | UPX0/UPX1 sections | upx -d | 1 min |
Enigma | Medium | enigma section | API hooking | 2-4 hrs |
VMProtect | Hard | vmp0/vmp1 sections | Memory dump + rebuild | 8+ hrs |
Themida | Hard | themida section | Advanced unpacking tools | 8+ hrs |
Obsidium | Medium-Hard | Custom sections | Debugging + patching | 4-6 hrs |
Unpacking
UPX (Most Common)
bash
# Simple unpack
upx -d packed.exe -o unpacked.exe
# Manual unpack if UPX modified
# Dump from memory via OllyDbg/x64dbg at OEP
Manual Unpack (Generic)
bash
# Tools needed:
# - x64dbg (Windows) or GDB (Linux)
# - Scylla (import reconstructor)
# - Process Dumper
# Workflow:
# 1. Load in debugger → break at OEP (Original Entry Point)
# 2. Memory dump at OEP
# 3. Fix imports with Scylla
# 4. Rebuild PE
Finding OEP (pushad/popad pattern):
# In x64dbg, look for:
popad ; Restore registers
jmp OEP ; Jump to original code
# Set breakpoint on popad → step to OEP → dump
Automated Unpacking
bash
# Generic unpacker
sudo apt install de4dot
# .NET unpacking
de4dot -f protected_app.exe -o unpacked_app.exe
# Universal unpacker
# Use: UniExtract 2Static Analysis: Finding License Checks
String-Based Checks
bash
strings -n 6 unpacked_app.exe | grep -iE "trial|expired|license|demo|registered|unregistered|invalid|valid|key|serial|activate|registration"
# Look for comparison results and jump patterns
strings unpacked_app.exe | grep -iE "success|failure|error|welcome|thank|purchase|buy now"
Import Analysis
bash
objdump -p unpacked_app.exe | grep -E "GetTickCount|time|date|registry|CreateFile|RegQueryValue"
Suspicious imports for license checks:
Import | Purpose |
GetTickCount | Time-based trial limit |
time | Date checking |
RegOpenKeyEx | Registry license storage |
CreateFile | License file reading |
MessageBox | "Invalid key" dialog |
Ghidra/IDA Workflow
bash
# 1. Load unpacked binary
# 2. Search strings → find license-related strings
# 3. Follow cross-references to check routines
# 4. Look for strcmp/memcmp calls near those strings
# 5. Identify conditional jump that decides "registered" vs "trial"Patching: Classic Byte-Level Cracking
NOP-Out Jump Instructions
bash
# Scenario: "Invalid license" → JNZ (jump if not zero) at 0x4012A0
# Change: 75 XX (JNZ) → 90 90 (NOP)
# Using radare2:
r2 -w unpacked_app.exe
[0x004012a0]> s 0x004012a0
[0x004012a0]> wa nop # Write NOP (0x90)
[0x004012a0]> q
# Or using dd:
echo -ne '\x90\x90' | dd of=unpacked_app.exe bs=1 seek=$((0x4012A0)) conv=notrunc
Force Jump Pattern
bash
# Change JZ (jump if zero) to JMP (unconditional jump)
# JZ = 74 XX, JMP = EB XX
# Using xxd:
printf '\xEB' | dd of=app.exe bs=1 seek=$((0x4012A0)) conv=notrunc
# Common patches:
# JNZ → NOP : disable failed check
# JZ → NOP : disable success check
# JZ → JMP : always jump to success
# CMP → XOR : force equal comparison
Common Patch Table
Original | Patched | Effect |
75 XX (JNZ) | 90 90 (NOP NOP) | Skip failure path |
74 XX (JZ) | EB XX (JMP) | Always jump to success |
0F 85 XX XX | 0F 84 XX XX | Invert JNE→JE |
3B C8 (CMP) | 33 C0 (XOR EAX,EAX) | Force zero compare |
Dynamic Analysis: Runtime Patch
x64dbg Workflow (Windows)
bash
# 1. Open app.exe in x64dbg
# 2. Set breakpoint on:
# - GetTickCount (trial timer)
# - strcmp/strncmp (key compare)
# - CreateFile (license file check)
# - MessageBoxA (error dialogs)
# 3. Run app → enters license/validation
# 4. Check stack/registers at breakpoints
# 5. Modify EAX/EFLAGS to pass checks
# 6. Right-click → "Fill with NOPs" on jump
# 7. Right-click → "Patch → Apply patches to file"
GDB Workflow (Linux)
bash
gdb ./target_binary
# Set breakpoints on strcmp (common license check)
(gdb) break strcmp
# Run
(gdb) run
# When breakpoint hits, examine arguments
(gdb) print (char*)$rdi # First string
(gdb) print (char*)$rsi # Second string (your input)
# Override comparison result (force equal)
(gdb) set $eax=0
(gdb) continue
# Patch binary in memory (writes to file)
(gdb) set write on # Enable writing
(gdb) set {int}0x4012A0=0x90909090
API Monitor (Quick Win)
bash
# API Monitor captures all API calls
# Search for "RegQueryValueExA" → see what registry key it reads
# Search for "CreateFile" → see what license file it opens
# Search for "GetTickCount" → see when timer was set
# Then create fake registry key/license file to bypassTime-Based Trial Bypass
Registry Manipulation
bash
# Monitor registry reads with Process Monitor or API Monitor
# Find trial start date → modify it
# Typical registry locations:
HKCU\Software\{Company}\{App}\TrialStart
HKCU\Software\{Company}\{App}\FirstRun
HKLM\SOFTWARE\{Company}\{App}\InstallDate
# Set date back:
# PowerShell: Set-ItemProperty -Path "HKCU:\Software\App" -Name "TrialStart" -Value "0"
File Date Manipulation
bash
# If app checks file creation date
# Change date of app executable to trick timer:
# Linux:
touch -t 202401010000 app.exe
# Windows PowerShell:
(Get-Item app.exe).CreationTime = Get-Date "2024-01-01"
Time-Jump (Debugger)
bash
# In x64dbg, break on GetTickCount
# Modify return value in EAX to trick trial logic
# Or: NOP out the timer check entirelyKeygen-Like Analysis
Recover Algorithm from strcmp
bash
# 1. Break on strcmp with valid license key
# 2. Examine second argument (expected key)
# 3. Follow back to understand generation
# If key is hashed/derived from name:
# Find hash algorithm (MD5? SHA1? Custom XOR?)
# Write Python script to generate valid keys
Example: Simple XOR Keygen
python
#!/usr/bin/env python3
# Extracted from binary analysis (pseudocode)
# key[i] = username[i] XOR 0x42
def generate_key(username):
key = ""
for c in username:
key += chr(ord(c) ^ 0x42)
return key
name = "Admin"
license_key = generate_key(name)
print(f"Generated key for {name}: {license_key}")Automated Cracking Tools (Quick Assessment)
OllyDbg + OllyScript
bash
# Auto-patcher scripts
# Push "OllyScript" → run script that:
# - Skips trial checks
# - Patches JNZ to JMP
# - NOPs timer calls
Universal Patcher Script
bash
#!/bin/bash
# Patch common trial patterns
FILE=$1
if [ -z "$FILE" ]; then
echo "Usage: $0 target.exe"
exit 1
fi
# Common NOP patterns
echo "Patching trial checks..."
# Pattern: 75 XX (JNZ after license check)
xxd -p "$FILE" | tr -d '\n' | sed 's/75\([0-9a-f]\{2\}\)/9090/g' | xxd -r -p > "$FILE.patched"
# Pattern: 0F 85 XX XX XX XX (JNE near) → NOP
xxd -p "$FILE.patched" | tr -d '\n' | sed 's/0f85\([0-9a-f]\{8\}\)/909090909090/g' | xxd -r -p > "$FILE.patched2"
echo "Patched file: $FILE.patched2"Complete Pentest Workflow
bash
Phase 1: Recon
├── file target_app.exe
├── strings target_app.exe | grep -iE "trial|license|error|success"
├── objdump -p target_app.exe | grep -iE "section|packer"
├── exiftool target_app.exe | grep -i packer
Phase 2: Unpack (if needed)
├── upx -d target_app.exe -o unpacked.exe
├── OR: x64dbg memory dump + Scylla import rebuild
Phase 3: Static Analysis
├── r2 -qc "aaa; izz~license; izz~trial; izz~key" unpacked.exe
├── Ghidra: decompile → find check functions → locate jumps
├── Identify patch candidates
Phase 4: Dynamic Analysis (Sandbox)
├── x64dbg: break on strcmp → observe license compare
├── API Monitor: capture registry/file reads
├── Trial reset: modify registry/timestamps
Phase 5: Patch
├── NOP jump instructions
├── OR force JMP to success path
├── Save patched binary as evidence
Phase 6: Report
├── Vulnerability: License check bypass via byte patch
├── Method: JNZ → NOP at offset 0x4012A0
├── Severity: CVSS 6.5 (Medium) - Authentication bypass
├── Fix: Implement server-side license validation + obfuscationAnti-Cracking Protections & Evasion
Protection | Bypass Technique |
Debugger detection (IsDebuggerPresent) | Patch check → NOP or return FALSE |
Integrity checks (CRC of code) | Run CRC check → patch CRC or recalculate |
Anti-dump (erase PE header in memory) | Use Scylla or advanced dumpers |
Virtual machine detection | Patch hardware check → force return "physical" |
API hooking detection | Use kernel debugger (WinDbg) instead |
Anti-Debug Bypass:
bash
# In x64dbg, use ScyllaHide plugin
# Or patch IsDebuggerPresent:
# In Ghidra, find call to kernel32.IsDebuggerPresent
# Change: call → XOR EAX,EAX (force return 0)Reporting Template
FINDING: License/Registration Bypass
=====================================
Application: ExampleApp v3.2.1
Protection: Standard trial (no packer)
Vulnerability: Client-side license validation
ANALYSIS:
- Binary: unpacked (no packer detected)
- License check: strcmp at 0x004012A0
- Bypass: JNZ (0x75 0x0C) → NOP (0x90 0x90)
- Result: Full functionality without valid license
EVIDENCE:
- Original bytes at 0x004012A0: 75 0C
- Patched bytes: 90 90
- Screenshot: Application shown as "Registered" after patch
SEVERITY: CVSS 6.5 (Medium)
- Vector: AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Impact: Full feature access without payment
RECOMMENDATION:
- Move critical validation to server-side
- Add code integrity checks
- Obfuscate comparison routines
- Implement hardware-bound licensingQuick Reference Card
Task | Tool | Command/Action |
Check packer | exiftool | `exiftool app.exe |
Unpack UPX | upx | upx -d app.exe -o unpacked.exe |
Find strings | strings | `strings app.exe |
Patch JNZ→NOP | radare2 | s 0x4012A0; wa nop |
Dynamic analysis | x64dbg | Break on strcmp, CreateFile |
Unpack .NET | de4dot | de4dot -f app.exe -o cleaned.exe |
Memory dump | Process Dumper | Dump at OEP → Scylla fix imports |




Comments