ctf-agent 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/AGENTS.md +131 -0
  2. package/Dockerfile +192 -0
  3. package/README.md +522 -0
  4. package/agents/ctf-analyzer.md +58 -0
  5. package/agents/ctf-controller.md +151 -0
  6. package/agents/ctf-speedrun.md +74 -0
  7. package/bin/ctf-agent.js +119 -0
  8. package/docker-compose.yml +13 -0
  9. package/mcp_config.json +19 -0
  10. package/package.json +44 -0
  11. package/references/ctf-triage-ladder.md +68 -0
  12. package/references/exploit-databases.md +575 -0
  13. package/references/llm-safety-and-policy-compliance.md +173 -0
  14. package/references/multi-agent-orchestration-and-policy-routing.md +278 -0
  15. package/references/security-events-and-intelligence.md +566 -0
  16. package/references/version-matrix.md +59 -0
  17. package/rules/ctf-execution-rules.md +44 -0
  18. package/rules/ctf-safety-framing-rules.md +140 -0
  19. package/rules/flag-validation-rules.md +25 -0
  20. package/scripts/__init__.py +1 -0
  21. package/scripts/ctf-tools.lock +205 -0
  22. package/scripts/ctf_init.py +1026 -0
  23. package/scripts/ctf_update.py +583 -0
  24. package/scripts/ctfd_client.py +81 -0
  25. package/scripts/cve_lookup.py +453 -0
  26. package/scripts/extract_flags.py +155 -0
  27. package/scripts/install_as_agent.py +278 -0
  28. package/scripts/install_ctf_tools.sh +603 -0
  29. package/scripts/parallel_triage.py +395 -0
  30. package/scripts/prompt_policy_sanitizer.py +283 -0
  31. package/scripts/scope_guard.py +444 -0
  32. package/scripts/skill_validator.py +504 -0
  33. package/scripts/workspace_cleaner.py +141 -0
  34. package/skills/ctf-ai-ml/SKILL.md +120 -0
  35. package/skills/ctf-ai-ml/adversarial-ml.md +623 -0
  36. package/skills/ctf-ai-ml/llm-attacks.md +487 -0
  37. package/skills/ctf-ai-ml/model-attacks.md +422 -0
  38. package/skills/ctf-crypto/SKILL.md +320 -0
  39. package/skills/ctf-crypto/advanced-math.md +798 -0
  40. package/skills/ctf-crypto/classic-ciphers.md +651 -0
  41. package/skills/ctf-crypto/ecc-attacks.md +347 -0
  42. package/skills/ctf-crypto/exotic-crypto-2.md +380 -0
  43. package/skills/ctf-crypto/exotic-crypto.md +528 -0
  44. package/skills/ctf-crypto/historical.md +113 -0
  45. package/skills/ctf-crypto/lattice-and-lwe.md +524 -0
  46. package/skills/ctf-crypto/modern-ciphers-2.md +563 -0
  47. package/skills/ctf-crypto/modern-ciphers-3.md +453 -0
  48. package/skills/ctf-crypto/modern-ciphers.md +649 -0
  49. package/skills/ctf-crypto/prng-attacks.md +257 -0
  50. package/skills/ctf-crypto/prng.md +664 -0
  51. package/skills/ctf-crypto/rsa-attacks-2.md +792 -0
  52. package/skills/ctf-crypto/rsa-attacks.md +487 -0
  53. package/skills/ctf-crypto/stream-ciphers.md +390 -0
  54. package/skills/ctf-crypto/zkp-and-advanced.md +456 -0
  55. package/skills/ctf-forensics/3d-printing.md +121 -0
  56. package/skills/ctf-forensics/SKILL.md +379 -0
  57. package/skills/ctf-forensics/disk-advanced.md +497 -0
  58. package/skills/ctf-forensics/disk-and-memory.md +491 -0
  59. package/skills/ctf-forensics/disk-recovery.md +699 -0
  60. package/skills/ctf-forensics/linux-forensics.md +511 -0
  61. package/skills/ctf-forensics/network-advanced.md +583 -0
  62. package/skills/ctf-forensics/network.md +645 -0
  63. package/skills/ctf-forensics/peripheral-capture.md +287 -0
  64. package/skills/ctf-forensics/signals-and-hardware.md +713 -0
  65. package/skills/ctf-forensics/steganography.md +694 -0
  66. package/skills/ctf-forensics/stego-advanced-2.md +475 -0
  67. package/skills/ctf-forensics/stego-advanced.md +481 -0
  68. package/skills/ctf-forensics/stego-image.md +691 -0
  69. package/skills/ctf-forensics/windows.md +625 -0
  70. package/skills/ctf-malware/SKILL.md +181 -0
  71. package/skills/ctf-malware/c2-and-protocols.md +274 -0
  72. package/skills/ctf-malware/pe-and-dotnet.md +108 -0
  73. package/skills/ctf-malware/scripts-and-obfuscation.md +449 -0
  74. package/skills/ctf-misc/SKILL.md +498 -0
  75. package/skills/ctf-misc/bashjails.md +323 -0
  76. package/skills/ctf-misc/ctfd-navigation.md +465 -0
  77. package/skills/ctf-misc/dns.md +255 -0
  78. package/skills/ctf-misc/encodings-advanced.md +504 -0
  79. package/skills/ctf-misc/encodings.md +431 -0
  80. package/skills/ctf-misc/games-and-vms-2.md +254 -0
  81. package/skills/ctf-misc/games-and-vms-3.md +690 -0
  82. package/skills/ctf-misc/games-and-vms-4.md +229 -0
  83. package/skills/ctf-misc/games-and-vms.md +529 -0
  84. package/skills/ctf-misc/linux-privesc.md +333 -0
  85. package/skills/ctf-misc/pyjails.md +671 -0
  86. package/skills/ctf-misc/rf-sdr.md +91 -0
  87. package/skills/ctf-osint/SKILL.md +198 -0
  88. package/skills/ctf-osint/geolocation-and-media.md +464 -0
  89. package/skills/ctf-osint/social-media.md +312 -0
  90. package/skills/ctf-osint/web-and-dns.md +341 -0
  91. package/skills/ctf-pwn/SKILL.md +214 -0
  92. package/skills/ctf-pwn/advanced-exploits-2.md +579 -0
  93. package/skills/ctf-pwn/advanced-exploits-3.md +598 -0
  94. package/skills/ctf-pwn/advanced-exploits-4.md +590 -0
  95. package/skills/ctf-pwn/advanced-exploits-5.md +119 -0
  96. package/skills/ctf-pwn/advanced-exploits.md +773 -0
  97. package/skills/ctf-pwn/advanced.md +326 -0
  98. package/skills/ctf-pwn/field-notes.md +245 -0
  99. package/skills/ctf-pwn/format-string.md +694 -0
  100. package/skills/ctf-pwn/heap-fsop.md +285 -0
  101. package/skills/ctf-pwn/heap-techniques-2.md +333 -0
  102. package/skills/ctf-pwn/heap-techniques.md +513 -0
  103. package/skills/ctf-pwn/kernel-bypass.md +421 -0
  104. package/skills/ctf-pwn/kernel-techniques.md +366 -0
  105. package/skills/ctf-pwn/kernel.md +636 -0
  106. package/skills/ctf-pwn/overflow-basics.md +611 -0
  107. package/skills/ctf-pwn/rop-advanced.md +725 -0
  108. package/skills/ctf-pwn/rop-and-shellcode.md +659 -0
  109. package/skills/ctf-pwn/sandbox-escape.md +313 -0
  110. package/skills/ctf-reverse/SKILL.md +163 -0
  111. package/skills/ctf-reverse/anti-analysis-ctf.md +204 -0
  112. package/skills/ctf-reverse/anti-analysis.md +693 -0
  113. package/skills/ctf-reverse/field-notes.md +376 -0
  114. package/skills/ctf-reverse/languages-compiled.md +666 -0
  115. package/skills/ctf-reverse/languages-platforms.md +592 -0
  116. package/skills/ctf-reverse/languages.md +553 -0
  117. package/skills/ctf-reverse/patterns-ctf-2.md +397 -0
  118. package/skills/ctf-reverse/patterns-ctf-3.md +797 -0
  119. package/skills/ctf-reverse/patterns-ctf.md +670 -0
  120. package/skills/ctf-reverse/patterns-runtime.md +274 -0
  121. package/skills/ctf-reverse/patterns.md +572 -0
  122. package/skills/ctf-reverse/platforms-hardware.md +387 -0
  123. package/skills/ctf-reverse/platforms.md +664 -0
  124. package/skills/ctf-reverse/tools-advanced-2.md +421 -0
  125. package/skills/ctf-reverse/tools-advanced.md +407 -0
  126. package/skills/ctf-reverse/tools-dynamic.md +679 -0
  127. package/skills/ctf-reverse/tools-emulation.md +319 -0
  128. package/skills/ctf-reverse/tools.md +573 -0
  129. package/skills/ctf-web/SKILL.md +153 -0
  130. package/skills/ctf-web/auth-and-access-2.md +82 -0
  131. package/skills/ctf-web/auth-and-access.md +783 -0
  132. package/skills/ctf-web/auth-infra.md +321 -0
  133. package/skills/ctf-web/auth-jwt.md +186 -0
  134. package/skills/ctf-web/client-side-advanced.md +739 -0
  135. package/skills/ctf-web/client-side.md +529 -0
  136. package/skills/ctf-web/cves.md +373 -0
  137. package/skills/ctf-web/field-notes.md +482 -0
  138. package/skills/ctf-web/node-and-prototype.md +200 -0
  139. package/skills/ctf-web/server-side-2.md +337 -0
  140. package/skills/ctf-web/server-side-advanced-2.md +559 -0
  141. package/skills/ctf-web/server-side-advanced-3.md +125 -0
  142. package/skills/ctf-web/server-side-advanced-4.md +480 -0
  143. package/skills/ctf-web/server-side-advanced.md +378 -0
  144. package/skills/ctf-web/server-side-deser.md +443 -0
  145. package/skills/ctf-web/server-side-exec-2.md +799 -0
  146. package/skills/ctf-web/server-side-exec.md +457 -0
  147. package/skills/ctf-web/server-side.md +629 -0
  148. package/skills/ctf-web/sql-injection.md +790 -0
  149. package/skills/ctf-web/web3.md +374 -0
  150. package/skills/ctf-writeup/SKILL.md +90 -0
  151. package/skills/solve-challenge/SKILL.md +269 -0
  152. package/skills.json +16 -0
