metasploit-framework/lib/msf/core/payload/uuid.rb

155 lines
4.1 KiB
Ruby
Raw Normal View History

2015-03-18 22:03:47 +00:00
# -*- coding => binary -*-
require 'msf/core/module/platform'
require 'rex/constants'
require 'rex/text'
#
# This module provides methods for calculating, extracting, and parsing
# unique ID values used by payloads.
#
class Msf::Payload::UUID
2015-03-18 22:03:47 +00:00
Architectures = {
0 => nil,
1 => ARCH_X86,
2 => ARCH_X86_64,
3 => ARCH_MIPS,
4 => ARCH_MIPSLE,
5 => ARCH_MIPSBE,
6 => ARCH_PPC,
7 => ARCH_PPC64,
8 => ARCH_CBEA,
9 => ARCH_CBEA64,
10 => ARCH_SPARC,
11 => ARCH_ARMLE,
12 => ARCH_ARMBE,
13 => ARCH_CMD,
14 => ARCH_PHP,
15 => ARCH_TTY,
16 => ARCH_JAVA,
17 => ARCH_RUBY,
18 => ARCH_DALVIK,
19 => ARCH_PYTHON,
20 => ARCH_NODEJS,
21 => ARCH_FIREFOX
}
Platforms = {
0 => nil,
1 => 'windows',
2 => 'netware',
3 => 'android',
4 => 'java',
5 => 'ruby',
6 => 'linux',
7 => 'cisco',
8 => 'solaris',
9 => 'osx',
10 => 'bsd',
11 => 'openbsd',
12 => 'bsdi',
13 => 'netbsd',
14 => 'freebsd',
15 => 'aix',
16 => 'hpux',
17 => 'irix',
18 => 'unix',
19 => 'php',
20 => 'js',
21 => 'python',
22 => 'nodejs',
23 => 'firefox'
}
RawLength = 16
UriLength = 22
2015-03-18 22:03:47 +00:00
#
2015-03-20 00:11:58 +00:00
# Generate a raw 16-byte payload UUID given a seed, platform, architecture, and timestamp
2015-03-18 22:03:47 +00:00
#
# @options opts [String] :seed A optional string to use for generated the unique payload ID, deterministic
# @options opts [String] :arch The hardware architecture for this payload
# @options opts [String] :platform The operating system platform for this payload
2015-03-20 00:11:58 +00:00
# @options opts [String] :timestamp The timestamp in UTC Unix epoch format
# @return [String] The encoded payoad UUID as a binary string
2015-03-18 22:03:47 +00:00
#
def self.payload_uuid_generate_raw(opts={})
2015-03-20 00:11:58 +00:00
plat_id = find_platform_id(opts[:platform]) || 0
arch_id = find_architecture_id(opts[:arch]) || 0
2015-03-18 22:03:47 +00:00
seed = opts[:seed] || Rex::Text.rand_text(16)
2015-03-20 00:11:58 +00:00
tstamp = opts[:timestamp] || Time.now.utc.to_i
2015-03-18 22:03:47 +00:00
plat_xor = rand(255)
arch_xor = rand(255)
2015-03-20 00:11:58 +00:00
# Recycle the previous two XOR bytes to keep our output small
time_xor = [plat_xor, arch_xor, plat_xor, arch_xor].pack('C4').unpack('N').first
2015-03-18 22:03:47 +00:00
# Combine the last 64-bits of the SHA1 of seed with the arch/platform
2015-03-20 00:11:58 +00:00
# Use XOR to obscure the platform, architecture, and timestamp
2015-03-18 22:03:47 +00:00
Rex::Text.sha1_raw(seed)[12,8] +
[
plat_xor, arch_xor,
plat_xor ^ plat_id,
2015-03-20 00:11:58 +00:00
arch_xor ^ arch_id,
time_xor ^ tstamp
].pack('C4N')
2015-03-18 22:03:47 +00:00
end
#
2015-03-20 00:11:58 +00:00
# Parse a raw 16-byte payload UUID and return the payload ID, platform, architecture, and timestamp
2015-03-18 22:03:47 +00:00
#
2015-03-20 00:11:58 +00:00
# @param raw [String] The raw 16-byte payload UUID to parse
# @return [Hash] A hash containing the Payload ID, platform, architecture, and timestamp
2015-03-18 22:03:47 +00:00
#
def self.payload_uuid_parse_raw(raw)
2015-03-20 00:11:58 +00:00
puid, plat_xor, arch_xor, plat_id, arch_id, tstamp = raw.unpack('A8C4N')
plat = find_platform_name(plat_xor ^ plat_id)
arch = find_architecture_name(arch_xor ^ arch_id)
time_xor = [plat_xor, arch_xor, plat_xor, arch_xor].pack('C4').unpack('N').first
time = time_xor ^ tstamp
{ puid: puid, platform: plat, arch: arch, timestamp: time }
2015-03-18 22:03:47 +00:00
end
# Alias for the class method
def payload_uuid_generate_raw(opts)
self.class.payload_uuid_generate_raw(opts)
end
# Alias for the class method
def parse_payload_uuid_raw(raw)
self.class.payload_uuid_parse_raw(raw)
end
def self.find_platform_id(platform)
# Handle a PlatformList input by grabbing the first entry
if platform.respond_to? :platforms
platform = platform.platforms.first.realname.downcase
end
# Map a platform abbreviation to the real name
name = Msf::Platform::Abbrev[platform]
Platforms.keys.select{ |k|
Platforms[k] == name
}.first || Platforms[0]
end
def self.find_architecture_id(name)
name = name.first if name.kind_of? ::Array
2015-03-18 22:03:47 +00:00
Architectures.keys.select{ |k|
Architectures[k] == name
}.first || Architectures[0]
end
def self.find_platform_name(num)
Platforms[num]
end
def self.find_architecture_name(num)
Architectures[num]
end
end