pwn 0.5.709 → 0.5.711

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/documentation/Installation.md +8 -5
  4. data/etc/default_skills/exploitdev/SKILL.md +38 -0
  5. data/etc/default_skills/pwn/plugins/aflplusplus/SKILL.md +1 -0
  6. data/etc/default_skills/pwn/plugins/credential_attack/SKILL.md +7 -0
  7. data/etc/default_skills/pwn/plugins/credential_attack/references/urls.md +3 -0
  8. data/etc/default_skills/pwn/plugins/detect_os/SKILL.md +3 -1
  9. data/etc/default_skills/pwn/plugins/exploit_db/SKILL.md +49 -0
  10. data/etc/default_skills/pwn/plugins/exploit_dev/SKILL.md +2 -0
  11. data/etc/default_skills/pwn/plugins/frida/SKILL.md +2 -0
  12. data/etc/default_skills/pwn/plugins/fuzz/SKILL.md +2 -0
  13. data/etc/default_skills/pwn/plugins/gdb/SKILL.md +1 -0
  14. data/etc/default_skills/pwn/plugins/k8s/SKILL.md +51 -0
  15. data/etc/default_skills/pwn/plugins/nuclei/SKILL.md +2 -0
  16. data/etc/default_skills/pwn/plugins/{doctor → preflight_checker}/SKILL.md +13 -11
  17. data/etc/default_skills/pwn/plugins/process_tube/SKILL.md +1 -0
  18. data/etc/default_skills/pwn/plugins/recon/SKILL.md +2 -0
  19. data/etc/default_skills/pwn/plugins/recon/references/urls.md +1 -0
  20. data/etc/default_skills/pwn/plugins/semgrep/SKILL.md +48 -0
  21. data/etc/default_skills/pwn/plugins/volatility/SKILL.md +1 -0
  22. data/etc/default_skills/pwn/setup/SKILL.md +3 -2
  23. data/lib/pwn/ai/agent/prompt_builder.rb +1 -1
  24. data/lib/pwn/ai/agent/tools/sessions.rb +8 -1
  25. data/lib/pwn/ffi/stdio.rb +3 -1
  26. data/lib/pwn/plugins/aflplusplus.rb +21 -1
  27. data/lib/pwn/plugins/android.rb +9 -3
  28. data/lib/pwn/plugins/credential_attack.rb +63 -4
  29. data/lib/pwn/plugins/detect_os.rb +224 -15
  30. data/lib/pwn/plugins/exploit_db.rb +69 -0
  31. data/lib/pwn/plugins/exploit_dev.rb +69 -3
  32. data/lib/pwn/plugins/frida.rb +60 -9
  33. data/lib/pwn/plugins/fuzz.rb +33 -0
  34. data/lib/pwn/plugins/gdb.rb +25 -5
  35. data/lib/pwn/plugins/jobs.rb +1 -0
  36. data/lib/pwn/plugins/k8s.rb +73 -0
  37. data/lib/pwn/plugins/nuclei.rb +36 -3
  38. data/lib/pwn/plugins/packet.rb +1 -1
  39. data/lib/pwn/plugins/{doctor.rb → preflight_checker.rb} +26 -5
  40. data/lib/pwn/plugins/process_tube.rb +20 -1
  41. data/lib/pwn/plugins/radare2.rb +1 -1
  42. data/lib/pwn/plugins/recon.rb +40 -5
  43. data/lib/pwn/plugins/semgrep.rb +61 -0
  44. data/lib/pwn/plugins/sock.rb +1 -0
  45. data/lib/pwn/plugins/sqlmap.rb +1 -1
  46. data/lib/pwn/plugins/volatility.rb +21 -2
  47. data/lib/pwn/plugins.rb +4 -1
  48. data/lib/pwn/setup.rb +180 -15
  49. data/lib/pwn/version.rb +1 -1
  50. data/spec/documentation/installation_md_spec.rb +1 -1
  51. data/spec/integration/help_contract_spec.rb +2 -0
  52. data/spec/lib/pwn/plugins/detect_os_spec.rb +54 -4
  53. data/spec/lib/pwn/plugins/exploit_db_spec.rb +13 -0
  54. data/spec/lib/pwn/plugins/k8s_spec.rb +13 -0
  55. data/spec/lib/pwn/plugins/{doctor_spec.rb → preflight_checker_spec.rb} +1 -1
  56. data/spec/lib/pwn/plugins/semgrep_spec.rb +13 -0
  57. data/spec/lib/pwn/req_queue_spec.rb +168 -0
  58. data/spec/lib/pwn/setup_spec.rb +54 -0
  59. data/third_party/pwn_rdoc.jsonl +61 -13
  60. metadata +20 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a21d92ef6104c4aec2f54470689f0398fda97a2894bb9a61b1034a72b5291e1f
