gyntoolkit 2.1.1__tar.gz → 2.3.0__tar.gz

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 (42) hide show
  1. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/PKG-INFO +75 -9
  2. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/README.md +74 -8
  3. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/__init__.py +22 -5
  4. gyntoolkit-2.3.0/gyntoolkit/audit.py +162 -0
  5. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/brute.py +6 -2
  6. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/cli.py +154 -6
  7. gyntoolkit-2.3.0/gyntoolkit/commands.py +358 -0
  8. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/config.py +2 -0
  9. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/core.py +1 -1
  10. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/export.py +90 -1
  11. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/i18n.py +79 -3
  12. gyntoolkit-2.3.0/gyntoolkit/mailsec.py +159 -0
  13. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/recon.py +101 -0
  14. gyntoolkit-2.3.0/gyntoolkit/scan.py +480 -0
  15. gyntoolkit-2.3.0/gyntoolkit/web.py +125 -0
  16. gyntoolkit-2.3.0/gyntoolkit/wordlist.py +103 -0
  17. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit.egg-info/PKG-INFO +75 -9
  18. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit.egg-info/SOURCES.txt +15 -1
  19. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/pyproject.toml +1 -1
  20. gyntoolkit-2.3.0/tests/test_audit.py +94 -0
  21. gyntoolkit-2.3.0/tests/test_brute.py +30 -0
  22. gyntoolkit-2.3.0/tests/test_commands.py +56 -0
  23. gyntoolkit-2.3.0/tests/test_cve_enrich.py +116 -0
  24. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/tests/test_export.py +35 -0
  25. gyntoolkit-2.3.0/tests/test_mailsec.py +109 -0
  26. gyntoolkit-2.3.0/tests/test_scan_parse.py +47 -0
  27. gyntoolkit-2.3.0/tests/test_shodan.py +44 -0
  28. gyntoolkit-2.3.0/tests/test_web.py +67 -0
  29. gyntoolkit-2.3.0/tests/test_wordlist.py +69 -0
  30. gyntoolkit-2.1.1/gyntoolkit/scan.py +0 -150
  31. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/LICENSE +0 -0
  32. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/__main__.py +0 -0
  33. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/ui.py +0 -0
  34. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit/utils.py +0 -0
  35. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit.egg-info/dependency_links.txt +0 -0
  36. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit.egg-info/entry_points.txt +0 -0
  37. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit.egg-info/requires.txt +0 -0
  38. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/gyntoolkit.egg-info/top_level.txt +0 -0
  39. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/setup.cfg +0 -0
  40. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/tests/test_config.py +0 -0
  41. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/tests/test_i18n.py +0 -0
  42. {gyntoolkit-2.1.1 → gyntoolkit-2.3.0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gyntoolkit
3
- Version: 2.1.1
3
+ Version: 2.3.0
4
4
  Summary: Canivete suíço de pentest — recon, port scan, CVE lookup e brute force.
5
5
  Author: PH, Fl4vs
6
6
  License-Expression: MIT
@@ -49,7 +49,7 @@ Dynamic: license-file
49
49
  ██████╗██╗ ██╗███╗ ██╗ ████████╗ ██████╗ ██████╗ ██╗ ██╗ ██╗██╗████████╗
50
50
  ██╔════╝╚██╗ ██╔╝████╗ ██║ ╚══██╔══╝██╔═══██╗██╔═══██╗██║ ██║ ██╔╝██║╚══██╔══╝
51
51
  ██║ ███╗╚████╔╝ ██╔██╗ ██║ ██║ ██║ ██║██║ ██║██║ █████╔╝ ██║ ██║
52
- ██║ ██║ ╚██╔╝ ██║╚██╗██║ ██║ ██║ ██║██║ ██║██║ ██╔═██╗ ██║ ██║ v2.1
52
+ ██║ ██║ ╚██╔╝ ██║╚██╗██║ ██║ ██║ ██║██║ ██║██║ ██╔═██╗ ██║ ██║ v2.3
53
53
  ╚██████╔╝ ██║ ██║ ╚████║ ██║ ╚██████╔╝╚██████╔╝███████╗██║ ██╗██║ ██║ by: PH,Fl4vs
54
54
  ╚═════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝
55
55
  ```
@@ -124,23 +124,34 @@ Dynamic: license-file
124
124
  | 9 | **HIBP Breach Check** | Domain → known breaches via Have I Been Pwned |
125
125
  | 10 | **MAC Vendor Lookup** | `api.macvendors.com` — OUI → vendor |
126
126
  | 11 | **Traceroute (TCP)** | `scapy` — hops + RTT (needs privilege) |
127
+ | 12 | **DNS Zone Transfer (AXFR)** | `dnspython` — tries AXFR against each authoritative NS |
128
+ | 13 | **Web Content Discovery** | `aiohttp` — robots.txt / sitemap / security.txt + built-in path wordlist |
129
+ | 14 | **Shodan Host** | Full `api.shodan.io` host lookup (ports, CPEs, CVEs, tags) — needs `api_keys.shodan`; falls back to InternetDB hint without a key |
130
+ | 15 | **Email Security** | `dnspython` — SPF, DKIM, DMARC, DNSSEC and CAA analyzer with per-item verdict (`ok`/`weak`/`missing`) |
127
131
 
128
132
  ### `[2]` Brute Force
129
133
 
130
134
  | # | Module | Details |
131
135
  |---|--------|---------|
132
- | 1 | **CUPP wordlist** | Wrapper for `cupp.py -i` — custom wordlist generator |
133
- | 2 | **SSH brute** | `paramiko`, async via `asyncio.to_thread`, concurrency `Semaphore`, delay |
134
- | 3 | **HTTP brute** | `aiohttp` — Basic Auth or form POST with configurable `fail_signature` |
136
+ | 1 | **Native wordlist** | Built-in CUPP-style generator (offline, no external clone) — case/leet variants, years, suffixes, term combos |
137
+ | 2 | **CUPP wordlist** | Optional wrapper for `cupp.py -i` |
138
+ | 3 | **SSH brute** | `paramiko`, async via `asyncio.to_thread`, concurrency `Semaphore`, delay |
139
+ | 4 | **HTTP brute** | `aiohttp` — Basic Auth or form POST with configurable `fail_signature` |
135
140
 
136
- > Every attack requires typing `AUTORIZO` to confirm — no silent bypass.
141
+ > Every attack requires typing the authorization word (`AUTHORIZE` / `AUTORIZO`)
142
+ > to confirm — no silent bypass.
137
143
 
138
144
  ### `[3]` Advanced Scanning
139
145
 
140
146
  - **Port scan** — fast (Top 21 common ports) or full (1–65535)
141
147
  - **SYN scan** (stealth) when privileged, automatic fallback to **TCP connect**
142
148
  - **Banner grabbing** — async, parallel
143
- - **CVE analysis** per service via **NVD API v2.0**
149
+ - **CVE analysis** per service via **NVD API v2.0** — parses product + version
150
+ from the banner and matches by **CPE** (`virtualMatchString`), falling back to
151
+ keyword search; rate-limited and deduplicated per banner
152
+ - **Risk scoring** — each CVE is enriched with **CVSS** base score/severity,
153
+ **EPSS** exploitation probability and a **CISA KEV** flag; host risk is the
154
+ highest severity found (KEV forces critical). Filter with `--min-cvss` / `--kev-only`
144
155
  - **Host discovery** (ARP scan) by CIDR — e.g. `192.168.0.0/24`
145
156
  - Automatic risk classification based on CVEs found
146
157
 
@@ -154,6 +165,12 @@ Dynamic: license-file
154
165
  | 4 | **Base64 decode** | base64 → UTF-8 with auto-padding |
155
166
  | 5 | **JWT decode** | Header + payload without signature verification |
156
167
 
168
+ ### `[5]` Audit — one target, consolidated profile
169
+
170
+ Orchestrates the recon modules (and, with `--active --authorize`, the port scan)
171
+ into a **single report** with an executive summary. Passive by default; stage
172
+ selection via `--only` / `--skip`. See the [CLI examples](#non-interactive-cli-scriptable).
173
+
157
174
  ---
158
175
 
159
176
  ## Installation
@@ -203,6 +220,55 @@ An interactive dark CLI opens with a numbered menu. Commands are entered at the
203
220
 
204
221
  ---
205
222
 
223
+ ## Non-interactive CLI (scriptable)
224
+
225
+ Pass a subcommand to run a single action and print the result as JSON on stdout
226
+ (pipe-friendly) — no menu. Omit the subcommand to open the interactive menu.
227
+
228
+ ```bash
229
+ gyntoolkit recon dns example.com --type MX # DNS lookup
230
+ gyntoolkit recon axfr example.com # zone transfer attempt
231
+ gyntoolkit recon webscan http://example.com # web content discovery
232
+ gyntoolkit recon shodan 1.1.1.1 # Shodan host (needs api_keys.shodan)
233
+ gyntoolkit recon ssl example.com --port 443 # TLS cert
234
+ gyntoolkit scan 127.0.0.1 --type fast # port scan + CVEs (CVSS/EPSS/KEV)
235
+ gyntoolkit scan 10.0.0.5 --min-cvss 7.0 --kev-only # only high-risk / actively exploited
236
+ gyntoolkit scan 192.168.0.0/24 # host discovery (CIDR)
237
+ gyntoolkit audit example.com # full passive profile → one report
238
+ gyntoolkit audit 10.0.0.5 --active --authorize # + active port scan (authorized)
239
+ gyntoolkit utils hash "text" --algo sha1
240
+ gyntoolkit utils jwt <token>
241
+ gyntoolkit wordlist --terms alice,fluffy,acme --years 1990,2020 --leet --save wl.txt
242
+ ```
243
+
244
+ `audit` runs a pipeline over one target and consolidates everything into a single
245
+ report with an executive summary. It is **passive by default** (WHOIS, DNS, geo,
246
+ subdomains, TLS, HTTP fingerprint, InternetDB, HIBP, email security); the active
247
+ port scan only runs with `--active --authorize`. Narrow it with `--only a,b` or
248
+ `--skip a,b`.
249
+
250
+ Global flags (place after the subcommand): `-o/--output DIR` saves a report,
251
+ `-f/--format {json,html,csv,md}` picks its format, `-q/--quiet` silences stdout,
252
+ `--lang {en,pt}` overrides the language.
253
+
254
+ ```bash
255
+ gyntoolkit scan scanme.example.com -o reports -f md # also save a Markdown report
256
+ gyntoolkit recon geo 1.1.1.1 -o reports -f csv -q # CSV only, no stdout
257
+ ```
258
+
259
+ Active attacks are available but require explicit authorization:
260
+
261
+ ```bash
262
+ gyntoolkit brute ssh HOST --users users.txt --passwords pass.txt --authorize
263
+ gyntoolkit brute http URL --users admin --passwords pass.txt --mode form \
264
+ --user-field user --pass-field pass --fail-signature "Invalid" --authorize
265
+ ```
266
+
267
+ Without `--authorize`, brute subcommands abort — you confirm you have **written
268
+ authorization** for the target.
269
+
270
+ ---
271
+
206
272
  ## Example
207
273
 
208
274
  Target: the **local security lab** (never a third-party system).
@@ -256,8 +322,8 @@ Full walkthrough: [`docs/security-lab.md`](docs/security-lab.md) and
256
322
 
257
323
  ## Reports
258
324
 
259
- After scans and recon lookups, the CLI offers to export results as **JSON** or a
260
- dark-themed **HTML report**. Files are written to
325
+ After scans and recon lookups, the CLI offers to export results as **JSON**, a
326
+ dark-themed **HTML report**, **CSV** or **Markdown**. Files are written to
261
327
  `reports/<module>-<timestamp>.<fmt>` (configurable via `export.dir`; set
262
328
  `export.auto: true` to export without prompting). Details in
263
329
  [`docs/reports.md`](docs/reports.md).
@@ -6,7 +6,7 @@
6
6
  ██████╗██╗ ██╗███╗ ██╗ ████████╗ ██████╗ ██████╗ ██╗ ██╗ ██╗██╗████████╗
7
7
  ██╔════╝╚██╗ ██╔╝████╗ ██║ ╚══██╔══╝██╔═══██╗██╔═══██╗██║ ██║ ██╔╝██║╚══██╔══╝
8
8
  ██║ ███╗╚████╔╝ ██╔██╗ ██║ ██║ ██║ ██║██║ ██║██║ █████╔╝ ██║ ██║
9
- ██║ ██║ ╚██╔╝ ██║╚██╗██║ ██║ ██║ ██║██║ ██║██║ ██╔═██╗ ██║ ██║ v2.1
9
+ ██║ ██║ ╚██╔╝ ██║╚██╗██║ ██║ ██║ ██║██║ ██║██║ ██╔═██╗ ██║ ██║ v2.3
10
10
  ╚██████╔╝ ██║ ██║ ╚████║ ██║ ╚██████╔╝╚██████╔╝███████╗██║ ██╗██║ ██║ by: PH,Fl4vs
11
11
  ╚═════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝
12
12
  ```
@@ -81,23 +81,34 @@
81
81
  | 9 | **HIBP Breach Check** | Domain → known breaches via Have I Been Pwned |
82
82
  | 10 | **MAC Vendor Lookup** | `api.macvendors.com` — OUI → vendor |
83
83
  | 11 | **Traceroute (TCP)** | `scapy` — hops + RTT (needs privilege) |
84
+ | 12 | **DNS Zone Transfer (AXFR)** | `dnspython` — tries AXFR against each authoritative NS |
85
+ | 13 | **Web Content Discovery** | `aiohttp` — robots.txt / sitemap / security.txt + built-in path wordlist |
86
+ | 14 | **Shodan Host** | Full `api.shodan.io` host lookup (ports, CPEs, CVEs, tags) — needs `api_keys.shodan`; falls back to InternetDB hint without a key |
87
+ | 15 | **Email Security** | `dnspython` — SPF, DKIM, DMARC, DNSSEC and CAA analyzer with per-item verdict (`ok`/`weak`/`missing`) |
84
88
 
85
89
  ### `[2]` Brute Force
86
90
 
87
91
  | # | Module | Details |
88
92
  |---|--------|---------|
89
- | 1 | **CUPP wordlist** | Wrapper for `cupp.py -i` — custom wordlist generator |
90
- | 2 | **SSH brute** | `paramiko`, async via `asyncio.to_thread`, concurrency `Semaphore`, delay |
91
- | 3 | **HTTP brute** | `aiohttp` — Basic Auth or form POST with configurable `fail_signature` |
93
+ | 1 | **Native wordlist** | Built-in CUPP-style generator (offline, no external clone) — case/leet variants, years, suffixes, term combos |
94
+ | 2 | **CUPP wordlist** | Optional wrapper for `cupp.py -i` |
95
+ | 3 | **SSH brute** | `paramiko`, async via `asyncio.to_thread`, concurrency `Semaphore`, delay |
96
+ | 4 | **HTTP brute** | `aiohttp` — Basic Auth or form POST with configurable `fail_signature` |
92
97
 
93
- > Every attack requires typing `AUTORIZO` to confirm — no silent bypass.
98
+ > Every attack requires typing the authorization word (`AUTHORIZE` / `AUTORIZO`)
99
+ > to confirm — no silent bypass.
94
100
 
95
101
  ### `[3]` Advanced Scanning
96
102
 
97
103
  - **Port scan** — fast (Top 21 common ports) or full (1–65535)
98
104
  - **SYN scan** (stealth) when privileged, automatic fallback to **TCP connect**
99
105
  - **Banner grabbing** — async, parallel
100
- - **CVE analysis** per service via **NVD API v2.0**
106
+ - **CVE analysis** per service via **NVD API v2.0** — parses product + version
107
+ from the banner and matches by **CPE** (`virtualMatchString`), falling back to
108
+ keyword search; rate-limited and deduplicated per banner
109
+ - **Risk scoring** — each CVE is enriched with **CVSS** base score/severity,
110
+ **EPSS** exploitation probability and a **CISA KEV** flag; host risk is the
111
+ highest severity found (KEV forces critical). Filter with `--min-cvss` / `--kev-only`
101
112
  - **Host discovery** (ARP scan) by CIDR — e.g. `192.168.0.0/24`
102
113
  - Automatic risk classification based on CVEs found
103
114
 
@@ -111,6 +122,12 @@
111
122
  | 4 | **Base64 decode** | base64 → UTF-8 with auto-padding |
112
123
  | 5 | **JWT decode** | Header + payload without signature verification |
113
124
 
125
+ ### `[5]` Audit — one target, consolidated profile
126
+
127
+ Orchestrates the recon modules (and, with `--active --authorize`, the port scan)
128
+ into a **single report** with an executive summary. Passive by default; stage
129
+ selection via `--only` / `--skip`. See the [CLI examples](#non-interactive-cli-scriptable).
130
+
114
131
  ---
115
132
 
116
133
  ## Installation
@@ -160,6 +177,55 @@ An interactive dark CLI opens with a numbered menu. Commands are entered at the
160
177
 
161
178
  ---
162
179
 
180
+ ## Non-interactive CLI (scriptable)
181
+
182
+ Pass a subcommand to run a single action and print the result as JSON on stdout
183
+ (pipe-friendly) — no menu. Omit the subcommand to open the interactive menu.
184
+
185
+ ```bash
186
+ gyntoolkit recon dns example.com --type MX # DNS lookup
187
+ gyntoolkit recon axfr example.com # zone transfer attempt
188
+ gyntoolkit recon webscan http://example.com # web content discovery
189
+ gyntoolkit recon shodan 1.1.1.1 # Shodan host (needs api_keys.shodan)
190
+ gyntoolkit recon ssl example.com --port 443 # TLS cert
191
+ gyntoolkit scan 127.0.0.1 --type fast # port scan + CVEs (CVSS/EPSS/KEV)
192
+ gyntoolkit scan 10.0.0.5 --min-cvss 7.0 --kev-only # only high-risk / actively exploited
193
+ gyntoolkit scan 192.168.0.0/24 # host discovery (CIDR)
194
+ gyntoolkit audit example.com # full passive profile → one report
195
+ gyntoolkit audit 10.0.0.5 --active --authorize # + active port scan (authorized)
196
+ gyntoolkit utils hash "text" --algo sha1
197
+ gyntoolkit utils jwt <token>
198
+ gyntoolkit wordlist --terms alice,fluffy,acme --years 1990,2020 --leet --save wl.txt
199
+ ```
200
+
201
+ `audit` runs a pipeline over one target and consolidates everything into a single
202
+ report with an executive summary. It is **passive by default** (WHOIS, DNS, geo,
203
+ subdomains, TLS, HTTP fingerprint, InternetDB, HIBP, email security); the active
204
+ port scan only runs with `--active --authorize`. Narrow it with `--only a,b` or
205
+ `--skip a,b`.
206
+
207
+ Global flags (place after the subcommand): `-o/--output DIR` saves a report,
208
+ `-f/--format {json,html,csv,md}` picks its format, `-q/--quiet` silences stdout,
209
+ `--lang {en,pt}` overrides the language.
210
+
211
+ ```bash
212
+ gyntoolkit scan scanme.example.com -o reports -f md # also save a Markdown report
213
+ gyntoolkit recon geo 1.1.1.1 -o reports -f csv -q # CSV only, no stdout
214
+ ```
215
+
216
+ Active attacks are available but require explicit authorization:
217
+
218
+ ```bash
219
+ gyntoolkit brute ssh HOST --users users.txt --passwords pass.txt --authorize
220
+ gyntoolkit brute http URL --users admin --passwords pass.txt --mode form \
221
+ --user-field user --pass-field pass --fail-signature "Invalid" --authorize
222
+ ```
223
+
224
+ Without `--authorize`, brute subcommands abort — you confirm you have **written
225
+ authorization** for the target.
226
+
227
+ ---
228
+
163
229
  ## Example
164
230
 
165
231
  Target: the **local security lab** (never a third-party system).
@@ -213,8 +279,8 @@ Full walkthrough: [`docs/security-lab.md`](docs/security-lab.md) and
213
279
 
214
280
  ## Reports
215
281
 
216
- After scans and recon lookups, the CLI offers to export results as **JSON** or a
217
- dark-themed **HTML report**. Files are written to
282
+ After scans and recon lookups, the CLI offers to export results as **JSON**, a
283
+ dark-themed **HTML report**, **CSV** or **Markdown**. Files are written to
218
284
  `reports/<module>-<timestamp>.<fmt>` (configurable via `export.dir`; set
219
285
  `export.auto: true` to export without prompting). Details in
220
286
  [`docs/reports.md`](docs/reports.md).
@@ -5,9 +5,10 @@ Este ``__init__`` re-exporta a API pública para manter compatibilidade com
5
5
  ``import gyntoolkit as g`` (usado pelo lab E2E) e pelo entry point do pyproject.
6
6
  """
7
7
 
8
- __version__ = "2.1.1"
8
+ __version__ = "2.3.0"
9
9
 
10
10
  from . import i18n, ui
11
+ from .audit import run_audit
11
12
  from .brute import (
12
13
  cupp_generate,
13
14
  http_bruteforce,
@@ -29,7 +30,8 @@ from .core import (
29
30
  sanitize_input,
30
31
  show_menu,
31
32
  )
32
- from .export import export_html, export_json, save_report
33
+ from .export import export_csv, export_html, export_json, export_md, save_report
34
+ from .mailsec import DEFAULT_DKIM_SELECTORS, mailsec_report
33
35
  from .recon import (
34
36
  DNS_TYPES,
35
37
  TECH_SIGNATURES,
@@ -41,20 +43,25 @@ from .recon import (
41
43
  internetdb_lookup,
42
44
  mac_vendor,
43
45
  reverse_dns,
46
+ shodan_host,
44
47
  ssl_inspect,
45
48
  subdomain_enum,
46
49
  traceroute,
47
50
  whois_lookup,
51
+ zone_transfer,
48
52
  )
49
53
  from .scan import (
50
54
  check_vulnerabilities,
51
55
  connect_scan,
52
56
  get_banner,
53
57
  network_discovery,
58
+ parse_service,
54
59
  perform_scan,
55
60
  syn_scan,
56
61
  )
57
62
  from .utils import b64_decode, b64_encode, hash_file, hash_text, jwt_decode
63
+ from .web import COMMON_PATHS, web_discovery
64
+ from .wordlist import generate_wordlist
58
65
 
59
66
  __all__ = [
60
67
  "__version__",
@@ -63,18 +70,28 @@ __all__ = [
63
70
  "clear_screen", "is_admin_windows", "sanitize_input", "show_menu",
64
71
  # scan
65
72
  "syn_scan", "connect_scan", "get_banner", "check_vulnerabilities",
66
- "network_discovery", "perform_scan",
73
+ "parse_service", "network_discovery", "perform_scan",
67
74
  # recon
68
75
  "whois_lookup", "dns_lookup", "geo_ip", "reverse_dns", "subdomain_enum",
69
76
  "ssl_inspect", "http_fingerprint", "internetdb_lookup", "hibp_breaches",
70
- "mac_vendor", "traceroute", "escolher_tipo_dns", "DNS_TYPES", "TECH_SIGNATURES",
77
+ "mac_vendor", "traceroute", "zone_transfer", "shodan_host",
78
+ "escolher_tipo_dns", "DNS_TYPES", "TECH_SIGNATURES",
79
+ # web discovery
80
+ "web_discovery", "COMMON_PATHS",
81
+ # mail security
82
+ "mailsec_report", "DEFAULT_DKIM_SELECTORS",
83
+ # audit
84
+ "run_audit",
85
+ # wordlist
86
+ "generate_wordlist",
71
87
  # brute
72
88
  "print_ethical_warning", "load_wordlist", "cupp_generate",
73
89
  "ssh_bruteforce", "http_bruteforce",
74
90
  # utils
75
91
  "hash_text", "hash_file", "b64_encode", "b64_decode", "jwt_decode",
76
92
  # config / export / ui
77
- "CONFIG", "DEFAULTS", "load_config", "save_report", "export_json", "export_html", "ui", "i18n",
93
+ "CONFIG", "DEFAULTS", "load_config", "save_report",
94
+ "export_json", "export_html", "export_csv", "export_md", "ui", "i18n",
78
95
  # cli
79
96
  "main_flow", "main_entry",
80
97
  ]
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env python3
2
+ """Audit: orquestrador de engajamento — 1 alvo, perfil consolidado.
3
+
4
+ Roda um pipeline de etapas (recon passivo por padrão; scan ativo só com
5
+ ``active=True`` + ``authorized=True``) e agrega tudo num único relatório com
6
+ resumo executivo. Reaproveita os módulos existentes (recon/scan/mailsec).
7
+
8
+ Etapas são resilientes: a falha de uma registra ``{"error": ...}`` na sua seção
9
+ sem derrubar o resto.
10
+ """
11
+
12
+ import asyncio
13
+ import ipaddress
14
+ import socket
15
+ from datetime import datetime, timezone
16
+ from typing import Any
17
+
18
+ from .core import log, sanitize_input
19
+
20
+ # Etapas passivas (seguras) e ativas (intrusivas). Ordem define a saída.
21
+ PASSIVE_STAGES = ("whois", "dns", "geo", "subdomains", "ssl", "httpfp",
22
+ "internetdb", "hibp", "mailsec")
23
+ ACTIVE_STAGES = ("scan",)
24
+ ALL_STAGES = PASSIVE_STAGES + ACTIVE_STAGES
25
+
26
+ # Etapas que só fazem sentido p/ domínio (não p/ IP literal).
27
+ _DOMAIN_ONLY = {"whois", "subdomains", "hibp", "mailsec"}
28
+
29
+
30
+ def _is_ip(target: str) -> bool:
31
+ try:
32
+ ipaddress.ip_address(target)
33
+ return True
34
+ except ValueError:
35
+ return False
36
+
37
+
38
+ def _resolve(target: str) -> str | None:
39
+ try:
40
+ return socket.gethostbyname(target)
41
+ except socket.gaierror:
42
+ return None
43
+
44
+
45
+ # --------------------------------------------------------------------------
46
+ # Runners por etapa.
47
+ # --------------------------------------------------------------------------
48
+ def _passive_stage(name: str, target: str, ctx: dict) -> Any:
49
+ """Executa uma etapa passiva (síncrona: requests/dns). Roda em thread."""
50
+ from . import recon
51
+ from .mailsec import mailsec_report
52
+
53
+ is_ip = ctx["is_ip"]
54
+ if name == "whois":
55
+ return {"whois": str(recon.whois_lookup(target))}
56
+ if name == "dns":
57
+ return {t: recon.dns_lookup(target, t) for t in ("A", "MX", "NS", "TXT")}
58
+ if name == "geo":
59
+ return recon.geo_ip(target)
60
+ if name == "subdomains":
61
+ subs = recon.subdomain_enum(target)
62
+ return {"total": len(subs), "subdomains": subs}
63
+ if name == "ssl":
64
+ return recon.ssl_inspect(target, 443)
65
+ if name == "httpfp":
66
+ scheme = "http" if is_ip else "https"
67
+ return recon.http_fingerprint(f"{scheme}://{target}")
68
+ if name == "internetdb":
69
+ return recon.internetdb_lookup(target)
70
+ if name == "hibp":
71
+ return {"breaches": recon.hibp_breaches(target)}
72
+ if name == "mailsec":
73
+ return mailsec_report(target)
74
+ raise ValueError(f"unknown passive stage: {name}")
75
+
76
+
77
+ async def _run_one(name: str, target: str, ctx: dict) -> tuple[str, Any]:
78
+ """Executa uma etapa com captura de erro. Passivas rodam em thread."""
79
+ try:
80
+ if name == "scan":
81
+ from .scan import perform_scan
82
+
83
+ ip = target if ctx["is_ip"] else (_resolve(target) or target)
84
+ results = await perform_scan(
85
+ ip, ctx["scan_type"], concurrency=ctx["concurrency"], nvd_api_key=ctx["nvd_key"],
86
+ )
87
+ return (name, {str(port): data for port, data in results.items()})
88
+ return (name, await asyncio.to_thread(_passive_stage, name, target, ctx))
89
+ except Exception as e: # noqa: BLE001 - etapa resiliente
90
+ log.warning("audit stage '%s' falhou: %s", name, e)
91
+ return (name, {"error": str(e)})
92
+
93
+
94
+ def _select_stages(is_ip: bool, active: bool, only: list[str] | None,
95
+ skip: list[str] | None) -> list[str]:
96
+ """Resolve a lista final de etapas conforme tipo de alvo e flags."""
97
+ stages = list(PASSIVE_STAGES) + (list(ACTIVE_STAGES) if active else [])
98
+ if only:
99
+ wanted = set(only)
100
+ stages = [s for s in ALL_STAGES if s in wanted and (active or s not in ACTIVE_STAGES)]
101
+ if skip:
102
+ stages = [s for s in stages if s not in set(skip)]
103
+ if is_ip:
104
+ stages = [s for s in stages if s not in _DOMAIN_ONLY]
105
+ return stages
106
+
107
+
108
+ def _summarize(stages_out: dict) -> dict:
109
+ """Resumo executivo: contagens e destaques das seções coletadas."""
110
+ summary: dict[str, Any] = {}
111
+ scan = stages_out.get("scan")
112
+ if isinstance(scan, dict) and "error" not in scan:
113
+ open_ports = list(scan.keys())
114
+ cves = [c for port in scan.values() for c in port.get("vulnerabilidades", [])]
115
+ kev = [c for c in cves if c.get("kev")]
116
+ summary["open_ports"] = len(open_ports)
117
+ summary["cves"] = len(cves)
118
+ summary["kev_cves"] = len(kev)
119
+ subs = stages_out.get("subdomains")
120
+ if isinstance(subs, dict) and "total" in subs:
121
+ summary["subdomains"] = subs["total"]
122
+ mail = stages_out.get("mailsec")
123
+ if isinstance(mail, dict) and "summary" in mail:
124
+ summary["mailsec_weak"] = mail["summary"].get("weak", 0) + mail["summary"].get("missing", 0)
125
+ return summary
126
+
127
+
128
+ async def run_audit(
129
+ target: str,
130
+ active: bool = False,
131
+ authorized: bool = False,
132
+ only: list[str] | None = None,
133
+ skip: list[str] | None = None,
134
+ concurrency: int = 100,
135
+ nvd_key: str = "",
136
+ scan_type: str = "fast",
137
+ ) -> dict:
138
+ """Roda o audit e devolve o relatório consolidado.
139
+
140
+ Etapas ativas (scan) só rodam com ``active=True`` **e** ``authorized=True`` —
141
+ autorização é exigida p/ qualquer ação intrusiva.
142
+ """
143
+ target = sanitize_input(target, r"[A-Za-z0-9.:/-]")
144
+ is_ip = _is_ip(target)
145
+ run_active = active and authorized
146
+ ctx = {"is_ip": is_ip, "concurrency": concurrency, "nvd_key": nvd_key, "scan_type": scan_type}
147
+
148
+ stages = _select_stages(is_ip, run_active, only, skip)
149
+ results = await asyncio.gather(*[_run_one(s, target, ctx) for s in stages])
150
+ stages_out = dict(results)
151
+ # reordena conforme ALL_STAGES p/ saída estável
152
+ ordered = {s: stages_out[s] for s in ALL_STAGES if s in stages_out}
153
+
154
+ return {
155
+ "target": target,
156
+ "is_ip": is_ip,
157
+ "active": run_active,
158
+ "active_requested_without_auth": active and not authorized,
159
+ "generated": datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC"),
160
+ "summary": _summarize(ordered),
161
+ "stages": ordered,
162
+ }
@@ -21,7 +21,9 @@ def print_ethical_warning(action: str) -> bool:
21
21
  print(f"{Fore.RED}{i18n.t('brute.warn_crime')}{Style.RESET_ALL}")
22
22
  print(f"{Fore.RED}{'=' * 60}{Style.RESET_ALL}")
23
23
  confirm = input(f"{Fore.YELLOW}{i18n.t('brute.confirm')}{Style.RESET_ALL}").strip()
24
- return confirm == "AUTORIZO"
24
+ # Aceita a palavra localizada (en/pt) e o legado "AUTORIZO" como alias.
25
+ accepted = {i18n.t("brute.confirm_word").strip().upper(), "AUTORIZO"}
26
+ return confirm.upper() in accepted
25
27
 
26
28
 
27
29
  def load_wordlist(path: str) -> list[str]:
@@ -158,7 +160,9 @@ async def http_bruteforce(
158
160
  if mode == "basic":
159
161
  auth = aiohttp.BasicAuth(u, p)
160
162
  async with session.get(url, auth=auth) as r:
161
- ok = r.status not in (401, 403)
163
+ # Basic Auth: sucesso = 2xx. 401/403 = falha; 404/5xx
164
+ # NÃO são credencial válida (evita falso-positivo).
165
+ ok = 200 <= r.status < 300
162
166
  else:
163
167
  payload = {user_field: u, pass_field: p}
164
168
  async with session.post(url, data=payload, allow_redirects=False) as r: