librex 0.0.70 → 0.0.71

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +5 -13
  2. data/README.markdown +5 -10
  3. data/Rakefile +1 -1
  4. data/lib/rex/arch.rb +1 -1
  5. data/lib/rex/encoder/bloxor/bloxor.rb +1 -0
  6. data/lib/rex/encoder/ndr.rb +1 -1
  7. data/lib/rex/exploitation/heaplib.rb +4 -2
  8. data/lib/rex/exploitation/powershell.rb +62 -0
  9. data/lib/rex/exploitation/powershell/function.rb +63 -0
  10. data/lib/rex/exploitation/powershell/obfu.rb +98 -0
  11. data/lib/rex/exploitation/powershell/output.rb +151 -0
  12. data/lib/rex/exploitation/powershell/param.rb +23 -0
  13. data/lib/rex/exploitation/powershell/parser.rb +183 -0
  14. data/lib/rex/exploitation/powershell/psh_methods.rb +70 -0
  15. data/lib/rex/exploitation/powershell/script.rb +99 -0
  16. data/lib/rex/exploitation/ropdb.rb +1 -0
  17. data/lib/rex/mac_oui.rb +1 -0
  18. data/lib/rex/ole/util.rb +2 -2
  19. data/lib/rex/parser/group_policy_preferences.rb +185 -0
  20. data/lib/rex/parser/outpost24_nokogiri.rb +1 -0
  21. data/lib/rex/poly/machine.rb +1 -0
  22. data/lib/rex/poly/machine/machine.rb +1 -0
  23. data/lib/rex/poly/machine/x86.rb +1 -0
  24. data/lib/rex/post/meterpreter/extensions/android/android.rb +128 -0
  25. data/lib/rex/post/meterpreter/extensions/android/tlv.rb +40 -0
  26. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_psapi.rb +32 -0
  27. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +6 -6
  28. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +4 -4
  29. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +2 -1
  30. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb +4 -4
  31. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +4 -4
  32. data/lib/rex/post/meterpreter/packet.rb +3 -3
  33. data/lib/rex/post/meterpreter/ui/console.rb +2 -0
  34. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +383 -0
  35. data/lib/rex/proto/dcerpc/ndr.rb +1 -1
  36. data/lib/rex/proto/ipmi/channel_auth_reply.rb +1 -0
  37. data/lib/rex/proto/ipmi/open_session_reply.rb +1 -0
  38. data/lib/rex/proto/ipmi/rakp2.rb +1 -0
  39. data/lib/rex/proto/natpmp/packet.rb +8 -8
  40. data/lib/rex/proto/ntp.rb +3 -0
  41. data/lib/rex/proto/ntp/constants.rb +12 -0
  42. data/lib/rex/proto/ntp/modes.rb +130 -0
  43. data/lib/rex/proto/pjl.rb +1 -0
  44. data/lib/rex/proto/pjl/client.rb +1 -0
  45. data/lib/rex/proto/sip.rb +4 -0
  46. data/lib/rex/proto/sip/response.rb +61 -0
  47. data/lib/rex/proto/smb/exceptions.rb +11 -3
  48. data/lib/rex/random_identifier_generator.rb +1 -0
  49. data/lib/rex/registry/lfkey.rb +1 -1
  50. data/lib/rex/registry/nodekey.rb +10 -10
  51. data/lib/rex/registry/valuekey.rb +5 -5
  52. data/lib/rex/registry/valuelist.rb +1 -1
  53. data/lib/rex/socket/ip.rb +1 -0
  54. data/lib/rex/sslscan/result.rb +1 -0
  55. data/lib/rex/sslscan/scanner.rb +1 -0
  56. data/lib/rex/text.rb +2 -13
  57. data/lib/rex/ui/text/output/buffer/stdout.rb +1 -0
  58. data/lib/rex/ui/text/table.rb +4 -4
  59. metadata +23 -4
@@ -34,7 +34,7 @@ class NDR
34
34
  # byte element_1;
35
35
  def self.byte(string)
36
36
  warn 'should be using Rex::Encoder::NDR'
37
- return [string].pack('c')
37
+ return [string].pack('C')
38
38
  end
39
39
 
40
40
  # Encode a byte array
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
 
2
3
  module Rex
3
4
  module Proto
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
 
2
3
  module Rex
