rex 2.0.8 → 2.0.9

Sign up to get free protection for your applications and to get access to all the features.
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