Welcome to snare’s documentation!

Indices and tables

snare

Capture and manipulate traffic off the network

Snare provides a Sniffer class and a few “modules” which can be assembled to form attack tools. These classes are based on Scapy and provide a convenient way to interact with and compose tools from it’s functionality.

The advanced functions such as ARP poisoning, packet forwarding, and analysis are decomposed into modules to allow for greater flexibility and flexibility. Look at the constructed strategies for examples of how to compose the modules.

Docs are hosted on Read the Docs

Example

Suppose you hate the string “search” and you want to MitM your local network, replacing all instances of the word in HTTP responses with the word “replace”. Well the following script will do that for you!

import scapy.all as scapy
import snare

# Hello
@snare.tcpfilter
def inject(pkt):
  if all(layer in pkt for layer in (scapy.IP, scapy.TCP)):
      if scapy.Raw in pkt and pkt[scapy.TCP].sport == 80:

          s = b"search"
          r = b"replacement"

          raw = pkt[scapy.Raw]
          if s in raw.load:
              raw.load = raw.load.replace(s, r)
              print(pkt.show())
  return pkt

sniffer = snare.Sniffer(
    iface="eth0",
    modules=[snare.ArpMitmModule(filter=inject)]
)
sniffer.start()
input("Starting injection attack. Press enter to quit.")
sniffer.stop()

Development

Testing

Tests are written in pytest and can be run with the pytest command.

Note

Testing is pretty spare at the momment. In order to really test things, a testing framework that can feed in pcap files and evaluate the repsonse is required.

Documentation

Documentation can be built with Sphinx from the docs folder by running make html, or another target.

Sniffer

class snare.sniffer.Module[source]

Module provides functionalies on top of the sniffing platform. User defined modules should inherit from this class.

process(pkt)[source]

Process will be called for every packet recieved by the sniffer. Process may raise StopSniffing to signal that the sniffer should terminate.

start(sniffer)[source]

Start when the sniffer starts or this module is added to a running sniffer.

stop()[source]

Stop will be called when the sniffer stops.

class snare.sniffer.Sniffer(iface, processor=None, store=False, filter=None, quantum=0.25, modules=None)[source]

Sniffer is the core component of the traffic capture framework.

This class uses the Scapy sniffer to collect packets off the wire. It then passes them to the modules for processing.

Example:
>>> import snare
...
>>> def show_pkt(pkt):
...     print(pkt.summary())
...     return pkt
...
>>> sniffer = snare.Sniffer(
...     iface='tap0',
...     modules=[snare.ArpMitmModule(filter=show_pkt)]
... )
...
>>> # Run the sniffer in background thread with:
>>> # sniffer.start()
>>> # Or run it blocking on the current thread with:
>>> # sniffer.run()
Parameters:
  • iface (str) – Name of the interface to listen on.
  • processor (function(scapy.Packet), optional) – Function to be called each time a packet is intercepted. The given packet is mutable.
  • store (bool, optional) – Whether to store sniffed packets or discard them. If True, packets will be collected in the sniffer.packets field.
  • filter (str, optional) – pcap filter applied to the socket, such that only filtered packets will be processed. See man pcap-filter for more details on pcap filters.
  • quantum (float, optional) – Interval, in seconds, to stop the sniffer to check the stop event.
  • modules (list(Module), optional) – List of modules to launch the sniffer with.
join()[source]

Block until the sniffer thread has terminated

process(pkt)[source]

Process the given packet through each active module, and self.processor

register(*mods)[source]

Add new modules to the sniffer

run()[source]

Run the sniffer on the current thread, blocking until it terminates

start()[source]

Start the sniffer on a new background thread

stop()[source]

Signal the sniffer to stop

exception snare.sniffer.StopSniffing[source]

StopSniffing may raised while processing a packet to indicate stop the sniffer.

ARP

class snare.arp.ArpCacheModule(ignore=None)[source]

ArpCacheModule listens for ARP messages and provides a cache of the ARP associations seen on the network. It ignores ARP messages sent from this host and any other hosts specified in ignore, in order to avoid self-poisoning of the ARP cache when sending out spoofed ARP messsages.

Parameters:ignore (set(str), optional) – A set of MAC addresses. ARP messages with a source in ignore will be ignored for building the ARP cache. Automatically includes the sniffer interface.
process(pkt)[source]

Process will be called for every packet recieved by the sniffer. Process may raise StopSniffing to signal that the sniffer should terminate.