3
4
  module Proto
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
 
2
3
  module Rex
3
4
  module Proto
@@ -12,32 +12,32 @@ module Proto
12
12
  module NATPMP
13
13
 
14
14
  # Return a NAT-PMP request to get the external address.
15
- def self.external_address_request
15
+ def external_address_request
16
16
  [ 0, 0 ].pack('nn')
17
17
  end
18
18
 
19
19
  # Parse a NAT-PMP external address response +resp+.
20
20
  # Returns the decoded parts of the response as an array.
21
- def self.parse_external_address_response(resp)
22
- (ver, op, result, epoch, addr) = resp.unpack("CCSLN")
21
+ def parse_external_address_response(resp)
22
+ (ver, op, result, epoch, addr) = resp.unpack("CCnNN")
23
23
  [ ver, op, result, epoch, Rex::Socket::addr_itoa(addr) ]
24
24
  end
25
25
 
26
26
  # Return a NAT-PMP request to map remote port +rport+/+protocol+ to local port +lport+ for +lifetime+ ms
27
- def self.map_port_request(lport, rport, protocol, lifetime)
28
- [ Rex::Proto::NATPMP::Version, # version
27
+ def map_port_request(lport, rport, protocol, lifetime)
28
+ [ Rex::Proto::NATPMP::Version, # version
29
29
  protocol, # opcode, which is now the protocol we are asking to forward
30
30
  0, # reserved
31
31
  lport,
32
32
  rport,
33
33
  lifetime
34
- ].pack("ccnnnN")
34
+ ].pack("CCnnnN")
35
35
  end
36
36
 
37
37
  # Parse a NAT-PMP mapping response +resp+.
38
38
  # Returns the decoded parts as an array.
39
- def self.parse_map_port_response(resp)
40
- resp.unpack("CCSLnnN")
39
+ def parse_map_port_response(resp)
40
+ resp.unpack("CCnNnnN")
41
41
  end
42
42
  end
43
43
 
