Skip to content

Commit 970e36a

Browse files
committed
refactor: improve typing, logging, and privilege handling
- Add comprehensive type annotations with version-aware typing - Implement module-specific logging throughout application - Improve privilege detection to support sudo users (not just root UID=0) - Enhance subprocess cleanup and asyncio cancellation handling - Add clean exception hierarchy with NmapError base class - Remove redundant code while maintaining full backward compatibility
1 parent 52a52a9 commit 970e36a

File tree

10 files changed

+541
-279
lines changed

10 files changed

+541
-279
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,4 @@ venv.bak/
102102

103103
# mypy
104104
.mypy_cache/
105+
PR*

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"python.analysis.typeCheckingMode": "standard"
3+
}

README.md

Lines changed: 98 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,35 @@
11

2-
32
# python3-nmap
43

54
A python 3 library which helps in using nmap port scanner. The way this tools works is by defining each nmap command into a python function making it very easy to use sophisticated nmap commands in other python scripts. Nmap is a complicated piece of software used for reconnaissance on target networks, over the years new features have been added making it more sophisticated.
65

76
With this python3-nmap we make using nmap in python very easy and painless
87

98
For example in nmap if you want to scan for common ports you would to something like this
9+
1010
```sh
11-
$ nmap your-host.com --top-ports 10
11+
nmap your-host.com --top-ports 10
1212
```
13+
1314
But in this python3-nmap script you would do something like this
15+
1416
```py
1517
import nmap3
1618
nmap = nmap3.Nmap()
1719
results = nmap.scan_top_ports("your-host.com")
1820
# And you would get your results in json
1921
```
22+
2023
You will notice each nmap command is defined as a python function/method. this make it easy to remember this in python and easily use them.
2124

2225
Again in nmap if you want to use the famous dns-brute script you would do something like this
26+
2327
```sh
24-
$ nmap your-host.com --script dns-brute.nse
28+
nmap your-host.com --script dns-brute.nse
2529
```
30+
2631
But in this python3 script again it's very easy you just do something like this
32+
2733
```py
2834
import nmap3
2935
nmap = nmap3.Nmap()
@@ -43,9 +49,11 @@ results = nmap.nmap_dns_brute_script("your-host.com")
4349
```
4450

4551
#### How to use python3-nmap
52+
4653
Using this scripts is very easy, though it assumes you have nmap already installed, as it is the primary dependence required. Also this tools supports both windows and linux, it's cross platform so to say.
4754

4855
**Installation**
56+
4957
```sh
5058
$ git clone https://github.com/wangoloj/python3-nmap.git
5159

@@ -57,7 +65,9 @@ $ apt-get install nmap
5765

5866
# That's all is needed to get started
5967
```
68+
6069
In nmap some commands require root privileges for example the command to identify OS requires root privileges;
70+
6171
```sh
6272
$ nmap -O your-host.com
6373

@@ -68,14 +78,17 @@ QUITTING!
6878
$ sudo nmap -O your-host.com
6979

7080
```
81+
7182
The same applies to the script to be able to run the os identifier you have to be a super user.
7283

7384
### How to use the script to identify OS
85+
7486
```py
7587
import nmap3
7688
nmap = nmap3.Nmap()
7789
os_results = nmap.nmap_os_detection("192.168.178.2") # MOST BE ROOT
7890
```
91+
7992
```json
8093
[
8194
{
@@ -134,23 +147,29 @@ os_results = nmap.nmap_os_detection("192.168.178.2") # MOST BE ROOT
134147
```
135148

136149
### Class components of python3-nmap
150+
137151
The script is made of up the following classes, each holding different nmap abilities and scan types.
138152

139-
- Nmap
140-
- NmapHostDiscovery
141-
- NmapScanTechniques
153+
- Nmap
154+
- NmapHostDiscovery
155+
- NmapScanTechniques
142156

143157
### Identifying service version
158+
144159
In nmap if you want to identify versions you would run this kind of command
160+
145161
```sh
146-
$ nmap 192.168.178.1 -sV
162+
nmap 192.168.178.1 -sV
147163
```
164+
148165
In this python script you would do something like this
166+
149167
```py
150168
import nmap3
151169
nmap = nmap3.Nmap()
152170
version_result = nmap.nmap_version_detection("your-host.com")
153171
```
172+
154173
```json
155174
[
156175
{
@@ -210,121 +229,157 @@ version_result = nmap.nmap_version_detection("your-host.com")
210229
}
211230
]
212231
```
232+
213233
### Nmap commands available
234+
214235
The following nmaps commands have been added to the following scripts
215236

