Built by: Oliver-Sec | Language: Python 3 | Platform: Windows / Linux / macOS
Stealth Port Scanner is a command-line network reconnaissance tool that probes a target machine or network range and reports which ports are open, what services are running on them, and what version information they expose. It was built as a portfolio project to demonstrate how professional penetration testers perform the very first phase of an assessment — reconnaissance and enumeration.
It does five core things:
- Scans ports in parallel — uses multi-threading so hundreds of ports are tested simultaneously, making it significantly faster than a standard linear scan.
- Identifies services — maps open ports to 50+ known service names (HTTP, SSH, RDP, SMB, MySQL, etc.) without needing an internet connection.
- Grabs banners — connects to each open port and reads the initial response, often revealing the software name and version (e.g.
OpenSSH_8.9,nginx/1.24.0). - Fingerprints the OS — analyses collected banners to make an educated guess about whether the target is running Windows or Linux.
- Saves a timestamped report — automatically writes a full
.txtlog to areports/folder for later review.
Make sure you have Python 3.8 or higher installed. Download it from python.org.
Windows tip: During installation, tick the box that says "Add Python to PATH" — this is required.
Open your terminal (PowerShell or Command Prompt) and run:
pip install -r requirements.txtOr install it directly:
pip install coloramaOption A — Double-click (beginner-friendly):
Simply double-click scanner.py in File Explorer. The tool will launch and ask you for your target and settings interactively — no command-line knowledge needed.
Option B — From the terminal (recommended):
python scanner.py 192.168.1.1A reports/ folder will be created automatically, and a full scan log will be saved inside it.
| Flag | Description | Default |
|---|---|---|
TARGET |
IP address, hostname, or CIDR range | (required) |
-ps / --port-start |
First port to scan | 1 |
-pe / --port-end |
Last port to scan | 1024 |
-t / --threads |
Number of parallel threads | 200 |
--timeout |
Seconds to wait per connection attempt | 1.0 |
-d / --delay |
Stealth delay in seconds between probes | 0.0 |
--no-banners |
Skip banner grabbing (faster, quieter) | off |
--no-log |
Do not save a report file | off |
Examples:
# Scan a router's top 1024 ports
python scanner.py 192.168.1.1
# Full scan of all 65535 ports with 300 threads
python scanner.py 10.0.0.1 -ps 1 -pe 65535 -t 300
# Stealth scan with a 500ms delay and 2s timeout
python scanner.py 10.10.10.5 -d 0.5 --timeout 2.0
# Scan an entire subnet (CIDR notation)
python scanner.py 192.168.1.0/24 -ps 1 -pe 1024
# Scan the official legal test target (no installation needed)
python scanner.py scanme.nmap.orgThis is the most important concept in the whole script. Here's how it works in plain English.
Imagine you need to check whether 1,024 post boxes are empty or full. The slow way is to open box #1, look inside, close it, then move to box #2, and so on — one at a time. That would take ages.
The fast way is to hire 200 people and send them all out at once. Each person checks a different box simultaneously, and they all report back to you at the same time.
concurrent.futures.ThreadPoolExecutor is the manager who hires those 200 workers (threads). Each worker is given a single port to test. They all run at the same time, and the moment one of them finds an open port, they shout the result back immediately — you don't have to wait for all of them to finish.
with concurrent.futures.ThreadPoolExecutor(max_workers=args.threads) as executor:- This creates a pool of worker threads.
max_workers=200means up to 200 port checks can run simultaneously.
future_map = {
executor.submit(scan_port, target_ip, port, ...): port
for port in ports
}executor.submit()sends a job to the pool. It returns a Future — an object that represents "a result that will exist at some point in the future."- We store each Future in a dictionary so we can match it back to its port number.
for future in concurrent.futures.as_completed(future_map):
result = future.result()as_completed()is a generator that yields each Future as soon as its thread finishes — not in the order they were submitted, but in the order they complete. This means open ports appear on screen almost instantly, even while hundreds of other checks are still running.
In a professional penetration test, the very first phase is called reconnaissance (also called enumeration). Before a penetration tester can attempt to exploit anything, they need to build a picture of the target:
- What machines are on the network?
- What ports are open on each machine?
- What software is running, and what version?
A port scanner is the fundamental tool for answering these questions. It is the equivalent of a burglar checking every window and door of a house — before picking the lock, you need to know which entry points exist.
PHASE 1 — Run the Port Scanner
|
v
PHASE 2 — Review the Open Ports
|
--> Is there an RDP port (3389) open? --> Potential brute-force target.
--> Is there an SMB port (445) open? --> Check for EternalBlue / MS17-010.
--> Is there an old SSH version? --> Check CVE database for vulnerabilities.
--> Is there an unknown port open? --> Investigate with Netcat or Wireshark.
|
v
PHASE 3 — Analyse the Banners
|
--> Does the banner reveal a specific version?
--> Search that version on exploit-db.com or the NVD.
|
v
PHASE 4 — OS Fingerprint
|
--> Knowing the OS narrows down which exploits, payloads,
and privilege escalation techniques might apply.
Imagine the scanner produces this output:
+== Scanning: 10.10.10.40 ==================
| [OPEN] 22 | SSH
| -> OpenSSH 7.2p2 Ubuntu
| [OPEN] 80 | HTTP
| -> Apache httpd 2.4.18
| [OPEN] 3389 | RDP
+====================================================
| Open Ports : 3
| OS Guess : Linux (Confidence: High)
A penetration tester would immediately note:
OpenSSH 7.2p2— this exact version has a publicly documented user enumeration vulnerability (CVE-2016-6210). Worth investigating.Apache 2.4.18— a very old version with multiple known CVEs. The tester would checkexploit-db.comfor available exploits.- Port 3389 (RDP) on a Linux machine — unusual. This could be
xrdpand might indicate a misconfiguration.
This is exactly how real assessments begin.
When you connect to most network services, they immediately send you an introductory message. This is called a banner. It often contains the service name, the version number, and sometimes the operating system.
Think of it like calling a company's phone line and hearing:
"Thank you for calling Acme Corp. You're connected to our customer service system running ServicePro v2.3."
You didn't ask for that information — they just told you. Network services do the same thing.
Why does this matter for security?
If a service announces that it is running version 2.3 of something, an attacker can look up that exact version in the CVE database and immediately find every known vulnerability for it. This is why security-conscious administrators configure their servers to suppress or falsify banners — a technique called "security through obscurity."
| File | Description |
|---|---|
scanner.py |
The main script — all logic lives here |
requirements.txt |
The one library you need to install |
reports/ |
Auto-created folder where scan logs are saved |
reports/scan_<IP>_<timestamp>.txt |
A full report from each scan run |
MIT License
Copyright (c) 2025 Oliver-Sec
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This tool is intended for use only on systems you own or have explicit, written permission to test. Running a port scanner against systems without authorisation is illegal in most countries, including under the Computer Misuse Act 1990 (UK), the Computer Fraud and Abuse Act (USA), and equivalent legislation worldwide.
The author accepts no liability for any misuse, damage, data loss, or legal consequences arising from the use of this tool.
Always get written permission before scanning any network. Hack ethically.
| Target | Notes |
|---|---|
scanme.nmap.org |
Officially provided by the Nmap project for exactly this purpose |
127.0.0.1 |
Your own local machine |
| Your home router | Usually 192.168.1.1 or 192.168.0.1 |
| A virtual machine you control | Best practice — set up a lab environment |
| Library / Module | Why We Use It |
|---|---|
socket |
Built into Python; used to open TCP connections to each port |
concurrent.futures |
Built into Python; provides the multi-threading thread pool |
ipaddress |
Built into Python; used to parse and expand CIDR notation |
argparse |
Built into Python; handles the command-line argument parsing |
colorama |
Third-party library; enables coloured terminal output on Windows |
datetime |
Built into Python; used to timestamp reports and filenames |
random |
Built into Python; used to add jitter to the stealth delay |
Once you're comfortable with this script, here are some ways to level it up:
- Add UDP scanning — TCP scanning only finds TCP services. Many important services (DNS, SNMP, DHCP) use UDP instead.
- VirusTotal / AbuseIPDB integration — automatically check discovered IPs against threat intelligence databases via their free APIs.
- HTML report output — generate a browser-viewable report with colour-coded results instead of a plain text file.
- Ping sweep first — before scanning ports, do an ICMP ping sweep of the CIDR range to identify which hosts are actually online.
- Custom service file — load the service map from an external
.jsonfile so users can add their own port-to-service mappings. - CVE lookup — parse the banner, extract the version string, and automatically query the NVD API for known vulnerabilities.
- Nmap XML export — output results in Nmap-compatible XML format for use with tools like Metasploit.
- TryHackMe — Free, beginner-friendly cybersecurity labs with guided paths
- Hack The Box — Intermediate/advanced practice machines
- Nmap Documentation — The professional standard for port scanning
- CVE Database (NVD) — Look up known vulnerabilities by software version
- Exploit-DB — Public database of known exploits
- OWASP Top 10 — The most common web application security risks
Happy hacking (ethically)! 🚀