@@ -0,0 +1,3 @@
1
+ # -*- coding: binary -*-
2
+ require 'rex/proto/ntp/constants'
3
+ require 'rex/proto/ntp/modes'
@@ -0,0 +1,12 @@
1
+ # -*- coding: binary -*-
2
+ module Rex
3
+ module Proto
4
+ module NTP
5
+ VERSIONS = (0..7).to_a
6
+ MODES = (0..7).to_a
7
+ MODE_6_OPERATIONS = (0..31).to_a
8
+ MODE_7_IMPLEMENTATIONS = (0..255).to_a
9
+ MODE_7_REQUEST_CODES = (0..255).to_a
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,130 @@
1
+ # -*- coding: binary -*-
2
+
3
+ require 'bit-struct'
4
+
5
+ module Rex
6
+ module Proto
7
+ module NTP
8
+
9
+ # A very generic NTP message
10
+ #
11
+ # Uses the common/similar parts from versions 1-4 and considers everything
12
+ # after to be just one big field. For the particulars on the different versions,
13
+ # see:
14
+ # http://tools.ietf.org/html/rfc958#appendix-B
15
+ # http://tools.ietf.org/html/rfc1059#appendix-B
16
+ # pages 45/48 of http://tools.ietf.org/pdf/rfc1119.pdf
17
+ # http://tools.ietf.org/html/rfc1305#appendix-D
18
+ # http://tools.ietf.org/html/rfc5905#page-19
19
+ class NTPGeneric < BitStruct
20
+ # 0 1 2 3
21
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
22
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23
+ # |LI | VN | mode| Stratum | Poll | Precision |
24
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25
+ unsigned :li, 2, default: 0
26
+ unsigned :version, 3, default: 0
27
+ unsigned :mode, 3, default: 0
28
+ unsigned :stratum, 8, default: 0
29
+ unsigned :poll, 8, default: 0
30
+ unsigned :precision, 8, default: 0
31
+ rest :payload
32
+ end
33
+
34
+ # An NTP control message. Control messages are only specified for NTP
35
+ # versions 2-4, but this is a fuzzer so why not try them all...
36
+ class NTPControl < BitStruct
37
+ # 0 1 2 3
38
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
39
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40
+ # |00 | VN | 6 |R E M| op | Sequence |
41
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42
+ # | status | association id |
43
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44
+ # | offset | count |
45
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46
+ unsigned :reserved, 2, default: 0
47
+ unsigned :version, 3, default: 0
48
+ unsigned :mode, 3, default: 6
49
+ unsigned :response, 1, default: 0
50
+ unsigned :error, 1, default: 0
51
+ unsigned :more, 1, default: 0
52
+ unsigned :operation, 5, default: 0
53
+ unsigned :sequence, 16, default: 0
54
+ unsigned :status, 16, default: 0
55
+ unsigned :association_id, 16, default: 0
56
+ # TODO: there *must* be bugs in the handling of these next two fields!
57
+ unsigned :payload_offset, 16, default: 0
58
+ unsigned :payload_size, 16, default: 0
59
+ rest :payload
60
+ end
61
+
62
+ # An NTP "private" message. Private messages are only specified for NTP
63
+ # versions 2-4, but this is a fuzzer so why not try them all...
64
+ class NTPPrivate < BitStruct
65
+ # 0 1 2 3
66
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
67
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68
+ # |R M| VN | 7 |A| Sequence | Implementation| Req code |
69
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70
+ # | err | Number of data items | MBZ | Size of data item |
71
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72
+ unsigned :response, 1, default: 0
73
+ unsigned :more, 1, default: 0
74
+ unsigned :version, 3, default: 0
75
+ unsigned :mode, 3, default: 7
76
+ unsigned :auth, 1, default: 0
77
+ unsigned :sequence, 7, default: 0
78
+ unsigned :implementation, 8, default: 0
79
+ unsigned :request_code, 8, default: 0
80
+ unsigned :error, 4, default: 0
81
+ unsigned :record_count, 12, default: 0
82
+ unsigned :mbz, 4, default: 0
83
+ unsigned :record_size, 12, default: 0
84
+ rest :payload
85
+
86
+ def records
87
+ records = []
88
+ 1.upto(record_count) do |record_num|
89
+ records << payload[record_size*(record_num-1), record_size]
90
+ end
91
+ records
92
+ end
93
+ end
94
+
95
+ def self.ntp_control(version, operation, payload = nil)
96
+ n = NTPControl.new
97
+ n.version = version
98
+ n.operation = operation
99
+ if payload
100
+ n.payload_offset = 0
101
+ n.payload_size = payload.size
102
+ n.payload = payload
103
+ end
104
+ n
105
+ end
106
+
107
+ def self.ntp_private(version, implementation, request_code, payload = nil)
108
+ n = NTPPrivate.new
109
+ n.version = version
110
+ n.implementation = implementation
111
+ n.request_code = request_code
112
+ n.payload = payload if payload
113
+ n
114
+ end
115
+
116
+ def self.ntp_generic(version, mode)
117
+ n = NTPGeneric.new
118
+ n.version = version
119
+ n.mode = mode
120
+ n
121
+ end
122
+
123
+ # Parses the given message and provides a description about the NTP message inside
124
+ def self.describe(message)
125
+ ntp = NTPGeneric.new(message)
126
+ "#{message.size}-byte version #{ntp.version} mode #{ntp.mode} reply"
127
+ end
128
+ end
129
+ end
130
+ end
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
  # https://en.wikipedia.org/wiki/Printer_Job_Language
2
3
  # See external links for PJL spec
3
4
 
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
  # https://en.wikipedia.org/wiki/Printer_Job_Language
2
3
  # See external links for PJL spec
3
4
 