start(sniffer)[source]

Start when the sniffer starts or this module is added to a running sniffer.

class snare.arp.ArpMitmModule(filter=None, iface=None, hwaddr=None)[source]

ArpMitmModule uses ARP poinsoning to MitM the network on the given interface. This module combines the ARP cache, ARP poisoner, and forwarder modules.

Parameters:filter – Filter, used by the forwarder, to modify or drop packets. Defaults to forwarding all packets, modifying only the source MAC address.

:type filter:(function scapy.Packet -> scapy.Packet), optional :param iface: Interface name to execute the attack on. Defaults to the sniffer interface. :type iface: str, optional :param hwaddr: MAC address to use for outgoing packets. :type hwaddr: str, optional

process(pkt)[source]

Process will be called for every packet recieved by the sniffer. Process may raise StopSniffing to signal that the sniffer should terminate.

start(sniffer)[source]

Start when the sniffer starts or this module is added to a running sniffer.

stop()[source]

Stop will be called when the sniffer stops.

class snare.arp.ArpPoisonerModule(arpcache, iface=None, hwaddr=None, target=None, impersonate=None, poison_interval=2, ping_interval=30)[source]

ArpPoisonerModule will send out spoofed ARP messages at regular intervals to poison the network. It also starts by sending out an arping to all targets to see who is on the network and populate the cache.

Parameters:
  • arpcache (mapping(str) -> str) – Mapping of MAC addresses to IP addresses.
  • iface (str, optional) – Interface name over which ARP messages should be sent. Defaults to sniffer interface.
  • hwaddr (str, optional) – Source MAC address to set on outgoing messages. Defaults to interface MAC address.
  • target (scapy.Net, optional) – A Scapy network object designating targets for poisoning by IP. Defaults to interface subnet.
  • impersonate (scapy.Net, optional) – A Scapy network object designating targets for impersonation by IP. Defaults to interface subnet.
  • poison_interval (float, optional) – Interval, in seconds, for periodically sending poison messages.
  • ping_interval (float, optional) – Interval, in seconds, for periodically scanning for targets.
arping(target=None)[source]

Sends a batch of ARP who-has messages to the specified targets.

Parameters:target (scapy.Net, optional) – IP addres targets for the ARP messages. Defaults to the union of target and impersonate sets.
arpoison(target=None, impersonate=None)[source]

Sends a batch of poisoned ARP messages to the target set, impersonating the given hosts.

Parameters:
  • target (scapy.Net, optional) – IP addres targets for the ARP messages. Defaults to this modules target set.
  • impersonate (scapy.Net, optional) – IP addres targets for the ARP messages. Defaults to this modules impersonate set.
run()[source]

Run the ARP poisoner module, periodically scanning and poisoning peers

start(sniffer)[source]

Start the ARP poisoner module. Called on sniffer.start()

stop()[source]

Stop the ARP poisoner module. Called on sniffer.stop()

TCP

class snare.tcp.TcpFilter(filter=None)[source]

TcpFilter wraps a packet filter and adjusts seq and ack numbers to account for altered data lengths The wrapped filter should not change the seq or ack number, as they will be reset The wrapped filter may drop a packet by returning None in which case nothing will be forwarded

Parameters:filter (function(scapy.packet.Packet) -> scapy.packet.Packet or None, optional) – Filter function to use for packets being passed through this filter. If provided, overrides the filter function defined on the class.
filter(pkt)[source]

Filter function to use for packets being passed through this filter. Should be overriden if TcpFilter is subclassed

offsets

A dictionary of offsets indicating how seq and ack numbers need to be adjusted.

class snare.tcp.TcpFlags[source]

An enumeration.

class snare.tcp.TcpFlowKey(src, sport, dst, dport)[source]

TcpFlowKey can be used to uniquely identify a TCP flow by source and destination IP address and port

class snare.tcp.TcpProxyModule(handler, bind, target=None, source=None, backlog=16, timeout=30)[source]

TcpProxyModule provides a TCP proxing mechanism using OS sockets, and therefore the kernel’s TCP stack. The handler provided when constructing this will be called with (client-facing socket, server-facing socket) as args