4
- data.tar.gz: 19a47d2db6aae502ab6a2380853569f172ff393839187818b891f01272029f5f
3
+ metadata.gz: 2ab0eff0005f523bb5972be43cf49ab4c15ab9eaecda0968c9206621e2997e47
4
+ data.tar.gz: 2a166f6ff6b5620e820de709d5dc1ae356550e23afffbc52de138d3ab6499d7f
5
5
  SHA512:
6
- metadata.gz: 79f9a1ac713919b1e4cd239f5475b9d14f2b73dcc19152fc0b1e82312d6f1c25062bb90f45ffe5533bd3fda09769faf3207d946110a196d3d050847344ac3549
7
- data.tar.gz: 8718455cc9a5db44fa41ce916b26292a92889c4c7208ecaa74df310dddafeddfd4d8ba1983ea8c437b83c67a36bc589fb06d5c0d2729e6b104a3bff598c2a7c3
6
+ metadata.gz: c74d677beb74e9cd348faebbc1b02dff1b48956b0225487ef48af1be080f94137472f892dce6698a2d55c0febbbb1637a477e4ec090098ffe64cc5e26030b33b
7
+ data.tar.gz: 6bf02d8127f74b609d3cc8ae1c03586b96f29e44c921e00893dc550f516817c6b4d3456ad516262c1d919e93a36cceffedc7891039460801de2c937dfbbaf2d1
data/Gemfile CHANGED
@@ -22,7 +22,7 @@ gem 'brakeman', '8.0.6'
22
22
  gem 'bson', '5.2.0'
23
23
  gem 'bundler', '>=4.0.19'
24
24
  gem 'bundler-audit', '>=0.9.3'
25
- gem 'bunny', '3.2.0'
25
+ gem 'bunny', '3.3.0'
26
26
  gem 'colorize', '1.1.0'
27
27
  gem 'credit_card_validations', '9.0.0'
28
28
  gem 'curses', '1.7.0'
@@ -77,7 +77,7 @@ gem 'rbvmomi2', '3.10.0'
77
77
  gem 'rdoc', '7.0.4'
78
78
  gem 'rest-client', '2.1.0'
79
79
  gem 'rex', '2.0.13'
80
- gem 'rmagick', '7.1.1'
80
+ gem 'rmagick', '7.1.3'
81
81
  gem 'rqrcode', '3.2.0'
82
82
  gem 'rspec', '3.13.2'
83
83
  gem 'rtesseract', '3.1.4'
@@ -103,10 +103,13 @@ pwn setup --list-profiles
103
103
  `--deps` / `--profile` will:
104
104
 
105
105
  1. Resolve the profile → set of native gems + external binaries.
106
- 2. Map those to OS packages for **your** package manager (data lives in
107
- `PWN::Setup::NATIVE_GEMS` / `::TOOLCHAIN` - versioned with the gem, so
108
- `gem install --verbose pwn`, git checkout, Docker, Packer and Vagrant all read the
109
- same table).
106
+ 2. Map those to OS packages for **this** distro and version
107
+ (`PWN::Plugins::DetectOS.distro` / `.version`, e.g. Kali `2026.3` vs Ubuntu
108
+ `24.04`) via `PWN::Setup.packages_for`. Family fallbacks still live in
109
+ `PWN::Setup::NATIVE_GEMS` / `::TOOLCHAIN`. Tools with no OS package on this
110
+ distro (Frida, one_gadget, ROPgadget, checksec, ropper, kube-hunter, or
111
+ Kali-only names on Ubuntu) install via `pip` / `gem` or are skipped so
112
+ `apt-get` does not abort the whole profile.
110
113
  3. Show the exact commands, prompt (unless `--yes`), run them, then
111
114
  `gem pristine` / `gem install` any native extension that still fails to
112
115
  load, and re-run the doctor.
@@ -127,7 +130,7 @@ pwn setup --list-profiles
127
130
  | `voice` | `PWN::Plugins::Voice` · `extro_voice` · espeak-ng / sox |
