Noah Koster
Noah Koster

Reputation: 175

Sending low level raw tcp packets python

I have been working on a program lately for raw packets. We recently had a lecture about raw packets so I have been trying to learn and do exactly what my professor told me. I have a problem with my program it comes up with an error saying destination address required, its raw so I don't want to do socket.connect(destaddr) even though that will fix the error. Here is my code: Here is the class and function:

#not real mac address to protect privacy also removed preamble
class packet(object):
    b = ""
    def __init__(self, payload):
        self.payload = payload

    def ether(self):
        #preamble = "55555555555555D5" 
        macdest = "123456789101" #my mac address - needed to remove colons 
        macsource = "123456789101" #router mac address without colons
        ethertype = "0800" #removed 0x because it is not needed
        fcs = "" #frame check sequence none so far
        frame = macdest+macsource+ethertype
        return frame

    def ip(self): #in hexadecimal
        version = "4" #ipv4 hex
        ihl = "5" #header length hex
        dscp = "00" #default
        ecn = "00" #default
        length = "36" #ether-24 + ip-20 + tcp-30 = 54 to hexa = 35
        idip="0000" #random id
        flags = "40" #dont fragment flag is 2 to hex is 4
        offset = "00" #space taker
        ttl = "40"#hex(64) = 40
        protocol = "06" #for tcp
        checksum = "0000"
        ipaddrfrom = "c0a8010a"
        ipaddrto =   "c0a80101"
        datagram = version+ihl+dscp+ecn+length+idip+flags+offset+ttl+protocol+checksum+ipaddrfrom+ipaddrto
        return datagram

    def tcp(self):
        portsrc = "15c0" #5568
        portdest = "0050" #80
        syn = "00000000" 
        ack = "00000000"
        nonce = "80"
        fin = "10"
        windowscale = "813b"
        checksum = "0000"
        segment = portsrc+portdest+syn+ack+nonce+fin+windowscale + checksum
        return segment

    def getpacket(self):
        frame = self.ether()
        datagram = self.ip()
        segment = self.tcp()
        payload = self.payload
        packet = frame+datagram+segment+payload

        a = 0
        b = ""
        for char in packet:
            a = a+1
            b = b + char
            if a == 4:
                b = b + " "
                a=0
        self.fmtpacket = b
        return packet

def raw():
    s = socket(AF_INET, SOCK_RAW, IPPROTO_IP)
    s.bind(('192.168.1.10', 0))
    pckt = packet("")
    netpacket = pckt.getpacket()
    print "Sending: " + pckt.fmtpacket
    print ""
    s.sendall(netpacket)
    data = s.recv(4096)
    print data

Upvotes: 0

Views: 7171

Answers (3)

Prabhjot Singh Sethi
Prabhjot Singh Sethi

Reputation: 11

packet to be sent should contain the actual bytes and not the string.

Upvotes: 1

Jay Atkinson
Jay Atkinson

Reputation: 3287

If your professor is okay with it, you may find Scapy a lot easier to work with in creating raw packets in python.

From their website:

Scapy is a powerful interactive packet manipulation program. It is able to forge or decode packets of a wide number of protocols, send them on the wire, capture them, match requests and replies, and much more. It can easily handle most classical tasks like scanning, tracerouting, probing, unit tests, attacks or network discovery (it can replace hping, 85% of nmap, arpspoof, arp-sk, arping, tcpdump, tethereal, p0f, etc.)

Upvotes: 2

Pochi
Pochi

Reputation: 2196

Is there a reason for binding to '0.0.0.0'? When you create a raw socket, you'll need to bind it to an interface.

One thing I notice is that you'll need the '\x' prefix for hex.

Right now, you're stringing together chars.

For example, in ip(), version + ihl = '45'. That's a string, not a hex value. When you're sending this along, as a raw packet, that's two bytes instead of the one that you want. You want to send '\x45', not '45'.

Upvotes: 1

Related Questions