librex 0.0.70 → 0.0.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  #