128
131
  | `exploit` | `Metasploit` · `sqlmap` |
129
132
  | `hardware` | `Serial` · `BusPirate` · `Android` · `BareSIP` · `extro_serial` · `extro_telecomm` |
130
- | `re` | `Radare2` · `GDB` · `ExploitDev` · `Frida` · Android RE (`apktool`/`jadx`) |
133
+ | `re` | `Radare2` · `GDB` · `ExploitDev` · `Frida` · Android RE (`apktool`/`jadx`) · `pwndbg` · `ropper` · `rizin` |
131
134
  | `full` | everything above |
132
135
 
133
136
  ### All flags
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: exploitdev
3
+ description: "Exploit-dev SOP: packing, cyclic, ROP, one_gadget, libc offsets."
4
+ ---
5
+
6
+ # Exploit development
7
+
8
+ Use `PWN::Plugins::ExploitDev` from `pwn_eval` — do not shell out to pwntools unless a plugin method is missing.
9
+
10
+ ## Packing
11
+
12
+ ```ruby
13
+ PWN::Plugins::ExploitDev.p32(value: 0x41414141)
14
+ PWN::Plugins::ExploitDev.p64(value: addr, endian: :little)
15
+ PWN::Plugins::ExploitDev.flat(parts: [0xdeadbeef, "A" * 32, 0x401000])
16
+ ```
17
+
18
+ ## Cyclic
19
+
20
+ ```ruby
21
+ pattern = PWN::Plugins::ExploitDev.cyclic(length: 200)
22
+ offset = PWN::Plugins::ExploitDev.cyclic_find(value: "Aa0A", length: 200)
23
+ ```
24
+
25
+ ## Shellcode / ROP
26
+
27
+ ```ruby
28
+ PWN::Plugins::ExploitDev.shellcode(arch: 'x86_64', kind: 'execve_bin_sh')
29
+ PWN::Plugins::ExploitDev.gadgets(path: '/path/to/binary')
30
+ PWN::Plugins::ExploitDev.one_gadget(path: '/lib/x86_64-linux-gnu/libc.so.6')
31
+ PWN::Plugins::ExploitDev.libc_offsets(path: '/lib/x86_64-linux-gnu/libc.so.6')
32
+ ```
33
+
34
+ ## Interactive
35
+
36
+ `PWN::Plugins::ProcessTube.spawn` or `.connect` then `write_line` / `recvuntil`.
37
+ `PWN::Plugins::GDB.run_to_crash` / `.breakpoints` / `.core`.
38
+ `PWN::Plugins::Radare2.open` then `cmd` (text) or `cmdj` (JSON).
@@ -35,6 +35,7 @@ PWN::Plugins::AFLplusplus.required_bins(opts)
35
35
 
36
36
  - `required_bins`
37
37
  - `fuzz`
38
+ - `crash_triage`
38
39
  - `authors`
39
40
  - `help`
40
41
 
@@ -38,9 +38,16 @@ PWN::Plugins::CredentialAttack.required_bins(opts)
38
38
  - `hydra`
39
39
  - `john`
40
40
  - `hashcat`
41
+ - `medusa`
42
+ - `identify_hash`
43
+ - `fetch_seclists`
41
44
  - `authors`
42
45
  - `help`
43
46
 
47
+ ## References
48
+
49
+ - `references/urls.md` — URLs from source
50
+
44
51
  ## Source
45
52
 
46
53
  `pwn/plugins/credential_attack.rb`
@@ -0,0 +1,3 @@
1
+ # PWN::Plugins::CredentialAttack source links
2
+
3
+ - https://github.com/danielmiessler/SecLists.git
@@ -12,7 +12,7 @@ metadata:
12
12
 
13
13
  # PWN::Plugins::DetectOS
14
14
 
15
- This plugin converts images to readable text
15
+ Detect host OS family, distro flavor, and version string.
16
16
 
17
17
  ## When to use
18
18
 
@@ -36,6 +36,8 @@ PWN::Plugins::DetectOS.type(opts)
36
36
  - `type`
37
37
  - `arch`
38
38
  - `endian`
39
+ - `distro`
40
+ - `version`
39
41
  - `authors`
40
42
  - `help`
