rex 2.0.8 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rex.rb +1 -0
  3. data/lib/rex/arch.rb +5 -0
  4. data/lib/rex/arch/x86.rb +19 -5
  5. data/lib/rex/arch/zarch.rb +17 -0
  6. data/lib/rex/compat.rb +5 -4
  7. data/lib/rex/constants.rb +3 -1
  8. data/lib/rex/encoder/alpha2/alpha_mixed.rb +70 -9
  9. data/lib/rex/encoder/alpha2/alpha_upper.rb +67 -8
  10. data/lib/rex/exploitation/cmdstager.rb +1 -0
  11. data/lib/rex/exploitation/cmdstager/certutil.rb +115 -0
  12. data/lib/rex/exploitation/cmdstager/echo.rb +6 -3
  13. data/lib/rex/exploitation/egghunter.rb +1 -1
  14. data/lib/rex/google/geolocation.rb +68 -0
  15. data/lib/rex/io/bidirectional_pipe.rb +0 -4
  16. data/lib/rex/java/serialization.rb +2 -0
  17. data/lib/rex/java/serialization/decode_error.rb +11 -0
  18. data/lib/rex/java/serialization/encode_error.rb +11 -0
  19. data/lib/rex/java/serialization/model.rb +2 -0
  20. data/lib/rex/java/serialization/model/annotation.rb +3 -3
  21. data/lib/rex/java/serialization/model/block_data.rb +3 -3
  22. data/lib/rex/java/serialization/model/block_data_long.rb +3 -3
  23. data/lib/rex/java/serialization/model/class_desc.rb +6 -6
  24. data/lib/rex/java/serialization/model/contents.rb +17 -10
  25. data/lib/rex/java/serialization/model/field.rb +12 -11
  26. data/lib/rex/java/serialization/model/long_utf.rb +3 -3
  27. data/lib/rex/java/serialization/model/new_array.rb +22 -23
  28. data/lib/rex/java/serialization/model/new_class.rb +57 -0
  29. data/lib/rex/java/serialization/model/new_class_desc.rb +15 -16
  30. data/lib/rex/java/serialization/model/new_enum.rb +5 -5
  31. data/lib/rex/java/serialization/model/new_object.rb +22 -17
  32. data/lib/rex/java/serialization/model/proxy_class_desc.rb +109 -0
  33. data/lib/rex/java/serialization/model/reference.rb +4 -4
  34. data/lib/rex/java/serialization/model/stream.rb +7 -7
  35. data/lib/rex/java/serialization/model/utf.rb +3 -3
  36. data/lib/rex/json_hash_file.rb +94 -0
  37. data/lib/rex/logging/log_sink.rb +1 -0
  38. data/lib/rex/logging/sinks/timestamp_flatfile.rb +21 -0
  39. data/lib/rex/parser/appscan_nokogiri.rb +13 -23
  40. data/lib/rex/parser/fs/ntfs.rb +10 -5
  41. data/lib/rex/parser/nmap_nokogiri.rb +3 -1
  42. data/lib/rex/parser/openvas_nokogiri.rb +70 -73
  43. data/lib/rex/parser/winscp.rb +108 -0
  44. data/lib/rex/parser/x509_certificate.rb +92 -0
  45. data/lib/rex/payloads.rb +0 -1
  46. data/lib/rex/payloads/meterpreter/config.rb +154 -0
  47. data/lib/rex/payloads/meterpreter/uri_checksum.rb +136 -0
  48. data/lib/rex/post/meterpreter.rb +1 -1
  49. data/lib/rex/post/meterpreter/client.rb +26 -3
  50. data/lib/rex/post/meterpreter/client_core.rb +387 -75
  51. data/lib/rex/post/meterpreter/extensions/android/android.rb +127 -37
  52. data/lib/rex/post/meterpreter/extensions/android/tlv.rb +46 -25
  53. data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +4 -0
  54. data/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb +39 -0
  55. data/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb +44 -0
  56. data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +9 -0
  57. data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +16 -1
  58. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +1 -1
  59. data/lib/rex/post/meterpreter/extensions/python/python.rb +114 -0
  60. data/lib/rex/post/meterpreter/extensions/python/tlv.rb +21 -0
  61. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +17 -14
  62. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +33 -12
  63. data/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb +57 -0
  64. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3 -3
  65. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +3 -1
  66. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +2 -0
  67. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +16 -3
  68. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +29 -6
  69. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +5 -1
  70. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +18 -6
  71. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +2 -2
  72. data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +34 -36
  73. data/lib/rex/post/meterpreter/packet.rb +29 -0
  74. data/lib/rex/post/meterpreter/packet_dispatcher.rb +20 -7
  75. data/lib/rex/post/meterpreter/ui/console.rb +1 -0
  76. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +230 -72
  77. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +544 -34
  78. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +188 -57
  79. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +115 -93
  80. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +1 -1
  81. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +1 -1
  82. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +49 -15
  83. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +11 -2
  84. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/python.rb +187 -0
  85. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +324 -133
  86. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +52 -2
  87. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +68 -65
  88. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +9 -1
  89. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +113 -118
  90. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +3 -0
  91. data/lib/rex/powershell.rb +62 -0
  92. data/lib/rex/powershell/command.rb +359 -0
  93. data/lib/rex/{exploitation/powershell → powershell}/function.rb +0 -2
  94. data/lib/rex/{exploitation/powershell → powershell}/obfu.rb +0 -2
  95. data/lib/rex/{exploitation/powershell → powershell}/output.rb +11 -5
  96. data/lib/rex/{exploitation/powershell → powershell}/param.rb +0 -2
  97. data/lib/rex/powershell/parser.rb +182 -0
  98. data/lib/rex/powershell/payload.rb +78 -0
  99. data/lib/rex/{exploitation/powershell → powershell}/psh_methods.rb +16 -2
  100. data/lib/rex/{exploitation/powershell → powershell}/script.rb +2 -4
  101. data/lib/rex/proto/dcerpc/client.rb +6 -6
  102. data/lib/rex/proto/dcerpc/exceptions.rb +26 -0
  103. data/lib/rex/proto/http/client.rb +3 -3
  104. data/lib/rex/proto/http/client_request.rb +0 -5
  105. data/lib/rex/proto/http/response.rb +86 -0
  106. data/lib/rex/proto/ipmi/utils.rb +30 -26
  107. data/lib/rex/proto/kerberos/client.rb +1 -1
  108. data/lib/rex/proto/kerberos/model/kdc_request.rb +2 -2
  109. data/lib/rex/proto/rfb/client.rb +8 -3
  110. data/lib/rex/proto/rfb/constants.rb +1 -1
  111. data/lib/rex/proto/rmi.rb +2 -0
  112. data/lib/rex/proto/rmi/decode_error.rb +10 -0
  113. data/lib/rex/proto/rmi/exception.rb +10 -0
  114. data/lib/rex/proto/rmi/model.rb +5 -0
  115. data/lib/rex/proto/rmi/model/call.rb +4 -4
  116. data/lib/rex/proto/rmi/model/call_data.rb +137 -0
  117. data/lib/rex/proto/rmi/model/dgc_ack.rb +2 -2
  118. data/lib/rex/proto/rmi/model/element.rb +26 -11
  119. data/lib/rex/proto/rmi/model/output_header.rb +4 -4
  120. data/lib/rex/proto/rmi/model/ping.rb +2 -2
  121. data/lib/rex/proto/rmi/model/ping_ack.rb +2 -2
  122. data/lib/rex/proto/rmi/model/protocol_ack.rb +2 -2
  123. data/lib/rex/proto/rmi/model/return_data.rb +5 -5
  124. data/lib/rex/proto/rmi/model/return_value.rb +124 -0
  125. data/lib/rex/proto/rmi/model/unique_identifier.rb +77 -0
  126. data/lib/rex/proto/steam.rb +3 -0
  127. data/lib/rex/proto/steam/message.rb +125 -0
  128. data/lib/rex/proto/tftp/client.rb +35 -14
  129. data/lib/rex/random_identifier_generator.rb +2 -0
  130. data/lib/rex/ropbuilder.rb +1 -1
  131. data/lib/rex/socket/parameters.rb +9 -0
  132. data/lib/rex/socket/ssl_tcp.rb +25 -41
  133. data/lib/rex/socket/ssl_tcp_server.rb +10 -21
  134. data/lib/rex/sslscan/result.rb +20 -1
  135. data/lib/rex/text.rb +241 -55
  136. data/lib/rex/ui/output.rb +0 -3
  137. data/lib/rex/ui/subscriber.rb +0 -10
  138. data/lib/rex/ui/text/color.rb +9 -0
  139. data/lib/rex/ui/text/dispatcher_shell.rb +1 -0
  140. data/lib/rex/ui/text/output.rb +15 -4
  141. data/lib/rex/ui/text/output/file.rb +1 -0
  142. data/lib/rex/ui/text/output/stdio.rb +0 -16
  143. data/lib/rex/ui/text/shell.rb +3 -0
  144. data/lib/rex/ui/text/table.rb +85 -19
  145. data/lib/rex/user_agent.rb +118 -0
  146. data/rex.gemspec +2 -2
  147. metadata +41 -14
  148. data/lib/rex/exploitation/powershell.rb +0 -62
  149. data/lib/rex/exploitation/powershell/parser.rb +0 -183
  150. data/lib/rex/payloads/meterpreter.rb +0 -2
  151. 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 [RuntimeError] if fails to decode stream id
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 ::RuntimeError, 'Failed to decode DgcAck stream id'
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 [RuntimeError] if the byte can't be read from io
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 ::RuntimeError, 'Failed to read byte' unless raw
89
+ raise Rex::Proto::Rmi::DecodeError, 'Failed to read byte' unless raw
90
90
 
