Python ACK 端口扫描器:模拟 Nmap 扫描端口
由于 ACK 方式需要使用原始套接字,需要以管理员权限运行该程序。
import argparse
import socket
import struct
def scan_ports(target_ip, start_port, end_port):
for port in range(start_port, end_port+1):
try:
# 创建原始套接字
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
# 构造 TCP 头部
source_port = 12345 # 随便指定一个源端口
dest_port = port
seq_num = 0
ack_num = 0
data_offset = 5
reserved = 0
flags = 0x10 # ACK 标志位
window_size = socket.htons(5840)
checksum = 0
urgent_pointer = 0
tcp_header = struct.pack('!HHLLBBHHH', source_port, dest_port, seq_num, ack_num, data_offset, reserved, flags, window_size, checksum, urgent_pointer)
# 构造 IP 头部
source_ip = socket.gethostbyname(socket.gethostname())
dest_ip = target_ip
version = 4
ihl = 5
tos = 0
total_length = 20 + 20
id = 54321
flags = 0
ttl = 255
protocol = socket.IPPROTO_TCP
checksum = 0
ip_header = struct.pack('!BBHHHBBH4s4s', (version << 4) + ihl, tos, total_length, id, flags, ttl, protocol, checksum, socket.inet_aton(source_ip), socket.inet_aton(dest_ip))
# 计算 TCP 校验和
pseudo_header = struct.pack('!4s4sBBH', socket.inet_aton(source_ip), socket.inet_aton(dest_ip), 0, socket.IPPROTO_TCP, len(tcp_header))
pseudo_header = pseudo_header + tcp_header
tcp_checksum = checksum_func(pseudo_header)
# 将 TCP 校验和填入 TCP 头部
tcp_header = struct.pack('!HHLLBBHHH', source_port, dest_port, seq_num, ack_num, data_offset, reserved, flags, window_size, tcp_checksum, urgent_pointer)
# 将 IP 头部和 TCP 头部组合成一个完整的数据包
packet = ip_header + tcp_header
# 发送数据包
s.sendto(packet, (dest_ip, 0))
# 接收响应数据包
s.settimeout(0.1)
response = s.recvfrom(1024)[0]
# 解析响应数据包
tcp_header_length = (response[12] >> 4) * 4
tcp_header = response[20:20+tcp_header_length]
tcp_header = struct.unpack('!HHLLBBHHH', tcp_header)
flags = tcp_header[5]
# 判断端口是否开放
if flags == 0x14: # RST/ACK 标志位
print('Port ' + str(port) + ' is open')
s.close()
except:
pass
def checksum_func(data):
if len(data) % 2 == 1:
data += b'�'
res = sum(struct.unpack('!{}H'.format(len(data) // 2), data))
res = (res >> 16) + (res & 0xffff)
res = res + (res >> 16)
return (~res) & 0xffff
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Python port scanner using ACK scan')
parser.add_argument('target', help='target IP address')
parser.add_argument('-p', '--port', help='port number or range (e.g. 80 or 1-1024)', required=True)
args = parser.parse_args()
target_ip = args.target
port_range = args.port.split('-')
if len(port_range) == 1:
start_port = end_port = int(port_range[0])
else:
start_port = int(port_range[0])
end_port = int(port_range[1])
scan_ports(target_ip, start_port, end_port)
使用示例:
sudo python3 ack_scan.py 192.168.0.1 -p 1-1024
该程序将扫描 192.168.0.1 主机的 1-1024 端口,输出开放的端口号。
原文地址: https://www.cveoy.top/t/topic/f0Aw 著作权归作者所有。请勿转载和采集!