41
43
 
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: pwn-plugins-exploitdb
3
+ description: Drive PWN::Plugins::ExploitDB from pwn_eval.
4
+ license: MIT
5
+ allowed-tools: [pwn, pwn_eval]
6
+ metadata:
7
+ bundled: true
8
+ generated: true
9
+ module: PWN::Plugins::ExploitDB
10
+ source: pwn/plugins/exploit_db.rb
11
+ ---
12
+
13
+ # PWN::Plugins::ExploitDB
14
+
15
+ searchsploit / ExploitDB plus a CPE string builder for nmap versions.
16
+
17
+ ## When to use
18
+
19
+ Call `PWN::Plugins::ExploitDB` from `pwn_eval` when the task needs this module.
20
+ Do not reimplement it in shell.
21
+
22
+ ## Methodologies
23
+
24
+ Generated from `pwn/plugins/exploit_db.rb`. Prefer the public class methods below.
25
+ Class methods take `(opts = {})` and read `opts`.
26
+
27
+ ## How to call
28
+
29
+ ```ruby
30
+ PWN::Plugins::ExploitDB.help
31
+ PWN::Plugins::ExploitDB.required_bins(opts)
32
+ ```
33
+
34
+ ## Public methods
35
+
36
+ - `required_bins`
37
+ - `search`
38
+ - `cve_for_cpe`
39
+ - `authors`
40
+ - `help`
41
+
42
+ ## Source
43
+
44
+ `pwn/plugins/exploit_db.rb`
45
+
46
+ ## Verification
47
+
48
+ `PWN::Plugins::ExploitDB.respond_to?(:required_bins)` after the
49
+ module is loaded. Read the source for parameter names.
@@ -46,6 +46,8 @@ PWN::Plugins::ExploitDev.required_bins(opts)
46
46
  - `cyclic_find`
47
47
  - `flat`
48
48
  - `shellcode`
49
+ - `one_gadget`
50
+ - `libc_offsets`
49
51
  - `fmt_writes`
50
52
  - `gadgets`
51
53
  - `authors`
@@ -36,6 +36,8 @@ PWN::Plugins::Frida.required_bins(opts)
36
36
  - `required_bins`
37
37
  - `ps`
38
38
  - `attach`
39
+ - `spawn`
40
+ - `ssl_pinning_script`
39
41
  - `authors`
40
42
  - `help`
41
43
 
@@ -34,6 +34,8 @@ PWN::Plugins::Fuzz.socket(opts)
34
34
  ## Public methods
35
35
 
36
36
  - `socket`
37
+ - `http`
38
+ - `file_format`
37
39
  - `authors`
38
40
  - `help`
39
41
 
@@ -39,6 +39,7 @@ PWN::Plugins::GDB.required_bins(opts)
39
39
  - `registers`
40
40
  - `mitigations`
41
41
  - `core`
42
+ - `breakpoints`
42
43
  - `authors`
43
44
  - `help`
44
45
 
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: pwn-plugins-k8s
3
+ description: Drive PWN::Plugins::K8s from pwn_eval.
4
+ license: MIT
5
+ allowed-tools: [pwn, pwn_eval]
6
+ metadata:
7
+ bundled: true
8
+ generated: true
9
+ module: PWN::Plugins::K8s
10
+ source: pwn/plugins/k8s.rb
11
+ ---
12
+
13
+ # PWN::Plugins::K8s
14
+
15
+ trivy / kube-hunter wrappers plus docker-socket preflight.
16
+
17
+ ## When to use
18
+
19
+ Call `PWN::Plugins::K8s` from `pwn_eval` when the task needs this module.
20
+ Do not reimplement it in shell.
21
+
22
+ ## Methodologies
23
+
24
+ Generated from `pwn/plugins/k8s.rb`. Prefer the public class methods below.
25
+ Class methods take `(opts = {})` and read `opts`.
26
+
27
+ ## How to call
28
+
29
+ ```ruby
30
+ PWN::Plugins::K8s.help
31
+ PWN::Plugins::K8s.required_bins(opts)
32
+ ```
33
+
34
+ ## Public methods
35
+
36
+ - `required_bins`
37
+ - `trivy`
38
+ - `kube_hunter`
39
+ - `docker_socket`
40
+ - `authors`
41
+ - `help`
42
+ - `docker_socket?`
43
+
44
+ ## Source
45
+
46
+ `pwn/plugins/k8s.rb`
47
+
48
+ ## Verification
49
+
50
+ `PWN::Plugins::K8s.respond_to?(:required_bins)` after the
51
+ module is loaded. Read the source for parameter names.
@@ -35,6 +35,8 @@ PWN::Plugins::Nuclei.required_bins(opts)
35
35
 
