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.
- checksums.yaml +5 -13
- data/README.markdown +5 -10
- data/Rakefile +1 -1
- data/lib/rex/arch.rb +1 -1
- data/lib/rex/encoder/bloxor/bloxor.rb +1 -0
- data/lib/rex/encoder/ndr.rb +1 -1
- data/lib/rex/exploitation/heaplib.rb +4 -2
- data/lib/rex/exploitation/powershell.rb +62 -0
- data/lib/rex/exploitation/powershell/function.rb +63 -0
- data/lib/rex/exploitation/powershell/obfu.rb +98 -0
- data/lib/rex/exploitation/powershell/output.rb +151 -0
- data/lib/rex/exploitation/powershell/param.rb +23 -0
- data/lib/rex/exploitation/powershell/parser.rb +183 -0
- data/lib/rex/exploitation/powershell/psh_methods.rb +70 -0
- data/lib/rex/exploitation/powershell/script.rb +99 -0
- data/lib/rex/exploitation/ropdb.rb +1 -0
- data/lib/rex/mac_oui.rb +1 -0
- data/lib/rex/ole/util.rb +2 -2
- data/lib/rex/parser/group_policy_preferences.rb +185 -0
- data/lib/rex/parser/outpost24_nokogiri.rb +1 -0
- data/lib/rex/poly/machine.rb +1 -0
- data/lib/rex/poly/machine/machine.rb +1 -0
- data/lib/rex/poly/machine/x86.rb +1 -0
- data/lib/rex/post/meterpreter/extensions/android/android.rb +128 -0
- data/lib/rex/post/meterpreter/extensions/android/tlv.rb +40 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_psapi.rb +32 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +6 -6
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +4 -4
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +2 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb +4 -4
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +4 -4
- data/lib/rex/post/meterpreter/packet.rb +3 -3
- data/lib/rex/post/meterpreter/ui/console.rb +2 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +383 -0
- data/lib/rex/proto/dcerpc/ndr.rb +1 -1
- data/lib/rex/proto/ipmi/channel_auth_reply.rb +1 -0
- data/lib/rex/proto/ipmi/open_session_reply.rb +1 -0
- data/lib/rex/proto/ipmi/rakp2.rb +1 -0
- data/lib/rex/proto/natpmp/packet.rb +8 -8
- data/lib/rex/proto/ntp.rb +3 -0
- data/lib/rex/proto/ntp/constants.rb +12 -0
- data/lib/rex/proto/ntp/modes.rb +130 -0
- data/lib/rex/proto/pjl.rb +1 -0
- data/lib/rex/proto/pjl/client.rb +1 -0
- data/lib/rex/proto/sip.rb +4 -0
- data/lib/rex/proto/sip/response.rb +61 -0
- data/lib/rex/proto/smb/exceptions.rb +11 -3
- data/lib/rex/random_identifier_generator.rb +1 -0
- data/lib/rex/registry/lfkey.rb +1 -1
- data/lib/rex/registry/nodekey.rb +10 -10
- data/lib/rex/registry/valuekey.rb +5 -5
- data/lib/rex/registry/valuelist.rb +1 -1
- data/lib/rex/socket/ip.rb +1 -0
- data/lib/rex/sslscan/result.rb +1 -0
- data/lib/rex/sslscan/scanner.rb +1 -0
- data/lib/rex/text.rb +2 -13
- data/lib/rex/ui/text/output/buffer/stdout.rb +1 -0
- data/lib/rex/ui/text/table.rb +4 -4
- metadata +23 -4
data/lib/rex/proto/dcerpc/ndr.rb
CHANGED
data/lib/rex/proto/ipmi/rakp2.rb
CHANGED
@@ -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
|
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
|
22
|
-
(ver, op, result, epoch, addr) = resp.unpack("
|
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
|
28
|
-
[
|
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("
|
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
|
40
|
-
resp.unpack("
|
39
|
+
def parse_map_port_response(resp)
|
40
|
+
resp.unpack("CCnNnnN")
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -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
|
data/lib/rex/proto/pjl.rb
CHANGED
data/lib/rex/proto/pjl/client.rb
CHANGED
@@ -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
|
-
|
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.
|
818
|
+
self.error_name +
|
811
819
|
" (Command=#{self.command} WordCount=#{self.word_count})"
|
812
820
|
end
|
813
821
|
end
|
data/lib/rex/registry/lfkey.rb
CHANGED
@@ -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('
|
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
|
|
data/lib/rex/registry/nodekey.rb
CHANGED
@@ -23,16 +23,16 @@ class NodeKey
|
|
23
23
|
return
|
24
24
|
end
|
25
25
|
|
26
|
-
@timestamp = hive[offset+0x04, 8].unpack('
|
27
|
-
@parent_offset = hive[offset+0x10, 4].unpack('
|
28
|
-
@subkeys_count = hive[offset+0x14, 4].unpack('
|
29
|
-
@lf_record_offset = hive[offset+0x1c, 4].unpack('
|
30
|
-
@value_count = hive[offset+0x24, 4].unpack('
|
31
|
-
@value_list_offset = hive[offset+0x28, 4].unpack('
|
32
|
-
@security_key_offset = hive[offset+0x2c, 4].unpack('
|
33
|
-
@class_name_offset = hive[offset+0x30, 4].unpack('
|
34
|
-
@name_length = hive[offset+0x48, 2].unpack('
|
35
|
-
@class_name_length = hive[offset+0x4a, 2].unpack('
|
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('
|
21
|
-
@length_of_data = hive[offset+0x04, 4].unpack('
|
22
|
-
@data_offset = hive[offset+ 0x08, 4].unpack('
|
23
|
-
@value_type = hive[offset+0x0C, 4].unpack('
|
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('
|
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('
|
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
|
data/lib/rex/socket/ip.rb
CHANGED
data/lib/rex/sslscan/result.rb
CHANGED
data/lib/rex/sslscan/scanner.rb
CHANGED
data/lib/rex/text.rb
CHANGED
@@ -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
|
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
|
#
|