@@ -0,0 +1,4 @@
1
+ # encoding: binary
2
+
3
+ # SIP protocol support
4
+ require 'rex/proto/sip/response'
@@ -0,0 +1,61 @@
1
+ # encoding: binary
2
+
3
+ module Rex
4
+ module Proto
5
+ # SIP protocol support
6
+ module SIP
7
+ SIP_STATUS_REGEX = /^SIP\/(\d\.\d) (\d{3})\s*(.*)$/
8
+
9
+ # Represents a generic SIP message
10
+ class Message
11
+ attr_accessor :headers
12
+
13
+ def initialize
14
+ @headers = {}
15
+ end
16
+
17
+ # Returns a list of all values from all +name+ headers, regardless of case,
18
+ # or nil if no matching header is found
19
+ def header(name)
20
+ matches = @headers.select { |k, _| k.downcase == name.downcase }
21
+ return nil if matches.empty?
22
+ matches.values.flatten
23
+ end
24
+
25
+ # Returns a hash of header name to values mapping
26
+ # from the provided message, or nil if no headers
27
+ # are found
28
+ def self.extract_headers(message)
29
+ pairs = message.scan(/^([^\s:]+):\s*(.*)$/)
30
+ return nil if pairs.empty?
31
+ headers = {}
32
+ pairs.each do |pair|
33
+ headers[pair.first] ||= []
34
+ headers[pair.first] << pair.last.strip
35
+ end
36
+ headers
37
+ end
38
+ end
39
+
40
+ # Represents a SIP response message
41
+ class Response < Message
42
+ attr_accessor :code, :message, :status_line, :version
43
+
44
+ # Parses +data+, constructs and returns a Response
45
+ def self.parse(data)
46
+ response = Response.new
47
+ # do some basic sanity checking on this response to ensure that it is SIP
48
+ response.status_line = data.split(/\r\n/)[0]
49
+ unless response.status_line && response.status_line =~ SIP_STATUS_REGEX
50
+ fail(ArgumentError, "Invalid SIP status line: #{response.status_line}")
51
+ end
52
+ response.version = Regexp.last_match(1)
53
+ response.code = Regexp.last_match(2)
54
+ response.message = Regexp.last_match(3)
55
+ response.headers = extract_headers(data)
56
+ response
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -739,11 +739,15 @@ class Error < ::RuntimeError
739
739
  # returns an error string if it exists, otherwise just the error code
740
740
  def get_error(error)
741
741
  string = ''
742
- if @@errors[error]
742
+ if error && @@errors[error]
743
743
  string = @@errors[error]
744
- else
744
+ elsif error
745
745
  string = sprintf('0x%.8x',error)
746
+ else
747
+ string = "Unknown error"
746
748
  end
749
+
750
+ string
747
751
  end
748
752
  end
749
753
 
@@ -781,6 +785,10 @@ class InvalidPacket < Error
781
785
  attr_accessor :word_count
782
786
  attr_accessor :command
783
787
  attr_accessor :error_code
788
+
789
+ def error_name
790
+ get_error(error_code)
791
+ end
784
792
  end
785
793
 
786
794
  class InvalidWordCount < InvalidPacket
@@ -807,7 +815,7 @@ end
807
815
  class ErrorCode < InvalidPacket
808
816
  def to_s
809
817
  'The server responded with error: ' +
810
- self.get_error(self.error_code) +
818
+ self.error_name +
811
819
  " (Command=#{self.command} WordCount=#{self.word_count})"
812
820
  end
813
821
  end
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
 
2
3
  # A quick way to produce unique random strings that follow the rules of
3
4
  # identifiers, i.e., begin with a letter and contain only alphanumeric
@@ -41,7 +41,7 @@ class LFHashRecord
41
41
  attr_accessor :nodekey_offset, :nodekey_name_verification
42
42
 
43
43
  def initialize(hive_blob, offset)
44
- @nodekey_offset = hive_blob[offset, 4].unpack('l').first
44
+ @nodekey_offset = hive_blob[offset, 4].unpack('V').first
45
45
  @nodekey_name_verification = hive_blob[offset+0x04, 4].to_s
46
46
  end
47
47
 
@@ -23,16 +23,16 @@ class NodeKey
23
23
  return
24
24
  end
25
25
 
26
- @timestamp = hive[offset+0x04, 8].unpack('q').first
27
- @parent_offset = hive[offset+0x10, 4].unpack('l').first
28
- @subkeys_count = hive[offset+0x14, 4].unpack('l').first
29
- @lf_record_offset = hive[offset+0x1c, 4].unpack('l').first
30
- @value_count = hive[offset+0x24, 4].unpack('l').first
31
- @value_list_offset = hive[offset+0x28, 4].unpack('l').first
32
- @security_key_offset = hive[offset+0x2c, 4].unpack('l').first
33
- @class_name_offset = hive[offset+0x30, 4].unpack('l').first
34
- @name_length = hive[offset+0x48, 2].unpack('c').first
35
- @class_name_length = hive[offset+0x4a, 2].unpack('c').first
26
+ @timestamp = hive[offset+0x04, 8].unpack('Q').first
27
+ @parent_offset = hive[offset+0x10, 4].unpack('V').first
28
+ @subkeys_count = hive[offset+0x14, 4].unpack('V').first
29
+ @lf_record_offset = hive[offset+0x1c, 4].unpack('V').first
30
+ @value_count = hive[offset+0x24, 4].unpack('V').first
31
+ @value_list_offset = hive[offset+0x28, 4].unpack('V').first
32
+ @security_key_offset = hive[offset+0x2c, 4].unpack('V').first
33
+ @class_name_offset = hive[offset+0x30, 4].unpack('V').first
34
+ @name_length = hive[offset+0x48, 2].unpack('C').first
35
+ @class_name_length = hive[offset+0x4a, 2].unpack('C').first
36
36
  @name = hive[offset+0x4c, @name_length].to_s