36
36
  - `required_bins`
37
37
  - `scan`
38
+ - `to_findings`
39
+ - `to_defectdojo`
38
40
  - `authors`
39
41
  - `help`
40
42
 
@@ -1,34 +1,34 @@
1
1
  ---
2
- name: pwn-plugins-doctor
3
- description: Drive PWN::Plugins::Doctor from pwn_eval.
2
+ name: pwn-plugins-preflightchecker
3
+ description: Drive PWN::Plugins::PreflightChecker from pwn_eval.
4
4
  license: MIT
5
5
  allowed-tools: [pwn, pwn_eval]
6
6
  metadata:
7
7
  bundled: true
8
8
  generated: true
9
- module: PWN::Plugins::Doctor
10
- source: pwn/plugins/doctor.rb
9
+ module: PWN::Plugins::PreflightChecker
10
+ source: pwn/plugins/preflight_checker.rb
11
11
  ---
12
12
 
13
- # PWN::Plugins::Doctor
13
+ # PWN::Plugins::PreflightChecker
14
14
 
15
15
  Plugin/binary/capability preflight. Plugins declare required_bins / required_caps; HOST summaries list degraded modules without autoloading the whole plugin tree.
16
16
 
17
17
  ## When to use
18
18
 
19
- Call `PWN::Plugins::Doctor` from `pwn_eval` when the task needs this module.
19
+ Call `PWN::Plugins::PreflightChecker` from `pwn_eval` when the task needs this module.
20
20
  Do not reimplement it in shell.
21
21
 
22
22
  ## Methodologies
23
23
 
24
- Generated from `pwn/plugins/doctor.rb`. Prefer the public class methods below.
24
+ Generated from `pwn/plugins/preflight_checker.rb`. Prefer the public class methods below.
25
25
  Class methods take `(opts = {})` and read `opts`.
26
26
 
27
27
  ## How to call
28
28
 
29
29
  ```ruby
30
- PWN::Plugins::Doctor.help
31
- PWN::Plugins::Doctor.required_bins(opts)
30
+ PWN::Plugins::PreflightChecker.help
31
+ PWN::Plugins::PreflightChecker.required_bins(opts)
32
32
  ```
33
33
 
34
34
  ## Public methods
@@ -38,6 +38,7 @@ PWN::Plugins::Doctor.required_bins(opts)
38
38
  - `require_bin`
39
39
  - `cap_net_raw`
40
40
  - `require_cap_net_raw`
41
+ - `service`
41
42
  - `check`
42
43
  - `host_summary`
43
44
  - `authors`
@@ -46,12 +47,13 @@ PWN::Plugins::Doctor.required_bins(opts)
46
47
  - `cap_net_raw?`
47
48
  - `require_bin!`
48
49
  - `require_cap_net_raw!`
50
+ - `service?`
49
51
 
50
52
  ## Source
51
53
 
52
- `pwn/plugins/doctor.rb`
54
+ `pwn/plugins/preflight_checker.rb`
53
55
 
54
56
  ## Verification
55
57
 
56
- `PWN::Plugins::Doctor.respond_to?(:required_bins)` after the
58
+ `PWN::Plugins::PreflightChecker.respond_to?(:required_bins)` after the
57
59
  module is loaded. Read the source for parameter names.
@@ -35,6 +35,7 @@ PWN::Plugins::ProcessTube.required_bins(opts)
35
35
 
36
36
  - `required_bins`
37
37
  - `spawn`
38
+ - `connect`
38
39
  - `write_line`
39
40
  - `recvuntil`
40
41
  - `recvline`
@@ -38,6 +38,8 @@ PWN::Plugins::Recon.required_bins(opts)
38
38
  - `httpx`
39
39
  - `masscan`
40
40
  - `crt_sh`
41
+ - `amass`
42
+ - `passive_dns`
41
43
  - `authors`
42
44
  - `help`
43
45
 
@@ -3,3 +3,4 @@
3
3
  - https://api.certspotter.com/v1/issuances?domain=#{URI.encode_www_form_component(domain
4
4
  - https://crt.sh/?q=#{URI.encode_www_form_component(domain
