Keygen Analysis
- Biohazard

- 6 hours ago
- 4 min read

Keygen (Key Generator) Analysis
Keygen (key generator) analysis means reverse engineering how a program generates license keys — either to understand weakness in the algorithm or to demonstrate that the licensing scheme is bypassable. This article is focused on Keygen Analysis.
Phase 1: Identify The License Algorithm
Step 1: Find Where License Key is Checked
String search:
bash
strings -n 6 target_app.exe | grep -iE "license|key|serial|register|activation|valid|invalid|thank you|trial"
Ghidra workflow:
1. Import binary → Auto-analyze
2. Symbol Tree → Strings → Filter by "license" or "key"
3. Right-click found string → "Show References to Address"
4. Follow cross-reference → found the license check function
Sample decompiler output showing license validation:
c
int validateLicense(char *userKey) {
char validChars[32];
GetSystemInfo(&sysInfo); // Some HW binding
generateValidKey(validChars, sysInfo); // Generates expected value
int result = strcmp(userKey, validChars); // Compare!
return result == 0; // Returns 1 if valid
}Phase 2: Reverse The Key Generation Function
Finding the Algorithm
Look for the function that generates the expected key (called generateValidKey above). It typically:
Reads system/hardware info (username, MAC, drive serial)
Performs operations: XOR, hashing (MD5/SHA1), base32/hex encoding
Possibly inserts dashes every 4-5 characters
Decompiler example:
c
void generateValidKey(char *output, SYSTEM_INFO *si) {
char raw[32];
// Step 1: concatenate hardware values
sprintf(raw, "%s-%08X-%08X", si->username, si->diskSerial, si->macHash);
// Step 2: take MD5
MD5((uchar*)raw, strlen(raw), md5hash);
// Step 3: convert to uppercase hex
for (int i = 0; i < 16; i++) {
sprintf(output + (i*2), "%02X", md5hash[i]);
}
// Step 4: Insert dashes every 4 chars -> output is a 32-char hex key
}
Tracing the Algorithm (radare2 / GDB)
bash
# Dynamic tracing with ltrace (captures library calls)
ltrace -e "*" ./target_app.exe TEST-1234-5678 2>&1 | grep -E "strcmp|md5|sha|crc|sprintf"
# GDB to step through generateValidKey
gdb ./target_app.exe
(gdb) break generateValidKey
(gdb) run
(gdb) ni # Step through line by line
(gdb) x/s $rdi # Print computed key at each stepPhase 3: Reimplement the Algorithm (Keygen)
Once you understand the algorithm, reimplement it in Python to generate valid keys.
Example: Simple XOR + Hex Key
Original algorithm (reversed from decompiler):
c
void generateKey(char *name, char *output) {
unsigned char key[8];
for (int i = 0; i < 8; i++) {
key[i] = name[i % strlen(name)] ^ 0x55;
}
sprintf(output, "%02X%02X-%02X%02X-%02X%02X-%02X%02X",
key[0],key[1],key[2],key[3],key[4],key[5],key[6],key[7]);
}
Keygen in Python:
python
#!/usr/bin/env python3
# Keygen for TargetApp v2.5 (Authorized Pentest)
# Algorithm: XOR name bytes with 0x55
def generate_key(name):
key_bytes = []
for i in range(8):
ch = name[i % len(name)]
key_bytes.append(ord(ch) ^ 0x55)
return f"{key_bytes[0]:02X}{key_bytes[1]:02X}-{key_bytes[2]:02X}{key_bytes[3]:02X}-{key_bytes[4]:02X}{key_bytes[5]:02X}-{key_bytes[6]:02X}{key_bytes[7]:02X}"
if __name__ == "__main__":
name = input("Enter username: ")
print(f"License key: {generate_key(name)}")
Test:
bash
python3 keygen.py <<< "John Doe"
# Output: 3A1F-4B2C-5D3E-6F40
# Enter this into target_app → "Registration successful!"Phase 4: Advanced Keygen Patterns
Hardware-Locked Seats (Machine Fingerprint)
c
// Reversed algorithm combines CPU serial + MAC + disk ID
void generateKey(char *output) {
char cpu_id[16], mac[6], disk[16];
GetCPUID(cpu_id); // CPU serial number
GetMACAddress(mac); // First NIC MAC
GetDiskSerial(disk); // C: drive serial
// HMAC-SHA1 of joined values
char raw[64];
sprintf(raw, "%s-%02X%02X-%s-%s", cpu_id, mac[0], mac[1], disk, SALT);
HMAC_SHA1((uchar*)raw, strlen(raw), SECRET_KEY, 16, hmac_result);
// Encode as base32
base32_encode(hmac_result, 20, output);
}
Keygen approach:
python
import hmac
import hashlib
import base64
# You need the SECRET_KEY (find it embedded in binary via strings)
# You need SALT (also embedded in binary)
def generate_hw_key(cpu_id, mac_prefix, disk_serial, secret, salt):
raw = f"{cpu_id}-{mac_prefix}-{disk_serial}-{salt}"
h = hmac.new(secret.encode(), raw.encode(), hashlib.sha1).digest()
# base32 encode with padding stripped
return base64.b32encode(h).decode().rstrip('=')
Elliptic Curve / RSA Signatures (Harder)
Some software uses asymmetric crypto — the binary has the public key to verify, and you need the private key to sign.
Bypass approach for asymmetric:
1. Find the public key in the binary
2. Source the public key → does it belong to a known vendor cert?
3. If no private key, don't brute-force — instead:
a. Patch the binary to accept any signed payload
b. OR: Replace the public key with your own (generate keypair)
c. OR: NOP the signature check entirelyPhase 5: Algorithm Weakness Assessment
Weakness | What It Means | Exploit Method |
Deterministic | Same input → same output | Keygen is trivial |
Short keyspace | Key is 6 decimal digits | Brute-force in seconds |
Weak hash | CRC32, XOR, custom (not crypto) | Invert/reverse the function |
No HW binding | Any machine accepts key | Generate unlimited keys |
Static seed | Hardcoded seed in binary | Always same key sequence |
Predictable PRNG | rand() without entropy | Recover state → predict all keys |
Embedded private key | Signature key in binary | Extract → sign anything |
Phase 6: Reporting Template
FINDING: Weak License Key Generation Algorithm
================================================
Product: TargetApp v2.5
Algorithm: XOR (name bytes ^ 0x55) → hex encode
Keyspace: 2^64 (theoretical) but deterministic — single valid key per username
SEVERITY: CVSS 6.5 (Medium)
Vector: AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Impact: Unauthorized full-feature access without purchase
EVIDENCE:
- Reverse-engineered keygen algorithm (Python script attached)
- Generated valid keys for 3 usernames — all accepted
- No server-side validation (key verified entirely locally)
ALGORITHM RECONSTRUCTION:
# Raw bytes from decompiler at 0x004012A0:
# XOR with 0x55, hex encode with dash every 4 chars
def keygen(username):
key = []
for i in range(8):
key.append(ord(username[i % len(username)]) ^ 0x55)
return '-'.join(f"{b:02X}" for b in key[:2]) + '-' + \
'-'.join(f"{b:02X}" for b in key[2:4]) + '-' + \
'-'.join(f"{b:02X}" for b in key[4:6]) + '-' + \
'-'.join(f"{b:02X}" for b in key[6:8])
TIMELINE:
- 30 min: Static analysis identified strcmp at 0x004012A0
- 15 min: Traced back to generateValidKey function
- 20 min: Reversed XOR algorithm from decompiler output
- 10 min: Wrote Python keygen (6 lines)
RECOMMENDATIONS:
1. Use asymmetric signature (RSA/ECDSA) — verify with public key only
2. Move critical validation to server-side
3. Obfuscate key generation logic (virtualization, control flow flattening)
4. Implement code integrity checks (CRC of license validation function)
5. Require periodic online re-validationQuick Reference: Common Keygen Patterns
Pattern | Detection in Ghidra | Attack |
strcmp literal string | "Expected key is hardcoded" | Copy the string (no algorithm) |
XOR with constant | Look for XOR instructions before compare | Invert XOR = same operation |
MD5/SHA1 | MD5_Init/Update/Final imports | Known algorithm, just copy |
sprintf format string | GUI for hex encoding | Map format → reverse |
rand() + srand() | PRNG calls | Fixed seed? Predictable sequence |
CRC32 | mmcrc32 or crc32 instruction | Reversible (not cryptographic) |
HMAC with hardcoded key | Look for embedded char key[] | Extract key → forge signatures |




Comments