Skip to content

Commit f54fc3d

Browse files
committed
More CDP cleanup. Loop, cleaner packet construction, style
1 parent 0dac2de commit f54fc3d

File tree

1 file changed

+53
-52
lines changed
  • modules/auxiliary/spoof/cisco

1 file changed

+53
-52
lines changed

modules/auxiliary/spoof/cisco/cdp.rb

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@ class Metasploit3 < Msf::Auxiliary
1111

1212
def initialize
1313
super(
14-
'Name' => 'CDP Discovery and Spoofing',
15-
'Description' => 'This module captures and sends Cisco Discovery Protocol (CDP) packets for discovery',
14+
'Name' => 'Send Cisco Discovery Protocol (CDP) Packets',
15+
'Description' => 'This module sends Cisco Discovery Protocol (CDP) packets',
1616
'Author' => 'Fatih Ozavci <viproy.com/fozavci>',
1717
'License' => MSF_LICENSE,
1818
'Actions' => [
19-
['Spoof', { 'Description' => 'Sends spoofed CDP packets' }]
19+
['Spoof', { 'Description' => 'Sends CDP packets' }]
2020
],
2121
'DefaultAction' => 'Spoof'
2222
)
23+
2324
register_options(
2425
[
2526
OptString.new('SMAC', [false, "MAC Address for MAC Spoofing"]),
@@ -32,6 +33,7 @@ def initialize
3233
OptString.new('SOFTWARE', [true, "Software of the device", "SCCP75.9-3-1SR2-1S"]),
3334
OptBool.new('FULL_DUPLEX', [true, 'True iff full-duplex, false otherwise', true])
3435
], self.class)
36+
3537
deregister_options('RHOST')
3638
end
3739

@@ -56,35 +58,30 @@ def run
5658
begin
5759
open_pcap
5860

59-
case action.name
60-
when 'Spoof'
61-
do_spoof
62-
else
63-
# this should never happen
64-
fail ArgumentError, "Invalid action #{action.name}"
61+
@run = true
62+
cdp_packet = build_cdp
63+
print_status("Sending CDP messages on #{interface}")
64+
while @run
65+
capture.inject(cdp_packet.to_s)
66+
Rex.sleep(60)
6567
end
6668
ensure
6769
close_pcap
6870
end
6971
end
7072

71-
def do_spoof
72-
print_status("Sending CDP message on #{interface}")
73-
p = prep_cdp # Preparation of the CDP content
74-
75-
# Injecting packet to the network
76-
l = PacketFu::Inject.new(iface: interface)
77-
cdp_length = ["%04X" % (p.length + 8).to_s].pack('H*')
78-
dot3 = PacketFu::EthHeader.mac2str("01:00:0C:CC:CC:CC") + PacketFu::EthHeader.mac2str(smac) + cdp_length
79-
llc = "\xAA\xAA\x03\x00\x00\x0c\x20\x00"
80-
l.array_to_wire(array: [dot3 + llc + p])
81-
end
82-
83-
def prep_cdp
73+
def build_cdp
74+
cdp = ''
75+
# CDP version
76+
cdp << "\x02"
77+
# TTL (180s)
78+
cdp << "\xB4"
79+
# checksum, empty for now
80+
cdp << "\x00\x00"
8481
# device ID
85-
p = tlv(1, datastore['DEVICE_ID'])
82+
cdp << tlv(1, datastore['DEVICE_ID'])
8683
# port ID
87-
p << tlv(3, datastore['PORT'])
84+
cdp << tlv(3, datastore['PORT'])
8885
# TODO: implement this correctly
8986
# capabilities = datastore['CAPABILITIES'] || "Host"
9087
# CAPABILITIES
@@ -95,47 +92,51 @@ def prep_cdp
9592
# define CDP_CAP_LEVEL2_SRB 0x04
9693
# define CDP_CAP_LEVEL2_TRBR 0x02
9794
# define CDP_CAP_LEVEL3_ROUTER 0x01
98-
p << tlv(4, "\x00\x00\x00\x41")
95+
cdp << tlv(4, "\x00\x00\x00\x41")
9996
# software version
100-
p << tlv(5, datastore['SOFTWARE'])
97+
cdp << tlv(5, datastore['SOFTWARE'])
10198
# platform
102-
p << tlv(6, datastore['PLATFORM'])
99+
cdp << tlv(6, datastore['PLATFORM'])
103100
# VTP management domain
104-
p << tlv(9, datastore['VTPDOMAIN']) if datastore['VTPDOMAIN']
101+
cdp << tlv(9, datastore['VTPDOMAIN']) if datastore['VTPDOMAIN']
105102
# random 1000-7000 power consumption in mW
106-
p << tlv(0x10, [1000 + rand(6000)].pack('n'))
103+
cdp << tlv(0x10, [1000 + rand(6000)].pack('n'))
107104
# duplex
108-
p << tlv(0x0b, datastore['FULL_DUPLEX'] ? "\x01" : "\x00")
109-
# VLAn query. TOD: figure out this field, use tlv, make configurable
110-
p << "\x00\x0F\x00\b \x02\x00\x01"
111-
112-
# VDP version
113-
version = "\x02"
114-
# TTL (180s)
115-
ttl = "\xB4"
116-
checksum = cdpchecksum(version + ttl + "\x00\x00" + p)
117-
version + ttl + checksum + p
105+
cdp << tlv(0x0b, datastore['FULL_DUPLEX'] ? "\x01" : "\x00")
106+
# VLAn query. TODO: figure out this field, use tlv, make configurable
107+
cdp << "\x00\x0F\x00\b \x02\x00\x01"
108+
109+
# compute and replace the checksum
110+
cdp[2, 2] = [compute_cdp_checksum(cdp)].pack('n')
111+
112+
# Build and return the final packet, which is 802.3 + LLC + CDP.
113+
# 802.3
114+
PacketFu::EthHeader.mac2str("01:00:0C:CC:CC:CC") +
115+
PacketFu::EthHeader.mac2str(smac) +
116+
[cdp.length + 8].pack('n') +
117+
# LLC
118+
"\xAA\xAA\x03\x00\x00\x0c\x20\x00" +
119+
# CDP
120+
cdp
118121
end
119122

120123
def tlv(t, v)
121124
[ t, v.length + 4 ].pack("nn") + v
122125
end
123126

124-
def cdpchecksum(p)
125-
num_shorts = p.length / 2
126-
cs = 0
127-
c = p.length
127+
def compute_cdp_checksum(cdp)
128+
num_shorts = cdp.length / 2
129+
checksum = 0
130+
remaining = cdp.length
128131

129-
p.unpack("S#{num_shorts}").each do |x|
130-
cs += x
131-
c -= 2
132+
cdp.unpack("S#{num_shorts}").each do |short|
133+
checksum += short
134+
remaining -= 2
132135
end
133136

134-
cs += p[p.length - 1].getbyte(0) << 8 if c == 1
135-
cs = (cs >> 16) + (cs & 0xffff)
136-
cs = ~((cs >> 16) + cs) & 0xffff
137-
cs = ([cs].pack("S*")).unpack("n*")[0]
138-
139-
[ "%02X" % cs ].pack('H*')
137+
checksum += cdp[cdp.length - 1].getbyte(0) << 8 if remaining == 1
138+
checksum = (checksum >> 16) + (checksum & 0xffff)
139+
checksum = ~((checksum >> 16) + checksum) & 0xffff
140+
([checksum].pack("S*")).unpack("n*")[0]
140141
end
141142
end

0 commit comments

Comments
 (0)