Skip to main content

Python3 package for low-level networking

Project description

PACKNET

Hacked together into entirety by c0mplh4cks


About

This 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 Contents


Go back

OSI model

Open Systems Interconnection model

No Layer Function Protocol (included in package)
7 Application Application communication DNS
6 Presentation Representation & Encryption
5 Session Interhost communication
4 Transport Connections & QoS TCP, UDP
3 Network IP IPv4, IPv6, ICMP, ICMPv6, ARP
2 Data Link MAC Ethernet
1 Physical Bits

Introduced 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 back

Installation

The following will show how this package can be installed.

Installation from PyPi

Install package by using pip:

pip3 install packnet

or

pip install packnet

Installation from Github

Clone the repository:

git clone https://github.com/c0mplh4cks/packnet

Move inside the directory:

cd packnet

Install the library by running the following command:

pip3 install .

or

pip install .

Go back

Packager

Packages is a class to simplify building packets.

Building packets using packager

This example shows how to build a ARP packet using packager. For more information about the ARP class: ARP

import packnet

src = ["192.168.0.1", 0, "aa:aa:aa:aa:aa:aa"]   # defining ip, port and mac
dst = ["192.168.0.2", 0, "bb:bb:bb:bb:bb:bb"]

package = packnet.Packager()        # creating packager object
package.fill( packnet.ARP.Header )  # tell packager to make use of the ARP class
package.src = src                   # set the source and destination addresses
package.dst = dst

print( package.packet )   # print the created packet in bytes

Reading packets using packager

This example also shows the usage of packager using the ARP protocol.

import packnet

encoded = 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 object
package.packet = encoded      # decoding the encoded packet

# displaying the source and destination address
print( 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)
for layer in package:
  print( layer )  

# displaying other useful information about the package object
package.debug()   

package[0].debug()  # accessing the first layer (ETHERNET)
package[1].debug()  # accessing the second layer (ETHERNET)

# displaying the operation code of the ARP protocol
print( package[1].op )  

Go back

General

General is a module containing some simple functions for gathering information.

getpublicip

This function does exactly what its name says: it requires the public ip by connecting to ifconfig.me

import packnet

print( packnet.general.getpublicip() )

maclookup

This function does a lookup for the vendor of the mac address.

import packnet

result = packnet.general.maclookup("aa:aa:aa:aa:aa:aa") # Try with your own mac
print( result ) # The function returns `None` when there is no vendor matching the mac

getmac

This 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 socket

import packnet

print( packnet.general.getmac("192.168.0.0") )
# It returns a ADDR object containing the IP address, the port (always zero) and the MAC address

Go back

Interface

This class makes it easier to require your addresses and simplifies the use of sockets.

import packnet

# 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 card
print( interface.card )

# `interface.addr` returns a ADDR object containing the bound address.
print( interface.addr )

