Scapy TCP-push to github

至此,我想我可以开始写这篇基于python、scapy的tcp交互的实现了,也许写这样的东西有点儿过时了,因为之前已经有好多人写过相关的东西,但是大家的方向不一样吧,更多的人偏向于写扫描,探测,以及简单的实现三次握手.感觉没有具体的讲某一点我觉得很重要的东西,比如是怎么实现一个完整的交互(当然可能是因为是我搜索的技术有限,没有找到相关的信息).

  • kali2.0 Linux
  • Python 2.7
  • scapy 2.33
  • Pycharm

三次握手的过程我是从网上在搜索scapy TCP交互实例的时候发现别人写的挺好的,所以直接拿来用了.2333,自己好挫……

TCP三次握手实现代码.png

我们通过执行脚本时传入源IP/目的IP/目的端口即可完成建立三次握手,网上很多都有讲到这个实例的实现过程,所以不多赘述.

注意:

  • 这里你可能会发现运行结果的wireshark抓包显示连接没有能够正常建立,直接是RST掉了,原因是什么???

  • 防火墙因为没有发syn包,所以对于回来的ack包直接RST掉了(就像是你没点菜服务员却告诉你你需要确认你刚刚点菜的菜单,所以你肯定是首先RST掉).

  • 这两条命令就是关于这个问题的解决方式,直接配置防火墙丢掉RST包.

      iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP
    
      iptables -L(查看状态~)
    

因为我自身接触的设备有一个类似于tcp三次握手的建连过程,所以在tcp建连之后还需要一次连接过程,这之间要涉及到ack和seq的问题,是我遇到的问题,不知道熟悉TCP的人会不会也遇到.

  • sr()函数拥有在第三层的接收和发送功能,所以我们通过sr()来负责发送接收含有data的数据包
  • send()只有发送功能,不管接收,我们可以用来发送ack等包

我用word做了一个简单的TCP握手和交互的过程:

模拟握手和交互示例图.png

我们从过程中可以看出,seq和ack是在不断变化的,我们只针对客户端,我们的seq值和ack值的变化是根据上一个数据包的ack和接收到的data数据的长度来决定

wireshark已经识别了数据长度并计算了下一个ack的值.png

如图我们可以清楚的看到,seq值和ack的关联以及我们如果计算,那么剩下的就可以通过代码实现.

seq值的实现代码.png

我们通过图片可以看到计算的方式是通过sr()函数接收到的数据包,来计算返回data的长度,以此来确定ack和seq.

另外,应该还要注意几个参数:

  • timeout 和 multi
这两个参数可以延长sr()的接收数据包的等待时间,接收足够的answer数据.因为sr()返回的数据格式是tuple类型,如下图.

scapy收到的元组格式.png

第二层元组访问数据包数据:

scapy查看深层的元组格式.png

运行程序,在结果中打印一个sr()接收到的answer数据:

scapy打印一个接收到的数据包.png

wireshark默认对接收到数据的处理,wireshark也计算了返回数据的长度并预算了下一个ack:

scapy确定收到数据中元组的返回数据内容和长度.png

这几张截图很关键,因为没有更好的显示方式,这里其实出现了一个问题,也就是我上面提到的要用timeout和multi这两个参数的原因,因为如果不设置等待的时间,那么我当前要测试的设备首先返回的是一个ack包而不是真正的数据包,所以等待时间不够是无法接收到真实数据并确定合理的ack和seq值.

做不到的话那么肯定是畸形数据包了,不会被接受并一直等待响应.

  • 解决办法
  • 笨办法 连续发包两次,第一个请求返回ack包后马上发第二个包,可以得到正确返回值 同一个数据包发送两次.png
  • 相对较好的解决办法 设置足够的等待时间,然后遍历所有的数据包,从中去获得真实的返回数据的数据包.

scapy发包命令行过程.png

scapy第一次完整的运行.png

在接收到畸形数据之后,目标直接返回RST,但是并没有在sr之中得到一个真实的返回数据,也就是说没有返回任何东西,只有一个ack,所以下一步怎么处理RST需要考虑一下?