使用Scapy发送tcp payload:为什么要吃掉一个字节?

时间:2012-06-02 18:58:50

标签: tcp scapy payload

我的问题如下:我想用scapy实现一个监听服务来刺激蜜罐(因为蜜罐使用假的ip,所以我不能使用OS套接字)而且我选择了scapy。

我实现了一个非常简单的TCP握手程序,但有一件事让我感到沮丧:我使用PSH发送的数据包被一个字节吃掉了!

例如,我将“abc”发送给客户端,但客户端的套接字(例如netcat或wget)只接收“bc”。另一个例子是“HTTP / 1.1 200 OK”变为“TTP / 1.1 200 OK”。我捕获数据包和wireshark可以正确识别我的手工数据包作为HTTP,但客户端套接字只缺少1个字节。我不知道为什么。

代码如下:   192.168.1.100代表服务器(我的)ip addr,9999是端口。例如,我在192.168.1.100上运行此python脚本,然后使用“nc 192.168.1.100 9999”。我希望得到“abc”,但我只能得到“bc”,但是Wireshark中的数据包似乎没问题。太奇怪了。

    '''
Created on Jun 2, 2012

@author: root
'''
from scapy import all
from scapy.layers.inet import IP, ICMP, TCP
from scapy.packet import ls, Raw
from scapy.sendrecv import sniff, send
from scipy.signal.signaltools import lfilter
import scapy.all
HOSTADDR = "192.168.1.100"
TCPPORT = 9999 'port to listen for'
SEQ_NUM = 100

ADD_TEST = "abc"


def tcp_monitor_callback(pkt):
    global SEQ_NUM
    global TCPPORT
    if(pkt.payload.payload.flags == 2):
        'A syn situation, 2 for SYN'
        print("tcp incoming connection")
        ACK=TCP(sport=TCPPORT, dport=pkt.payload.payload.sport, flags="SA",ack=pkt.payload.payload.seq + 1,seq=0)
        send(IP(src=pkt.payload.dst,dst=pkt.payload.src)/ACK)
    if(pkt.payload.payload.flags & 8 !=0):
        'accept push from client, 8 for PSH flag'
        print("tcp push connection")
        pushLen = len(pkt.payload.payload.load)
        httpPart=TCP(sport=TCPPORT, dport=pkt.payload.payload.sport, flags="PA", ack=pkt.payload.payload.seq + pushLen)/Raw(load=ADD_TEST)
        'PROBLEM HERE!!!! If I send out abc, the client socket only receive bc, one byte disappers!!!But the packet received by client is CORRECT'
        send(IP(src=pkt.payload.dst,dst=pkt.payload.src)/httpPart)
    if(pkt.payload.payload.flags & 1 !=0):
        'accept fin from cilent'
        print ("tcp fin connection")
        FIN=TCP(sport=TCPPORT, dport=pkt.payload.payload.sport, flags="FA", ack=pkt.payload.payload.seq +1, seq = pkt.payload.payload.ack)
        send(IP(src=pkt.payload.dst,dst=pkt.payload.src)/FIN)
def dispatcher_callback(pkt):
    print "packet incoming"
    global HOSTADDR
    global TCPPORT
    if(pkt.haslayer(TCP) and (pkt.payload.dst == HOSTADDR) and (pkt.payload.dport == TCPPORT)):
        tcp_monitor_callback(pkt)
    else:
        return
if __name__ == '__main__':
    print "HoneyPot listen Module Test"
    scapy.all.conf.iface = "eth0"
    sniff(filter=("(tcp dst port %s) and dst host %s") % (TCPPORT,HOSTADDR), prn=dispatcher_callback)

2 个答案:

答案 0 :(得分:1)

一些建议:

  1. Sniff可能会将一些有效负载附加到数据包的末尾,因此len(pkt.payload.payload.load)可能不是真正的有效负载长度。您可以使用pkt[IP].len-40(40是IP + TCP的公共标头长度)。您也可以使用-len(pkt[IP].options)-len(pkt[TCP].options)获得更准确的结果。
  2. 通常,TCP上方的应用程序层使用换行符(“\ r \ n”)来分隔命令,因此您最好将ADD_TEST更改为"abc\r\n"
  3. 如果上述方法都不起作用,您可以升级到最新的netcat并重试。

答案 1 :(得分:0)

我测试了你的代码,你缺少发送正确的tcp序列

httpPart = TCP(sport = TCPPORT,dport = pkt.payload.payload.sport,flags =“PA”,ack = pkt.payload.payload.seq + pushLen,seq = pkt.payload.payload.ack)/原始(负载= ADD_TEST)

应该解决问题,你可能有其他数据包长度问题,但是吃了1个字节是由于缺少正确的tcp序列引起的