# `send` requires `bytes` as argument
interface.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` argument
print( interface.recv(length=1024) )

Go back

Custom datatypes

Custom 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 INT

import packnet

integer = 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 = 5

datatype IP

This class can be used of IPv4 and IPv6 by setting the version argument.

import packnet

ip = 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 MAC

import packnet

mac = 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 ADDR

import packnet

addr = 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 = 6

datatype LEN

import packnet

length = packnet.LEN(header=0, payload=0, total=0, size=1)

print( length )
length.size = 2
print( length.header )
length.header.integer = 20
print( length )
print( length.total, length[2], length["total"] )

datatype NAME

import packnet

name = packnet.NAME("test.com")
print( name, name.name )
print( name.to_bytes(header=b"") )  # the `header` argument is used for compression
name.from_bytes(b"\x05hello\x03com\x00", header=b"")
name.name = "test.net"

datatype CHECKSUM

import packnet

checksum = packnet.CHECKSUM(
  packnet.INT(1, size=2),
  b"\xff\xff"
)
print( checksum.to_bytes() )

Go back

Protocol classes

Every protocol currently implemented will be explained here using examples.
It is recommended to use the Packager class for decoding. More about Packager here: 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 ETHERNET

import packnet

# defining `ETHERNET.Header` object
eth = packnet.ETHERNET.Header()   

# setting attributes
eth.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 bytes
print( eth.packet )

# print debug information
eth.debug()

protcol ARP

import packnet

# defining `ARP.Header` object
arp = packnet.ARP.Header()

# setting attributes
arp.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 bytes
print( arp.packet )

# print debug information
arp.debug()

protocol IPv4

import packnet

# defining `IPv4.Header` object
ipv4 = packnet.IPv4.Header()

# setting attributes
ipv4.src.ip = "192.168.0.1"
ipv4.dst.ip = "192.168.0.2"
ipv4.protocol.integer = 6

# printing encoded packet in bytes
print( ipv4.packet )

# print debug information
ipv4.debug()

protocol IPv6

import packnet

# defining `IPv6.Header` object
ipv6 = packnet.IPv6.Header()

# setting attributes
ipv6.src.ip = "ffff::ffff"
ipv6.dst.ip = "ffff::ffff"
ipv6.protocol.integer = 58

# printing encoded packet in bytes
print( ipv6.packet )

# print debug information
ipv6.debug()

protocol ICMP

import packnet

# defining `ICMP.Echo` object
echo = packnet.ICMP.Echo()
echo.id.integer = 1

# defining `ICMP.Header` object
icmp = packnet.ICMP.Header()

# setting attributes
icmp.type.integer = 8

# printing encoded packet in bytes
print( icmp.packet + echo.packet )

# print debug information
icmp.debug()
echo.debug()

protocol ICMPv6

import packnet

# defining `ICMPv6.Echo` object
echo = packnet.ICMPv6.Echo()
echo.id.integer = 1

# defining `ICMPv6.Header` object
icmpv6 = packnet.ICMPv6.Header()

# setting attributes
icmpv6.type.integer = 8
icmpv6.src.ip = "aaaa::aaaa"  # ip's required for calculating checksum
icmpv6.dst.ip = "bbbb::bbbb"

# printing encoded packet in bytes
print( icmpv6.packet + echo.packet )

# print debug information
icmpv6.debug()
echo.debug()

protocol TCP

import packnet

# defining `TCP.Header` object
tcp = packnet.TCP.Header()   

# setting attributes
tcp.src.ip = "255.255.255.255"  # ip's required for calculating checksum
tcp.dst.ip = "255.255.255.255"
tcp.seq.integer = 3
tcp.ack.integer = 100
tcp.src.port = 1234
tcp.dst.poprt = 4321

# adding options
for _ in range(4):
  tcp.options.append( packnet.TCP.Padding() )

# printing encoded packet in bytes
print( tcp.packet )

# print debug information
tcp.debug()

protocol UDP

import packnet

# defining `UDP.Header` object
udp = packnet.UDP.Header()

# setting attributes
udp.src.ip = "255.255.255.255"  # ip's required for calculating checksum
udp.dst.ip = "255.255.255.255"
udp.src.port = 4321
udp.dst.port = 1234

# adding payload
udp.payload = "hello".encode()

# printing encoded packet in bytes
print( udp.packet )

# print debug information
udp.debug()

protocol DNS

import packnet

# definign `DNS.Query` object
query = packnet.DNS.Query()
query.name.name = "test.com"

# defining `DNS.Header` object
dns = packnet.DNS.Header()

# setting attributes
dns.id.integer = 1234

# adding query to header
dns.question.append( query )

# printing encoded packet in bytes
print( dns.packet )

# print debug information
dns.debug()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

packnet-3.0.2.tar.gz (333.8 kB view hashes)

Uploaded Source

Built Distribution

packnet-3.0.2-py3-none-any.whl (341.5 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page