?实训项目制作的端口扫描脚本
附有详细的使用命令解释
可以实现单个端口进行扫描和端进行扫描
eg:1-65535
import optparse ?# 导入用于解析命令行参数的模块
import socket ?# 导入用于网络通信的模块# 定义函数:扫描指定主机的指定端口
def PortScan(targetHost, targetPort):
? ? try:
? ? ? ? connSkt = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ?# 创建套接字对象, ? # socket.AF_INET 表示地址族(Address Family),用于指定套接字使用的地址类型,这里是 IPv4 地址族。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # socket.SOCK_STREAM 表示套接字类型(Socket Type),用于指定套接字的传输类型,这里是 TCP。
? ? ? ? connSkt.settimeout(1) ?# 设置连接超时时间为 1 秒
? ? ? ? connSkt.connect((targetHost, targetPort)) ?# 尝试连接指定的主机和端口
? ? ? ? connSkt.send(b'PortScan\r\n') ?# 发送字节数据到连接的套接字
? ? ? ? results = connSkt.recv(1000) ?# 接收数据并存储结果
? ? ? ? print('[+] %d/tcp open' % targetPort) ?# 输出端口开放信息
? ? ? ? print('[+] ' + str(results)) ?# 输出收到的数据
? ? except socket.error:
? ? ? ? print('[-] %d/tcp closed' % targetPort) ?# 端口关闭或发生错误时输出信息
? ? finally:
? ? ? ? connSkt.close() ?# 关闭套接字连接# 定义函数:执行端口扫描
def Scan(targetHost, targetPorts):
? ? try:
? ? ? ? tgtIP = socket.getaddrinfo(targetHost, 0)[0][4][0] ?# 获取目标主机的 IP 地址,socket.getaddrinfo(targetHost, 0) 返回一个包含解析信息的列表。
? ? except socket.gaierror:
? ? ? ? print('[-] Cannot resolve %s: Unknown host' % targetHost) ?# 若无法解析主机名则输出错误信息并返回
? ? ? ? return
? ? try:
? ? ? ? tgtName = socket.gethostbyaddr(tgtIP)[0] ? ?# 获取 IP 地址对应的主机名
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # socket.gethostbyaddr() 函数用于执行 IP 地址到主机名的反向 DNS 解析。它接受一个 IP 地址作为参数,并返回与该地址关联的主机名。
? ? ? ? print("\n[+] Scan results for: " + tgtName) ?# 输出扫描结果的主机名
? ? except socket.herror: ? ? ? ? ? ? ? ? ? ? ? # 表示与主机和网络相关的错误。
? ? ? ? print("Scan Results for: " + tgtIP) ?# 若无法获取主机名则输出 IP 地址
? ? for targetPort in targetPorts: ?# 遍历指定的端口列表
? ? ? ? print("Scanning port: " + str(targetPort)) ?# 输出当前正在扫描的端口
? ? ? ? PortScan(targetHost, int(targetPort)) ?# 调用 PortScan 函数扫描各个端口# 解析端口范围参数
def parse_port_range(port_range):
? ? ports = []
? ? try:
? ? ? ? if "-" in port_range:
? ? ? ? ? ? start, end = port_range.split("-") ? ? ?#split("-") 方法通过分隔符 "-" 将字符串 port_range 拆分成两部分,左侧部分是起始端口,右侧部分是结束端口。这两部分被赋值给 start 和 end 变量。
? ? ? ? ? ? for port in range(int(start), int(end) + 1):
? ? ? ? ? ? ? ? ports.append(port)
? ? ? ? else:
? ? ? ? ? ? ports.append(int(port_range))
? ? except ValueError:
? ? ? ? print("Invalid port range specified. Please use format 'start-end' or 'port'.")
? ? ? ? exit(0)
? ? return ports# 主函数
def main():
? ? parser = optparse.OptionParser("Usage prog -H <target host> -p <target ports>") ? ? ? ?# 是 Python 中用于解析命令行参数的模块。它允许您编写带有选项和参数的命令行接口,并解析用户提供的输入
? ? parser.add_option('-H', dest='targetHost', type='string', help='specify target host') ? # add_option() 方法用于添加选项,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # dest 参数用于指定选项被解析后存储的目标属性名称。当用户在命令行中使用选项时,解析器会将解析后的值存储到指定的目标属性中。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # type 参数用于指定在解析命令行参数时所期望的数据类型。这个参数允许您告诉解析器应该将参数解析为何种数据类型。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # string 是一个数据类型或一个表示字符类型的字符串
? ? parser.add_option('-p', dest='targetPort', type='string', help='specify target port[s] inside \"\" separated by commas(1-65535)')
? ? (options, args) = parser.parse_args() ? ? ? ? ? ? ? #parse_args() 方法用于解析命令行参数,并返回解析后的结果。
? ? targetHost = options.targetHost ?# 获取目标主机
? ? port_range = options.targetPort ?# 获取端口范围参数? ? if (targetHost is None) or (port_range is None): ?# 如果未提供目标主机或端口范围,则输出用法信息并退出程序
? ? ? ? print(parser.usage) ? ? ? ? ? ? ? ? ? ? # parser.usage 是一个属性,用于获取程序使用说明的自定义文本。
? ? ? ? exit(0)? ? targetPorts = parse_port_range(port_range) ?# 解析端口范围参数
? ? Scan(targetHost, targetPorts) ?# 调用 Scan 函数执行端口扫描
# 程序入口
if __name__ == "__main__":
? ? main() ?# 调用主函数开始执行端口扫描
?