metasploit-aggregator 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,103 @@
1
+ # -*- coding: binary -*-
2
+ require 'metasploit/aggregator/tlv/packet'
3
+
4
+ module Metasploit
5
+ module Aggregator
6
+ module Tlv
7
+ ###
8
+ #
9
+ # This class is responsible for reading in and decrypting meterpreter
10
+ # packets that arrive on a socket
11
+ #
12
+ ###
13
+ class PacketParser
14
+
15
+ # 4 byte xor
16
+ # 4 byte length
17
+ # 4 byte type
18
+ HEADER_SIZE = 12
19
+
20
+ #
21
+ # Initializes the packet parser context with an optional cipher.
22
+ #
23
+ def initialize(cipher = nil)
24
+ self.cipher = cipher
25
+
26
+ reset
27
+ end
28
+
29
+ #
30
+ # Resets the parser state so that a new packet can begin being parsed.
31
+ #
32
+ def reset
33
+ self.raw = ''
34
+ self.hdr_length_left = HEADER_SIZE
35
+ self.payload_length_left = 0
36
+ end
37
+
38
+ #
39
+ # Reads data from the wire and parse as much of the packet as possible.
40
+ #
41
+ def recv(sock)
42
+ # Create a typeless packet
43
+ packet = Packet.new(0)
44
+
45
+ if (self.hdr_length_left > 0)
46
+ buf = sock.read(self.hdr_length_left)
47
+
48
+ if (buf)
49
+ self.raw << buf
50
+
51
+ self.hdr_length_left -= buf.length
52
+ else
53
+ raise EOFError
54
+ end
55
+
56
+ # If we've finished reading the header, set the
57
+ # payload length left to the number of bytes
58
+ # specified in the length
59
+ if (self.hdr_length_left == 0)
60
+ xor_key = raw[0, 4].unpack('N')[0]
61
+ length_bytes = packet.xor_bytes(xor_key, raw[4, 4])
62
+ # header size doesn't include the xor key, which is always tacked on the front
63
+ self.payload_length_left = length_bytes.unpack("N")[0] - (HEADER_SIZE - 4)
64
+ end
65
+ end
66
+ if (self.payload_length_left > 0)
67
+ buf = sock.read(self.payload_length_left)
68
+
69
+ if (buf)
70
+ self.raw << buf
71
+
72
+ self.payload_length_left -= buf.length
73
+ else
74
+ raise EOFError
75
+ end
76
+ end
77
+
78
+ # If we've finished reading the entire packet
79
+ if ((self.hdr_length_left == 0) &&
80
+ (self.payload_length_left == 0))
81
+
82
+ # TODO: cipher decryption
83
+ if (cipher)
84
+ end
85
+
86
+ # Deserialize the packet from the raw buffer
87
+ packet.from_r(self.raw)
88
+
89
+ # Reset our state
90
+ reset
91
+
92
+ return packet
93
+ end
94
+ end
95
+
96
+ protected
97
+ attr_accessor :cipher, :raw, :hdr_length_left, :payload_length_left # :nodoc:
98
+
99
+ end
100
+ end
101
+ end
102
+ end
103
+
@@ -0,0 +1,275 @@
1
+ # -*- coding => binary -*-
2
+ require 'rex/arch'
3
+ #
4
+ # This class provides methods for calculating, extracting, and parsing
5
+ # unique ID values used by payloads.
6
+ #
7
+ module Metasploit
8
+ module Aggregator
9
+ module Tlv
10
+ class UUID
11
+
12
+ include Rex::Arch
13
+ #
14
+ # Constants
15
+ #
16
+
17
+ Architectures = {
18
+ 0 => nil,
19
+ 1 => ARCH_X86,
20
+ 2 => ARCH_X64, # removed ARCH_X86_64, now consistent across the board
21
+ 3 => ARCH_X64,
22
+ 4 => ARCH_MIPS,
23
+ 5 => ARCH_MIPSLE,
24
+ 6 => ARCH_MIPSBE,
25
+ 7 => ARCH_PPC,
26
+ 8 => ARCH_PPC64,
27
+ 9 => ARCH_CBEA,
28
+ 10 => ARCH_CBEA64,
29
+ 11 => ARCH_SPARC,
30
+ 12 => ARCH_ARMLE,
31
+ 13 => ARCH_ARMBE,
32
+ 14 => ARCH_CMD,
33
+ 15 => ARCH_PHP,
34
+ 16 => ARCH_TTY,
35
+ 17 => ARCH_JAVA,
36
+ 18 => ARCH_RUBY,
37
+ 19 => ARCH_DALVIK,
38
+ 20 => ARCH_PYTHON,
39
+ 21 => ARCH_NODEJS,
40
+ 22 => ARCH_FIREFOX,
41
+ 23 => ARCH_ZARCH,
42
+ 24 => ARCH_AARCH64,
43
+ 25 => ARCH_MIPS64,
44
+ 26 => ARCH_PPC64LE
45
+ }
46
+
47
+ Platforms = {
48
+ 0 => nil,
49
+ 1 => 'windows',
50
+ 2 => 'netware',
51
+ 3 => 'android',
52
+ 4 => 'java',
53
+ 5 => 'ruby',
54
+ 6 => 'linux',
55
+ 7 => 'cisco',
56
+ 8 => 'solaris',
57
+ 9 => 'osx',
58
+ 10 => 'bsd',
59
+ 11 => 'openbsd',
60
+ 12 => 'bsdi',
61
+ 13 => 'netbsd',
62
+ 14 => 'freebsd',
63
+ 15 => 'aix',
64
+ 16 => 'hpux',
65
+ 17 => 'irix',
66
+ 18 => 'unix',
67
+ 19 => 'php',
68
+ 20 => 'js',
69
+ 21 => 'python',
70
+ 22 => 'nodejs',
71
+ 23 => 'firefox'
72
+ }
73
+
74
+ # The raw length of the UUID structure
75
+ RawLength = 16
76
+
77
+ # The base64url-encoded length of the UUID structure
78
+ UriLength = 22
79
+
80
+ # Validity constraints for UUID timestamps in UTC
81
+ TimestampMaxFuture = Time.now.utc.to_i + (30*24*3600) # Up to 30 days in the future
82
+ TimestampMaxPast = 1420070400 # Since 2015-01-01 00:00:00 UTC
83
+
84
+ #
85
+ # Class Methods
86
+ #
87
+
88
+ #
89
+ # Parse a raw 16-byte payload UUID and return the payload ID, platform, architecture, and timestamp
90
+ #
91
+ # @param raw [String] The raw 16-byte payload UUID to parse
92
+ # @return [Hash] A hash containing the Payload ID, platform, architecture, and timestamp
93
+ #
94
+ def self.parse_raw(raw)
95
+ if raw.to_s.length < 16
96
+ raise ArgumentError, "Raw UUID must be at least 16 bytes"
97
+ end
98
+
99
+ puid, plat_xor, arch_xor, plat_id, arch_id, tstamp = raw.unpack('a8C4N')
100
+ plat = find_platform_name(plat_xor ^ plat_id)
101
+ arch = find_architecture_name(arch_xor ^ arch_id)
102
+ time_xor = [plat_xor, arch_xor, plat_xor, arch_xor].pack('C4').unpack('N').first
103
+ time = time_xor ^ tstamp
104
+ { puid: puid, platform: plat, arch: arch, timestamp: time, xor1: plat_xor, xor2: arch_xor }
105
+ end
106
+
107
+ #
108
+ # Filter out UUIDs with obviously invalid fields and return either
109
+ # a validated UUID or a UUID with the arch, platform, and timestamp
110
+ # fields strippped out.
111
+ #
112
+ # @param uuid [Hash] The UUID in hash format
113
+ # @return [Hash] The filtered UUID in hash format
114
+ #
115
+ def self.filter_invalid(uuid)
116
+ # Verify the UUID fields and return just the Payload ID unless the
117
+ # timestamp is within our constraints and the UUID has either a
118
+ # valid architecture or platform
119
+ if uuid[:timestamp] > TimestampMaxFuture ||
120
+ uuid[:timestamp] < TimestampMaxPast ||
121
+ (uuid[:arch].nil? && uuid[:platform].nil?)
122
+ return { puid: uuid[:puid] }
123
+ end
124
+ uuid
125
+ end
126
+
127
+ #
128
+ # Look up the numeric platform ID given a string or PlatformList as input
129
+ #
130
+ # @param platform [String] The name of the platform to lookup
131
+ # @return [Fixnum] The integer value of this platform
132
+ #
133
+ def self.find_platform_id(platform)
134
+ name = name.first if name.kind_of? ::Array
135
+ ( Platforms.keys.select{ |k|
136
+ Platforms[k] == name
137
+ }.first || Platforms[0] ).to_i
138
+ end
139
+
140
+ #
141
+ # Look up the numeric architecture ID given a string as input
142
+ #
143
+ # @param name [String] The name of the architecture to lookup
144
+ # @return [Fixnum] The integer value of this architecture
145
+ #
146
+ def self.find_architecture_id(name)
147
+ name = name.first if name.kind_of? ::Array
148
+ ( Architectures.keys.select{ |k|
149
+ Architectures[k] == name
150
+ }.first || Architectures[0] ).to_i
151
+ end
152
+
153
+ def self.find_platform_name(num)
154
+ Platforms[num]
155
+ end
156
+
157
+ def self.find_architecture_name(num)
158
+ Architectures[num]
159
+ end
160
+
161
+ #
162
+ # Instance methods
163
+ #
164
+
165
+ def initialize(opts=nil)
166
+ opts = load_new if opts.nil?
167
+ opts = load_raw(opts[:raw]) if opts[:raw]
168
+
169
+ self.puid = opts[:puid]
170
+ self.timestamp = opts[:timestamp]
171
+ self.arch = opts[:arch]
172
+ self.platform = opts[:platform]
173
+ self.xor1 = opts[:xor1]
174
+ self.xor2 = opts[:xor2]
175
+
176
+ # Generate some sensible defaults
177
+ self.puid ||= SecureRandom.random_bytes(8)
178
+ self.xor1 ||= rand(256)
179
+ self.xor2 ||= rand(256)
180
+ self.timestamp ||= Time.now.utc.to_i
181
+ end
182
+
183
+ #
184
+ # Initializes a UUID object given a raw 16+ byte blob
185
+ #
186
+ # @param raw [String] The string containing at least 16 bytes of encoded data
187
+ # @return [Hash] The attributes encoded into this UUID
188
+ #
189
+ def load_raw(raw)
190
+ self.class.filter_invalid(self.class.parse_raw(raw))
191
+ end
192
+
193
+ def load_new
194
+ self.class.parse_raw(self.class.generate_raw())
195
+ end
196
+
197
+ #
198
+ # Provides a string representation of a UUID
199
+ #
200
+ # @return [String] The human-readable version of the UUID data
201
+ #
202
+ def to_s
203
+ arch_id = self.class.find_architecture_id(self.arch).to_s
204
+ plat_id = self.class.find_platform_id(self.platform).to_s
205
+ [
206
+ self.puid_hex,
207
+ [ self.arch || "noarch", arch_id ].join("="),
208
+ [ self.platform || "noplatform", plat_id ].join("="),
209
+ Time.at(self.timestamp.to_i).utc.strftime("%Y-%m-%dT%H:%M:%SZ")
210
+ ].join("/")
211
+ end
212
+
213
+ #
214
+ # Return a string that represents the Meterpreter arch/platform
215
+ #
216
+ def session_type
217
+ # mini-patch for x86 so that it renders x64 instead. This is
218
+ # mostly to keep various external modules happy.
219
+ arch = self.arch
220
+ if arch == ARCH_X86_64
221
+ arch = ARCH_X64
222
+ end
223
+ "#{arch}/#{self.platform}"
224
+ end
225
+
226
+ #
227
+ # Provides a hash representation of a UUID
228
+ #
229
+ # @return [Hash] The hash representation of the UUID suitable for creating a new one
230
+ #
231
+ def to_h
232
+ {
233
+ puid: self.puid,
234
+ arch: self.arch, platform: self.platform,
235
+ timestamp: self.timestamp,
236
+ xor1: self.xor1, xor2: self.xor2
237
+ }
238
+ end
239
+
240
+ #
241
+ # Provides a raw byte representation of a UUID
242
+ #
243
+ # @return [String] The 16-byte raw encoded version of the UUID
244
+ #
245
+ def to_raw
246
+ self.class.generate_raw(self.to_h)
247
+ end
248
+
249
+ #
250
+ # Provides a hex representation of the Payload UID of the UUID
251
+ #
252
+ # @return [String] The 16-byte hex string representing the Payload UID
253
+ #
254
+ def puid_hex
255
+ self.puid.unpack('H*').first
256
+ end
257
+
258
+ #
259
+ # Clears the two random XOR keys used for obfuscation
260
+ #
261
+ def xor_reset
262
+ self.xor1 = self.xor2 = nil
263
+ self
264
+ end
265
+
266
+ attr_accessor :arch
267
+ attr_accessor :platform
268
+ attr_accessor :timestamp
269
+ attr_accessor :puid
270
+ attr_accessor :xor1
271
+ attr_accessor :xor2
272
+ end
273
+ end
274
+ end
275
+ end
@@ -1,5 +1,5 @@
1
1
  module Metasploit