5
5
  - https://crt.sh/?q=#{URI.encode_www_form_component(
6
+ - https://api.hackertarget.com/hostsearch/?q=#{URI.encode_www_form_component(domain
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: pwn-plugins-semgrep
3
+ description: Drive PWN::Plugins::Semgrep from pwn_eval.
4
+ license: MIT
5
+ allowed-tools: [pwn, pwn_eval]
6
+ metadata:
7
+ bundled: true
8
+ generated: true
9
+ module: PWN::Plugins::Semgrep
10
+ source: pwn/plugins/semgrep.rb
11
+ ---
12
+
13
+ # PWN::Plugins::Semgrep
14
+
15
+ semgrep wrapper feeding SAST-shaped findings.
16
+
17
+ ## When to use
18
+
19
+ Call `PWN::Plugins::Semgrep` from `pwn_eval` when the task needs this module.
20
+ Do not reimplement it in shell.
21
+
22
+ ## Methodologies
23
+
24
+ Generated from `pwn/plugins/semgrep.rb`. Prefer the public class methods below.
25
+ Class methods take `(opts = {})` and read `opts`.
26
+
27
+ ## How to call
28
+
29
+ ```ruby
30
+ PWN::Plugins::Semgrep.help
31
+ PWN::Plugins::Semgrep.required_bins(opts)
32
+ ```
33
+
34
+ ## Public methods
35
+
36
+ - `required_bins`
37
+ - `scan`
38
+ - `authors`
39
+ - `help`
40
+
41
+ ## Source
42
+
43
+ `pwn/plugins/semgrep.rb`
44
+
45
+ ## Verification
46
+
47
+ `PWN::Plugins::Semgrep.respond_to?(:required_bins)` after the
48
+ module is loaded. Read the source for parameter names.
@@ -35,6 +35,7 @@ PWN::Plugins::Volatility.required_bins(opts)
35
35
 
36
36
  - `required_bins`
37
37
  - `run`
38
+ - `yara`
38
39
  - `authors`
39
40
  - `help`
40
41
 
@@ -28,11 +28,12 @@ Class methods take `(opts = {})` and read `opts`.
28
28
 
29
29
  ```ruby
30
30
  PWN::Setup.help
31
- PWN::Setup.pkg_manager(opts)
31
+ PWN::Setup.packages_for(opts)
32
32
  ```
33
33
 
34
34
  ## Public methods
35
35
 
36
+ - `packages_for`
36
37
  - `pkg_manager`
37
38
  - `check`
38
39
  - `deps`
@@ -49,5 +50,5 @@ PWN::Setup.pkg_manager(opts)
49
50
 
50
51
  ## Verification
51
52
 
52
- `PWN::Setup.respond_to?(:pkg_manager)` after the
53
+ `PWN::Setup.respond_to?(:packages_for)` after the
53
54
  module is loaded. Read the source for parameter names.
@@ -199,7 +199,7 @@ module PWN
199
199
  eval_s = ToolGuard.deadline_s(kind: :eval) if defined?(ToolGuard)
200
200
  shell_s = ToolGuard.deadline_s(kind: :shell) if defined?(ToolGuard)
201
201
  load_line = "load1=#{snap[:load1]} ncpu=#{snap[:ncpu]} mem_avail_mb=#{snap[:mem_avail_mb]}"
202
- doc = (PWN::Plugins::Doctor.host_summary if defined?(PWN::Plugins::Doctor))
202
+ doc = (PWN::Plugins::PreflightChecker.host_summary if defined?(PWN::Plugins::PreflightChecker))
203
203
  "#{load_line} pwn_eval/shell timeout = conservative seconds for this host " \
204
204
  "(defaults eval=#{eval_s || 20}s shell=#{shell_s || 30}s, clamped). " \
205
205
  "#{doc}"
@@ -31,7 +31,14 @@ PWN::AI::Agent::Registry.register(
31
31
  limit: args[:limit] || 12,
32
32
  exclude_session_id: exclude,
33
33
  include_current: args[:include_current] == true
34
- )
34
+ ).tap do |hits|
35
+ sid = exclude.to_s
36
+ next if sid.empty? || !defined?(PWN::Plugins::ArtifactRegistry)
37
+
38
+ artifacts = PWN::Plugins::ArtifactRegistry.list(session_id: sid)
39
+ hits[:artifacts] = artifacts if hits.is_a?(Hash)
40
+ hits << { artifacts: artifacts } if hits.is_a?(Array) && artifacts.any?
41
+ end
35
42
  }
