Make ARP request on python

20,338

Solution 1

socket.AF_INET is a socket for IP packets. Since ARP is Ethernet, it won't work this way, you need access to the Ethernet layer.

On Linux, you can use:

s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(3))

with s being any variable you use to assign the socket to.

To send the packet, you should bind the interface with

s.bind(("eth0", 0))

Where "eth0" is the network-interface name.

After that, you can send the packet with

s.send(packet)

with packet being your payload as bytestring.

The

AttributeError: module 'socket' has no attribute 'AF_PACKET'

is saying, that AF_PACKET is not implemented on your platform. Unfortunately Some platforms don't provide access to the low-level network layer, this is true for windows, and may be true for OS X. At least, even on linux, you need root privileges to access the low-level networking, otherwise you'll get an access denied error.

An Idea to get access to the low-level networking via Python is to use a Virtual Machine, like Virtualbox, and run a linux guest with it.

Solution 2

FTR, to work around this issue you can use Scapy. It will use:

  • AF_PACKET or libpcap on unix
  • BPF on BSD
  • Winpcap/Npcap on Windows

to access the raw layer in each case, which makes it cross platform.

Share:
20,338
0x1337
Author by

0x1337

Updated on September 24, 2020

Comments

  • 0x1337
    0x1337 over 3 years

    I'm trying to make ARP request on python. My code:

    import socket
    from struct import pack
    from uuid import getnode as get_mac
    
    def main():
        dest_ip = [10, 7, 31, 99]
        local_mac = [int(("%x" % get_mac())[i:i+2], 16) for i in range(0, 12, 2)]
        local_ip = [int(x) for x in socket.gethostbyname(socket.gethostname()).split('.')]
    
        sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.SOCK_RAW)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        sock.bind(('', 0))
    
        ARP_FRAME = [
            pack('!H', 0x0001), # HRD
            pack('!H', 0x0800), # PRO
            pack('!B', 0x06), # HLN
            pack('!B', 0x04), # PLN 
            pack('!H', 0x0001), # OP
            pack('!6B', *local_mac), # SHA
            pack('!4B', *local_ip), # SPA
            pack('!6B', *(0x00,)*6), # THA
            pack('!4B', *dest_ip), # TPA
        ]
        print(ARP_FRAME)
        sock.sendto(b''.join(ARP_FRAME), ('255.255.255.255', 0))
        sock.close()
    
    if __name__ == "__main__":
        main()
    

    When I execute this code, Wireshark does not catch any packets. I think problem in socket. When I do socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.SOCK_RAW) I get AttributeError: module 'socket' has no attribute 'AF_PACKET'. What am I doing wrong and how fix it?

    OS X 10.11.3

  • Mikhail Zakharov
    Mikhail Zakharov over 5 years
    Confirming "AttributeError: module 'socket' has no attribute 'AF_PACKET'" on MacOS. Actually AF_PACKET is Linux specific, on BSD-like systems it works a bit different: stackoverflow.com/questions/17169298/af-packet-on-osx