pwn 0.5.617 → 0.5.618
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.
- checksums.yaml +4 -4
- data/README.md +95 -85
- data/README.md.bak +200 -0
- data/documentation/AI-Integration.md +42 -26
- data/documentation/AWS.md +57 -0
- data/documentation/Agent-Tool-Registry.md +56 -0
- data/documentation/Banner.md +17 -0
- data/documentation/Blockchain.md +18 -0
- data/documentation/Bounty.md +21 -0
- data/documentation/BurpSuite.md +41 -16
- data/documentation/CLI-Drivers.md +58 -0
- data/documentation/Configuration.md +66 -0
- data/documentation/Contributing.md +33 -19
- data/documentation/Cron.md +47 -0
- data/documentation/Drivers.md +43 -16
- data/documentation/Extrospection.md +54 -0
- data/documentation/FFI.md +14 -0
- data/documentation/Fuzzing.md +36 -0
- data/documentation/Hardware.md +40 -0
- data/documentation/Metasploit.md +34 -0
- data/documentation/NmapIt.md +18 -12
- data/documentation/PWN.png +0 -0
- data/documentation/PWN_Contributors_and_Users.png +0 -0
- data/documentation/Persistence.md +38 -0
- data/documentation/Plugins.md +97 -47
- data/documentation/Reporting.md +25 -18
- data/documentation/SAST.md +39 -22
- data/documentation/SDR.md +40 -0
- data/documentation/Sessions.md +39 -0
- data/documentation/Skills-Memory-Learning.md +49 -29
- data/documentation/Swarm.md +71 -0
- data/documentation/Transparent-Browser.md +26 -22
- data/documentation/Troubleshooting.md +44 -25
- data/documentation/WWW.md +32 -0
- data/documentation/diagrams/agent-tool-registry.svg +284 -0
- data/documentation/diagrams/aws-cloud-security.svg +166 -0
- data/documentation/diagrams/cron-scheduling.svg +148 -0
- data/documentation/diagrams/dot/hardware-hacking.dot +48 -0
- data/documentation/diagrams/dot/persistence-filesystem.dot +29 -0
- data/documentation/diagrams/extrospection-world-awareness.svg +185 -0
- data/documentation/diagrams/hardware-hacking.svg +163 -0
- data/documentation/diagrams/persistence-filesystem.svg +174 -0
- data/documentation/diagrams/sdr-radio-flow.svg +146 -0
- data/documentation/diagrams/swarm-multi-agent.svg +225 -0
- data/documentation/fax-spectrogram.png +0 -0
- data/documentation/fax-waveform.png +0 -0
- data/documentation/pwn-REPL.md +40 -24
- data/documentation/pwn-ai-Agent.md +59 -30
- data/documentation/pwn_android_war_dialer_session.png +0 -0
- data/documentation/pwn_install.png +0 -0
- data/documentation/pwn_wallpaper.jpg +0 -0
- data/documentation/ringing-spectrogram.png +0 -0
- data/documentation/ringing-waveform.png +0 -0
- data/lib/pwn/version.rb +1 -1
- data/third_party/pwn_rdoc.jsonl +22 -5
- metadata +39 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Agent Tool Registry
|
|
2
|
+
|
|
3
|
+
`PWN::AI::Agent::Registry` (`lib/pwn/ai/agent/registry.rb`) collects every
|
|
4
|
+
LLM-callable function into named **toolsets**. A persona is granted a subset of
|
|
5
|
+
toolsets; the JSON-Schema for each tool is what the model actually sees.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Toolsets → Tools
|
|
10
|
+
|
|
11
|
+
| Toolset | Tools | Backed by |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `terminal` | `shell` | `Open3.capture3` on the host |
|
|
14
|
+
| `pwn` | `pwn_eval` | `TOPLEVEL_BINDING.eval` in the live REPL process |
|
|
15
|
+
| `memory` | `memory_remember` · `memory_recall` · `memory_forget` · `memory_clear` | `PWN::Memory` → `~/.pwn/memory.json` |
|
|
16
|
+
| `skills` | `skill_list` · `skill_view` · `skill_create` · `skill_add_reference` · `skill_delete` | `~/.pwn/skills/*.md` |
|
|
17
|
+
| `sessions` | `sessions_list` · `sessions_view` · `sessions_current` · `sessions_delete` · `sessions_stats` | `PWN::Sessions` → `~/.pwn/sessions/` |
|
|
18
|
+
| `learning` | `learning_note_outcome` · `learning_reflect` · `learning_distill_skill` · `learning_stats` · `learning_outcomes` · `learning_consolidate` · `learning_reset` · `learning_auto_reflect_toggle` | `PWN::AI::Agent::Learning` → `~/.pwn/learning.jsonl` |
|
|
19
|
+
| `metrics` | `metrics_summary` · `metrics_reset` | `PWN::AI::Agent::Metrics` → `~/.pwn/metrics.json` |
|
|
20
|
+
| `extrospection` | `extro_snapshot` · `extro_drift` · `extro_observe` · `extro_observations` · `extro_intel` · `extro_correlate` · `extro_stats` · `extro_reset` · `extro_auto_toggle` | `PWN::AI::Agent::Extrospection` → `~/.pwn/extrospection.json` |
|
|
21
|
+
| `cron` | `cron_list` · `cron_create` · `cron_run` · `cron_enable` · `cron_disable` · `cron_remove` | `PWN::Cron` → `~/.pwn/cron/jobs.yml` |
|
|
22
|
+
| `swarm` | `agent_list` · `agent_spawn` · `agent_ask` · `agent_debate` · `agent_broadcast` · `swarm_bus` · `swarm_list` | `PWN::AI::Agent::Swarm` → `~/.pwn/agents.yml` + `~/.pwn/swarm/` |
|
|
23
|
+
|
|
24
|
+
## Adding a tool
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
# lib/pwn/ai/agent/tools/my_thing.rb
|
|
28
|
+
PWN::AI::Agent::Registry.register(
|
|
29
|
+
name: 'my_thing_do',
|
|
30
|
+
toolset: 'my_thing',
|
|
31
|
+
description: 'One-line summary the LLM will read.',
|
|
32
|
+
parameters: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: { target: { type: 'string' } },
|
|
35
|
+
required: ['target']
|
|
36
|
+
}
|
|
37
|
+
) do |args|
|
|
38
|
+
PWN::Plugins::MyThing.do(target: args['target'])
|
|
39
|
+
end
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Drop the file in `lib/pwn/ai/agent/tools/`, it's auto-loaded on next launch.
|
|
43
|
+
|
|
44
|
+
## Restricting a persona
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
# ~/.pwn/agents.yml
|
|
48
|
+
recon:
|
|
49
|
+
role: "Passive OSINT only. Never touch the target directly."
|
|
50
|
+
toolsets: [terminal, pwn, memory, extrospection] # no swarm, no cron
|
|
51
|
+
engine: ollama
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**See also:** [pwn-ai Agent](pwn-ai-Agent.md) · [Swarm](Swarm.md)
|
|
55
|
+
|
|
56
|
+
[← Home](Home.md)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# `PWN::Banner` — Startup Art
|
|
2
|
+
|
|
3
|
+
15 ANSI banners; one is picked at random every time the REPL starts. Purely
|
|
4
|
+
cosmetic, entirely necessary.
|
|
5
|
+
|
|
6
|
+
`Anon · Bubble · Cheshire · CodeCave · DontPanic · ForkBomb · FSociety ·
|
|
7
|
+
JmpEsp · Matrix · Ninja · OffTheAir · Pirate · Radare2 · Radare2AI ·
|
|
8
|
+
WhiteRabbit`
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
puts PWN::Banner::Matrix.get
|
|
12
|
+
welcome-banner # REPL command: redraw a random one
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Add your own: drop a module in `lib/pwn/banner/` implementing `self.get`.
|
|
16
|
+
|
|
17
|
+
[← Home](Home.md)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# `PWN::Blockchain` — BTC · ETH
|
|
2
|
+
|
|
3
|
+
Lightweight helpers for on-chain recon and wallet interaction.
|
|
4
|
+
Source: `lib/pwn/blockchain/*.rb`.
|
|
5
|
+
|
|
6
|
+
| Module | Purpose |
|
|
7
|
+
|---|---|
|
|
8
|
+
| `PWN::Blockchain::BTC` | Address balance/UTXO lookup, tx broadcast, key helpers |
|
|
9
|
+
| `PWN::Blockchain::ETH` | Address balance, contract call, event log query |
|
|
10
|
+
|
|
11
|
+
Also exposed to the agent via `PWN::AI::Agent::BTC` for wallet-aware prompts.
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
PWN::Blockchain::BTC.balance(address: 'bc1q…')
|
|
15
|
+
PWN::Blockchain::ETH.call(contract: '0x…', method: 'owner()')
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
[← Home](Home.md)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# `PWN::Bounty` — Bug-Bounty Lifecycle Tooling
|
|
2
|
+
|
|
3
|
+
| Module | Purpose |
|
|
4
|
+
|---|---|
|
|
5
|
+
| `PWN::Bounty::LifecycleAuthzReplay` | Record an authenticated browser session, then replay every request under a *different* principal to surface horizontal/vertical authz bugs |
|
|
6
|
+
|
|
7
|
+
Pairs naturally with:
|
|
8
|
+
|
|
9
|
+
- [`PWN::WWW::HackerOne`](WWW.md) / `BugCrowd` / `Synack` — programme navigation
|
|
10
|
+
- `PWN::Plugins::HackerOne` — submissions API
|
|
11
|
+
- [`PWN::Plugins::BurpSuite`](BurpSuite.md) — capture the session to replay
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
PWN::Bounty::LifecycleAuthzReplay.start(
|
|
15
|
+
har_path: 'admin_session.har',
|
|
16
|
+
replay_as: { cookie: 'session=LOW_PRIV_TOKEN' },
|
|
17
|
+
proxy: 'http://127.0.0.1:8080'
|
|
18
|
+
)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
[← Home](Home.md) · [WWW](WWW.md)
|
data/documentation/BurpSuite.md
CHANGED
|
@@ -1,26 +1,51 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `PWN::Plugins::BurpSuite` ⭐
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
The **preferred** web proxy / scanner in PWN (see
|
|
4
|
+
[Burp vs ZAP](Diagrams.md#burp--vs-zap-selection)). Wraps Burp Suite
|
|
5
|
+
Professional's headless mode + REST API.
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+

|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
## Configure
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
```yaml
|
|
12
|
+
# ~/.pwn/config.yml
|
|
13
|
+
burp:
|
|
14
|
+
jar: /opt/burpsuite_pro/burpsuite_pro.jar
|
|
15
|
+
api_key: <REST-API-KEY>
|
|
16
|
+
bind_ip: 127.0.0.1
|
|
17
|
+
proxy_port: 8080
|
|
18
|
+
api_port: 1337
|
|
19
|
+
```
|
|
10
20
|
|
|
11
|
-
|
|
12
|
-
- `PWN::Plugins::BurpSuite.stop`
|
|
13
|
-
- `PWN::Plugins::BurpSuite.get_sitemap(...)`
|
|
14
|
-
- `PWN::Plugins::BurpSuite.send_request(...)`
|
|
15
|
-
- Live spidering and scanning orchestration
|
|
16
|
-
- Integration with TransparentBrowser for proxied browsing
|
|
21
|
+
## Core methods
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
```ruby
|
|
24
|
+
burp = PWN::Plugins::BurpSuite.start(headless: true)
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
# drive traffic through it
|
|
27
|
+
b = PWN::Plugins::TransparentBrowser.open(
|
|
28
|
+
browser_type: :headless, proxy: 'http://127.0.0.1:8080')
|
|
29
|
+
b[:browser].goto 'https://target'
|
|
21
30
|
|
|
22
|
-
|
|
31
|
+
# scan
|
|
32
|
+
PWN::Plugins::BurpSuite.active_scan(burp_obj: burp,
|
|
33
|
+
target_url: 'https://target')
|
|
34
|
+
issues = PWN::Plugins::BurpSuite.get_scan_issues(burp_obj: burp)
|
|
23
35
|
|
|
24
|
-
|
|
36
|
+
PWN::Plugins::BurpSuite.stop(burp_obj: burp)
|
|
37
|
+
```
|
|
25
38
|
|
|
26
|
-
|
|
39
|
+
## CLI drivers
|
|
40
|
+
|
|
41
|
+
- `pwn_burp_suite_pro_active_scan -t URL -o out/`
|
|
42
|
+
- `pwn_burp_suite_pro_active_rest_api_scan` — pure REST, no JVM spawn
|
|
43
|
+
|
|
44
|
+
## Why preferred over ZAP
|
|
45
|
+
|
|
46
|
+
Richer scanner, larger BApp ecosystem, more reliable REST surface. `Zaproxy`
|
|
47
|
+
remains as an OSS fallback and is API-compatible enough that swapping is a
|
|
48
|
+
one-line change.
|
|
49
|
+
|
|
50
|
+
[← Home](Home.md) · [Transparent-Browser](Transparent-Browser.md) ·
|
|
51
|
+
[Plugins](Plugins.md)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# CLI Drivers — `bin/pwn_*`
|
|
2
|
+
|
|
3
|
+
52 headless executables, each a thin `OptionParser` wrapper over one plugin
|
|
4
|
+
(or one workflow). They exist so CI/CD can call PWN without a REPL or an LLM.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Full list
|
|
9
|
+
|
|
10
|
+
```text
|
|
11
|
+
pwn pwn_jenkins_thinBackup_aws_s3
|
|
12
|
+
pwn_android_war_dialer pwn_jenkins_update_plugins
|
|
13
|
+
pwn_autoinc_version pwn_jenkins_useradd
|
|
14
|
+
pwn_aws_describe_resources pwn_mail_agent
|
|
15
|
+
pwn_bdba_groups pwn_msf_postgres_login
|
|
16
|
+
pwn_bdba_scan pwn_nessus_cloud_scan_crud
|
|
17
|
+
pwn_burp_suite_pro_active_rest_api_scan pwn_nessus_cloud_vulnscan
|
|
18
|
+
pwn_burp_suite_pro_active_scan pwn_nexpose
|
|
19
|
+
pwn_char_base64_encoding pwn_nmap_discover_tcp_udp
|
|
20
|
+
pwn_char_dec_encoding pwn_openvas_vulnscan
|
|
21
|
+
pwn_char_hex_escaped_encoding pwn_pastebin_sample_filter
|
|
22
|
+
pwn_char_html_entity_encoding pwn_phone
|
|
23
|
+
pwn_char_unicode_escaped_encoding pwn_rdoc_to_jsonl
|
|
24
|
+
pwn_char_url_encoding pwn_sast
|
|
25
|
+
pwn_crt_sh pwn_serial_check_voicemail
|
|
26
|
+
pwn_defectdojo_engagement_create pwn_serial_msr206
|
|
27
|
+
pwn_defectdojo_importscan pwn_serial_qualcomm_commands
|
|
28
|
+
pwn_defectdojo_reimportscan pwn_serial_son_micro_sm132_rfid
|
|
29
|
+
pwn_diff_csv_files_w_column_exclude pwn_shodan_graphql_introspection
|
|
30
|
+
pwn_domain_reversewhois pwn_shodan_search
|
|
31
|
+
pwn_fuzz_net_app_proto pwn_simple_http_server
|
|
32
|
+
pwn_gqrx_scanner pwn_web_cache_deception
|
|
33
|
+
pwn_jenkins_create_job pwn_www_checkip
|
|
34
|
+
pwn_jenkins_create_view pwn_www_uri_buster
|
|
35
|
+
pwn_jenkins_install_plugin pwn_xss_dom_vectors
|
|
36
|
+
pwn_zaproxy_active_rest_api_scan
|
|
37
|
+
pwn_zaproxy_active_scan
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Run any with `--help` for its flags.
|
|
41
|
+
|
|
42
|
+
## Typical CI usage
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
# .gitlab-ci.yml
|
|
46
|
+
sast:
|
|
47
|
+
image: 0dayinc/pwn:latest
|
|
48
|
+
script:
|
|
49
|
+
- pwn_sast -d "$CI_PROJECT_DIR" -o sast_out/
|
|
50
|
+
- pwn_defectdojo_importscan -f sast_out/report.json -e "$DD_ENGAGEMENT"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Write your own
|
|
54
|
+
|
|
55
|
+
See [Drivers](Drivers.md) — copy any file in `bin/`, swap the plugin call,
|
|
56
|
+
`rake install`, done.
|
|
57
|
+
|
|
58
|
+
[← Home](Home.md)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Configuration — `~/.pwn/config.yml`
|
|
2
|
+
|
|
3
|
+
Everything configurable lives in one YAML file, loaded by `PWN::Config` at
|
|
4
|
+
startup and available in-process as `PWN::Env`.
|
|
5
|
+
|
|
6
|
+
## Minimal example
|
|
7
|
+
|
|
8
|
+
```yaml
|
|
9
|
+
# ~/.pwn/config.yml
|
|
10
|
+
ai:
|
|
11
|
+
engine: anthropic # openai | anthropic | grok | gemini | ollama
|
|
12
|
+
anthropic:
|
|
13
|
+
key: sk-ant-…
|
|
14
|
+
openai:
|
|
15
|
+
key: sk-…
|
|
16
|
+
grok:
|
|
17
|
+
oauth: true # RFC-8628 device flow, no client_secret
|
|
18
|
+
ollama:
|
|
19
|
+
base_url: http://localhost:11434
|
|
20
|
+
model: llama3.1:70b
|
|
21
|
+
agent:
|
|
22
|
+
max_iters: 40 # tool-loop cap per turn
|
|
23
|
+
max_depth: 3 # swarm recursion cap
|
|
24
|
+
auto_reflect: true # Learning.auto_reflect after every final answer
|
|
25
|
+
auto_extrospect: true # Extrospection.auto_extrospect likewise
|
|
26
|
+
|
|
27
|
+
burp:
|
|
28
|
+
jar: /opt/burpsuite_pro/burpsuite_pro.jar
|
|
29
|
+
api_key: …
|
|
30
|
+
|
|
31
|
+
metasploit:
|
|
32
|
+
host: 127.0.0.1
|
|
33
|
+
port: 55553
|
|
34
|
+
user: msf
|
|
35
|
+
pass: …
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Reading / writing at runtime
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
PWN::Env[:ai][:engine] # => :anthropic
|
|
42
|
+
PWN::Env[:ai][:agent][:auto_reflect] # => true
|
|
43
|
+
PWN::Config.reload!
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Sections PWN looks for
|
|
47
|
+
|
|
48
|
+
| Key path | Consumed by |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `ai.engine` | `PWN::AI::Agent::Loop` — which client to instantiate |
|
|
51
|
+
| `ai.<engine>.key` / `.oauth` | `PWN::AI::OpenAI` / `Anthropic` / `Grok` / `Gemini` / `Ollama` |
|
|
52
|
+
| `ai.agent.max_iters` | hard stop on tool-call rounds |
|
|
53
|
+
| `ai.agent.max_depth` | `Swarm` recursion guard |
|
|
54
|
+
| `ai.agent.auto_reflect` | toggle `Learning.auto_reflect` |
|
|
55
|
+
| `ai.agent.auto_extrospect` | toggle `Extrospection.auto_extrospect` |
|
|
56
|
+
| `burp.*` | `PWN::Plugins::BurpSuite` |
|
|
57
|
+
| `metasploit.*` | `PWN::Plugins::Metasploit` |
|
|
58
|
+
| `zap.*` | `PWN::Plugins::Zaproxy` |
|
|
59
|
+
| `shodan.key` / `hunter.key` / … | respective OSINT plugins |
|
|
60
|
+
| `aws.*` | `PWN::AWS::*` (falls back to standard AWS SDK env/instance-profile) |
|
|
61
|
+
|
|
62
|
+
## Other files under `~/.pwn/`
|
|
63
|
+
|
|
64
|
+
See [Persistence](Persistence.md) for the full map.
|
|
65
|
+
|
|
66
|
+
[← Home](Home.md)
|
|
@@ -1,31 +1,45 @@
|
|
|
1
1
|
# Contributing
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Repo layout
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
```text
|
|
6
|
+
lib/pwn/ # all namespaces
|
|
7
|
+
lib/pwn/plugins/ # 66 plugin modules
|
|
8
|
+
lib/pwn/ai/agent/ # agent core
|
|
9
|
+
lib/pwn/ai/agent/tools/ # LLM tool registrations
|
|
10
|
+
bin/ # 52 pwn_* drivers
|
|
11
|
+
spec/ # RSpec (incl. conventions_spec)
|
|
12
|
+
documentation/ # this wiki + diagrams
|
|
13
|
+
```
|
|
6
14
|
|
|
7
|
-
|
|
8
|
-
- Improvements to existing modules
|
|
9
|
-
- New SAST signatures
|
|
10
|
-
- AI skills (see [Skills-Memory-Learning](Skills-Memory-Learning.md))
|
|
11
|
-
- Better documentation / wiki pages
|
|
12
|
-
- Bridges to more commercial/open security tools
|
|
13
|
-
- Bug reports with clear reproduction steps
|
|
15
|
+
## Conventions (enforced by `spec/conventions_spec.rb`)
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
1. Every public module method is `public_class_method def self.name(opts = {})`.
|
|
18
|
+
2. Every arg-accepting `def self.*` uses **exactly** `(opts = {})` — no
|
|
19
|
+
positional args, no keyword args.
|
|
20
|
+
3. Every module has `self.help` returning a usage string.
|
|
21
|
+
4. `# frozen_string_literal: true` at the top of every `.rb`.
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
2. Open an issue or PR on https://github.com/0dayInc/pwn
|
|
19
|
-
3. For large features, discuss first via email (support@0dayinc.com) or GitHub.
|
|
23
|
+
## Quality gates
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
```bash
|
|
26
|
+
rvmsudo rake # rubocop + rspec — must be zero offenses
|
|
27
|
+
```
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
## Adding a plugin
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
1. `lib/pwn/plugins/my_thing.rb` following the conventions above.
|
|
32
|
+
2. Autoload entry in `lib/pwn/plugins.rb`.
|
|
33
|
+
3. `spec/lib/pwn/plugins/my_thing_spec.rb`.
|
|
34
|
+
4. Optional `bin/pwn_my_thing` driver (see [Drivers](Drivers.md)).
|
|
35
|
+
5. Optional agent tool in `lib/pwn/ai/agent/tools/` (see
|
|
36
|
+
[Agent Tool Registry](Agent-Tool-Registry.md)).
|
|
37
|
+
6. Update [Plugins.md](Plugins.md) and, if it changes a data flow, the
|
|
38
|
+
relevant `.dot` in `documentation/diagrams/dot/` → `./build.sh`.
|
|
26
39
|
|
|
27
|
-
|
|
40
|
+
## Commit / release
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
`./git_commit.sh` bumps `PWN::VERSION`, regenerates
|
|
43
|
+
`third_party/pwn_rdoc.jsonl`, runs the gates, and pushes.
|
|
30
44
|
|
|
31
|
-
[
|
|
45
|
+
[← Home](Home.md)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Cron — Scheduled Autonomous Jobs
|
|
2
|
+
|
|
3
|
+
`PWN::Cron` (`lib/pwn/cron.rb`) stores job definitions in
|
|
4
|
+
`~/.pwn/cron/jobs.yml` and can install a matching system-`crontab` line that
|
|
5
|
+
invokes `PWN::Cron.run(<id>)` on schedule.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Job kinds
|
|
10
|
+
|
|
11
|
+
| Kind | Executed as | Use for |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `prompt:` | `pwn --ai "<prompt>"` one-shot | "Re-scan scope nightly and diff findings" |
|
|
14
|
+
| `ruby:` | `TOPLEVEL_BINDING.eval` in-process | Direct `PWN::Plugins` calls |
|
|
15
|
+
| `script:` | `exec` external file | Anything not in Ruby |
|
|
16
|
+
|
|
17
|
+
## Tools
|
|
18
|
+
|
|
19
|
+
| Tool | Purpose |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `cron_create(schedule:, prompt:/ruby:/script:, install_crontab:)` | Define a job |
|
|
22
|
+
| `cron_list` | id · name · schedule · enabled · last_run · last_status |
|
|
23
|
+
| `cron_run(id:)` | Fire immediately (updates last_run/last_status) |
|
|
24
|
+
| `cron_enable` / `cron_disable` | Toggle without deleting |
|
|
25
|
+
| `cron_remove` | Delete from `jobs.yml` (does **not** scrub crontab — `crontab -e` yourself) |
|
|
26
|
+
|
|
27
|
+
## Example
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
cron_create(
|
|
31
|
+
name: 'nightly_scope_sweep',
|
|
32
|
+
schedule: '0 2 * * *',
|
|
33
|
+
prompt: 'extro_snapshot, then NmapIt sweep 10.0.0.0/24, extro_observe every '\
|
|
34
|
+
'new open port, extro_correlate, and post a one-paragraph summary.',
|
|
35
|
+
install_crontab: true
|
|
36
|
+
)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
At 02:00 the system cron fires `PWN::Cron.run`, which spins up a headless
|
|
40
|
+
`pwn-ai` turn. Because `auto_reflect` and `auto_extrospect` are on, the run
|
|
41
|
+
also updates Learning/Metrics/Extrospection — so tomorrow's interactive
|
|
42
|
+
session already knows what changed overnight.
|
|
43
|
+
|
|
44
|
+
**See also:** [Sessions](Sessions.md) · [Extrospection](Extrospection.md) ·
|
|
45
|
+
[CLI Drivers](CLI-Drivers.md)
|
|
46
|
+
|
|
47
|
+
[← Home](Home.md)
|
data/documentation/Drivers.md
CHANGED
|
@@ -1,25 +1,52 @@
|
|
|
1
|
-
# Drivers
|
|
1
|
+
# Drivers — Turn a REPL Session into a Shipped Binary
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A **driver** is a small executable in `bin/` that wires `OptionParser` to one
|
|
4
|
+
or more `PWN::` calls. All 52 shipped `pwn_*` binaries follow the same
|
|
5
|
+
15-line template.
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+

|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
- Loads the `pwn` environment
|
|
9
|
-
- Orchestrates multiple plugins, AI calls, or custom logic
|
|
10
|
-
- Can be scheduled via cron or run standalone
|
|
9
|
+
## Workflow
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
1. **Prototype in the REPL** until the calls work.
|
|
12
|
+
2. `history` → copy the winning lines.
|
|
13
|
+
3. Drop them into the template below as `bin/pwn_<name>`.
|
|
14
|
+
4. `chmod +x bin/pwn_<name>` · add to `pwn.gemspec` executables · `rake install`.
|
|
15
|
+
5. (Optional) `learning_distill_skill(name: '<name>')` so the agent knows the
|
|
16
|
+
procedure too.
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
## Template
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
```ruby
|
|
21
|
+
#!/usr/bin/env ruby
|
|
22
|
+
# frozen_string_literal: true
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
3. Leverage the full plugin + AI surface.
|
|
21
|
-
4. Distill recurring successful patterns into **Skills**.
|
|
24
|
+
require 'optparse'
|
|
25
|
+
require 'pwn'
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
opts = {}
|
|
28
|
+
OptionParser.new do |o|
|
|
29
|
+
o.banner = "USAGE: #{File.basename($PROGRAM_NAME)} [opts]"
|
|
30
|
+
o.on('-tTARGET', '--target=TARGET', 'Required target') { |v| opts[:target] = v }
|
|
31
|
+
o.on('-oDIR', '--out=DIR', 'Output directory') { |v| opts[:out] = v }
|
|
32
|
+
end.parse!
|
|
24
33
|
|
|
25
|
-
[
|
|
34
|
+
raise OptionParser::MissingArgument, '-t' unless opts[:target]
|
|
35
|
+
|
|
36
|
+
result = PWN::Plugins::NmapIt.port_scan(target: opts[:target])
|
|
37
|
+
PWN::Reports::Fuzz.generate(result: result, dir_path: opts[:out]) if opts[:out]
|
|
38
|
+
puts result
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Three artefact types from one REPL session
|
|
42
|
+
|
|
43
|
+
| Artefact | Made with | Consumed by |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `bin/pwn_<name>` | template above | shell / CI |
|
|
46
|
+
| `~/.pwn/skills/<name>.md` | `learning_distill_skill` | every future pwn-ai prompt |
|
|
47
|
+
| `cron` job | `cron_create(ruby: '…')` | system crontab → unattended |
|
|
48
|
+
|
|
49
|
+
**See also:** [CLI Drivers](CLI-Drivers.md) · [Cron](Cron.md) ·
|
|
50
|
+
[Skills, Memory & Learning](Skills-Memory-Learning.md)
|
|
51
|
+
|
|
52
|
+
[← Home](Home.md)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Extrospection — World Awareness
|
|
2
|
+
|
|
3
|
+
`PWN::AI::Agent::Extrospection` is the **outward-facing** counterpart to
|
|
4
|
+
[Learning](Skills-Memory-Learning.md). Where Learning/Metrics ask *"how well
|
|
5
|
+
did **I** do?"*, Extrospection asks *"what does the **world** look like right
|
|
6
|
+
now, and has it changed under me?"*
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## Verbs
|
|
11
|
+
|
|
12
|
+
| Tool | Does | Persists to |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| `extro_snapshot` | Fingerprint host/net/toolchain/repo/env → hash | `extrospection.json` (`snapshot` + rotates `previous`) |
|
|
15
|
+
| `extro_drift` | Diff live-vs-stored (or stored-vs-previous) | — returns `{changed, added, removed}` with dotted keys |
|
|
16
|
+
| `extro_observe` | Record a recon fact (banner, CVE match, topology note) | `observations[]` |
|
|
17
|
+
| `extro_observations` | Query recorded facts by source/category/target/tag | — |
|
|
18
|
+
| `extro_intel` | Query NVD / CIRCL / Exploit-DB for keyword or CVE | optional `record: true` → `:intel` observations |
|
|
19
|
+
| `extro_correlate` | **Join** introspection ↔ extrospection | — actionable findings |
|
|
20
|
+
| `extro_stats` | snapshot age · observation count · drift counts | — |
|
|
21
|
+
| `extro_reset` | Wipe snapshot + observations (new engagement) | — |
|
|
22
|
+
| `extro_auto_toggle` | Enable/disable auto-snapshot after every final answer | `PWN::Env[:ai][:agent][:auto_extrospect]` |
|
|
23
|
+
|
|
24
|
+
## `extro_correlate` — the point of the whole thing
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
(a) Metrics tools with <50 % success × toolchain drift / missing binaries
|
|
28
|
+
(b) Learning failures on day X × host/net/repo drift on day X
|
|
29
|
+
(c) recorded :intel observations × installed component versions
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Output tells the agent whether a failure was **its own fault** ("I called the
|
|
33
|
+
API wrong") or **the world changed** ("nmap was upgraded and the flag moved")
|
|
34
|
+
— and that distinction is written back into MEMORY so the next run doesn't
|
|
35
|
+
waste iterations rediscovering it.
|
|
36
|
+
|
|
37
|
+
## Typical engagement flow
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
extro_reset(confirm: true) # clean slate for new scope
|
|
41
|
+
extro_snapshot # baseline
|
|
42
|
+
# … recon …
|
|
43
|
+
extro_observe(source: 'nmap', target: '10.0.0.5',
|
|
44
|
+
category: 'recon', data: 'OpenSSH 8.2p1 Ubuntu')
|
|
45
|
+
extro_intel(query: 'OpenSSH 8.2p1', record: true)
|
|
46
|
+
# … days later, something breaks …
|
|
47
|
+
extro_drift # what moved?
|
|
48
|
+
extro_correlate # why did it break?
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**See also:** [Skills, Memory & Learning](Skills-Memory-Learning.md) ·
|
|
52
|
+
[pwn-ai Agent](pwn-ai-Agent.md)
|
|
53
|
+
|
|
54
|
+
[← Home](Home.md)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# `PWN::FFI` — Native Calls
|
|
2
|
+
|
|
3
|
+
`PWN::FFI::Stdio` (`lib/pwn/ffi/stdio.rb`) exposes libc functions to Ruby via
|
|
4
|
+
the `ffi` gem — useful for shellcode testing, format-string research and
|
|
5
|
+
low-level RE without leaving the REPL.
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
PWN::FFI::Stdio.printf(fmt: "leak: %p\n", args: [0x41414141])
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Combine with `PWN::Plugins::Assembly` (opcodes ↔ asm) and `pwn-asm` for a
|
|
12
|
+
minimal in-process exploit-dev workbench.
|
|
13
|
+
|
|
14
|
+
[← Home](Home.md) · [Hardware](Hardware.md)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Fuzzing — `PWN::Plugins::Fuzz` · `Sock` · `Packet`
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
## Generate
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
payloads = PWN::Plugins::Fuzz.generate(
|
|
9
|
+
seed: "GET / HTTP/1.1\r\nHost: t\r\n\r\n",
|
|
10
|
+
strategy: :radamsa, # :radamsa | :bitflip | :dictionary
|
|
11
|
+
count: 500
|
|
12
|
+
)
|
|
13
|
+
enc = PWN::Plugins::Char.url_encode(str: payloads.first)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Deliver
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
payloads.each do |p|
|
|
20
|
+
PWN::Plugins::Sock.connect(target: '10.0.0.5', port: 8080) do |s|
|
|
21
|
+
s.write(p); s.read
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For raw L2/L3: `PWN::Plugins::Packet`.
|
|
27
|
+
CLI network fuzzer: `pwn_fuzz_net_app_proto -t HOST -p PORT -f seeds/`
|
|
28
|
+
|
|
29
|
+
## Monitor & report
|
|
30
|
+
|
|
31
|
+
`PWN::Plugins::PS` watches the target process; `PWN::Plugins::Log` tails its
|
|
32
|
+
log; `PWN::Reports::Fuzz` renders crash → HTML/JSON.
|
|
33
|
+
|
|
34
|
+
Feed unique crashes back as new seeds (`Log → Fuzz` dashed edge in the diagram).
|
|
35
|
+
|
|
36
|
+
[← Home](Home.md) · [Reporting](Reporting.md)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Hardware & Physical-Layer Hacking
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
## Serial / Bus
|
|
7
|
+
|
|
8
|
+
| Module | Use |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `PWN::Plugins::Serial` | Generic UART (`/dev/ttyUSB*`) — read/write, baud detect |
|
|
11
|
+
| `PWN::Plugins::BusPirate` | SPI/I²C/1-Wire via Bus Pirate |
|
|
12
|
+
| `PWN::Plugins::MSR206` | ISO magstripe read/write (tracks 1-3) |
|
|
13
|
+
|
|
14
|
+
CLI: `pwn_serial_msr206`, `pwn_serial_qualcomm_commands`,
|
|
15
|
+
`pwn_serial_check_voicemail`, `pwn_serial_son_micro_sm132_rfid`
|
|
16
|
+
|
|
17
|
+
## Mobile
|
|
18
|
+
|
|
19
|
+
`PWN::Plugins::Android` — `adb_net_connect`, `adb_sh`, `adb_push/pull`,
|
|
20
|
+
`take_screenshot`, `screen_record`, `list_installed_apps`, `dumpsys`,
|
|
21
|
+
`open_app`, `find_hidden_codes`, `swipe`, `input`, `input_special`,
|
|
22
|
+
`invoke_event_listener`. CLI war-dialer: `pwn_android_war_dialer`.
|
|
23
|
+
|
|
24
|
+
## Voice / Telephony
|
|
25
|
+
|
|
26
|
+
`PWN::Plugins::BareSIP` (SIP recon/war-dial), `PWN::Plugins::Voice` (TTS).
|
|
27
|
+
CLI: `pwn_phone`.
|
|
28
|
+
|
|
29
|
+
## Radio
|
|
30
|
+
|
|
31
|
+
See [SDR](SDR.md) — GQRX, FlipperZero, RFIDler, SonMicro.
|
|
32
|
+
|
|
33
|
+
## Binary / RE
|
|
34
|
+
|
|
35
|
+
- `PWN::Plugins::XXD` — hex dump / patch
|
|
36
|
+
- `PWN::Plugins::Assembly` + `pwn-asm` REPL — opcodes ↔ asm, multi-arch
|
|
37
|
+
- `PWN::Plugins::BlackDuckBinaryAnalysis` — SBOM + CVE match on firmware
|
|
38
|
+
- [`PWN::FFI`](FFI.md) — call libc from Ruby
|
|
39
|
+
|
|
40
|
+
[← Home](Home.md) · [SDR](SDR.md) · [FFI](FFI.md)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# `PWN::Plugins::Metasploit`
|
|
2
|
+
|
|
3
|
+
RPC client for `msfrpcd` — search modules, set options, run exploits, interact
|
|
4
|
+
with sessions, all from Ruby.
|
|
5
|
+
|
|
6
|
+
## Configure
|
|
7
|
+
|
|
8
|
+
```yaml
|
|
9
|
+
# ~/.pwn/config.yml
|
|
10
|
+
metasploit:
|
|
11
|
+
host: 127.0.0.1
|
|
12
|
+
port: 55553
|
|
13
|
+
user: msf
|
|
14
|
+
pass: …
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Start the daemon: `msfrpcd -U msf -P … -a 127.0.0.1 -p 55553 -S`
|
|
18
|
+
|
|
19
|
+
## Use
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
msf = PWN::Plugins::Metasploit.connect
|
|
23
|
+
mods = PWN::Plugins::Metasploit.search(msf_obj: msf, query: 'jenkins')
|
|
24
|
+
PWN::Plugins::Metasploit.use(msf_obj: msf,
|
|
25
|
+
module_type: 'exploit',
|
|
26
|
+
module_name: 'multi/http/jenkins_script_console')
|
|
27
|
+
PWN::Plugins::Metasploit.set_option(msf_obj: msf, opt: 'RHOSTS', val: '10.0.0.5')
|
|
28
|
+
job = PWN::Plugins::Metasploit.run(msf_obj: msf)
|
|
29
|
+
PWN::Plugins::Metasploit.sessions(msf_obj: msf)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
CLI: `pwn_msf_postgres_login -H 10.0.0.5 -U users.txt -P pass.txt`
|
|
33
|
+
|
|
34
|
+
[← Home](Home.md) · [Plugins](Plugins.md)
|