Pregunta

My issue is as follows: I want to implement a listen service using scapy to stimulate a honeypot (because honeypot uses a fake ip, so I can't use OS sockets) and I chose scapy.

I implemented a very simple TCP hand-shake procedure, however one thing frustrated me: one byte of the packet I use PSH to send is eaten.

For example I send "abc" out to a client, but the client's socket, for example netcat or wget, only receive "bc". Another example is "HTTP/1.1 200 OK" becomes "TTP/1.1 200 OK". I captured packet and wireshark can correctly recognize my hand-made packet as HTTP, but the client socket just lack 1 byte. I don't know why.

The code is as follows: 192.168.1.100 stands for server(my) ip addr,9999 is the port. For example, I run this python script on 192.168.1.100, then I use "nc 192.168.1.100 9999". I expect to get "abc", but I can only get "bc", but the packet seems no problem in Wireshark. it's so strange.

    '''
    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)
        
¿Fue útil?

Solución

I tested your code, you are missing sending proper tcp sequence

httpPart=TCP(sport=TCPPORT, dport=pkt.payload.payload.sport, flags="PA", ack=pkt.payload.payload.seq + pushLen, seq=pkt.payload.payload.ack)/Raw(load=ADD_TEST)

should fix the issue, you may have other packet length issue, but the eaten 1 byte is caused by missing proper tcp sequence

Otros consejos

Some suggestions:

  1. Sniff may append some payload to the end of the packet, so len(pkt.payload.payload.load) may not be the real payload length. You can use pkt[IP].len-40 (40 is the common header length of IP+TCP). You may also use -len(pkt[IP].options)-len(pkt[TCP].options) for more accurate results.
  2. Usually the application layer above TCP uses line breaks ("\r\n") to separate commands, so you'd better change ADD_TEST to "abc\r\n"

If none of above methods work, you may upgrade to the latest netcat and try again.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top