rex 2.0.4 → 2.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rex/arch/x86.rb +16 -0
- data/lib/rex/constants.rb +1 -0
- data/lib/rex/constants/windows.rb +147 -0
- data/lib/rex/encoder/xdr.rb +3 -2
- data/lib/rex/exceptions.rb +37 -5
- data/lib/rex/exploitation/cmdstager/bourne.rb +9 -1
- data/lib/rex/exploitation/cmdstager/tftp.rb +5 -5
- data/lib/rex/java.rb +3 -0
- data/lib/rex/java/serialization.rb +54 -0
- data/lib/rex/java/serialization/model.rb +20 -0
- data/lib/rex/java/serialization/model/annotation.rb +69 -0
- data/lib/rex/java/serialization/model/block_data.rb +70 -0
- data/lib/rex/java/serialization/model/block_data_long.rb +72 -0
- data/lib/rex/java/serialization/model/class_desc.rb +64 -0
- data/lib/rex/java/serialization/model/contents.rb +156 -0
- data/lib/rex/java/serialization/model/element.rb +44 -0
- data/lib/rex/java/serialization/model/end_block_data.rb +12 -0
- data/lib/rex/java/serialization/model/field.rb +172 -0
- data/lib/rex/java/serialization/model/long_utf.rb +48 -0
- data/lib/rex/java/serialization/model/new_array.rb +225 -0
- data/lib/rex/java/serialization/model/new_class_desc.rb +155 -0
- data/lib/rex/java/serialization/model/new_enum.rb +79 -0
- data/lib/rex/java/serialization/model/new_object.rb +223 -0
- data/lib/rex/java/serialization/model/null_reference.rb +12 -0
- data/lib/rex/java/serialization/model/reference.rb +61 -0
- data/lib/rex/java/serialization/model/reset.rb +12 -0
- data/lib/rex/java/serialization/model/stream.rb +123 -0
- data/lib/rex/java/serialization/model/utf.rb +69 -0
- data/lib/rex/mime/message.rb +9 -14
- data/lib/rex/payloads.rb +1 -0
- data/lib/rex/payloads/meterpreter.rb +2 -0
- data/lib/rex/payloads/meterpreter/patch.rb +136 -0
- data/lib/rex/payloads/win32/kernel/stager.rb +26 -25
- data/lib/rex/post/meterpreter/client.rb +50 -60
- data/lib/rex/post/meterpreter/client_core.rb +18 -25
- data/lib/rex/post/meterpreter/extensions/extapi/adsi/adsi.rb +102 -8
- data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +24 -14
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +18 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +1 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +43 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +9 -0
- data/lib/rex/proto/dcerpc/svcctl.rb +2 -0
- data/lib/rex/proto/dcerpc/svcctl/packet.rb +304 -0
- data/lib/rex/proto/kademlia.rb +8 -0
- data/lib/rex/proto/kademlia/bootstrap_request.rb +19 -0
- data/lib/rex/proto/kademlia/bootstrap_response.rb +79 -0
- data/lib/rex/proto/kademlia/message.rb +72 -0
- data/lib/rex/proto/kademlia/ping.rb +19 -0
- data/lib/rex/proto/kademlia/pong.rb +41 -0
- data/lib/rex/proto/kademlia/util.rb +22 -0
- data/lib/rex/proto/natpmp/packet.rb +30 -2
- data/lib/rex/proto/quake.rb +3 -0
- data/lib/rex/proto/quake/message.rb +73 -0
- data/lib/rex/proto/smb/client.rb +1 -0
- data/lib/rex/proto/smb/simpleclient.rb +4 -0
- data/lib/rex/proto/sunrpc/client.rb +14 -3
- data/lib/rex/socket/comm/local.rb +10 -7
- data/lib/rex/socket/ssl_tcp_server.rb +79 -40
- data/lib/rex/ui/text/input/readline.rb +33 -6
- data/lib/rex/ui/text/output/file.rb +2 -2
- data/lib/rex/ui/text/output/stdio.rb +70 -14
- data/rex.gemspec +1 -1
- metadata +38 -3
@@ -48,14 +48,7 @@ class Adsi
|
|
48
48
|
|
49
49
|
response = client.send_request(request)
|
50
50
|
|
51
|
-
results =
|
52
|
-
response.each(TLV_TYPE_EXT_ADSI_RESULT) { |r|
|
53
|
-
result = []
|
54
|
-
r.each(TLV_TYPE_EXT_ADSI_VALUE) { |v|
|
55
|
-
result << v.value
|
56
|
-
}
|
57
|
-
results << result
|
58
|
-
}
|
51
|
+
results = extract_results(response)
|
59
52
|
|
60
53
|
return {
|
61
54
|
:fields => fields,
|
@@ -65,6 +58,107 @@ class Adsi
|
|
65
58
|
|
66
59
|
attr_accessor :client
|
67
60
|
|
61
|
+
protected
|
62
|
+
|
63
|
+
#
|
64
|
+
# Retrieve the results of the query from the response
|
65
|
+
# packet that was returned from Meterpreter.
|
66
|
+
#
|
67
|
+
# @param response [Packet] Reference to the received
|
68
|
+
# packet that was returned from Meterpreter.
|
69
|
+
#
|
70
|
+
# @return [Array[Array[[Hash]]] Collection of results from
|
71
|
+
# the ADSI query.
|
72
|
+
#
|
73
|
+
def extract_results(response)
|
74
|
+
results = []
|
75
|
+
|
76
|
+
response.each(TLV_TYPE_EXT_ADSI_RESULT) do |r|
|
77
|
+
results << extract_values(r)
|
78
|
+
end
|
79
|
+
|
80
|
+
results
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Extract a single row of results from a TLV group.
|
85
|
+
#
|
86
|
+
# @param tlv_container [Packet] Reference to the TLV
|
87
|
+
# group to pull the values from.
|
88
|
+
#
|
89
|
+
# @return [Array[Hash]] Collection of values from
|
90
|
+
# the single ADSI query result row.
|
91
|
+
#
|
92
|
+
def extract_values(tlv_container)
|
93
|
+
values = []
|
94
|
+
tlv_container.get_tlvs(TLV_TYPE_ANY).each do |v|
|
95
|
+
values << extract_value(v)
|
96
|
+
end
|
97
|
+
values
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Convert a single ADSI result value into a usable
|
102
|
+
# value that also describes its type.
|
103
|
+
#
|
104
|
+
# @param v [TLV] The TLV item that contains the value.
|
105
|
+
#
|
106
|
+
# @return [Hash] The type/value pair from the TLV.
|
107
|
+
#
|
108
|
+
def extract_value(v)
|
109
|
+
value = {
|
110
|
+
:type => :unknown
|
111
|
+
}
|
112
|
+
|
113
|
+
case v.type
|
114
|
+
when TLV_TYPE_EXT_ADSI_STRING
|
115
|
+
value = {
|
116
|
+
:type => :string,
|
117
|
+
:value => v.value
|
118
|
+
}
|
119
|
+
when TLV_TYPE_EXT_ADSI_NUMBER, TLV_TYPE_EXT_ADSI_BIGNUMBER
|
120
|
+
value = {
|
121
|
+
:type => :number,
|
122
|
+
:value => v.value
|
123
|
+
}
|
124
|
+
when TLV_TYPE_EXT_ADSI_BOOL
|
125
|
+
value = {
|
126
|
+
:type => :bool,
|
127
|
+
:value => v.value
|
128
|
+
}
|
129
|
+
when TLV_TYPE_EXT_ADSI_RAW
|
130
|
+
value = {
|
131
|
+
:type => :raw,
|
132
|
+
:value => v.value
|
133
|
+
}
|
134
|
+
when TLV_TYPE_EXT_ADSI_ARRAY
|
135
|
+
value = {
|
136
|
+
:type => :array,
|
137
|
+
:value => extract_values(v.value)
|
138
|
+
}
|
139
|
+
when TLV_TYPE_EXT_ADSI_PATH
|
140
|
+
value = {
|
141
|
+
:type => :path,
|
142
|
+
:volume => v.get_tlv_value(TLV_TYPE_EXT_ADSI_PATH_VOL),
|
143
|
+
:path => v.get_tlv_value(TLV_TYPE_EXT_ADSI_PATH_PATH),
|
144
|
+
:vol_type => v.get_tlv_value(TLV_TYPE_EXT_ADSI_PATH_TYPE)
|
145
|
+
}
|
146
|
+
when TLV_TYPE_EXT_ADSI_DN
|
147
|
+
values = v.get_tlvs(TLV_TYPE_ALL)
|
148
|
+
value = {
|
149
|
+
:type => :dn,
|
150
|
+
:label => values[0].value
|
151
|
+
}
|
152
|
+
|
153
|
+
if values[1].type == TLV_TYPE_EXT_ADSI_STRING
|
154
|
+
value[:string] = value[1].value
|
155
|
+
else
|
156
|
+
value[:raw] = value[1].value
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
value
|
161
|
+
end
|
68
162
|
end
|
69
163
|
|
70
164
|
end; end; end; end; end; end
|
@@ -54,21 +54,31 @@ TLV_TYPE_EXT_CLIPBOARD_MON_WIN_CLASS = TLV_META_TYPE_STRING | (TLV_TYPE_E
|
|
54
54
|
TLV_TYPE_EXT_CLIPBOARD_MON_DUMP = TLV_META_TYPE_BOOL | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 52)
|
55
55
|
TLV_TYPE_EXT_CLIPBOARD_MON_PURGE = TLV_META_TYPE_BOOL | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 53)
|
56
56
|
|
57
|
-
TLV_TYPE_EXT_ADSI_DOMAIN = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS +
|
58
|
-
TLV_TYPE_EXT_ADSI_FILTER = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS +
|
59
|
-
TLV_TYPE_EXT_ADSI_FIELD = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS +
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
57
|
+
TLV_TYPE_EXT_ADSI_DOMAIN = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 54)
|
58
|
+
TLV_TYPE_EXT_ADSI_FILTER = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 55)
|
59
|
+
TLV_TYPE_EXT_ADSI_FIELD = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 56)
|
60
|
+
TLV_TYPE_EXT_ADSI_RESULT = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 57)
|
61
|
+
TLV_TYPE_EXT_ADSI_MAXRESULTS = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 58)
|
62
|
+
TLV_TYPE_EXT_ADSI_PAGESIZE = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 59)
|
63
|
+
TLV_TYPE_EXT_ADSI_ARRAY = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 60)
|
64
|
+
TLV_TYPE_EXT_ADSI_STRING = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 61)
|
65
|
+
TLV_TYPE_EXT_ADSI_NUMBER = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 62)
|
66
|
+
TLV_TYPE_EXT_ADSI_BIGNUMBER = TLV_META_TYPE_QWORD | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 63)
|
67
|
+
TLV_TYPE_EXT_ADSI_BOOL = TLV_META_TYPE_BOOL | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 64)
|
68
|
+
TLV_TYPE_EXT_ADSI_RAW = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 65)
|
69
|
+
TLV_TYPE_EXT_ADSI_PATH = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 66)
|
70
|
+
TLV_TYPE_EXT_ADSI_PATH_VOL = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 67)
|
71
|
+
TLV_TYPE_EXT_ADSI_PATH_PATH = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 68)
|
72
|
+
TLV_TYPE_EXT_ADSI_PATH_TYPE = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 69)
|
73
|
+
TLV_TYPE_EXT_ADSI_DN = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 70)
|
64
74
|
|
65
|
-
TLV_TYPE_EXT_WMI_DOMAIN = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS +
|
66
|
-
TLV_TYPE_EXT_WMI_QUERY = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS +
|
67
|
-
TLV_TYPE_EXT_WMI_FIELD = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS +
|
68
|
-
TLV_TYPE_EXT_WMI_VALUE = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS +
|
69
|
-
TLV_TYPE_EXT_WMI_FIELDS = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS +
|
70
|
-
TLV_TYPE_EXT_WMI_VALUES = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS +
|
71
|
-
TLV_TYPE_EXT_WMI_ERROR = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS +
|
75
|
+
TLV_TYPE_EXT_WMI_DOMAIN = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 90)
|
76
|
+
TLV_TYPE_EXT_WMI_QUERY = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 91)
|
77
|
+
TLV_TYPE_EXT_WMI_FIELD = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 92)
|
78
|
+
TLV_TYPE_EXT_WMI_VALUE = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 93)
|
79
|
+
TLV_TYPE_EXT_WMI_FIELDS = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 94)
|
80
|
+
TLV_TYPE_EXT_WMI_VALUES = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 95)
|
81
|
+
TLV_TYPE_EXT_WMI_ERROR = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 96)
|
72
82
|
|
73
83
|
end
|
74
84
|
end
|
@@ -20,6 +20,8 @@ module Sys
|
|
20
20
|
###
|
21
21
|
class Config
|
22
22
|
|
23
|
+
SYSTEM_SID = 'S-1-5-18'
|
24
|
+
|
23
25
|
def initialize(client)
|
24
26
|
self.client = client
|
25
27
|
end
|
@@ -33,6 +35,22 @@ class Config
|
|
33
35
|
client.unicode_filter_encode( response.get_tlv_value(TLV_TYPE_USER_NAME) )
|
34
36
|
end
|
35
37
|
|
38
|
+
#
|
39
|
+
# Gets the SID of the current process/thread.
|
40
|
+
#
|
41
|
+
def getsid
|
42
|
+
request = Packet.create_request('stdapi_sys_config_getsid')
|
43
|
+
response = client.send_request(request)
|
44
|
+
response.get_tlv_value(TLV_TYPE_SID)
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Determine if the current process/thread is running as SYSTEM
|
49
|
+
#
|
50
|
+
def is_system?
|
51
|
+
getsid == SYSTEM_SID
|
52
|
+
end
|
53
|
+
|
36
54
|
#
|
37
55
|
# Returns a hash of requested environment variables, along with their values.
|
38
56
|
# If a requested value doesn't exist in the response, then the value wasn't found.
|
@@ -116,6 +116,7 @@ TLV_TYPE_OS_NAME = TLV_META_TYPE_STRING | 1041
|
|
116
116
|
TLV_TYPE_USER_NAME = TLV_META_TYPE_STRING | 1042
|
117
117
|
TLV_TYPE_ARCHITECTURE = TLV_META_TYPE_STRING | 1043
|
118
118
|
TLV_TYPE_LANG_SYSTEM = TLV_META_TYPE_STRING | 1044
|
119
|
+
TLV_TYPE_SID = TLV_META_TYPE_STRING | 1045
|
119
120
|
|
120
121
|
# Environment
|
121
122
|
TLV_TYPE_ENV_VARIABLE = TLV_META_TYPE_STRING | 1100
|
@@ -96,7 +96,7 @@ module PacketDispatcher
|
|
96
96
|
|
97
97
|
# If the first 4 bytes are "RECV", return the oldest packet from the outbound queue
|
98
98
|
if req.body[0,4] == "RECV"
|
99
|
-
rpkt = send_queue.
|
99
|
+
rpkt = send_queue.shift
|
100
100
|
resp.body = rpkt || ''
|
101
101
|
begin
|
102
102
|
cli.send_response(resp)
|
@@ -106,7 +106,7 @@ class Console
|
|
106
106
|
log_error("Operation timed out.")
|
107
107
|
rescue RequestError => info
|
108
108
|
log_error(info.to_s)
|
109
|
-
rescue Rex::
|
109
|
+
rescue Rex::InvalidDestination => e
|
110
110
|
log_error(e.message)
|
111
111
|
rescue ::Errno::EPIPE, ::OpenSSL::SSL::SSLError, ::IOError
|
112
112
|
self.client.kill
|
@@ -176,7 +176,7 @@ class Console::CommandDispatcher::Extapi::Adsi
|
|
176
176
|
)
|
177
177
|
|
178
178
|
objects[:results].each do |c|
|
179
|
-
table << c
|
179
|
+
table << to_table_row(c)
|
180
180
|
end
|
181
181
|
|
182
182
|
print_line
|
@@ -189,6 +189,48 @@ class Console::CommandDispatcher::Extapi::Adsi
|
|
189
189
|
return true
|
190
190
|
end
|
191
191
|
|
192
|
+
protected
|
193
|
+
|
194
|
+
#
|
195
|
+
# Convert an ADSI result row to a table row so that it can
|
196
|
+
# be rendered to screen appropriately.
|
197
|
+
#
|
198
|
+
# @param result [Array[Hash]] Array of type/value pairs.
|
199
|
+
#
|
200
|
+
# @return [Array[String]] Renderable view of the value.
|
201
|
+
#
|
202
|
+
def to_table_row(result)
|
203
|
+
values = []
|
204
|
+
|
205
|
+
result.each do |v|
|
206
|
+
case v[:type]
|
207
|
+
when :string, :number, :bool
|
208
|
+
values << v[:value].to_s
|
209
|
+
when :raw
|
210
|
+
# for UI level stuff, rendering raw as hex is really the only option
|
211
|
+
values << Rex::Text.to_hex(v[:value], '')
|
212
|
+
when :array
|
213
|
+
val = "#{to_table_row(v[:value]).join(", ")}"
|
214
|
+
|
215
|
+
# we'll truncate the output of the array because it could be excessive if we
|
216
|
+
# don't. Users who want the detail of this stuff should probably script it.
|
217
|
+
if val.length > 50
|
218
|
+
val = "<#{val[0,50]}..."
|
219
|
+
end
|
220
|
+
|
221
|
+
values << val
|
222
|
+
when :dn
|
223
|
+
values << "#{value[:label]}: #{value[:string] || Rex::Text.to_hex(value[:raw], '')}"
|
224
|
+
when :path
|
225
|
+
values << "Vol: #{v[:volume]}, Path: #{v[:path]}, Type: #{v[:vol_type]}"
|
226
|
+
when :unknown
|
227
|
+
values << "(unknown)"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
values
|
232
|
+
end
|
233
|
+
|
192
234
|
end
|
193
235
|
|
194
236
|
end
|
@@ -221,7 +221,7 @@ class Console::CommandDispatcher::Incognito
|
|
221
221
|
end
|
222
222
|
|
223
223
|
def system_privilege_check
|
224
|
-
|
224
|
+
unless client.sys.config.is_system?
|
225
225
|
print_line("[-] Warning: Not currently running as SYSTEM, not all tokens will be available")
|
226
226
|
print_line(" Call rev2self if primary process token is SYSTEM")
|
227
227
|
end
|
@@ -88,6 +88,7 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|
88
88
|
"getpid" => "Get the current process identifier",
|
89
89
|
"getprivs" => "Attempt to enable all privileges available to the current process",
|
90
90
|
"getuid" => "Get the user that the server is running as",
|
91
|
+
"getsid" => "Get the SID of the user that the server is running as",
|
91
92
|
"getenv" => "Get one or more environment variable values",
|
92
93
|
"kill" => "Terminate a process",
|
93
94
|
"ps" => "List running processes",
|
@@ -107,6 +108,7 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|
107
108
|
"getpid" => [ "stdapi_sys_process_getpid" ],
|
108
109
|
"getprivs" => [ "stdapi_sys_config_getprivs" ],
|
109
110
|
"getuid" => [ "stdapi_sys_config_getuid" ],
|
111
|
+
"getsid" => [ "stdapi_sys_config_getsid" ],
|
110
112
|
"getenv" => [ "stdapi_sys_config_getenv" ],
|
111
113
|
"kill" => [ "stdapi_sys_process_kill" ],
|
112
114
|
"ps" => [ "stdapi_sys_process_get_processes" ],
|
@@ -279,6 +281,13 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|
279
281
|
print_line("Server username: #{client.sys.config.getuid}")
|
280
282
|
end
|
281
283
|
|
284
|
+
#
|
285
|
+
# Display the SID of the user that the server is running as.
|
286
|
+
#
|
287
|
+
def cmd_getsid(*args)
|
288
|
+
print_line("Server SID: #{client.sys.config.getsid}")
|
289
|
+
end
|
290
|
+
|
282
291
|
#
|
283
292
|
# Get the value of one or more environment variables from the target.
|
284
293
|
#
|
@@ -0,0 +1,304 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
module Rex
|
3
|
+
|
4
|
+
###
|
5
|
+
# This module implements MSRPC functions that control creating, deleting,
|
6
|
+
# starting, stopping, and querying system services.
|
7
|
+
###
|
8
|
+
module Proto::DCERPC::SVCCTL
|
9
|
+
|
10
|
+
require 'rex/constants/windows'
|
11
|
+
NDR = Rex::Encoder::NDR
|
12
|
+
|
13
|
+
|
14
|
+
class Client
|
15
|
+
|
16
|
+
include Rex::Constants::Windows
|
17
|
+
|
18
|
+
attr_accessor :dcerpc_client
|
19
|
+
|
20
|
+
def initialize(dcerpc_client)
|
21
|
+
self.dcerpc_client = dcerpc_client
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the Windows Error Code in numeric format
|
25
|
+
#
|
26
|
+
# @param raw_error [String] the raw error code in binary format.
|
27
|
+
#
|
28
|
+
# @return [Integer] the Windows Error Code integer.
|
29
|
+
def error_code(raw_error)
|
30
|
+
raw_error.unpack('V').first
|
31
|
+
end
|
32
|
+
|
33
|
+
# Calls OpenSCManagerW() to obtain a handle to the service control manager.
|
34
|
+
#
|
35
|
+
# @param rhost [String] the target host.
|
36
|
+
# @param access [Fixnum] the access flags requested.
|
37
|
+
#
|
38
|
+
# @return [Array<String,Integer>] the handle to the service control manager or nil if
|
39
|
+
# the call is not successful and the Windows error code
|
40
|
+
def openscmanagerw(rhost, access = SC_MANAGER_ALL_ACCESS)
|
41
|
+
scm_handle = nil
|
42
|
+
scm_status = nil
|
43
|
+
stubdata =
|
44
|
+
NDR.uwstring("\\\\#{rhost}") +
|
45
|
+
NDR.long(0) +
|
46
|
+
NDR.long(access)
|
47
|
+
begin
|
48
|
+
response = dcerpc_client.call(OPEN_SC_MANAGER_W, stubdata)
|
49
|
+
if response
|
50
|
+
scm_status = error_code(response[20,4])
|
51
|
+
if scm_status == ERROR_SUCCESS
|
52
|
+
scm_handle = response[0,20]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
56
|
+
print_error("#{peer} - Error getting scm handle: #{e}")
|
57
|
+
end
|
58
|
+
|
59
|
+
[scm_handle, scm_status]
|
60
|
+
end
|
61
|
+
|
62
|
+
# Calls CreateServiceW() to create a system service. Returns a handle to
|
63
|
+
# the service on success, or nil.
|
64
|
+
#
|
65
|
+
# @param scm_handle [String] the SCM handle (from {#openscmanagerw}).
|
66
|
+
# @param service_name [String] the service name.
|
67
|
+
# @param display_name [String] the display name.
|
68
|
+
# @param binary_path [String] the path of the binary to run.
|
69
|
+
# @param opts [Hash] arguments for CreateServiceW()
|
70
|
+
# @option opts [Fixnum] :access (SERVICE_ALL_ACCESS) the access level.
|
71
|
+
# @option opts [Fixnum] :type (SERVICE_WIN32_OWN_PROCESS ||
|
72
|
+
# SERVICE_INTERACTIVE_PROCESS) the type of service.
|
73
|
+
# @option opts [Fixnum] :start (SERVICE_DEMAND_START) the start options.
|
74
|
+
# @option opts [Fixnum] :errors (SERVICE_ERROR_IGNORE) the error options.
|
75
|
+
# @option opts [Fixnum] :load_order_group (0) the load order group.
|
76
|
+
# @option opts [Fixnum] :dependencies (0) the dependencies of the service.
|
77
|
+
# @option opts [Fixnum] :service_start (0)
|
78
|
+
# @option opts [Fixnum] :password1 (0)
|
79
|
+
# @option opts [Fixnum] :password2 (0)
|
80
|
+
# @option opts [Fixnum] :password3 (0)
|
81
|
+
# @option opts [Fixnum] :password4 (0)
|
82
|
+
#
|
83
|
+
# @return [String, Integer] a handle to the created service, windows
|
84
|
+
# error code.
|
85
|
+
def createservicew(scm_handle, service_name, display_name, binary_path, opts)
|
86
|
+
default_opts = {
|
87
|
+
:access => SERVICE_ALL_ACCESS,
|
88
|
+
:type => SERVICE_WIN32_OWN_PROCESS || SERVICE_INTERACTIVE_PROCESS,
|
89
|
+
:start => SERVICE_DEMAND_START,
|
90
|
+
:errors => SERVICE_ERROR_IGNORE,
|
91
|
+
:load_order_group => 0,
|
92
|
+
:dependencies => 0,
|
93
|
+
:service_start => 0,
|
94
|
+
:password1 => 0,
|
95
|
+
:password2 => 0,
|
96
|
+
:password3 => 0,
|
97
|
+
:password4 => 0
|
98
|
+
}.merge(opts)
|
99
|
+
|
100
|
+
svc_handle = nil
|
101
|
+
svc_status = nil
|
102
|
+
stubdata = scm_handle +
|
103
|
+
NDR.wstring(service_name) +
|
104
|
+
NDR.uwstring(display_name) +
|
105
|
+
NDR.long(default_opts[:access]) +
|
106
|
+
NDR.long(default_opts[:type]) +
|
107
|
+
NDR.long(default_opts[:start]) +
|
108
|
+
NDR.long(default_opts[:errors]) +
|
109
|
+
NDR.wstring(binary_path) +
|
110
|
+
NDR.long(default_opts[:load_order_group]) +
|
111
|
+
NDR.long(default_opts[:dependencies]) +
|
112
|
+
NDR.long(default_opts[:service_start]) +
|
113
|
+
NDR.long(default_opts[:password1]) +
|
114
|
+
NDR.long(default_opts[:password2]) +
|
115
|
+
NDR.long(default_opts[:password3]) +
|
116
|
+
NDR.long(default_opts[:password4])
|
117
|
+
begin
|
118
|
+
response = dcerpc_client.call(CREATE_SERVICE_W, stubdata)
|
119
|
+
if response
|
120
|
+
svc_status = error_code(response[24,4])
|
121
|
+
|
122
|
+
if svc_status == ERROR_SUCCESS
|
123
|
+
svc_handle = response[4,20]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
127
|
+
print_error("#{peer} - Error creating service: #{e}")
|
128
|
+
end
|
129
|
+
|
130
|
+
return svc_handle, svc_status
|
131
|
+
end
|
132
|
+
|
133
|
+
# Calls ChangeServiceConfig2() to change the service description.
|
134
|
+
#
|
135
|
+
# @param svc_handle [String] the service handle to change.
|
136
|
+
# @param service_description [String] the service description.
|
137
|
+
#
|
138
|
+
# @return [Integer] Windows error code
|
139
|
+
def changeservicedescription(svc_handle, service_description)
|
140
|
+
svc_status = nil
|
141
|
+
stubdata =
|
142
|
+
svc_handle +
|
143
|
+
NDR.long(SERVICE_CONFIG_DESCRIPTION) +
|
144
|
+
NDR.long(1) + # lpInfo -> *SERVICE_DESCRIPTION
|
145
|
+
NDR.long(0x0200) + # SERVICE_DESCRIPTION struct
|
146
|
+
NDR.long(0x04000200) +
|
147
|
+
NDR.wstring(service_description)
|
148
|
+
begin
|
149
|
+
response = dcerpc_client.call(CHANGE_SERVICE_CONFIG2_W, stubdata) # ChangeServiceConfig2
|
150
|
+
svc_status = error_code(response)
|
151
|
+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
152
|
+
print_error("#{peer} - Error changing service description : #{e}")
|
153
|
+
end
|
154
|
+
|
155
|
+
svc_status
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
# Calls CloseHandle() to close a handle.
|
160
|
+
#
|
161
|
+
# @param handle [String] the handle to close.
|
162
|
+
#
|
163
|
+
# @return [Integer] Windows error code
|
164
|
+
def closehandle(handle)
|
165
|
+
svc_status = nil
|
166
|
+
begin
|
167
|
+
response = dcerpc_client.call(CLOSE_SERVICE_HANDLE, handle)
|
168
|
+
if response
|
169
|
+
svc_status = error_code(response[20,4])
|
170
|
+
end
|
171
|
+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
172
|
+
print_error("#{peer} - Error closing service handle: #{e}")
|
173
|
+
end
|
174
|
+
|
175
|
+
svc_status
|
176
|
+
end
|
177
|
+
|
178
|
+
# Calls OpenServiceW to obtain a handle to an existing service.
|
179
|
+
#
|
180
|
+
# @param scm_handle [String] the SCM handle (from {#openscmanagerw}).
|
181
|
+
# @param service_name [String] the name of the service to open.
|
182
|
+
# @param access [Fixnum] the level of access requested (default is maximum).
|
183
|
+
#
|
184
|
+
# @return [String, nil] the handle of the service opened, or nil on failure.
|
185
|
+
def openservicew(scm_handle, service_name, access = SERVICE_ALL_ACCESS)
|
186
|
+
svc_handle = nil
|
187
|
+
svc_status = nil
|
188
|
+
stubdata = scm_handle + NDR.wstring(service_name) + NDR.long(access)
|
189
|
+
begin
|
190
|
+
response = dcerpc_client.call(OPEN_SERVICE_W, stubdata)
|
191
|
+
if response
|
192
|
+
svc_status = error_code(response[20,4])
|
193
|
+
if svc_status == ERROR_SUCCESS
|
194
|
+
svc_handle = response[0,20]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
198
|
+
print_error("#{peer} - Error opening service handle: #{e}")
|
199
|
+
end
|
200
|
+
|
201
|
+
svc_handle
|
202
|
+
end
|
203
|
+
|
204
|
+
# Calls StartService() on a handle to an existing service in order to start
|
205
|
+
# it. Returns true on success, or false.
|
206
|
+
#
|
207
|
+
# @param svc_handle [String] the handle of the service (from {#openservicew}).
|
208
|
+
# @param magic1 [Fixnum] an unknown value.
|
209
|
+
# @param magic2 [Fixnum] another unknown value.
|
210
|
+
#
|
211
|
+
# @return [Integer] Windows error code
|
212
|
+
def startservice(svc_handle, magic1 = 0, magic2 = 0)
|
213
|
+
svc_status = nil
|
214
|
+
stubdata = svc_handle + NDR.long(magic1) + NDR.long(magic2)
|
215
|
+
|
216
|
+
begin
|
217
|
+
response = dcerpc_client.call(0x13, stubdata)
|
218
|
+
if response
|
219
|
+
svc_status = error_code(response)
|
220
|
+
end
|
221
|
+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
222
|
+
print_error("#{peer} - Error starting service: #{e}")
|
223
|
+
end
|
224
|
+
|
225
|
+
svc_status
|
226
|
+
end
|
227
|
+
|
228
|
+
# Stops a running service.
|
229
|
+
#
|
230
|
+
# @param svc_handle [String] the handle of the service (from {#openservicew}).
|
231
|
+
#
|
232
|
+
# @return [Integer] Windows error code
|
233
|
+
def stopservice(svc_handle)
|
234
|
+
dce_controlservice(svc_handle, SERVICE_CONTROL_STOP)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Controls an existing service.
|
238
|
+
#
|
239
|
+
# @param svc_handle [String] the handle of the service (from {#openservicew}).
|
240
|
+
# @param operation [Fixnum] the operation number to perform (1 = stop
|
241
|
+
# service; others are unknown).
|
242
|
+
#
|
243
|
+
# @return [Integer] Windows error code
|
244
|
+
def controlservice(svc_handle, operation)
|
245
|
+
svc_status = nil
|
246
|
+
begin
|
247
|
+
response = dcerpc_client.call(CONTROL_SERVICE, svc_handle + NDR.long(operation))
|
248
|
+
if response
|
249
|
+
svc_status = error_code(response[28,4])
|
250
|
+
end
|
251
|
+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
252
|
+
print_error("#{peer} - Error controlling service: #{e}")
|
253
|
+
end
|
254
|
+
|
255
|
+
svc_status
|
256
|
+
end
|
257
|
+
|
258
|
+
# Calls DeleteService() to delete a service.
|
259
|
+
#
|
260
|
+
# @param svc_handle [String] the handle of the service (from {#openservicew}).
|
261
|
+
#
|
262
|
+
# @return [Integer] Windows error code
|
263
|
+
def deleteservice(svc_handle)
|
264
|
+
svc_status = nil
|
265
|
+
begin
|
266
|
+
response = dcerpc_client.call(DELETE_SERVICE, svc_handle)
|
267
|
+
if response
|
268
|
+
svc_status = error_code(response)
|
269
|
+
end
|
270
|
+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
271
|
+
print_error("#{peer} - Error deleting service: #{e}")
|
272
|
+
end
|
273
|
+
|
274
|
+
svc_status
|
275
|
+
end
|
276
|
+
|
277
|
+
# Calls QueryServiceStatus() to query the status of a service.
|
278
|
+
#
|
279
|
+
# @param svc_handle [String] the handle of the service (from {#openservicew}).
|
280
|
+
#
|
281
|
+
# @return [Fixnum] Returns 0 if the query failed (i.e.: a state was returned
|
282
|
+
# that isn't implemented), 1 if the service is running, and
|
283
|
+
# 2 if the service is stopped.
|
284
|
+
def queryservice(svc_handle)
|
285
|
+
ret = 0
|
286
|
+
|
287
|
+
begin
|
288
|
+
response = dcerpc_client.call(QUERY_SERVICE_STATUS, svc_handle)
|
289
|
+
if response[0,9] == "\x10\x00\x00\x00\x04\x00\x00\x00\x01"
|
290
|
+
ret = 1
|
291
|
+
elsif response[0,9] == "\x10\x00\x00\x00\x01\x00\x00\x00\x00"
|
292
|
+
ret = 2
|
293
|
+
end
|
294
|
+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
295
|
+
print_error("#{peer} - Error deleting service: #{e}")
|
296
|
+
end
|
297
|
+
|
298
|
+
ret
|
299
|
+
end
|
300
|
+
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|