Package: packnet
PACKNETHacked together into entirety by c0mplh4cksAboutThis package is created to build low-level networking packets which can be used when building various types of applications. Using this package, it is possible to make packets ranging from OSI model level 2 to level 7. One of the endless applications could be a network device discovery tool using the address resolution protocol for example. Apart from only building numerous headers and payloads, this package makes it also possible to read received data and extract useful information, making it possible to interact with a Python script.Table of ContentsOSI modelInstallationPyPiGitHubPackagerBuilding packetsReading packetsGeneralgetpublicipmaclookupgetmacInterfaceCustom DatatypesINTIPMACADDRLENNAMECHECKSUMProtocol ClassesETHERNETARPIPv4IPv6ICMPICMPv6TCPUDPDNSGo backOSI modelOpen Systems Interconnection modelNoLayerFunctionProtocol(included in package)7ApplicationApplication communicationDNS6PresentationRepresentation & Encryption5SessionInterhost communication4TransportConnections & QoSTCP, UDP3NetworkIPIPv4, IPv6, ICMP, ICMPv6, ARP2Data LinkMACEthernet1PhysicalBitsIntroduced to standardize networking protocols, allowing multiple networking devices from different developers to communicate among each other. The model consists of multiple layers with its own unique function. The OSI model differs from the TCP/IP model since it contains the presentation and session layers.Go backInstallationThe following will show how this package can be installed.Installation from PyPiInstall package by usingpip:pip3 install packnetorpip install packnetInstallation from GithubClone the repository:git clone https://github.com/c0mplh4cks/packnetMove inside the directory:cd packnetInstall the library by running the following command:pip3 install .orpip install .Go backPackagerPackages is a class to simplify building packets.Building packets using packagerThis example shows how to build a ARP packet using packager. For more information about the ARP class:ARPimportpacknetsrc=["192.168.0.1",0,"aa:aa:aa:aa:aa:aa"]# defining ip, port and macdst=["192.168.0.2",0,"bb:bb:bb:bb:bb:bb"]package=packnet.Packager()# creating packager objectpackage.fill(packnet.ARP.Header)# tell packager to make use of the ARP classpackage.src=src# set the source and destination addressespackage.dst=dstprint(package.packet)# print the created packet in bytesReading packets using packagerThis example also shows the usage of packager using the ARP protocol.importpacknetencoded=b'\xbb\xbb\xbb\xbb\xbb\xbb\xaa\xaa\xaa\xaa\xaa\xaa\x08\x06\x00\x01\x08\x00\x06\x04\x00\x01\xaa\xaa\xaa\xaa\xaa\xaa\xc0\xa8\x00\x01\xbb\xbb\xbb\xbb\xbb\xbb\xc0\xa8\x00\x02'# Encoded ARP packet ^ which we want to decode using packager.package=packnet.Packager()# creating packager objectpackage.packet=encoded# decoding the encoded packet# displaying the source and destination addressprint(package.src,package.dst)# looping through all the layers which the packet contained (these layers are not always the same as in the TCP/IP or OSI model)forlayerinpackage:print(layer)# displaying other useful information about the package objectpackage.debug()package[0].debug()# accessing the first layer (ETHERNET)package[1].debug()# accessing the second layer (ETHERNET)# displaying the operation code of the ARP protocolprint(package[1].op)Go backGeneralGeneral is a module containing some simple functions for gathering information.getpublicipThis function does exactly what its name says: it requires the public ip by connecting to ifconfig.meimportpacknetprint(packnet.general.getpublicip())maclookupThis function does a lookup for the vendor of the mac address.importpacknetresult=packnet.general.maclookup("aa:aa:aa:aa:aa:aa")# Try with your own macprint(result)# The function returns `None` when there is no vendor matching the macgetmacThis function requires the mac address of the given ip address by using ARP.This function only works using root access, due to the use of a low-level socketimportpacknetprint(packnet.general.getmac("192.168.0.0"))# It returns a ADDR object containing the IP address, the port (always zero) and the MAC addressGo backInterfaceThis class makes it easier to require your addresses and simplifies the use of sockets.importpacknet# the passive argument can be set to `True` if you don't want the socket to be bound.interface=packnet.Interface(card="eth0",port=0,passive=False,timeout=64)# display the bounded cardprint(interface.card)# `interface.addr` returns a ADDR object containing the bound address.print(interface.addr)# `send` requires `bytes` as argumentinterface.send(b"hello")# `hello` doesn't work, it needs to be a proper packet.# the amount of bytes to be received, can be set using the `length` argumentprint(interface.recv(length=1024))Go backCustom datatypesCustom datatypes made to simplify encoding/decoding will be described here.
Each example will cover most of the methods/use cases and should not require further explanation.datatype INTimportpacknetinteger=packnet.INT(2,size=4,format="big")print(integer)print(integer.to_bytes())print(integer.from_bytes(b"\x00\x00\x00\xff"))# returns (length of bytes, integer)integer.integer=5datatype IPThis class can be used of IPv4 and IPv6 by setting the version argument.importpacknetip=packnet.IP("192.168.0.0",version=4)print(ip)print(ip.to_bytes())print(ip.from_bytes(b"\xff\xff\xff\xff"))# returns (length of bytes, ip)ip.ip="127.0.0.1"datatype MACimportpacknetmac=packnet.MAC("ff:ff:ff:ff:ff:ff")print(mac)print(mac.to_bytes())print(mac.from_bytes(b"\x00\x00\x00\x00\x00\x00"))# returns (length of bytes, ip)mac.mac="aa:aa:aa:aa:aa:aa"datatype ADDRimportpacknetaddr=packnet.ADDR(ip="127.0.0.1",version=4,port=0,mac="ff:ff:ff:ff:ff:ff")print(addr)print(addr.mac.to_bytes())# same for `ip` and `port`print(addr[2].to_bytes())print(addr["mac"].to_bytes())addr.mac.from_bytes(b"\xff\xff\xff\xff\xff\xff")addr.ip.version=6datatype LENimportpacknetlength=packnet.LEN(header=0,payload=0,total=0,size=1)print(length)length.size=2print(length.header)length.header.integer=20print(length)print(length.total,length[2],length["total"])datatype NAMEimportpacknetname=packnet.NAME("test.com")print(name,name.name)print(name.to_bytes(header=b""))# the `header` argument is used for compressionname.from_bytes(b"\x05hello\x03com\x00",header=b"")name.name="test.net"datatype CHECKSUMimportpacknetchecksum=packnet.CHECKSUM(packnet.INT(1,size=2),b"\xff\xff")print(checksum.to_bytes())Go backProtocol classesEvery protocol currently implemented will be explained here using examples.It is recommended to use thePackagerclass for decoding. More aboutPackagerhere:Packager.Each protocol class makes use of the custom datatypes. More about customd datatypes here:Custom datatypes.Not every attribute and application is covered, but the examples should give a good example for usage.protocol ETHERNETimportpacknet# defining `ETHERNET.Header` objecteth=packnet.ETHERNET.Header()# setting attributeseth.src.mac="aa:aa:aa:aa:aa:aa"eth.dst.mac="bb:bb:bb:bb:bb:bb"eth.protocol.integer=0x0806# printing encoded packet in bytesprint(eth.packet)# print debug informationeth.debug()protcol ARPimportpacknet# defining `ARP.Header` objectarp=packnet.ARP.Header()# setting attributesarp.src.addr=("255.255.255.255",0,"ff:ff:ff:ff:ff:ff")arp.dst.addr=("255.255.255.255",0,"ff:ff:ff:ff:ff:ff")arp.op.integer=2# printing encoded packet in bytesprint(arp.packet)# print debug informationarp.debug()protocol IPv4importpacknet# defining `IPv4.Header` objectipv4=packnet.IPv4.Header()# setting attributesipv4.src.ip="192.168.0.1"ipv4.dst.ip="192.168.0.2"ipv4.protocol.integer=6# printing encoded packet in bytesprint(ipv4.packet)# print debug informationipv4.debug()protocol IPv6importpacknet# defining `IPv6.Header` objectipv6=packnet.IPv6.Header()# setting attributesipv6.src.ip="ffff::ffff"ipv6.dst.ip="ffff::ffff"ipv6.protocol.integer=58# printing encoded packet in bytesprint(ipv6.packet)# print debug informationipv6.debug()protocol ICMPimportpacknet# defining `ICMP.Echo` objectecho=packnet.ICMP.Echo()echo.id.integer=1# defining `ICMP.Header` objecticmp=packnet.ICMP.Header()# setting attributesicmp.type.integer=8# printing encoded packet in bytesprint(icmp.packet+echo.packet)# print debug informationicmp.debug()echo.debug()protocol ICMPv6importpacknet# defining `ICMPv6.Echo` objectecho=packnet.ICMPv6.Echo()echo.id.integer=1# defining `ICMPv6.Header` objecticmpv6=packnet.ICMPv6.Header()# setting attributesicmpv6.type.integer=8icmpv6.src.ip="aaaa::aaaa"# ip's required for calculating checksumicmpv6.dst.ip="bbbb::bbbb"# printing encoded packet in bytesprint(icmpv6.packet+echo.packet)# print debug informationicmpv6.debug()echo.debug()protocol TCPimportpacknet# defining `TCP.Header` objecttcp=packnet.TCP.Header()# setting attributestcp.src.ip="255.255.255.255"# ip's required for calculating checksumtcp.dst.ip="255.255.255.255"tcp.seq.integer=3tcp.ack.integer=100tcp.src.port=1234tcp.dst.poprt=4321# adding optionsfor_inrange(4):tcp.options.append(packnet.TCP.Padding())# printing encoded packet in bytesprint(tcp.packet)# print debug informationtcp.debug()protocol UDPimportpacknet# defining `UDP.Header` objectudp=packnet.UDP.Header()# setting attributesudp.src.ip="255.255.255.255"# ip's required for calculating checksumudp.dst.ip="255.255.255.255"udp.src.port=4321udp.dst.port=1234# adding payloadudp.payload="hello".encode()# printing encoded packet in bytesprint(udp.packet)# print debug informationudp.debug()protocol DNSimportpacknet# definign `DNS.Query` objectquery=packnet.DNS.Query()query.name.name="test.com"# defining `DNS.Header` objectdns=packnet.DNS.Header()# setting attributesdns.id.integer=1234# adding query to headerdns.question.append(query)# printing encoded packet in bytesprint(dns.packet)# print debug informationdns.debug()