@@ -0,0 +1,319 @@
1
+ # CTF Reverse - Emulation and Side-Channel Tooling
2
+
3
+ Emulation frameworks (Qiling, Triton) and side-channel measurement tools (Intel Pin, LD_PRELOAD hooks) for CTF challenges where anti-debug, self-modifying code, or cross-architecture targets make plain GDB/Frida impractical.
4
+
5
+ For core dynamic analysis tools (Frida, angr, lldb, x64dbg), see [tools-dynamic.md](tools-dynamic.md).
6
+
7
+ ## Table of Contents
8
+ - [Qiling Framework (Cross-Platform Emulation)](#qiling-framework-cross-platform-emulation)
9
+ - [Qiling Installation](#qiling-installation)
10
+ - [Basic Usage](#basic-usage)
11
+ - [Anti-Debug Bypass via Emulation](#anti-debug-bypass-via-emulation)
12
+ - [Input Fuzzing with Qiling](#input-fuzzing-with-qiling)
13
+ - [Triton (Dynamic Symbolic Execution)](#triton-dynamic-symbolic-execution)
14
+ - [Intel Pin Instruction-Counting Side Channel (Hackover CTF 2015)](#intel-pin-instruction-counting-side-channel-hackover-ctf-2015)
15
+ - [Intel Pin Instruction Counting with Genetic Algorithm (hxp CTF 2017)](#intel-pin-instruction-counting-with-genetic-algorithm-hxp-ctf-2017)
16
+ - [Opcode-Only Trace Reconstruction (0CTF 2016)](#opcode-only-trace-reconstruction-0ctf-2016)
17
+ - [LD_PRELOAD time() Freeze for Deterministic Analysis (EKOPARTY 2017)](#ld_preload-time-freeze-for-deterministic-analysis-ekoparty-2017)
18
+ - [LD_PRELOAD memcmp Side-Channel for Byte-by-Byte Bruteforce (Blaze CTF 2018)](#ld_preload-memcmp-side-channel-for-byte-by-byte-bruteforce-blaze-ctf-2018)
19
+
20
+ ---
21
+
22
+ ## Qiling Framework (Cross-Platform Emulation)
23
+
24
+ Qiling emulates binaries with OS-level support (syscalls, filesystem, registry). Built on Unicorn but adds the OS layer that Unicorn lacks.
25
+
26
+ ### Qiling Installation
27
+
28
+ ```bash
29
+ pip install qiling
30
+ # Download rootfs for target OS:
31
+ git clone https://github.com/qilingframework/rootfs
32
+ ```
33
+
34
+ ### Basic Usage
35
+
36
+ ```python
37
+ from qiling import Qiling
38
+ from qiling.const import QL_VERBOSE
39
+
40
+ # Linux ELF emulation
41
+ ql = Qiling(["./binary", "arg1"], "rootfs/x8664_linux",
42
+ verbose=QL_VERBOSE.DEFAULT)
43
+ ql.run()
44
+
45
+ # Windows PE emulation (no Windows needed!)
46
+ ql = Qiling(["rootfs/x86_windows/bin/binary.exe"], "rootfs/x86_windows")
47
+ ql.run()
48
+
49
+ # ARM/MIPS emulation (IoT firmware)
50
+ ql = Qiling(["rootfs/arm_linux/bin/binary"], "rootfs/arm_linux")
51
+ ql.run()
52
+ ```
53
+
54
+ ### Anti-Debug Bypass via Emulation
55
+
56
+ ```python
57
+ from qiling import Qiling
58
+
59
+ ql = Qiling(["./binary"], "rootfs/x8664_linux")
60
+
61
+ # Hook ptrace syscall — return 0 (success)
62
+ def hook_ptrace(ql, ptrace_request, pid, addr, data):
63
+ ql.log.info("ptrace bypassed")
64
+ return 0
65
+
66
+ ql.os.set_syscall("ptrace", hook_ptrace)
67
+
68
+ # Hook specific address (e.g., anti-VM check)
69
+ def skip_check(ql):
70
+ ql.arch.regs.rax = 0 # Force success
71
+ ql.log.info(f"Skipped check at {ql.arch.regs.rip:#x}")
72
+
73
+ ql.hook_address(skip_check, 0x401234)
74
+
75
+ ql.run()
76
+ ```
77
+
78
+ ### Input Fuzzing with Qiling
79
+
80
+ ```python
81
+ # Emulate binary with different inputs to find flag
82
+ import string
83
+ from qiling import Qiling
84
+
85
+ def test_input(candidate):
86
+ ql = Qiling(["./binary"], "rootfs/x8664_linux",
87
+ verbose=QL_VERBOSE.DISABLED, stdin=candidate.encode())
88
+ ql.run()
89
+ return ql.os.stdout.read()
90
+
91
+ for ch in string.printable:
92
+ output = test_input("flag{" + ch)
93
+ if b"Correct" in output:
94
+ print(f"Found: {ch}")
95
+ ```
96
+
97
+ **Advantages over GDB/Frida:**
98
+ - No debugger artifacts (bypasses all anti-debug by default)
99
+ - Cross-platform without hardware (ARM, MIPS, RISC-V on x86 host)
100
+ - Scriptable with Python (faster iteration than GDB)
101
+ - Snapshot/restore for brute-forcing
102
+
103
+ **Key insight:** Qiling emulates the entire OS layer (syscalls, filesystem, registry), not just the CPU. This means anti-debug checks like `ptrace(TRACEME)` naturally return success without patching, and you can analyze ARM/MIPS binaries on an x86 host without QEMU or real hardware.
104
+
105
+ **When to use:** Foreign architecture binaries, IoT firmware, heavy anti-debug, automated testing of many inputs.
106
+
107
+ ---
108
+
109
+ ## Triton (Dynamic Symbolic Execution)
110
+
111
+ See [tools-advanced.md](tools-advanced.md#triton-dynamic-symbolic-execution) for full Triton reference. Quick usage:
112
+
113
+ ```python
114
+ from triton import *
115
+
116
+ ctx = TritonContext(ARCH.X86_64)
117
+
118
+ # Symbolize input buffer
119
+ for i in range(32):
120
+ ctx.symbolizeMemory(MemoryAccess(0x600000 + i, CPUSIZE.BYTE), f"flag_{i}")
121
+
122
+ # Process instructions and collect constraints
123
+ # At comparison point, solve for flag
124
+ model = ctx.getModel(ctx.getPathConstraintsAst())
125
+ flag = ''.join(chr(v.getValue()) for _, v in sorted(model.items()))
126
+ ```
127
+
128
+ **Key insight:** Triton excels at single-path DSE (Dynamic Symbolic Execution) where angr's path explosion is a problem. Feed it a concrete execution trace, symbolize specific inputs, and solve for constraints at comparison points. Faster than angr for linear code paths with known execution flow.
129
+
130
+ **Best for:** Single-path symbolic execution, deobfuscation, taint analysis. Faster than angr for linear code paths.
131
+
132
+ ---
133
+
134
+ ## Intel Pin Instruction-Counting Side Channel (Hackover CTF 2015)
135
+
136
+ **Pattern:** Brute-force input character-by-character against a binary using Intel Pin's `inscount0` tool. Each correct character causes deeper execution (more instructions) in the comparison logic.
137
+
138
+ ```python
139
+ import string
140
+ from subprocess import Popen, PIPE
141
+
142
+ pin = './pin'
143
+ tool = './source/tools/ManualExamples/obj-ia32/inscount0.so'
144
+ binary = './target'
145
+
146
+ key = ''
147
+ while True:
148
+ best_count, best_char = 0, ''
149
+ for c in string.printable:
150
+ cmd = [pin, '-injection', 'child', '-t', tool, '--', binary]
151
+ p = Popen(cmd, stdout=PIPE, stdin=PIPE, stderr=PIPE)
152
+ p.communicate((key + c + '\n').encode())
153
+ with open('inscount.out') as f:
154
+ count = int(f.read().split()[-1])
155
+ if count > best_count:
156
+ best_count, best_char = count, c
157
+ key += best_char
158
+ print(f"Found: {key}")
159
+ ```
160
+
161
+ **Key insight:** Movfuscated binaries (compiled with `movfuscator`) expand every instruction into sequences of `mov` operations, making static analysis impractical. However, character-by-character comparison still creates measurable instruction count differences. Pin's `inscount0.so` counts total executed instructions — the correct character at each position causes ~1000+ more instructions (proceeding further in the comparison). Also works for obfuscated binaries with sequential input checks.
162
+
163
+ ---
164
+
165
+ ### Intel Pin Instruction Counting with Genetic Algorithm (hxp CTF 2017)
166
+
167
+ For self-modifying code that decrypts the next chunk only after each character check passes, standard character-by-character Pin counting fails because the search space is too large and characters may interact. Use a genetic algorithm instead to explore the input space more efficiently.
168
+
169
+ ```python
170
+ import subprocess
171
+ import random
172
+ import string
173
+
174
+ PIN_PATH = '/tmp/pin-3.5/pin'
175
+ TOOL_PATH = 'source/tools/ManualExamples/obj-intel64/inscount0.so'
176
+
177
+ def fitness(candidate):
178
+ """Run binary under Pin and return instruction count as fitness."""
179
+ proc = subprocess.Popen(
180
+ [PIN_PATH, '-t', TOOL_PATH, '--', './binary'],
181
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
182
+ stdout, stderr = proc.communicate(candidate.encode())
183
+ # inscount0 writes count to stderr or inscount.out
184
+ try:
185
+ with open('inscount.out') as f:
186
+ return int(f.read().split()[-1])
187
+ except:
188
+ return 0
189
+
190
+ def mutate(individual, rate=0.1):
191
+ """Randomly mutate characters in the individual."""
192
+ result = list(individual)
193
+ for i in range(len(result)):
194
+ if random.random() < rate:
195
+ result[i] = random.choice(string.printable[:62])
196
+ return result
197
+
198
+ # Genetic algorithm parameters
199
+ FLAG_LEN = 40
200
+ POP_SIZE = 100
201
+ SURVIVORS = 20
202
+
203
+ # Initialize random population
204
+ population = [random.choices(string.printable[:62], k=FLAG_LEN) for _ in range(POP_SIZE)]
205
+
206
+ for generation in range(10000):
207
+ # Score each individual by instruction count
208
+ scored = [(fitness(''.join(p)), p) for p in population]
209
+ scored.sort(reverse=True)
210
+ best_score, best_individual = scored[0]
211
+ print(f"Gen {generation}: {best_score} {''.join(best_individual)}")
212
+
213
+ # Keep top survivors, mutate to refill population
214
+ survivors = [s[1] for s in scored[:SURVIVORS]]
215
+ population = survivors + [mutate(random.choice(survivors)) for _ in range(POP_SIZE - SURVIVORS)]
216
+ ```
217
+
218
+ **Modified Pin for Go binaries (table-lookup flag checking):**
219
+ When standard `inscount` fails because counter increments don't correlate with correctness (e.g., table-lookup comparison), modify Pin's icount tool to only count executions at the success-branch address. Brute-force character-by-character with this targeted counter:
220
+ ```cpp
221
+ // Modified inscount0.cpp — count only executions of a specific address
222
+ static ADDRINT target_addr = 0x401234; // success-branch address
223
+ static UINT64 target_count = 0;
224
+
225
+ VOID CountAtTarget(ADDRINT ip) {
226
+ if (ip == target_addr) target_count++;
227
+ }
228
+
229
+ VOID Instruction(INS ins, VOID *v) {
230
+ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)CountAtTarget,
231
+ IARG_INST_PTR, IARG_END);
232
+ }
233
+ ```
234
+
235
+ **Key insight:** When each correct character unlocks a new code section (self-modifying or multi-stage decryption), instruction count increases monotonically with correctness. A genetic algorithm explores the input space more efficiently than character-by-character brute-force because it can discover multiple correct characters simultaneously. Converges in approximately 30 minutes for 40-character flags. For table-lookup comparisons where total instruction count doesn't correlate, target a specific branch address instead.
236
+
237
+ **References:** hxp CTF 2017
238
+
239
+ ---
240
+
241
+ ## Opcode-Only Trace Reconstruction (0CTF 2016)
242
+
243
+ Given an execution trace with only opcodes (no register/memory values), reconstruct the program: sort/dedup trace by address, split into basic blocks, annotate functions. Sorting algorithms are particularly vulnerable -- branch decisions leak element ordering.
244
+
245
+ **Approach:**
246
+ 1. Sort trace entries by address, deduplicate to recover code layout
247
+ 2. Identify basic block boundaries (jumps, calls, returns)
248
+ 3. Map branch taken/not-taken decisions from trace order
249
+ 4. For sorting algorithms, partition comparisons reveal relative ordering of all input elements
250
+
251
+ **Key insight:** Execution traces without data values still leak information through branch decisions. Quicksort partition comparisons reveal which element is greater/lesser at each step, enabling full recovery of the sorted input from branch direction alone.
252
+
253
+ ---
254
+
255
+ ## LD_PRELOAD time() Freeze for Deterministic Analysis (EKOPARTY 2017)
256
+
257
+ Override `time()` via LD_PRELOAD to return a constant value, freezing any timestamp-seeded PRNG. Once the binary's cipher becomes deterministic, brute-force each output byte without understanding the VM or cipher internals.
258
+
259
+ ```c
260
+ // freeze_time.c — compile: gcc -shared -fPIC -o freeze.so freeze_time.c
261
+ #include <time.h>
262
+
263
+ time_t time(time_t *t) {
264
+ if (t) *t = 1234567890;
265
+ return 1234567890;
266
+ }
267
+ ```
268
+
269
+ ```bash
270
+ # Build and use:
271
+ gcc -shared -fPIC -o freeze.so freeze_time.c
272
+ LD_PRELOAD=./freeze.so ./binary
273
+
274
+ # Byte-at-a-time oracle: run with frozen time, try each candidate byte,
275
+ # observe output — correct byte produces expected output character.
276
+ for byte in $(seq 0 255); do
277
+ output=$(echo -n "$(printf '\x%02x' $byte)" | LD_PRELOAD=./freeze.so ./binary)
278
+ # Check output against known/expected
279
+ done
280
+ ```
281
+
282
+ If `srand()` or `rand()` is also involved, override `rand()` too:
283
+ ```c
284
+ int rand(void) { return 42; }
285
+ ```
286
+
287
+ **Key insight:** LD_PRELOAD function interception freezes non-determinism sources (time, rand). Once deterministic, even complex VMs become tractable byte-at-a-time oracles.
288
+
289
+ **References:** EKOPARTY CTF 2017
290
+
291
+ ---
292
+
293
+ ### LD_PRELOAD memcmp Side-Channel for Byte-by-Byte Bruteforce (Blaze CTF 2018)
294
+
295
+ **Pattern:** Replace `memcmp` with an LD_PRELOAD library that returns the number of matching bytes instead of the standard -1/0/1 result. This converts any memcmp-based validation into a byte-by-byte oracle. Automate with GDB Python scripting to bruteforce each character position.
296
+
297
+ ```c
298
+ // memcmp_hook.c - compile: gcc -shared -fPIC -o hook.so memcmp_hook.c
299
+ int memcmp(const char *s1, const char *s2, int n) {
300
+ int cnt = 0;
301
+ for (int i = 0; i < n; ++i) {
302
+ if (s1[i] == s2[i]) cnt++;
303
+ else break;
304
+ }
305
+ return cnt;
306
+ }
307
+ ```
308
+
309
+ ```bash
310
+ # Use with GDB: LD_PRELOAD=./hook.so gdb ./binary
311
+ # Set breakpoint after memcmp, read return value to count matching bytes
312
+ # Iterate characters at each position to find the one that increases count
313
+ ```
314
+
315
+ **Key insight:** Replacing memcmp via LD_PRELOAD to return match count converts any comparison-based validation into a byte-by-byte oracle. Combined with GDB scripting, this automates bruteforce of password/flag checks without reversing the validation algorithm.
316
+
317
+ **Detection:** Binary uses `memcmp` or `strcmp` for flag validation (visible in `ltrace` output or import table). The comparison function is called with user input and a computed/stored expected value.
318
+
319
+ **References:** Blaze CTF 2018