CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/addp.rb
Views: 11655
1
# -*- coding: binary -*-
2
module Rex
3
module Proto
4
5
#
6
# This provides constants, encoding, and decoding routines for Digi International's ADDP protocol
7
#
8
class ADDP
9
10
require "rex/socket"
11
12
#
13
# See the following URLs for more information:
14
# - http://qbeukes.blogspot.com/2009/11/advanced-digi-discovery-protocol_21.html
15
# - http://www.digi.com/wiki/developer/index.php/Advanced_Device_Discovery_Protocol_%28ADDP%29
16
#
17
18
19
MAGICS = %W{ DIGI DVKT DGDP }
20
ERRORS = %W{ no_response unknown success authenticaton_failed unit_has_address invalid_value invalid_data unsupported_command }
21
WLAN_ENC_MODES = %W{ unknown none wep40 wep128 }
22
WLAN_AUTH_MODES = %W{ unknown open shared_key open_shared_key }
23
HWTYPES = %W{
24
unknown ps3_desk8 ps3_desk16 ps3_desk32 ps3_rack16 ps2_desk16 ps2_rack16
25
lets_desk1 lets_desk2 lets_desk4 dorpia_dinrail1 nubox01 nubox02 nubox04
26
digione_sp digione_ia digione_em
27
}
28
29
CMD_CONF_REQ = 1
30
CMD_CONF_REP = 2
31
CMD_SET_ADDR_REQ = 3
32
CMD_SET_ADDR_REP = 4
33
CMD_REBOOT_REQ = 5
34
CMD_REBOOT_REP = 6
35
CMD_SET_DHCP_REQ = 7
36
CMD_SET_DHCP_REP = 8
37
CMD_SET_WL_REQ = 9
38
CMD_SET_WL_REP = 10
39
CMD_SET_WL_COUNTRIES_REQ = 11
40
CMD_SET_WL_COUNTRIES_REP = 12
41
CMD_EDP = 13
42
CMD_CNT = 14
43
44
45
def self.encode_password(pwd="dbps")
46
[pwd.length].pack("C") + pwd
47
end
48
49
def self.request_config(magic, dmac="\xff\xff\xff\xff\xff\xff")
50
mac = (dmac.length == 6) ? dmac : Rex::Socket.eth_aton(dmac)
51
req = magic + [ CMD_CONF_REQ, 6].pack("nn") + mac
52
return req
53
end
54
55
def self.request_config_all(dmac="\xff\xff\xff\xff\xff\xff")
56
mac = (dmac.length == 6) ? dmac : Rex::Socket.eth_aton(dmac)
57
res = []
58
MAGICS.each { |m| res << self.request_config(m, dmac) }
59
return res
60
end
61
62
def self.request_static_ip(magic, dmac, ip, mask, gw, pwd="dbps")
63
mac = (dmac.length == 6) ? dmac : Rex::Socket.eth_aton(dmac)
64
buf =
65
Rex::Socket.addr_aton(ip) +
66
Rex::Socket.addr_aton(mask) +
67
Rex::Socket.addr_aton(gw) +
68
mac +
69
self.encode_password(pwd)
70
71
req = magic + [CMD_SET_ADDR_REQ, buf.length].pack("nn") + buf
72
return req
73
end
74
75
def self.request_dhcp(magic, dmac, enabled, pwd="dbps")
76
mac = (dmac.length == 6) ? dmac : Rex::Socket.eth_aton(dmac)
77
buf =
78
[ enabled ? 1 : 0 ].pack("C") +
79
mac +
80
self.encode_password(pwd)
81
82
req = magic + [CMD_SET_DHCP_REQ, buf.length].pack("nn") + buf
83
return req
84
end
85
86
def self.request_reboot(magic, dmac, pwd="dbps")
87
mac = (dmac.length == 6) ? dmac : Rex::Socket.eth_aton(dmac)
88
buf =
89
mac +
90
self.encode_password(pwd)
91
92
req = magic + [CMD_REBOOT_REQ, buf.length].pack("nn") + buf
93
return req
94
end
95
96
def self.decode_reply(data)
97
res = {}
98
r_magic = data[0,4]
99
r_ptype = data[4,2].unpack("n").first
100
r_plen = data[6,2].unpack("n").first
101
buff = data[8, r_plen]
102
bidx = 0
103
104
res[:magic] = data[0,4]
105
res[:cmd] = r_ptype
106
107
while bidx < (buff.length - 2)
108
i_type, i_len = buff[bidx, 2].unpack("CC")
109
i_data = buff[bidx + 2, i_len]
110
111
break if i_data.length != i_len
112
113
case i_type
114
when 0x01
115
res[:mac] = Rex::Socket.eth_ntoa(i_data)
116
when 0x02
117
res[:ip] = Rex::Socket.addr_ntoa(i_data)
118
when 0x03
119
res[:mask] = Rex::Socket.addr_ntoa(i_data)
120
when 0x04
121
res[:hostname] = i_data
122
when 0x05
123
res[:domain] = i_data
124
when 0x06
125
res[:hwtype] = HWTYPES[ i_data.unpack("C").first ] || HWTYPES[ 0 ]
126
when 0x07
127
res[:hwrev] = i_data.unpack("C").first
128
when 0x08
129
res[:fwrev] = i_data
130
when 0x09
131
res[:msg] = i_data
132
when 0x0a
133
res[:result] = i_data.unpack("C").first
134
when 0x0b
135
res[:gw] = Rex::Socket.addr_ntoa(i_data)
136
when 0x0c
137
res[:advisory] = i_data.unpack("n").first
138
when 0x0d
139
res[:hwname] = i_data
140
when 0x0e
141
res[:realport] = i_data.unpack("N").first
142
when 0x0f
143
res[:dns] = Rex::Socket.addr_ntoa(i_data)
144
when 0x10
145
res[:dhcp] = (i_data.unpack("C").first == 0) ? false : true
146
when 0x11
147
res[:error] = ERRORS[ i_data.unpack("C").first ] || ERRORS[0]
148
when 0x12
149
res[:ports] = i_data.unpack("C").first
150
when 0x13
151
res[:realport_enc] = (i_data.unpack("C").first == 0) ? false : true
152
when 0x14
153
res[:version] = i_data.unpack("n").first
154
when 0x15
155
res[:vendor_guid] = i_data.unpack("H*") # GUID
156
when 0x16
157
res[:iftype] = i_data.unpack("C").first
158
when 0x17
159
res[:challenge] = i_data # Unknown format
160
when 0x18
161
res[:cap_port] = i_data.unpack("n").first
162
when 0x19
163
res[:edp_devid] = i_data.unpack("H*").first # Unknown format
164
when 0x1a
165
res[:edp_enabled] = (i_data.unpack("C").first == 0) ? false : true
166
when 0x1b
167
res[:edp_url] = i_data
168
when 0x1c
169
res[:wl_ssid] = i_data
170
when 0x1d
171
res[:wl_auto_ssid] = (i_data.unpack("n").first == 0) ? false : true
172
when 0x1e
173
res[:wl_tx_enh_power] = i_data.unpack("n").first
174
when 0x1f
175
res[:wl_auth_mode] = WLAN_AUTH_MODES[ i_data.unpack("n").first ] || WLAN_AUTH_MODES[ 0 ]
176
when 0x20
177
res[:wl_enc_mode] = WLAN_ENC_MODES[ i_data.unpack("n").first ] || WLAN_ENC_MODES[ 0 ]
178
when 0x21
179
res[:wl_enc_key] = i_data
180
when 0x22
181
res[:wl_cur_country] = i_data
182
when 0x23
183
res[:wl_country_list] = i_data
184
else
185
# Store unknown responses
186
res["unknown_0x#{"%.2x" % i_type}".to_sym] = i_data
187
end
188
189
bidx = bidx + 2 + i_len
190
end
191
return res
192
end
193
194
def self.reply_to_string(res)
195
str = ""
196
197
fields = [
198
:hwname, :hwtype, :hwrev, :fwrev,
199
:mac, :ip, :mask, :gw, :hostname, :domain, :dns, :dhcp,
200
:msg, :result, :error,
201
:advisory, :ports, :realport, :realport_enc,
202
:version, :vendor_guid, :iftype, :challenge, :cap_port, :edp_devid, :edp_enabled,
203
:edp_url, :wl_ssid, :wl_auto_ssid, :wl_tx_enh_power, :wl_auth_mode, :wl_enc_mode,
204
:wl_enc_key, :wl_cur_country, :wl_country_list, :magic
205
]
206
207
fields.each do |fname|
208
next unless res.has_key?(fname)
209
str << "#{fname}:#{res[fname]} "
210
end
211
return str
212
end
213
214
end
215
216
end
217
end
218
219
220