Parameters:
  • handler (function(socket.socket, socket.socket)) – Handler function that will be called each time a connection is received by the proxy. Each invocation of the handler will be passed a socket open to the client (i.e. the peer that initiated the connection) and a socket open to the server (i.e. intended recipient of the connection)
  • bind (tuple(str, int)) – IP address and port number to listen for incoming TCP connections on.
  • target (tuple(str, int), optional) – Host to open a connection to when a client connection is received.
  • source (tuple(str, int), optional) – Source IP address and port to use for new connections.
  • backlog (int, optional) – Maximum number of connections to keep accept into the backlog.
  • timeout (int, optional) – Timeout, in seconds, for opening a connection to the target.
start(sniffer=None)[source]

Start when the sniffer starts or this module is added to a running sniffer.

stop()[source]

Stop will be called when the sniffer stops.

snare.tcp.tcpfilter(filter)[source]

Decorator to create a TcpFilter function for use in modifying TCP streams. Wraps a function that accepts a packet and returns a single packet, list of packets, or None.

Forward

class snare.forward.ForwarderModule(arpcache, filter=None, iface=None, hwaddr=None, ipaddr=None, routes=None)[source]

ForwarderModule forwards packets received by the sniffer and in the ARP cache, after applying a filter. This serves to forward on packets intercepted, such as by ARP poisoning, onto the intended hosts. The filter function should return one packet, a list of packets, or None. Returned packets will be sent after having their eithernet addresses set.

nexthop(ip)[source]

Returns the MAC address for the next hop towards the given IP

process(pkt)[source]

Process will be called for every packet recieved by the sniffer. Process may raise StopSniffing to signal that the sniffer should terminate.

start(sniffer)[source]

Start when the sniffer starts or this module is added to a running sniffer.

snare.forward.clear_chksums(pkt)[source]

Deletes IP, UDP, and TCP checksums from pkt, such that they are recalculated by Scapy

Parameters:pkt (scapy.packet.Packet) – Packet for which to clear checksums.

Net

Network address functions and an OpenVPN utility class.

Addr

Network address functions

class snare.net.addr.Addr(addr)[source]

Generic network address with support for various conversions and operators

Parameters:addr (str|int|bytes|Addr) – Address to create in string, int or bytes representation.
class snare.net.addr.Ip(addr)[source]

IPv4 address with support for conversion to/from strings and byte operations

class snare.net.addr.IpNet(ip, mask)[source]

IPv4 address and network mask, representing a subnet.

broadcast()[source]

Calculate the broadcast address from the IP and mask.

cidr()[source]

Returns the CIDR representation of this subnet.

contains(ip)[source]

Determines if the given address is in this subnet

Parameters:ip (Ip) – IPv4 to check if contained in this subnet.
network()[source]

Calculate the network address from the IP and mask.

class snare.net.addr.Mac(addr)[source]

Ethernet MAC address

snare.net.addr.ifaddr(ifname)[source]

Retrieves the IPv4 address for the given network interface name.

Parameters:ifname (str) – Interface name to retreive the IP address from.
Example:
>>> ifaddr('lo')
<snare.net.addr.Ip 127.0.0.1>
snare.net.addr.ifcidr(ifname)[source]

Retrieves the IPv4 address and network mask from the given inerface name.

Parameters:ifname (str) – Interface name to retreive the IP address and network mask from.
Example:
>>> ifcidr('lo')
<snare.net.addr.IpNet 127.0.0.1/8>
snare.net.addr.ifhwaddr(ifname)[source]

Retrieves the Ethernet MAC address for the given network interface name.

Parameters:ifname (str) – Interface name to retreive the MAC address from.
Example:
>>> ifhwaddr('lo')
<snare.net.addr.Mac 00:00:00:00:00:00>
snare.net.addr.ifmask(ifname)[source]

Retrieves the IPv4 network mask for the given network interface name.

Parameters:ifname (str) – Interface name to retreive the IP network mask from.
Example:
>>> ifmask('lo')
<snare.net.addr.Ip 255.0.0.0>
snare.net.addr.parsecidr(ipnet)[source]

Parses and returns the given CIDR string as an IpNet subnet object.

Parameters:ipnet (str) – String representation of the subnet.
Example:
>>> parsecidr('172.16.224.70/20')
<snare.net.addr.IpNet 172.16.224.70/20>

iptables

iptables manipulation functions.

exception snare.net.iptables.BadRuleError(rule)[source]

Raised when an iptables command failes with the “Bad rule” message This will occur when trying to check or delete a rule which does not exist

OpenVPN

OpenVPN functions.

exception snare.net.openvpn.OpenVpnError(instance, msg)[source]

Route

snare.net.route.routes()[source]

Retrieve routes from the system