@@ -11,15 +11,16 @@ class Metasploit3 < Msf::Auxiliary
11
11
12
12
def initialize
13
13
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' ,
16
16
'Author' => 'Fatih Ozavci <viproy.com/fozavci>' ,
17
17
'License' => MSF_LICENSE ,
18
18
'Actions' => [
19
- [ 'Spoof' , { 'Description' => 'Sends spoofed CDP packets' } ]
19
+ [ 'Spoof' , { 'Description' => 'Sends CDP packets' } ]
20
20
] ,
21
21
'DefaultAction' => 'Spoof'
22
22
)
23
+
23
24
register_options (
24
25
[
25
26
OptString . new ( 'SMAC' , [ false , "MAC Address for MAC Spoofing" ] ) ,
@@ -32,6 +33,7 @@ def initialize
32
33
OptString . new ( 'SOFTWARE' , [ true , "Software of the device" , "SCCP75.9-3-1SR2-1S" ] ) ,
33
34
OptBool . new ( 'FULL_DUPLEX' , [ true , 'True iff full-duplex, false otherwise' , true ] )
34
35
] , self . class )
36
+
35
37
deregister_options ( 'RHOST' )
36
38
end
37
39
@@ -56,35 +58,30 @@ def run
56
58
begin
57
59
open_pcap
58
60
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 )
65
67
end
66
68
ensure
67
69
close_pcap
68
70
end
69
71
end
70
72
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 "
84
81
# device ID
85
- p = tlv ( 1 , datastore [ 'DEVICE_ID' ] )
82
+ cdp << tlv ( 1 , datastore [ 'DEVICE_ID' ] )
86
83
# port ID
87
- p << tlv ( 3 , datastore [ 'PORT' ] )
84
+ cdp << tlv ( 3 , datastore [ 'PORT' ] )
88
85
# TODO: implement this correctly
89
86
# capabilities = datastore['CAPABILITIES'] || "Host"
90
87
# CAPABILITIES
@@ -95,47 +92,51 @@ def prep_cdp
95
92
# define CDP_CAP_LEVEL2_SRB 0x04
96
93
# define CDP_CAP_LEVEL2_TRBR 0x02
97
94
# define CDP_CAP_LEVEL3_ROUTER 0x01
98
- p << tlv ( 4 , "\x00 \x00 \x00 \x41 " )
95
+ cdp << tlv ( 4 , "\x00 \x00 \x00 \x41 " )
99
96
# software version
100
- p << tlv ( 5 , datastore [ 'SOFTWARE' ] )
97
+ cdp << tlv ( 5 , datastore [ 'SOFTWARE' ] )
101
98
# platform
102
- p << tlv ( 6 , datastore [ 'PLATFORM' ] )
99
+ cdp << tlv ( 6 , datastore [ 'PLATFORM' ] )
103
100
# VTP management domain
104
- p << tlv ( 9 , datastore [ 'VTPDOMAIN' ] ) if datastore [ 'VTPDOMAIN' ]
101
+ cdp << tlv ( 9 , datastore [ 'VTPDOMAIN' ] ) if datastore [ 'VTPDOMAIN' ]
105
102
# 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' ) )
107
104
# 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
118
121
end
119
122
120
123
def tlv ( t , v )
121
124
[ t , v . length + 4 ] . pack ( "nn" ) + v
122
125
end
123
126
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
128
131
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
132
135
end
133
136
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 ]
140
141
end
141
142
end
0 commit comments