When to use / when not to use
- Boundary (inherits [[re-cracking]]): limited to own software / authorized testing / CTF·research environments; unauthorized software unlocking and commercial software bypass are prohibited; before dynamic steps such as observing return values at breakpoints, the user must state the target's ownership (ownership / test authorization / research environment)
- Use: the program has a registration / activation flow (entering a serial number, registration code, authorization file), and you need to locate "where it is checked and how it is checked"
- Use: cracking prerequisite -- provides the check point address and check algorithm for [[re-patching]] / [[re-keygen]]
- Use: determine whether authorization is online activation or offline verification; identify machine code binding, validity period / subscription-based authorization
- Don't use: the target has already localized the check branch and you only need to change bytes to bypass (directly [[re-patching]])
- Don't use: confirm there is no authorization mechanism (no registration UI / registry / authorization file reading -- honestly tell the user, see pitfall 5)
- Don't use: only doing protocol-layer analysis (traffic analysis of online activation goes to [[re-protocol]])
- Note: if the sample is packed, unpack first ([[re-anti-analysis]]); if the check function is obfuscated, [[re-deobfuscate]] first (see pitfall 1); execute dynamic parts in a sandbox ([[re-sandbox]], highest principle of [[re-analyze/platform-tips]])
Tool preparation
Debugger (by OS)
- Debugging PE under Linux / Wine: [[re-gdb]] --
apt install gdb/dnf install gdb/pacman -S gdb, verifygdb --version;Wine direct read:wine sample.exeafter running,gdb -p <pid>attach ([[re-analyze/platform-tips]] Linux branch) - Windows: [[re-x64dbg]] -- official release zip, attach requires administrator privileges ([[re-analyze/platform-tips]] Windows branch); verify: loading the sample allows single-stepping
- macOS: [[re-lldb]] ——
brew install lldb, verifylldb --version; before attach, check Developer Tools authorization ([[re-analyze/platform-tips]] macOS branch) - WSL: cannot attach to Windows processes -- cross-boundary analysis uses Windows-side tools, only static work inside WSL ([[re-analyze/platform-tips]] WSL branch)
Decompiler ([[re-ghidra]] etc., cross-reference workbench)
- Ghidra:
apt install ghidra/dnf install ghidra/pacman -S ghidra/brew install --cask ghidra, verifyanalyzeHeadless -help(installation details see [[re-ghidra]]) - Alternative: [[re-ida]] (headless
idat, commands see that skill), [[re-radare2]] (installation matrix see that skill, after installation verify withrizin -v) - Purpose: cross-references (xref) of strings / APIs are the key to "who is calling registration-related functions"
strings -- quick scan of printable strings (all platforms)
- Linux:
apt install binutils/dnf install binutils/pacman -S binutils(most bundled) - macOS: system built-in /usr/bin/strings
- Windows/WSL: the Linux version inside WSL; on native Windows use Sysinternals
strings.exe - Verify:
strings --version
Dynamic supplement (optional): strace / ltrace / ProcMon
- Linux:
apt install strace ltrace, verifystrace --version; observe registry (under Wine) / file / API calls (details see [[re-tracing]]) - Windows: Sysinternals Process Monitor (standalone exe downloaded from the official site, no package manager) -- full trace of registry / file / process / network (connects with [[re-behavior]]); registry operations are the main path for authorization reading
Operation steps
Execute in order, recording the result at each step (checkpoint address + evidence path, see [[re-triage]]). Artifacts:List of all checkpoints + verification algorithm, hand off to [[re-patching]] / [[re-keygen]].
-
Locate the verification function via string / API cross-references:
strings -n 5 sample.exe | grep -iE 'register|serial|license|invalid|activation|trial|key' | head -50 strings -el sample.exe | grep -iE 'register|serial|license' | head -20 # UTF-16LE(Windows 常见)- In the decompiler, look up xrefs for the hit string (Ghidra right-click Find References / IDA
x/ rizinaxt @ str.*) — see which function references it:The referencing function near the popup/input box is the candidate verification function(MessageBox-type "Invalid registration code", registration dialog, registry readRegOpenKeyExW/RegQueryValueExW、GetVolumeInformationWmachine code read) - API side: search the import table for
MessageBox/Reg*/GetVolumeInformation/GetSystemTimeAsFileTime, decompile the referencing function; for Linux targets use ltrace to observestrcmp/ file read calls ([[re-tracing]]) - Record the address and file name of each candidate function (there may be multiple verification functions, see pitfall 3)
- In the decompiler, look up xrefs for the hit string (Ghidra right-click Find References / IDA
-
Call graph and verification branches (success / failure jumps):
- Decompile the verification function, confirm the structure: read input (serial number string / registry value) → compute / compare → jump based on the result(
jz/jnzto success or failure handling). Failure path characteristics: MessageBox error, set registration flag to false, callExitProcess - Find the registration flag: a global variable (0/1) set to 1 on the success path, which the feature code checks; xref that flag to findallfeature checkpoints that consume it (not just the startup check, see pitfall 3)
- Dynamic confirmation (inside the sandbox, [[re-analyze/platform-tips]] highest principle): in the debugger, break at the verification function's return to see the return value and jump direction — [[re-gdb]]:
break <addr>aftersifollow the jump; [[re-x64dbg]]:bp <addr>after, look at the flags - Artifacts: each checkpoint's address / caller / success-failure branch addresses / registration flag
- Decompile the verification function, confirm the structure: read input (serial number string / registry value) → compute / compare → jump based on the result(
-
Algorithm recovery (comparison / decryption / signature verification):
- Comparison type:
strcmp/ byte-by-byte comparison → the serial number is compared against a fixed value or a dynamically derived value, recover the derivation computation (may be [[re-crypto-id]]'s XOR / table lookup / simple transformation) - Decryption type: the serial number is first decrypted (XOR / base64 / custom implementation) then compared → recover the decryption as the generation step (XOR is symmetric and can be inverted directly; table lookup requires inverse mapping)
- Signature verification type:
RSA_verify/ECCsignature verification → the algorithm is irreversible, forward generation is impossible → report to the gateway and hand off to [[re-patching]] (see pitfall 4) - Use [[re-crypto-id]] / [[re-crypto-decrypt]] approaches to recover the encryption/decryption steps; convert the decompiled pseudocode into a standalone script and verify it (for a known valid serial number, the program behavior matches the script result)
- Comparison type:
-
Distinguishing online activation vs offline verification:
- Characteristics: the import table contains network APIs (WinINet
InternetOpen*/WinHttp*/socket), the activation flow is "enter serial number → go online → return activation code", strings contain a server URL / "activation failed" - Online activation: locally only the response format is verified (pseudo-verification), the real verification is on the server → hand off to [[re-protocol]] ([[re-netcap]] sandbox packet capture + [[re-crypto-id]] [[re-crypto-keys]] [[re-crypto-decrypt]] to handle encryption); the local side only handles response verification and offline fallback logic
- Offline verification: the algorithm is entirely local, restoring normally via step 3
- Distinguishing method: run without network (sandbox with network disabled) to see whether activation fails/times out ([[re-sandbox]] network isolation)
- Characteristics: the import table contains network APIs (WinINet
-
Machine-code binding identification:
- Search for imports/calls:
GetVolumeInformationW(volume serial number),GetComputerNameW、GetUserProfileDirectoryW, Windows registryMachineGuid、Linux/etc/machine-idreads - Confirm that serial number generation / verification input contains the machine code: decompile to see whether the verification function first reads the machine code and then includes it in the computation
- After binding is confirmed:The keygen generation logic must include the input(username / machine code parameterized, see [[re-keygen]] pitfall 2); note in the report "this authorization is bound to the machine code"
- Search for imports/calls:
-
License model identification (determines the remediation route):
- Node-locked(machine-bound): serial number = f(machine code) → if reversible, use the [[re-keygen]] route
- Validity period / subscription type: verify the expiration time → time-based verification branch (step 7); locate via xref to the expiration message strings ("expired"/"trial")
- Feature toggle type(freemium): verification points are scattered across feature entry points, and there are multiple registration flags → the full inventory must be complete (pitfall 3)
- Floating license(license server): there is no complete local verification → switch to [[re-protocol]] to analyze the license protocol
- Basis for model determination: contents of the license file / registry entries (containing an expiration date field = subscription type; containing a machine code hash = node-locked)
-
Time-based verification (validity period):
- Time-reading APIs: Windows
GetSystemTimeAsFileTime/GetLocalTime,Linuxtime()/gettimeofday——xref to the comparison logic (> 到期时间) - Anti-tampering: the program may record the "last run time" and detect clock rollback (current time < last recorded → error) — locate this detection point before changing the system time
- Outputs: expiration time storage location (registry / file), comparison function address — patch or bypass target
- Time-reading APIs: Windows
-
Evidence verification (wrap-up):
- The full inventory of verification points (address / branch / flag / evidence level) is filed into [[re-analyze/analysis-contract]]; conclusions are annotated by evidence level (dynamic confirmation vs static inference, see [[decision-tree]])
- Deliverables: verification point inventory + algorithm documentation → unified validation via the [[re-cracking]] gateway
Cross-domain combination
- [[re-cracking]]: this gateway is step 2 of the re-cracking workflow (license location); its outputs (verification point inventory + algorithm) serve steps 4 / 5
- [[re-patching]]: downstream — after obtaining the verification point addresses, modify branches / skip verification
- [[re-keygen]]: downstream — after obtaining the verification algorithm, reverse-engineer the generation logic
- [[re-anti-analysis]]: for packed samples, unpack first (analyze after OEP); if the verification function is obfuscated, first [[re-deobfuscate]]
- [[re-protocol]]: online activation → capture and analyze the activation protocol (netcap → crypto-id → crypto-keys → crypto-decrypt → proto-rev)
- [[re-binary-core]]: decompilation workbench ([[re-ghidra]] / [[re-ida]] / [[re-radare2]])
- Dynamic: [[re-gdb]] / [[re-x64dbg]] / [[re-lldb]] (set breakpoints to inspect branch return values), [[re-tracing]] (strace / ltrace to inspect registry / file / API calls), [[re-memdump]] (registration flags / verification results in memory)
- [[re-behavior]]: Windows-side ProcMon registry / file behavior trace linkage
- [[re-sandbox]]: dynamic location and verification sandbox ([[re-analyze/platform-tips]] highest principle)
- [[re-ioc]]: registration-related strings / verification fingerprints can serve as YARA features
Common pitfalls and traps
- Verification function is obfuscated / encrypted: Symptom—the located verification function decompiles into nothing but junk instructions / flattening / encrypted strings, and the comparison logic cannot be seen; Cause—license verification is a key protection target and is often layered with obfuscation; Countermeasure—first [[re-deobfuscate]] (junk instruction removal → flattening restoration → string decryption) before analysis, do not force your way through the ciphertext
- Treating online activation as offline cracking: Symptom—all local decision branches have been modified, yet the program still refuses to run / functionality is locked; Cause—the real verification is on the server side (locally there is only response verification); Countermeasure—in step 4, first distinguish online / offline (disconnect test); for online, switch to [[re-protocol]] packet capture to analyze the activation protocol, and handle only response verification on the local side
- Verification may occur multiple times (startup + feature points): Symptom—startup verification is bypassed successfully, but a registration prompt appears again when using core features; Cause—there is more than one verification point (startup, feature points, timers, version upgrade checks); Countermeasure—in step 2, traverse all xrefs of the verification function / all consumption points of the registration flag, and make a full verification point checklist (this is the root of [[re-cracking]] gateway pitfall 2)
- Forcing restoration even when the algorithm is irreversible: Symptom—verification includes SHA / MD5 / RSA signature verification, and the serial number generation logic cannot be derived forward; Cause—one-way function; Countermeasure—honestly report that it is irreversible, switch to [[re-patching]] (skip signature verification / change branches), do not fabricate a "restoration success"
- Fake verification misleads: Symptom—after modifying the decision branch, the program still exits as usual / has no effect; Cause—the modified point is not the real authorization decision (fake branch / honeypot verification, the real decision is elsewhere); Countermeasure—use dynamic breakpoints to confirm that each branch truly affects the registration flag and program behavior, then proceed to the patching stage
- Time-based verification missed: Symptom—after modifying all serial number verifications, it still reports expired; Cause—there is also an expiration time verification (subscription / trial) independent of the serial number verification; Countermeasure—in step 7, check time API xrefs and the expiration storage location, and include them in the full checklist
- For more decision branches and boundaries (authorization model decision tree / evidence grading / time tampering counterexamples), see [[decision-tree]] and [[gotchas]]