rex 2.0.8 → 2.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rex.rb +1 -0
- data/lib/rex/arch.rb +5 -0
- data/lib/rex/arch/x86.rb +19 -5
- data/lib/rex/arch/zarch.rb +17 -0
- data/lib/rex/compat.rb +5 -4
- data/lib/rex/constants.rb +3 -1
- data/lib/rex/encoder/alpha2/alpha_mixed.rb +70 -9
- data/lib/rex/encoder/alpha2/alpha_upper.rb +67 -8
- data/lib/rex/exploitation/cmdstager.rb +1 -0
- data/lib/rex/exploitation/cmdstager/certutil.rb +115 -0
- data/lib/rex/exploitation/cmdstager/echo.rb +6 -3
- data/lib/rex/exploitation/egghunter.rb +1 -1
- data/lib/rex/google/geolocation.rb +68 -0
- data/lib/rex/io/bidirectional_pipe.rb +0 -4
- data/lib/rex/java/serialization.rb +2 -0
- data/lib/rex/java/serialization/decode_error.rb +11 -0
- data/lib/rex/java/serialization/encode_error.rb +11 -0
- data/lib/rex/java/serialization/model.rb +2 -0
- data/lib/rex/java/serialization/model/annotation.rb +3 -3
- data/lib/rex/java/serialization/model/block_data.rb +3 -3
- data/lib/rex/java/serialization/model/block_data_long.rb +3 -3
- data/lib/rex/java/serialization/model/class_desc.rb +6 -6
- data/lib/rex/java/serialization/model/contents.rb +17 -10
- data/lib/rex/java/serialization/model/field.rb +12 -11
- data/lib/rex/java/serialization/model/long_utf.rb +3 -3
- data/lib/rex/java/serialization/model/new_array.rb +22 -23
- data/lib/rex/java/serialization/model/new_class.rb +57 -0
- data/lib/rex/java/serialization/model/new_class_desc.rb +15 -16
- data/lib/rex/java/serialization/model/new_enum.rb +5 -5
- data/lib/rex/java/serialization/model/new_object.rb +22 -17
- data/lib/rex/java/serialization/model/proxy_class_desc.rb +109 -0
- data/lib/rex/java/serialization/model/reference.rb +4 -4
- data/lib/rex/java/serialization/model/stream.rb +7 -7
- data/lib/rex/java/serialization/model/utf.rb +3 -3
- data/lib/rex/json_hash_file.rb +94 -0
- data/lib/rex/logging/log_sink.rb +1 -0
- data/lib/rex/logging/sinks/timestamp_flatfile.rb +21 -0
- data/lib/rex/parser/appscan_nokogiri.rb +13 -23
- data/lib/rex/parser/fs/ntfs.rb +10 -5
- data/lib/rex/parser/nmap_nokogiri.rb +3 -1
- data/lib/rex/parser/openvas_nokogiri.rb +70 -73
- data/lib/rex/parser/winscp.rb +108 -0
- data/lib/rex/parser/x509_certificate.rb +92 -0
- data/lib/rex/payloads.rb +0 -1
- data/lib/rex/payloads/meterpreter/config.rb +154 -0
- data/lib/rex/payloads/meterpreter/uri_checksum.rb +136 -0
- data/lib/rex/post/meterpreter.rb +1 -1
- data/lib/rex/post/meterpreter/client.rb +26 -3
- data/lib/rex/post/meterpreter/client_core.rb +387 -75
- data/lib/rex/post/meterpreter/extensions/android/android.rb +127 -37
- data/lib/rex/post/meterpreter/extensions/android/tlv.rb +46 -25
- data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +4 -0
- data/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb +39 -0
- data/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb +44 -0
- data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +9 -0
- data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +16 -1
- data/lib/rex/post/meterpreter/extensions/priv/priv.rb +1 -1
- data/lib/rex/post/meterpreter/extensions/python/python.rb +114 -0
- data/lib/rex/post/meterpreter/extensions/python/tlv.rb +21 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +17 -14
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +33 -12
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb +57 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3 -3
- data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +3 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +2 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +16 -3
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +29 -6
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +5 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +18 -6
- data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +2 -2
- data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +34 -36
- data/lib/rex/post/meterpreter/packet.rb +29 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +20 -7
- data/lib/rex/post/meterpreter/ui/console.rb +1 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +230 -72
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +544 -34
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +188 -57
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +115 -93
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +49 -15
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +11 -2
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/python.rb +187 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +324 -133
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +52 -2
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +68 -65
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +9 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +113 -118
- data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +3 -0
- data/lib/rex/powershell.rb +62 -0
- data/lib/rex/powershell/command.rb +359 -0
- data/lib/rex/{exploitation/powershell → powershell}/function.rb +0 -2
- data/lib/rex/{exploitation/powershell → powershell}/obfu.rb +0 -2
- data/lib/rex/{exploitation/powershell → powershell}/output.rb +11 -5
- data/lib/rex/{exploitation/powershell → powershell}/param.rb +0 -2
- data/lib/rex/powershell/parser.rb +182 -0
- data/lib/rex/powershell/payload.rb +78 -0
- data/lib/rex/{exploitation/powershell → powershell}/psh_methods.rb +16 -2
- data/lib/rex/{exploitation/powershell → powershell}/script.rb +2 -4
- data/lib/rex/proto/dcerpc/client.rb +6 -6
- data/lib/rex/proto/dcerpc/exceptions.rb +26 -0
- data/lib/rex/proto/http/client.rb +3 -3
- data/lib/rex/proto/http/client_request.rb +0 -5
- data/lib/rex/proto/http/response.rb +86 -0
- data/lib/rex/proto/ipmi/utils.rb +30 -26
- data/lib/rex/proto/kerberos/client.rb +1 -1
- data/lib/rex/proto/kerberos/model/kdc_request.rb +2 -2
- data/lib/rex/proto/rfb/client.rb +8 -3
- data/lib/rex/proto/rfb/constants.rb +1 -1
- data/lib/rex/proto/rmi.rb +2 -0
- data/lib/rex/proto/rmi/decode_error.rb +10 -0
- data/lib/rex/proto/rmi/exception.rb +10 -0
- data/lib/rex/proto/rmi/model.rb +5 -0
- data/lib/rex/proto/rmi/model/call.rb +4 -4
- data/lib/rex/proto/rmi/model/call_data.rb +137 -0
- data/lib/rex/proto/rmi/model/dgc_ack.rb +2 -2
- data/lib/rex/proto/rmi/model/element.rb +26 -11
- data/lib/rex/proto/rmi/model/output_header.rb +4 -4
- data/lib/rex/proto/rmi/model/ping.rb +2 -2
- data/lib/rex/proto/rmi/model/ping_ack.rb +2 -2
- data/lib/rex/proto/rmi/model/protocol_ack.rb +2 -2
- data/lib/rex/proto/rmi/model/return_data.rb +5 -5
- data/lib/rex/proto/rmi/model/return_value.rb +124 -0
- data/lib/rex/proto/rmi/model/unique_identifier.rb +77 -0
- data/lib/rex/proto/steam.rb +3 -0
- data/lib/rex/proto/steam/message.rb +125 -0
- data/lib/rex/proto/tftp/client.rb +35 -14
- data/lib/rex/random_identifier_generator.rb +2 -0
- data/lib/rex/ropbuilder.rb +1 -1
- data/lib/rex/socket/parameters.rb +9 -0
- data/lib/rex/socket/ssl_tcp.rb +25 -41
- data/lib/rex/socket/ssl_tcp_server.rb +10 -21
- data/lib/rex/sslscan/result.rb +20 -1
- data/lib/rex/text.rb +241 -55
- data/lib/rex/ui/output.rb +0 -3
- data/lib/rex/ui/subscriber.rb +0 -10
- data/lib/rex/ui/text/color.rb +9 -0
- data/lib/rex/ui/text/dispatcher_shell.rb +1 -0
- data/lib/rex/ui/text/output.rb +15 -4
- data/lib/rex/ui/text/output/file.rb +1 -0
- data/lib/rex/ui/text/output/stdio.rb +0 -16
- data/lib/rex/ui/text/shell.rb +3 -0
- data/lib/rex/ui/text/table.rb +85 -19
- data/lib/rex/user_agent.rb +118 -0
- data/rex.gemspec +2 -2
- metadata +41 -14
- data/lib/rex/exploitation/powershell.rb +0 -62
- data/lib/rex/exploitation/powershell/parser.rb +0 -183
- data/lib/rex/payloads/meterpreter.rb +0 -2
- data/lib/rex/payloads/meterpreter/patch.rb +0 -136
@@ -22,11 +22,11 @@ module Rex
|
|
22
22
|
#
|
23
23
|
# @param io [IO] the IO to read from
|
24
24
|
# @return [String]
|
25
|
-
# @raise [
|
25
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if fails to decode stream id
|
26
26
|
def decode_stream_id(io)
|
27
27
|
stream_id = read_byte(io)
|
28
28
|
unless stream_id == DGC_ACK_MESSAGE
|
29
|
-
raise ::
|
29
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to decode DgcAck stream id'
|
30
30
|
end
|
31
31
|
|
32
32
|
stream_id
|
@@ -83,42 +83,57 @@ module Rex
|
|
83
83
|
#
|
84
84
|
# @param io [IO] the IO to read from
|
85
85
|
# @return [Fixnum]
|
86
|
-
# @raise [
|
86
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if the byte can't be read from io
|
87
87
|
def read_byte(io)
|
88
88
|
raw = io.read(1)
|
89
|
-
raise ::
|
89
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to read byte' unless raw
|
90
90
|
|
91
|
-
raw.unpack('
|
91
|
+
raw.unpack('c')[0]
|
92
92
|
end
|
93
93
|
|
94
94
|
# Reads a two bytes short from an IO
|
95
95
|
#
|
96
96
|
# @param io [IO] the IO to read from
|
97
97
|
# @return [Fixnum]
|
98
|
-
# @raise [
|
98
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if the short can't be read from io
|
99
99
|
def read_short(io)
|
100
100
|
raw = io.read(2)
|
101
101
|
|
102
102
|
unless raw && raw.length == 2
|
103
|
-
raise ::
|
103
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to read short'
|
104
104
|
end
|
105
105
|
|
106
|
-
raw.unpack('
|
106
|
+
raw.unpack('s>')[0]
|
107
107
|
end
|
108
108
|
|
109
109
|
# Reads a four bytes int from an IO
|
110
110
|
#
|
111
111
|
# @param io [IO] the IO to read from
|
112
112
|
# @return [Fixnum]
|
113
|
-
# @raise [
|
113
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if the int can't be read from io
|
114
114
|
def read_int(io)
|
115
115
|
raw = io.read(4)
|
116
116
|
|
117
117
|
unless raw && raw.length == 4
|
118
|
-
raise ::
|
118
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to read int'
|
119
119
|
end
|
120
120
|
|
121
|
-
raw.unpack('
|
121
|
+
raw.unpack('l>')[0]
|
122
|
+
end
|
123
|
+
|
124
|
+
# Reads a 8 bytes long from an IO
|
125
|
+
#
|
126
|
+
# @param io [IO] the IO to read from
|
127
|
+
# @return [Fixnum]
|
128
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if the long can't be read from io
|
129
|
+
def read_long(io)
|
130
|
+
raw = io.read(8)
|
131
|
+
|
132
|
+
unless raw && raw.length == 8
|
133
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to read long'
|
134
|
+
end
|
135
|
+
|
136
|
+
raw.unpack('q>')[0]
|
122
137
|
end
|
123
138
|
|
124
139
|
# Reads an string from an IO
|
@@ -126,12 +141,12 @@ module Rex
|
|
126
141
|
# @param io [IO] the IO to read from
|
127
142
|
# @param length [Fixnum] the string length
|
128
143
|
# @return [String]
|
129
|
-
# @raise [
|
144
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if the string can't be read from io
|
130
145
|
def read_string(io, length)
|
131
146
|
raw = io.read(length)
|
132
147
|
|
133
148
|
unless raw && raw.length == length
|
134
|
-
raise ::
|
149
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to read string'
|
135
150
|
end
|
136
151
|
|
137
152
|
raw
|
@@ -23,11 +23,11 @@ module Rex
|
|
23
23
|
#
|
24
24
|
# @param io [IO] the IO to read from
|
25
25
|
# @return [String]
|
26
|
-
# @raise [
|
26
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if fails to decode signature
|
27
27
|
def decode_signature(io)
|
28
28
|
signature = read_string(io, 4)
|
29
29
|
unless signature == SIGNATURE
|
30
|
-
raise ::
|
30
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to decode OutputHeader signature'
|
31
31
|
end
|
32
32
|
|
33
33
|
signature
|
@@ -47,13 +47,13 @@ module Rex
|
|
47
47
|
#
|
48
48
|
# @param io [IO] the IO to read from
|
49
49
|
# @return [Fixnum]
|
50
|
-
# @raise [
|
50
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if fails to decode the protocol
|
51
51
|
def decode_protocol(io)
|
52
52
|
valid_protocols = [STREAM_PROTOCOL, SINGLE_OP_PROTOCOL, MULTIPLEX_PROTOCOL]
|
53
53
|
protocol = read_byte(io)
|
54
54
|
|
55
55
|
unless valid_protocols.include?(protocol)
|
56
|
-
raise ::
|
56
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to decode OutputHeader protocol'
|
57
57
|
end
|
58
58
|
|
59
59
|
protocol
|
@@ -18,11 +18,11 @@ module Rex
|
|
18
18
|
#
|
19
19
|
# @param io [IO] the IO to read from
|
20
20
|
# @return [String]
|
21
|
-
# @raise [
|
21
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if fails to decode stream id
|
22
22
|
def decode_stream_id(io)
|
23
23
|
stream_id = read_byte(io)
|
24
24
|
unless stream_id == PING_MESSAGE
|
25
|
-
raise ::
|
25
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to decode Ping stream id'
|
26
26
|
end
|
27
27
|
|
28
28
|
stream_id
|
@@ -18,11 +18,11 @@ module Rex
|
|
18
18
|
#
|
19
19
|
# @param io [IO] the IO to read from
|
20
20
|
# @return [String]
|
21
|
-
# @raise [
|
21
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if fails to decode stream id
|
22
22
|
def decode_stream_id(io)
|
23
23
|
stream_id = read_byte(io)
|
24
24
|
unless stream_id == PING_ACK
|
25
|
-
raise ::
|
25
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to decode PingAck stream id'
|
26
26
|
end
|
27
27
|
|
28
28
|
stream_id
|
@@ -26,11 +26,11 @@ module Rex
|
|
26
26
|
#
|
27
27
|
# @param io [IO] the IO to read from
|
28
28
|
# @return [String]
|
29
|
-
# @raise [
|
29
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if fails to decode stream id
|
30
30
|
def decode_stream_id(io)
|
31
31
|
stream_id = read_byte(io)
|
32
32
|
unless stream_id == PROTOCOL_ACK
|
33
|
-
raise ::
|
33
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to decode ProtocolAck stream id'
|
34
34
|
end
|
35
35
|
|
36
36
|
stream_id
|
@@ -11,7 +11,7 @@ module Rex
|
|
11
11
|
# @return [Fixnum] the stream id
|
12
12
|
attr_accessor :stream_id
|
13
13
|
# @!attribute return value
|
14
|
-
# @return [Rex::
|
14
|
+
# @return [Rex::Proto::Rmi::Model::ReturnValue] the return value
|
15
15
|
attr_accessor :return_value
|
16
16
|
|
17
17
|
private
|
@@ -20,11 +20,11 @@ module Rex
|
|
20
20
|
#
|
21
21
|
# @param io [IO] the IO to read from
|
22
22
|
# @return [String]
|
23
|
-
# @raise [
|
23
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if fails to decode the stream id
|
24
24
|
def decode_stream_id(io)
|
25
25
|
stream_id = read_byte(io)
|
26
26
|
unless stream_id == RETURN_DATA
|
27
|
-
raise ::
|
27
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to decode ReturnData stream id'
|
28
28
|
end
|
29
29
|
|
30
30
|
stream_id
|
@@ -33,9 +33,9 @@ module Rex
|
|
33
33
|
# Reads and deserializes the return value from the IO
|
34
34
|
#
|
35
35
|
# @param io [IO] the IO to read from
|
36
|
-
# @return [Rex::
|
36
|
+
# @return [Rex::Proto::Rmi::Model::ReturnValue]
|
37
37
|
def decode_return_value(io)
|
38
|
-
return_value = Rex::
|
38
|
+
return_value = Rex::Proto::Rmi::Model::ReturnValue.decode(io)
|
39
39
|
|
40
40
|
return_value
|
41
41
|
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
module Rex
|
4
|
+
module Proto
|
5
|
+
module Rmi
|
6
|
+
module Model
|
7
|
+
# This class provides a representation of an RMI return value
|
8
|
+
class ReturnValue < Element
|
9
|
+
|
10
|
+
# @!attribute code
|
11
|
+
# @return [Fixnum] the return code
|
12
|
+
attr_accessor :code
|
13
|
+
# @!attribute uid
|
14
|
+
# @return [Rex::Proto::Rmi::Model::UniqueIdentifier] unique identifier of the returned value
|
15
|
+
attr_accessor :uid
|
16
|
+
# @!attribute value
|
17
|
+
# @return [Array] the returned exception or value according to code
|
18
|
+
attr_accessor :value
|
19
|
+
|
20
|
+
# Encodes the Rex::Proto::Rmi::Model::ReturnValue into an String.
|
21
|
+
#
|
22
|
+
# @return [String]
|
23
|
+
def encode
|
24
|
+
stream = Rex::Java::Serialization::Model::Stream.new
|
25
|
+
block_data = Rex::Java::Serialization::Model::BlockData.new(nil, encode_code + encode_uid)
|
26
|
+
|
27
|
+
stream.contents << block_data
|
28
|
+
value.each do |v|
|
29
|
+
stream.contents << v
|
30
|
+
end
|
31
|
+
|
32
|
+
stream.encode
|
33
|
+
end
|
34
|
+
|
35
|
+
# Decodes the Rex::Proto::Rmi::Model::ReturnValue from the input.
|
36
|
+
#
|
37
|
+
# @param io [IO] the IO to read from
|
38
|
+
# @return [Rex::Proto::Rmi::Model::ReturnValue]
|
39
|
+
def decode(io)
|
40
|
+
stream = Rex::Java::Serialization::Model::Stream.decode(io)
|
41
|
+
|
42
|
+
block_data = stream.contents[0]
|
43
|
+
block_data_io = StringIO.new(block_data.contents, 'rb')
|
44
|
+
|
45
|
+
self.code = decode_code(block_data_io)
|
46
|
+
self.uid = decode_uid(block_data_io)
|
47
|
+
self.value = []
|
48
|
+
|
49
|
+
stream.contents[1..stream.contents.length - 1].each do |content|
|
50
|
+
self.value << content
|
51
|
+
end
|
52
|
+
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
# Answers if the ReturnValue is an exception
|
57
|
+
#
|
58
|
+
# @return [Boolean]
|
59
|
+
def is_exception?
|
60
|
+
code == RETURN_EXCEPTION
|
61
|
+
end
|
62
|
+
|
63
|
+
# The object/exception class of the returned value
|
64
|
+
#
|
65
|
+
# @return [String, NilClass] the returned value class, nil it cannot be retrieved
|
66
|
+
def get_class_name
|
67
|
+
unless value[0] && value[0].is_a?(Rex::Java::Serialization::Model::NewObject)
|
68
|
+
return nil
|
69
|
+
end
|
70
|
+
|
71
|
+
case value[0].class_desc.description
|
72
|
+
when Rex::Java::Serialization::Model::NewClassDesc
|
73
|
+
return value[0].class_desc.description.class_name.contents
|
74
|
+
when Rex::Java::Serialization::Model::ProxyClassDesc
|
75
|
+
return value[0].class_desc.description.interfaces[0].contents
|
76
|
+
else
|
77
|
+
return nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Reads the return code from the IO
|
84
|
+
#
|
85
|
+
# @param io [IO] the IO to read from
|
86
|
+
# @return [String]
|
87
|
+
# @raise [Rex::Proto::Rmi::DecodeError] if fails to decode the return code
|
88
|
+
def decode_code(io)
|
89
|
+
code = read_byte(io)
|
90
|
+
unless code == RETURN_VALUE || code == RETURN_EXCEPTION
|
91
|
+
raise Rex::Proto::Rmi::DecodeError, 'Failed to decode the ReturnValue code'
|
92
|
+
end
|
93
|
+
|
94
|
+
code
|
95
|
+
end
|
96
|
+
|
97
|
+
# Reads and deserializes the uid from the IO
|
98
|
+
#
|
99
|
+
# @param io [IO] the IO to read from
|
100
|
+
# @return [Rex::Proto::Rmi::Model::UniqueIdentifier]
|
101
|
+
def decode_uid(io)
|
102
|
+
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.decode(io)
|
103
|
+
|
104
|
+
uid
|
105
|
+
end
|
106
|
+
|
107
|
+
# Encodes the code field
|
108
|
+
#
|
109
|
+
# @return [String]
|
110
|
+
def encode_code
|
111
|
+
[code].pack('c')
|
112
|
+
end
|
113
|
+
|
114
|
+
# Encodes the uid field
|
115
|
+
#
|
116
|
+
# @return [String]
|
117
|
+
def encode_uid
|
118
|
+
uid.encode
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
module Rex
|
4
|
+
module Proto
|
5
|
+
module Rmi
|
6
|
+
module Model
|
7
|
+
# This class provides a representation of UniqueIdentifier as used in RMI calls
|
8
|
+
class UniqueIdentifier < Element
|
9
|
+
|
10
|
+
# @!attribute number
|
11
|
+
# @return [Fixnum] Identifies the VM where an object is generated
|
12
|
+
attr_accessor :number
|
13
|
+
# @!attribute time
|
14
|
+
# @return [Fixnum] Time where the object was generated
|
15
|
+
attr_accessor :time
|
16
|
+
# @!attribute count
|
17
|
+
# @return [Fixnum] Identifies different instance of the same object generated from the same VM
|
18
|
+
# at the same time
|
19
|
+
attr_accessor :count
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# Reads the number from the IO
|
24
|
+
#
|
25
|
+
# @param io [IO] the IO to read from
|
26
|
+
# @return [Fixnum]
|
27
|
+
def decode_number(io)
|
28
|
+
number = read_int(io)
|
29
|
+
|
30
|
+
number
|
31
|
+
end
|
32
|
+
|
33
|
+
# Reads the time from the IO
|
34
|
+
#
|
35
|
+
# @param io [IO] the IO to read from
|
36
|
+
# @return [Fixnum]
|
37
|
+
def decode_time(io)
|
38
|
+
time = read_long(io)
|
39
|
+
|
40
|
+
time
|
41
|
+
end
|
42
|
+
|
43
|
+
# Reads the count from the IO
|
44
|
+
#
|
45
|
+
# @param io [IO] the IO to read from
|
46
|
+
# @return [Fixnum]
|
47
|
+
def decode_count(io)
|
48
|
+
count = read_short(io)
|
49
|
+
|
50
|
+
count
|
51
|
+
end
|
52
|
+
|
53
|
+
# Encodes the number field
|
54
|
+
#
|
55
|
+
# @return [String]
|
56
|
+
def encode_number
|
57
|
+
[number].pack('l>')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Encodes the time field
|
61
|
+
#
|
62
|
+
# @return [String]
|
63
|
+
def encode_time
|
64
|
+
[time].pack('q>')
|
65
|
+
end
|
66
|
+
|
67
|
+
# Encodes the count field
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
def encode_count
|
71
|
+
[count].pack('s>')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
module Rex
|
4
|
+
module Proto
|
5
|
+
##
|
6
|
+
#
|
7
|
+
# Steam protocol support, taken from https://developer.valvesoftware.com/wiki/Server_queries
|
8
|
+
#
|
9
|
+
##
|
10
|
+
module Steam
|
11
|
+
# The Steam header ussed when the message is fragmented.
|
12
|
+
FRAGMENTED_HEADER = 0xFFFFFFFE
|
13
|
+
# The Steam header ussed when the message is not fragmented.
|
14
|
+
UNFRAGMENTED_HEADER = 0xFFFFFFFF
|
15
|
+
|
16
|
+
# Decodes a Steam response message.
|
17
|
+
#
|
18
|
+
# @param message [String] the message to decode
|
19
|
+
# @return [Array] the message type and body
|
20
|
+
def decode_message(message)
|
21
|
+
# minimum size is header (4) + type (1)
|
22
|
+
return if message.length < 5
|
23
|
+
header, type = message.unpack('NC')
|
24
|
+
# TODO: handle fragmented responses
|
25
|
+
return if header != UNFRAGMENTED_HEADER
|
26
|
+
[type, message[5, message.length]]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Encodes a Steam message.
|
30
|
+
#
|
31
|
+
# @param type [String, Fixnum] the message type
|
32
|
+
# @param body [String] the message body
|
33
|
+
# @return [String] the encoded Steam message
|
34
|
+
def encode_message(type, body)
|
35
|
+
if type.is_a? Fixnum
|
36
|
+
type_num = type
|
37
|
+
elsif type.is_a? String
|
38
|
+
type_num = type.ord
|
39
|
+
else
|
40
|
+
fail ArgumentError, 'type must be a String or Fixnum'
|
41
|
+
end
|
42
|
+
|
43
|
+
[UNFRAGMENTED_HEADER, type_num ].pack('NC') + body
|
44
|
+
end
|
45
|
+
|
46
|
+
# Builds an A2S_INFO message
|
47
|
+
#
|
48
|
+
# @return [String] the A2S_INFO message
|
49
|
+
def a2s_info
|
50
|
+
encode_message('T', "Source Engine Query\x00")
|
51
|
+
end
|
52
|
+
|
53
|
+
# Decodes an A2S_INFO response message
|
54
|
+
#
|
55
|
+
# @parameter response [String] the A2S_INFO resposne to decode
|
56
|
+
# @return [Hash] the fields extracted from the response
|
57
|
+
def a2s_info_decode(response)
|
58
|
+
# abort if it is impossibly short
|
59
|
+
return nil if response.length < 19
|
60
|
+
message_type, body = decode_message(response)
|
61
|
+
# abort if it isn't a valid Steam response
|
62
|
+
return nil if message_type != 0x49 # 'I'
|
63
|
+
info = {}
|
64
|
+
info[:version], info[:name], info[:map], info[:folder], info[:game_name],
|
65
|
+
info[:game_id], players, players_max, info[:bots],
|
66
|
+
type, env, vis, vac, info[:game_version], _edf = body.unpack("CZ*Z*Z*Z*SCCCCCCCZ*C")
|
67
|
+
|
68
|
+
# translate type
|
69
|
+
case type
|
70
|
+
when 100 # d
|
71
|
+
server_type = 'Dedicated'
|
72
|
+
when 108 # l
|
73
|
+
server_type = 'Non-dedicated'
|
74
|
+
when 112 # p
|
75
|
+
server_type = 'SourceTV relay (proxy)'
|
76
|
+
else
|
77
|
+
server_type = "Unknown (#{type})"
|
78
|
+
end
|
79
|
+
info[:type] = server_type
|
80
|
+
|
81
|
+
# translate environment
|
82
|
+
case env
|
83
|
+
when 108 # l
|
84
|
+
server_env = 'Linux'
|
85
|
+
when 119 # w
|
86
|
+
server_env = 'Windows'
|
87
|
+
when 109 # m
|
88
|
+
when 111 # o
|
89
|
+
server_env = 'Mac'
|
90
|
+
else
|
91
|
+
server_env = "Unknown (#{env})"
|
92
|
+
end
|
93
|
+
info[:environment] = server_env
|
94
|
+
|
95
|
+
# translate visibility
|
96
|
+
case vis
|
97
|
+
when 0
|
98
|
+
server_vis = 'public'
|
99
|
+
when 1
|
100
|
+
server_vis = 'private'
|
101
|
+
else
|
102
|
+
server_vis = "Unknown (#{vis})"
|
103
|
+
end
|
104
|
+
info[:visibility] = server_vis
|
105
|
+
|
106
|
+
# translate VAC
|
107
|
+
case vac
|
108
|
+
when 0
|
109
|
+
server_vac = 'unsecured'
|
110
|
+
when 1
|
111
|
+
server_vac = 'secured'
|
112
|
+
else
|
113
|
+
server_vac = "Unknown (#{vac})"
|
114
|
+
end
|
115
|
+
info[:VAC] = server_vac
|
116
|
+
|
117
|
+
# format players/max
|
118
|
+
info[:players] = "#{players}/#{players_max}"
|
119
|
+
|
120
|
+
# TODO: parse EDF
|
121
|
+
info
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|