216-
- get Nmap version details
237+
- get Nmap version details
238+
217239
```python
218240
import nmap3
219241
nmap = nmap3.Nmap()
220242
results = nmap.nmap_version()
221243
```
222-
- Nmap top port scan
244+
245+
- Nmap top port scan
246+
223247
```python
224248
import nmap3
225249
nmap = nmap3.Nmap()
226250
results = nmap.scan_top_ports("your-host")
227251
```
228-
- Nmap Dns-brute-script( to get subdomains )
252+
253+
- Nmap Dns-brute-script( to get subdomains )
254+
229255
```python
230256
import nmap3
231257
nmap = nmap3.Nmap()
232258
results = nmap.nmap_dns_brute_script("domain")
233259
```
234-
- Nmap list scan
260+
261+
- Nmap list scan
262+
235263
```python
236264
import nmap3
237265
nmap = nmap3.Nmap()
238266
results = nmap.nmap_list_scan("your-host")
239267
```
240-
- Nmap Os detection
268+
269+
- Nmap Os detection
270+
241271
```python
242272
import nmap3
243273
nmap = nmap3.Nmap()
244274
results = nmap.nmap_os_detection("your-host");
245275
```
246-
- Nmap subnet scan
276+
277+
- Nmap subnet scan
278+
247279
```python
248280
import nmap3
249281
nmap = nmap3.Nmap()
250282
results = nmap.nmap_subnet_scan("your-host") #Must be root
251283
```
252-
- Nmap version detection
284+
285+
- Nmap version detection
286+
253287
```python
254288
import nmap3
255289
nmap = nmap3.Nmap()
256290
results = nmap.nmap_version_detection("your-host") # Must be root
257291
```
258292

259-
### Nmap Scanning Techniques
293+
### Nmap Scanning Techniques
294+
260295
The script offers nmap scan techniques also as python function/methods
261-
- nmap_fin_scan
296+
297+
- nmap_fin_scan
298+
262299
```python
263300
import nmap3
264301
nmap = nmap3.NmapScanTechniques()
265302
result = nmap.nmap_fin_scan("192.168.178.1")
266303
```
267-
268-
- nmap_idle_scan
304+
305+
- nmap_idle_scan
306+
269307
```python
270308
import nmap3
271309
nmap = nmap3.NmapScanTechniques()
272310
result = nmap.nmap_idle_scan("192.168.178.1")
273311
```
274-
- nmap_ping_scan
312+
313+
- nmap_ping_scan
314+
275315
```python
276316
import nmap3
277317
nmap = nmap3.NmapScanTechniques()
278318
result = nmap.nmap_ping_scan("192.168.178.1")
279319
```
280-
- nmap_syn_scan
320+
321+
- nmap_syn_scan
322+
281323
```python
282324
import nmap3
283325
nmap = nmap3.NmapScanTechniques()
284326
result = nmap.nmap_syn_scan("192.168.178.1")
285327
```
286-
- nmap_tcp_scan
328+
329+
- nmap_tcp_scan
330+
287331
```python
288332
import nmap3
289333
nmap = nmap3.NmapScanTechniques()
290334
result = nmap.nmap_tcp_scan("192.168.178.1")
291335
```
292-
336+
293337
- nmap_udp_scan
338+
294339
```python
295340
import nmap3
296341
nmap = nmap3.NmapScanTechniques()
297342
result = nmap.nmap_udp_scan("192.168.178.1")
298343
```
344+
299345
### Supporting the nmap host discovery
346+
300347
The script also offers support for map Added Nmap Host discovery techniques still as python function/methods
301348

302-
- Only port scan (-Pn)
303-
- Only host discover (-sn)
304-
- Arp discovery on a local network (-PR)
305-
- Disable DNS resolution (-n)
349+
- Only port scan (-Pn)
350+
- Only host discover (-sn)
351+
- Arp discovery on a local network (-PR)
352+
- Disable DNS resolution (-n)
306353

307354
NmapHostDiscovery
308355

309-
- `def nmap_portscan_only(self, host, args=None)`
356+
- `def nmap_portscan_only(self, host, args=None)`
357+
310358
```python
311359
import nmap3
312360
nmap = nmap3.NmapHostDiscovery()
313361
results = nmap.nmap_portscan_only("your-host")
314362
```
315-
- `def nmap_no_portscan(self, host, args=None):`
363+
364+
- `def nmap_no_portscan(self, host, args=None):`
365+
316366
```python
317367
import nmap3
318368
nmap = nmap3.NmapHostDiscovery()
319369
results = nmap.nmap_no_portscan("your-host")
320370
```
321-
- `def nmap_arp_discovery(self, host, args=None):`
371+
372+
- `def nmap_arp_discovery(self, host, args=None):`
373+
322374
```python
323375
import nmap3
324376
nmap = nmap3.NmapHostDiscovery()
325377
results = nmap.nmap_arp_discovery("your-host")
378+
326379
```
327-
- `def nmap_disable_dns(self, host, args=None):`
380+
381+
- `def nmap_disable_dns(self, host, args=None):`
382+
328383
```python
329384
import nmap3
330385
nmap = nmap3.NmapHostDiscovery()
@@ -333,7 +388,8 @@ NmapHostDiscovery
333388

334389
Nmap is a large tool, as you can see python3-nmap provides only things what you could say commonly used nmap features.
335390

336-
### Using custom nmap command line arguments.
391+
### Using custom nmap command line arguments
392+
337393
As we said, the script defines each set of nmap command as python function/methods. You can also pass arguments to those methods/function thus extending your capabilities for example.
338394
Let's say we want to scan top ports but also perform version detection .
339395

@@ -344,6 +400,7 @@ Let's say we want to scan top ports but also perform version detection .
344400
```
345401