36
43
  )
37
44
 
data/lib/pwn/ffi/stdio.rb CHANGED
@@ -34,7 +34,9 @@ module PWN
34
34
  # Display Usage for this Module
35
35
 
36
36
  public_class_method def self.help
37
- puts "USAGE:
37
+ # libc `puts` is attached on this module; use Kernel so $stdout capture
38
+ # (rspec help_contract) and the REPL both see Ruby IO, not fd 1 raw.
39
+ Kernel.puts "USAGE:
38
40
  # Run available and return its result
39
41
  #{self}.available?
40
42
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'open3'
4
+ require 'digest'
4
5
 
5
6
  module PWN
6
7
  module Plugins
@@ -11,7 +12,7 @@ module PWN
11
12
  end
12
13
 
13
14
  public_class_method def self.fuzz(opts = {})
14
- PWN::Plugins::Doctor.require_bin!(name: 'afl-fuzz')
15
+ PWN::Plugins::PreflightChecker.require_bin!(name: 'afl-fuzz')
15
16
  in_dir = opts[:in_dir] || opts[:corpus]
16
17
  out_dir = opts[:out_dir] || opts[:output]
17
18
  target = opts[:target]
@@ -23,6 +24,19 @@ module PWN
23
24
  { stdout: stdout, stderr: stderr, exit: status.exitstatus }
24
25
  end
25
26
 
27
+ public_class_method def self.crash_triage(opts = {})
28
+ out_dir = (opts[:out_dir] || opts[:output]).to_s
29
+ raise 'ERROR: out_dir is required' if out_dir.empty?
30
+
31
+ crashes = Dir[File.join(out_dir, '**/crashes/id:*')]
32
+ hashes = crashes.map { |p| [p, Digest::SHA256.file(p).hexdigest] }
33
+ {
34
+ crashes: crashes,
35
+ unique: hashes.map(&:last).uniq,
36
+ asan: crashes.any? { |p| File.binread(p).include?('AddressSanitizer') }
37
+ }
38
+ end
39
+
26
40
  public_class_method def self.authors
27
41
  "AUTHOR(S):\n 0day Inc. <support@0dayinc.com>\n"
28
42
  end
@@ -42,6 +56,12 @@ module PWN
42
56
  args: 'optional - Array args value consumed by #fuzz'
43
57
  )
44
58
 
59
+ # Dedup AFL++ crash files by sha256 and note AddressSanitizer hits.
60
+ #{self}.crash_triage(
61
+ out_dir: 'required - AFL output directory containing crashes/',
62
+ output: 'optional - alias for out_dir'
63
+ )
64
+
45
65
  # Print the AUTHOR(S) string for this module.
46
66
  #{self}.authors
47
67
  "
@@ -1286,16 +1286,22 @@ module PWN
1286
1286
  decoded = File.join(out, 'apktool')
1287
1287
  jadx_out = File.join(out, 'jadx')
1288
1288
  steps = []
1289
- if PWN::Plugins::Doctor.bin?(name: 'apktool')
1289
+ if PWN::Plugins::PreflightChecker.bin?(name: 'apktool')
1290
1290
  system('apktool', 'd', '-f', '-o', decoded, apk)
1291
1291
  steps << :apktool
1292
1292
  end
1293
- if PWN::Plugins::Doctor.bin?(name: 'jadx')
1293
+ if PWN::Plugins::PreflightChecker.bin?(name: 'jadx')
1294
1294
  FileUtils.mkdir_p(jadx_out)
1295
1295
  system('jadx', '-d', jadx_out, apk)
1296
1296
  steps << :jadx
1297
1297
  end
1298
- { out_dir: out, steps: steps, apk: apk }
1298
+ manifest = File.join(decoded, 'AndroidManifest.xml')
1299
+ perms = []
1300
+ if File.file?(manifest)
1301
+ txt = File.read(manifest)
1302
+ perms = txt.scan(/android:name="([^"]+)"/).flatten.grep(/PERMISSION|permission/)
1303
+ end
1304
+ { out_dir: out, steps: steps, apk: apk, permissions: perms, manifest: (File.file?(manifest) ? manifest : nil) }
1299
1305
  end
1300
1306
 
1301
1307
  # Author(s):: 0day Inc. <support@0dayinc.com>