前言
Nmap 是一个开源的网络扫描和嗅探工具包,最初由Gordon Lyon(Fyodor V. Schmitt)开发。Nmap设计用于快速扫描大型网络,但它同样适用于单个主机。通过使用各种协议,如TCP/IP,Nmap能够发现网络上的哪些主机在运行,提供的服务(应用程序名称和版本),开放的端口,操作系统类型,以及防火墙/IDS配置等信息。Nmap不仅限于简单的ping扫描或端口扫描;除了简单的扫描,还可以做渗透检测,比如脚本小子喜欢使用该工具来批量检索目标服务器上的内容等(就不展开细说),本教程使用 Python.
准备工作
不一定是 PyCharm,其他编辑器也可以
Nmap:[ 官网下载 ]
Python:[ 官网下载 ]
PyCharm:[ 官网下载 ]
安装 python-nmap 包
pip install python-nmap主机存活探测
步骤1:启动脚本
python main.py步骤2:命令行参数处理
- 脚本检测到没有提供命令行参数,提示用户输入目标主机地址。
请输入目标主机地址或主机组 (例如 192.168.50.0/24 或 192.168.50.1): 步骤3:用户输入
- 用户输入目标主机地址
192.168.1.0/24。
请输入目标主机地址或主机组 (例如 192.168.50.0/24 或 192.168.50.1): 192.168.1.0/24步骤4:用户输入验证
- 脚本使用正则表达式验证输入的有效性。
- 输入有效,继续下一步。
步骤5:网络扫描
- 脚本创建 nmap.PortScanner() 对象
- 执行扫描 scanner.scan(hosts='192.168.1.0/24', arguments='-sn')
- 解析扫描结果,提取每个主机的信息
步骤6:打印和保存结果
- 对于每个主机,调用 print_host_info(host, host_info) 函数解析并打印主机信息。
=== 主机信息 ===
主机: 192.168.1.1
主机名: router.localdomain
主机名类型: ptr
IPv4 地址: 192.168.1.1
MAC 地址: 00:1A:2B:3C:4D:5E
设备品牌: Cisco Systems, Inc.
状态: up
响应: echo-reply步骤7:完成提示
- 扫描完成后,程序会提示结果和保存到指定文件
=== 主机信息 ===
主机: 192.168.50.1
主机名:
主机名类型:
IPv4 地址: 192.168.50.1
MAC 地址: 74:D0:2B:87:30:2D
设备品牌: 未知
状态: up
响应: arp-response完整代码
import argparse
import sys
from datetime import datetime
import nmap
def print_host_info(host, host_info):
"""解析并打印单个主机信息"""
output = [
"\n=== 主机信息 ===",
f"主机: {host}",
f"主机名: {host_info.get('hostnames', [{'name': '未知'}])[0].get('name')}",
f"主机名类型: {host_info.get('hostnames', [{'type': '未知'}])[0].get('type')}",
f"IPv4 地址: {host_info.get('addresses', {}).get('ipv4', '未知')}",
f"MAC 地址: {host_info.get('addresses', {}).get('mac', '未知')}",
f"设备品牌: {host_info.get('vendor', {}).get(host_info.get('addresses', {}).get('mac', ''), '未知')}",
f"状态: {host_info.get('status', {}).get('state', '未知')}",
f"响应: {host_info.get('status', {}).get('reason', '未知')}"
]
print("\n".join(output))
return "\n".join(output)
def scan_network(hosts):
"""执行一次扫描并输出结果"""
scanner = nmap.PortScanner()
try:
print(f"开始扫描目标: {hosts}...")
scan_result = scanner.scan(hosts=hosts, arguments='-sn')
all_output = []
for host in scan_result['scan']:
host_info = scan_result['scan'][host]
result = print_host_info(host, host_info)
all_output.append(result)
# 获取当前时间戳
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# 保存结果到文件
output_filename = f"{hosts.replace('/', '_')}_{timestamp}.txt"
with open(output_filename, "w", encoding="utf-8") as f:
f.write("\n".join(all_output))
print(f"扫描完成!结果已保存到 {output_filename}")
except Exception as e:
print(f"扫描过程中发生错误: {e}")
def main():
parser = argparse.ArgumentParser(description="网络扫描工具")
parser.add_argument("target_hosts", type=str, nargs='?', help="目标主机地址或主机组 (例如 192.168.50.0/24 或 192.168.50.1)")
args = parser.parse_args()
if args.target_hosts is None:
target_hosts = input("请输入目标主机地址或主机组 (例如 192.168.50.0/24 或 192.168.50.1): ")
else:
target_hosts = args.target_hosts
if not validate_ip_or_cidr(target_hosts):
print("无效的目标主机地址或主机组,请检查输入格式。")
sys.exit(1)
scan_network(target_hosts)
def validate_ip_or_cidr(ip_or_cidr):
import re
pattern = re.compile(r'^(\d{1,3}\.){3}\d{1,3}(/\d{1,2})?$')
return bool(pattern.match(ip_or_cidr))
if __name__ == "__main__":
main()