2
2
  module Aggregator
3
- VERSION = '0.1.1'
3
+ VERSION = '0.1.2'
4
4
  end
5
5
  end
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
  f.match(%r{^(test|spec|features)/})
18
18
  end
19
19
  spec.bindir = "bin"
20
- spec.executables << 'msfaggregator'
20
+ spec.executables << 'metasploit-aggregator'
21
21
  spec.require_paths = ["lib"]
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.13"
@@ -25,4 +25,5 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "rspec", "~> 3.0"
26
26
  spec.add_runtime_dependency 'msgpack'
27
27
  spec.add_runtime_dependency 'msgpack-rpc'
28
+ spec.add_runtime_dependency 'rex-arch'
28
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metasploit-aggregator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Metasploit Hackers
@@ -88,7 +88,7 @@ cert_chain:
88
88
  G+Hmcg1v810agasPdoydE0RTVZgEOOMoQ07qu7JFXVWZ9ZQpHT7qJATWL/b2csFG
89
89
  8mVuTXnyJOKRJA==
90
90
  -----END CERTIFICATE-----
91
- date: 2017-01-31 00:00:00.000000000 Z
91
+ date: 2017-02-02 00:00:00.000000000 Z
92
92
  dependencies:
93
93
  - !ruby/object:Gem::Dependency