91
- raw.unpack('C')[0]
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 [RuntimeError] if the short can't be read from io
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 ::RuntimeError, 'Failed to read short'
103
+ raise Rex::Proto::Rmi::DecodeError, 'Failed to read short'
104
104
  end
105
105
 
106
- raw.unpack('n')[0]
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 [RuntimeError] if the int can't be read from io
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 ::RuntimeError, 'Failed to read short'
118
+ raise Rex::Proto::Rmi::DecodeError, 'Failed to read int'
119
119
  end
120
120
 
121
- raw.unpack('N')[0]
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 [RuntimeError] if the string can't be read from io
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 ::RuntimeError, 'Failed to read string'
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 [RuntimeError] if fails to decode signature
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 ::RuntimeError, 'Failed to decode OutputHeader signature'
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 [RuntimeError] if fails to decode the protocol
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 ::RuntimeError, 'Failed to decode OutputHeader protocol'
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 [RuntimeError] if fails to decode stream id
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 ::RuntimeError, 'Failed to decode Ping stream id'
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 [RuntimeError] if fails to decode stream id
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 ::RuntimeError, 'Failed to decode PingAck stream id'
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 [RuntimeError] if fails to decode stream id
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 ::RuntimeError, 'Failed to decode ProtocolAck stream id'
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::Java::Serialization::Model::Stream] the serialized return data
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 [RuntimeError] if fails to decode the stream id
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 ::RuntimeError, 'Failed to decode ReturnData stream id'
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::Java::Serialization::Model::Stream]
36
+ # @return [Rex::Proto::Rmi::Model::ReturnValue]
37
37
  def decode_return_value(io)
38
- return_value = Rex::Java::Serialization::Model::Stream.decode(io)
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,3 @@
1
+ # -*- coding: binary -*-
2
+
3
+ require 'rex/proto/steam/message'
@@ -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