346402
### Using the nmap vulners script to identify vulnerabilities (CVE's)
403+
347404
You scan the the target IP using version detection ('-sV') to get the service and, the script performs a lookup in the CVE database. The nmap vulners script is part of the default Nmap installation, so you shouldn't need to install any other packages.
348405

349406
```python
@@ -353,15 +410,17 @@ You scan the the target IP using version detection ('-sV') to get the service an
353410
```
354411

355412
## Cross-Selling
356-
* [Ethical-tools](https://ethicaltools.gitbook.io/subdomainfinder/)
357-
* [Wappalyzer online](https://www.nmmapper.com/st/cms-detection/wappalyzer-online/)
358-
* [Whatweb online](https://www.nmmapper.com/tools/cms-detection/whatweb-online/WhatWeb/)
359-
* [Raccoon By Offensive security](https://www.nmmapper.com/tools/reconnaissance-tools/raccoon-vulnerability-scanning/Raccoon%20tool/)
360-
* [Detect WAF](https://www.nmmapper.com/tools/reconnaissance-tools/waf/web-application-firewall-detector/)
361-
* [Dnsdumpster](https://dnsdumpster.readthedocs.io/)
362-
* [Become a patreon](https://www.patreon.com/nmmapper)
363-
* [Online port scanner](https://www.nmmapper.com/st/networkmapper/nmap/online-port-scanning/)
364413

414+
- [Ethical-tools](https://ethicaltools.gitbook.io/subdomainfinder/)
415+
416+
- [Wappalyzer online](https://www.nmmapper.com/st/cms-detection/wappalyzer-online/)
417+
- [Whatweb online](https://www.nmmapper.com/tools/cms-detection/whatweb-online/WhatWeb/)
418+
- [Raccoon By Offensive security](https://www.nmmapper.com/tools/reconnaissance-tools/raccoon-vulnerability-scanning/Raccoon%20tool/)
419+
- [Detect WAF](https://www.nmmapper.com/tools/reconnaissance-tools/waf/web-application-firewall-detector/)
420+
- [Dnsdumpster](https://dnsdumpster.readthedocs.io/)
421+
- [Become a patreon](https://www.patreon.com/nmmapper)
422+
- [Online port scanner](https://www.nmmapper.com/st/networkmapper/nmap/online-port-scanning/)
365423

366424
## Stargazers over time
425+
367426
[![Stargazers over time](https://starchart.cc/nmmapper/python3-nmap.svg?variant=adaptive)](https://starchart.cc/nmmapper/python3-nmap)

docs/conf.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,41 +17,40 @@
1717

1818
# -- Project information -----------------------------------------------------
1919

20-
project = 'python3-nmap'
21-
copyright = '2019, Wangolo Joel'
22-
author = 'Wangolo Joel'
20+
project = "python3-nmap"
21+
copyright = "2019, Wangolo Joel"
22+
author = "Wangolo Joel"
2323

2424

2525
# -- General configuration ---------------------------------------------------
2626

2727
# Add any Sphinx extension module names here, as strings. They can be
2828
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
2929
# ones.
30-
extensions = [
31-
]
30+
extensions = []
3231

3332
# Add any paths that contain templates here, relative to this directory.
34-
templates_path = ['_templates']
33+
templates_path = ["_templates"]
3534

3635
# List of patterns, relative to source directory, that match files and
3736
# directories to ignore when looking for source files.
3837
# This pattern also affects html_static_path and html_extra_path.
39-
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
38+
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
4039

4140

4241
# -- Options for HTML output -------------------------------------------------
4342

4443
# The theme to use for HTML and HTML Help pages. See the documentation for
4544
# a list of builtin themes.
4645
#
47-
html_theme = 'sphinx_rtd_theme'
46+
html_theme = "sphinx_rtd_theme"
4847

4948
# Add any paths that contain custom static files (such as style sheets) here,
5049
# relative to this directory. They are copied after the builtin static files,
5150
# so a file named "default.css" will overwrite the builtin "default.css".
52-
html_static_path = ['_static']
51+
html_static_path = ["_static"]
5352

5453

55-
#-----PERSONAL----
56-
master_doc = 'index'
57-
source_suffix = '.rst'
54+
# -----PERSONAL----
55+
master_doc = "index"
56+
source_suffix = ".rst"

0 commit comments

Comments
 (0)