94
94
  name: bundler
@@ -160,11 +160,25 @@ dependencies:
160
160
  - - ">="
161
161
  - !ruby/object:Gem::Version
162
162
  version: '0'
163
+ - !ruby/object:Gem::Dependency
164
+ name: rex-arch
165
+ requirement: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
170
+ type: :runtime
171
+ prerelease: false
172
+ version_requirements: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
163
177
  description: metasploit-aggregator
164
178
  email:
165
179
  - metasploit-hackers@lists.sourceforge.net
166
180
  executables:
167
- - msfaggregator
181
+ - metasploit-aggregator
168
182
  extensions: []
169
183
  extra_rdoc_files: []
170
184
  files:
@@ -177,7 +191,7 @@ files:
177
191
  - LICENSE
178
192
  - README.md
179
193
  - Rakefile
180
- - bin/msfaggregator
194
+ - bin/metasploit-aggregator
181
195
  - lib/metasploit/aggregator.rb
182
196
  - lib/metasploit/aggregator/cable.rb
183
197
  - lib/metasploit/aggregator/connection_manager.rb
@@ -192,6 +206,10 @@ files:
192
206
  - lib/metasploit/aggregator/https_forwarder.rb
193
207
  - lib/metasploit/aggregator/logger.rb
194
208
  - lib/metasploit/aggregator/router.rb
209
+ - lib/metasploit/aggregator/session_detail_service.rb
210
+ - lib/metasploit/aggregator/tlv/packet.rb
211
+ - lib/metasploit/aggregator/tlv/packet_parser.rb
212
+ - lib/metasploit/aggregator/tlv/uuid.rb
195
213
  - lib/metasploit/aggregator/version.rb
196
214
  - metasploit-aggregator.gemspec
197
215
  homepage: https://www.msf.com