加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
2016.03.14 Scapy模拟TCP交互全过程 4.55 KB
一键复制 编辑 原始数据 按行查看 历史
现任明教教主-乾颐堂 提交于 2016-03-14 08:48 . new file
========================Socket Server=========================================
#!/usr/bin/python3.4
# -*- coding=utf-8 -*-
import sys, time
from select import select
from socket import *
def now(): return time.ctime(time.time())
myHost = '202.100.1.138'
myPort = 6668
if len(sys.argv) == 3:
myHost, myPort = sys.argv[1:]
numPortSocks = 2
mainsocks, readsocks, writesocks = [], [], []
for i in range(numPortSocks):
portsock = socket(AF_INET, SOCK_STREAM)
portsock.bind((myHost, myPort))
portsock.listen(5)
mainsocks.append(portsock)
readsocks.append(portsock)
myPort += 1
print('select-server loop starting')
while True:
readables, writeables, exceptions = select(readsocks, writesocks, [])
for sockobj in readables:
if sockobj in mainsocks:
newsock, address = sockobj.accept()
print('Connect:', address, id(newsock))
readsocks.append(newsock)
else:
data = sockobj.recv(1024)
print('\tgot', data, 'on', id(sockobj))
if not data:
sockobj.close()
readsocks.remove(sockobj)
else:
reply = 'Echo=>%s at %s' % (data, now())
sockobj.send(reply.encode())
========================Scapy(模拟客户端)===================================
#!/usr/bin/python3.4
# -*- coding=utf-8 -*-
import logging
import re
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
#设置目的端口号
dstport = 6668
#随机产生源端口
sportid = random.randint(1024, 2000)
#随机产生目的端口
seqid = random.randint(20000, 30000)
#产生SYN包(FLAG = 2 为SYN)
result_raw_synack = sr(IP(dst='202.100.1.138')/TCP(dport=dstport,sport=sportid,flags=2,seq=seqid), verbose = False)
#响应的数据包产生数组([0]为响应,[1]为未响应)
result_synack_list = result_raw_synack[0].res
#第一层[0]位第一组数据包
#第二层[0]表示发送的包,[1]表示收到的包
#第三层[0]为IP信息,[1]为TCP信息,[2]为TCP数据
tcpfields_synack = result_synack_list[0][1][1].fields
#由于SYN算一个字节,所以客户到服务器序列号(sc_sn)需要增加1
sc_sn = tcpfields_synack['seq'] + 1
cs_sn = tcpfields_synack['ack']
#发送ACK(flag = 16),完成三次握手!
send(IP(dst='202.100.1.138')/TCP(dport=dstport,sport=sportid,flags=16,seq=cs_sn,ack=sc_sn), verbose = False)
#发送数据(b"Welcome to qytang"),flag为24(ACK = 16,PUSH = 8)
#注意‘multi=1’,服务器会先给一个ACK确认,然后发送回显数据。
#如果客户没有及时确认,还会有多次重传!
result_raw_msg = sr(IP(dst='202.100.1.138')/TCP(dport=dstport,sport=sportid,flags=24,seq=cs_sn,ack=sc_sn)/b"Welcome to qytang", verbose = False, multi=1, timeout=1)
#响应的数据包产生数组([0]为响应,[1]为未响应)
result_msg_list = result_raw_msg[0].res
#提取服务器响应包的IP信息,生成字典(注意是提取的第二组数据,第一组仅仅是ACK)
msgback_ip_fields = result_msg_list[1][1][0].fields
#提取服务器响应包的TCP信息,生成字典(注意是提取的第二组数据,第一组仅仅是ACK)
msgback_tcp_fields = result_msg_list[1][1][1].fields
#提取服务器响应包的TCP数据信息,生成字典(注意是提取的第二组数据,第一组仅仅是ACK)
msgback_data_fields = result_msg_list[1][1][2].fields
#如果回显数据中有‘Echo’字段就打印回显内容
if re.search(b'Echo', msgback_data_fields['load']):
print(msgback_data_fields['load'])
#技术数据长度,ip总长度 - ip头部长度(['ihl']*4) - tcp头部长度(['dataofs']*4)
data_len = msgback_ip_fields['len'] - msgback_ip_fields['ihl']*4 - msgback_tcp_fields['dataofs']*4
#客户到服务器端的序列号为,服务器回显中的‘seq’加上传输的数据长度!
sc_sn = msgback_tcp_fields['seq'] + data_len
cs_sn = msgback_tcp_fields['ack']
#发送ACK对服务器的回显进行确认,flag = 16(ACK)
send(IP(dst='202.100.1.138')/TCP(dport=dstport,sport=sportid,flags=16,seq=cs_sn,ack=sc_sn), verbose = False)
#客户端主动发送FIN(1) + ACK(16),进行连接终结。
result_raw_fin = sr1(IP(dst='202.100.1.138')/TCP(dport=dstport,sport=sportid,flags=17,seq=cs_sn,ack=sc_sn), verbose = False)
#由于FIN算一个字节,所以客户到服务器序列号(sc_sn)需要增加1
sc_sn = result_raw_fin[1].fields['seq'] + 1
cs_sn = result_raw_fin[1].fields['ack']
#发送最后一个ACK(16),结束整个TCP连接!!!
send(IP(dst='202.100.1.138')/TCP(dport=dstport,sport=sportid,flags=16,seq=cs_sn,ack=sc_sn), verbose = False)
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化