37
37
 
38
38
  windows_time = @timestamp
@@ -17,10 +17,10 @@ class ValueKey
17
17
  return
18
18
  end
19
19
 
20
- @name_length = hive[offset+0x02, 2].unpack('c').first
21
- @length_of_data = hive[offset+0x04, 4].unpack('l').first
22
- @data_offset = hive[offset+ 0x08, 4].unpack('l').first
23
- @value_type = hive[offset+0x0C, 4].unpack('c').first
20
+ @name_length = hive[offset+0x02, 2].unpack('C').first
21
+ @length_of_data = hive[offset+0x04, 4].unpack('V').first
22
+ @data_offset = hive[offset+ 0x08, 4].unpack('V').first
23
+ @value_type = hive[offset+0x0C, 4].unpack('C').first
24
24
 
25
25
  if @value_type == 1
26
26
  @readable_value_type = "Unicode character string"
@@ -34,7 +34,7 @@ class ValueKey
34
34
  @readable_value_type = "Multiple unicode strings separated with '\\x00'"
35
35
  end
36
36
 
37
- flag = hive[offset+0x10, 2].unpack('c').first
37
+ flag = hive[offset+0x10, 2].unpack('C').first
38
38
 
39
39
  if flag == 0
40
40
  @name = "Default"
@@ -18,7 +18,7 @@ class ValueList
18
18
  valuekey_offset = hive[offset + inner_offset, 4]
19
19
  next if !valuekey_offset
20
20
 
21
- valuekey_offset = valuekey_offset.unpack('l').first
21
+ valuekey_offset = valuekey_offset.unpack('V').first
22
22
  @values << ValueKey.new(hive, valuekey_offset + 0x1000)
23
23
  inner_offset = inner_offset + 4
24
24
  end
@@ -75,6 +75,7 @@ module Rex::Socket::Ip
75
75
  Rex::Compat.is_macosx
76
76
  )
77
77
  gram=gram.dup
78
+ # Note that these are *intentionally* host order for BSD support
78
79
  gram[2,2]=gram[2,2].unpack("n").pack("s")
79
80
  gram[6,2]=gram[6,2].unpack("n").pack("s")
80
81
  end
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
 
2
3
  require 'rex/socket'
3
4
  require 'rex/ui/text/table'
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
  require 'rex/socket'
2
3
  require 'rex/sslscan/result'
3
4
 
@@ -3,6 +3,7 @@ require 'digest/md5'
3
3
  require 'digest/sha1'
4
4
  require 'stringio'
5
5
  require 'cgi'
6
+ require 'rex/exploitation/powershell'
6
7
 
7
8
  %W{ iconv zlib }.each do |libname|
8
9
  begin
@@ -305,19 +306,7 @@ module Text
305
306
  # Converts a raw string to a powershell byte array
306
307
  #
307
308
  def self.to_powershell(str, name = "buf")
308
- return "[Byte[]]$#{name} = ''" if str.nil? or str.empty?
309
-
310
- code = str.unpack('C*')
311
- buff = "[Byte[]]$#{name} = 0x#{code[0].to_s(16)}"
312
- 1.upto(code.length-1) do |byte|
313
- if(byte % 10 == 0)
314
- buff << "\r\n$#{name} += 0x#{code[byte].to_s(16)}"
315
- else
316
- buff << ",0x#{code[byte].to_s(16)}"
317
- end
318
- end
319
-
320
- return buff
309
+ return Rex::Exploitation::Powershell::Script.to_byte_array(str, name)
321
310
  end
322
311
 
323
312
  #