Scapy TCP-push to github
至此,我想我可以开始写这篇基于python、scapy的tcp交互的实现了,也许写这样的东西有点儿过时了,因为之前已经有好多人写过相关的东西,但是大家的方向不一样吧,更多的人偏向于写扫描,探测,以及简单的实现三次握手.感觉没有具体的讲某一点我觉得很重要的东西,比如是怎么实现一个完整的交互(当然可能是因为是我搜索的技术有限,没有找到相关的信息).
1 0x00 环境
- kali2.0 Linux
- Python 2.7
- scapy 2.33
- Pycharm
2 0x01 TCP三次握手
三次握手的过程我是从网上在搜索scapy TCP交互实例的时候发现别人写的挺好的,所以直接拿来用了.2333,自己好挫……
我们通过执行脚本时传入源IP/目的IP/目的端口即可完成建立三次握手,网上很多都有讲到这个实例的实现过程,所以不多赘述.
注意:
这里你可能会发现运行结果的wireshark抓包显示连接没有能够正常建立,直接是RST掉了,原因是什么???
防火墙因为没有发syn包,所以对于回来的ack包直接RST掉了(就像是你没点菜服务员却告诉你你需要确认你刚刚点菜的菜单,所以你肯定是首先RST掉).
这两条命令就是关于这个问题的解决方式,直接配置防火墙丢掉RST包.
iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP iptables -L(查看状态~)
3 0x02 与设备握手交互
因为我自身接触的设备有一个类似于tcp三次握手的建连过程,所以在tcp建连之后还需要一次连接过程,这之间要涉及到ack和seq的问题,是我遇到的问题,不知道熟悉TCP的人会不会也遇到.
3.0.1 函数
- sr()函数拥有在第三层的接收和发送功能,所以我们通过sr()来负责发送接收含有data的数据包
- send()只有发送功能,不管接收,我们可以用来发送ack等包
我用word做了一个简单的TCP握手和交互的过程:
我们从过程中可以看出,seq和ack是在不断变化的,我们只针对客户端,我们的seq值和ack值的变化是根据上一个数据包的ack和接收到的data数据的长度来决定
如图我们可以清楚的看到,seq值和ack的关联以及我们如果计算,那么剩下的就可以通过代码实现.
我们通过图片可以看到计算的方式是通过sr()函数接收到的数据包,来计算返回data的长度,以此来确定ack和seq.
另外,应该还要注意几个参数:
- timeout 和 multi
这两个参数可以延长sr()的接收数据包的等待时间,接收足够的answer数据.因为sr()返回的数据格式是tuple类型,如下图.
第二层元组访问数据包数据:
运行程序,在结果中打印一个sr()接收到的answer数据:
wireshark默认对接收到数据的处理,wireshark也计算了返回数据的长度并预算了下一个ack:
这几张截图很关键,因为没有更好的显示方式,这里其实出现了一个问题,也就是我上面提到的要用timeout和multi这两个参数的原因,因为如果不设置等待的时间,那么我当前要测试的设备首先返回的是一个ack包而不是真正的数据包,所以等待时间不够是无法接收到真实数据并确定合理的ack和seq值.
做不到的话那么肯定是畸形数据包了,不会被接受并一直等待响应.
- 解决办法
- 笨办法 连续发包两次,第一个请求返回ack包后马上发第二个包,可以得到正确返回值
- 相对较好的解决办法 设置足够的等待时间,然后遍历所有的数据包,从中去获得真实的返回数据的数据包.
4 0x03 新的问题
在接收到畸形数据之后,目标直接返回RST,但是并没有在sr之中得到一个真实的返回数据,也就是说没有返回任何东西,只有一个ack,所以下一步怎么处理RST需要考虑一下?

如果你觉得这篇文章对你有所帮助,欢迎赞赏~
