rex 2.0.5 → 2.0.7
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 +4 -4
- data/lib/rex/exploitation/egghunter.rb +4 -6
- data/lib/rex/exploitation/powershell/psh_methods.rb +9 -0
- data/lib/rex/java/serialization.rb +2 -1
- data/lib/rex/java/serialization/builder.rb +94 -0
- data/lib/rex/java/serialization/model.rb +29 -18
- data/lib/rex/java/serialization/model/annotation.rb +2 -2
- data/lib/rex/java/serialization/model/field.rb +2 -2
- data/lib/rex/java/serialization/model/new_array.rb +8 -3
- data/lib/rex/java/serialization/model/new_class_desc.rb +3 -3
- data/lib/rex/java/serialization/model/new_enum.rb +4 -4
- data/lib/rex/java/serialization/model/new_object.rb +17 -10
- data/lib/rex/ole/direntry.rb +1 -1
- data/lib/rex/ole/samples/create_ole.rb +0 -0
- data/lib/rex/ole/samples/dir.rb +0 -0
- data/lib/rex/ole/samples/dump_stream.rb +0 -0
- data/lib/rex/ole/samples/ole_info.rb +0 -0
- data/lib/rex/parser/foundstone_nokogiri.rb +1 -1
- data/lib/rex/parser/fs/ntfs.rb +252 -0
- data/lib/rex/parser/openvas_nokogiri.rb +2 -0
- data/lib/rex/payloads/win32/kernel.rb +3 -3
- data/lib/rex/post/meterpreter/client_core.rb +172 -64
- data/lib/rex/post/meterpreter/extensions/priv/priv.rb +3 -2
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +12 -10
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb +64 -37
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +8 -2
- data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +15 -3
- data/lib/rex/post/meterpreter/packet.rb +41 -38
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +7 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +17 -4
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +11 -4
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +1 -1
- data/lib/rex/proto.rb +2 -0
- data/lib/rex/proto/acpp.rb +17 -0
- data/lib/rex/proto/acpp/client.rb +29 -0
- data/lib/rex/proto/acpp/message.rb +183 -0
- data/lib/rex/proto/http/client.rb +1 -2
- data/lib/rex/proto/iax2/call.rb +22 -3
- data/lib/rex/proto/iax2/client.rb +1 -0
- data/lib/rex/proto/kerberos.rb +13 -0
- data/lib/rex/proto/kerberos/client.rb +213 -0
- data/lib/rex/proto/kerberos/credential_cache.rb +19 -0
- data/lib/rex/proto/kerberos/credential_cache/cache.rb +81 -0
- data/lib/rex/proto/kerberos/credential_cache/credential.rb +151 -0
- data/lib/rex/proto/kerberos/credential_cache/element.rb +49 -0
- data/lib/rex/proto/kerberos/credential_cache/key_block.rb +62 -0
- data/lib/rex/proto/kerberos/credential_cache/principal.rb +70 -0
- data/lib/rex/proto/kerberos/credential_cache/time.rb +69 -0
- data/lib/rex/proto/kerberos/crypto.rb +21 -0
- data/lib/rex/proto/kerberos/crypto/rc4_hmac.rb +65 -0
- data/lib/rex/proto/kerberos/crypto/rsa_md5.rb +15 -0
- data/lib/rex/proto/kerberos/model.rb +133 -0
- data/lib/rex/proto/kerberos/model/ap_req.rb +98 -0
- data/lib/rex/proto/kerberos/model/authenticator.rb +143 -0
- data/lib/rex/proto/kerberos/model/authorization_data.rb +85 -0
- data/lib/rex/proto/kerberos/model/checksum.rb +59 -0
- data/lib/rex/proto/kerberos/model/element.rb +67 -0
- data/lib/rex/proto/kerberos/model/enc_kdc_response.rb +215 -0
- data/lib/rex/proto/kerberos/model/encrypted_data.rb +171 -0
- data/lib/rex/proto/kerberos/model/encryption_key.rb +106 -0
- data/lib/rex/proto/kerberos/model/kdc_request.rb +166 -0
- data/lib/rex/proto/kerberos/model/kdc_request_body.rb +315 -0
- data/lib/rex/proto/kerberos/model/kdc_response.rb +141 -0
- data/lib/rex/proto/kerberos/model/krb_error.rb +219 -0
- data/lib/rex/proto/kerberos/model/last_request.rb +82 -0
- data/lib/rex/proto/kerberos/model/pre_auth_data.rb +104 -0
- data/lib/rex/proto/kerberos/model/pre_auth_enc_time_stamp.rb +126 -0
- data/lib/rex/proto/kerberos/model/pre_auth_pac_request.rb +81 -0
- data/lib/rex/proto/kerberos/model/principal_name.rb +116 -0
- data/lib/rex/proto/kerberos/model/ticket.rb +151 -0
- data/lib/rex/proto/kerberos/pac.rb +36 -0
- data/lib/rex/proto/kerberos/pac/client_info.rb +53 -0
- data/lib/rex/proto/kerberos/pac/element.rb +52 -0
- data/lib/rex/proto/kerberos/pac/logon_info.rb +566 -0
- data/lib/rex/proto/kerberos/pac/priv_svr_checksum.rb +29 -0
- data/lib/rex/proto/kerberos/pac/server_checksum.rb +30 -0
- data/lib/rex/proto/kerberos/pac/type.rb +121 -0
- data/lib/rex/proto/rmi.rb +7 -0
- data/lib/rex/proto/rmi/model.rb +31 -0
- data/lib/rex/proto/rmi/model/call.rb +60 -0
- data/lib/rex/proto/rmi/model/continuation.rb +76 -0
- data/lib/rex/proto/rmi/model/dgc_ack.rb +62 -0
- data/lib/rex/proto/rmi/model/element.rb +143 -0
- data/lib/rex/proto/rmi/model/output_header.rb +86 -0
- data/lib/rex/proto/rmi/model/ping.rb +41 -0
- data/lib/rex/proto/rmi/model/ping_ack.rb +41 -0
- data/lib/rex/proto/rmi/model/protocol_ack.rb +100 -0
- data/lib/rex/proto/rmi/model/return_data.rb +60 -0
- data/lib/rex/socket.rb +9 -1
- data/lib/rex/socket/tcp_server.rb +3 -0
- data/lib/rex/ui/text/dispatcher_shell.rb +4 -4
- data/lib/rex/ui/text/output/tee.rb +2 -0
- data/lib/rex/zip/samples/comment.rb +0 -0
- data/lib/rex/zip/samples/mkwar.rb +0 -0
- data/lib/rex/zip/samples/mkzip.rb +0 -0
- data/lib/rex/zip/samples/recursive.rb +0 -0
- data/rex.gemspec +1 -1
- metadata +56 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5cc2f7d9e9457482ffe5b8935f8b93c4e57560cc
|
|
4
|
+
data.tar.gz: b6e6ee56e59286b54a62d28540e92fa6363dd6ae
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 17d81b1cda43811ec7acc076f4c903da5cb48316c399dd08abf2839df6e979b9de977f321e004ec1391fe86d472b450af2262f9be6a30aad8ddc30c2358a107e
|
|
7
|
+
data.tar.gz: f921d0e028d10c3b96eaaa65eff57a39d085dae29067d7e5b64addef567aff2043fc4079801a0cf11053abea603055a3d1ffcaeb9c3bf7788644bf44c0011d1c
|
|
@@ -65,12 +65,10 @@ class Egghunter
|
|
|
65
65
|
flippage = "\n\tor dx,0xfff"
|
|
66
66
|
edxdirection = "\n\tinc edx"
|
|
67
67
|
|
|
68
|
-
if searchforward
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
edxdirection = "\n\tdec edx"
|
|
73
|
-
end
|
|
68
|
+
if searchforward.to_s.downcase == 'false'
|
|
69
|
+
# go backwards
|
|
70
|
+
flippage = "\n\txor dl,dl"
|
|
71
|
+
edxdirection = "\n\tdec edx"
|
|
74
72
|
end
|
|
75
73
|
|
|
76
74
|
# other vars
|
|
@@ -64,6 +64,15 @@ module Powershell
|
|
|
64
64
|
def self.get_last_login(user)
|
|
65
65
|
%Q^ Get-QADComputer -ComputerRole DomainController | foreach { (Get-QADUser -Service $_.Name -SamAccountName "#{user}").LastLogon} | Measure-Latest^
|
|
66
66
|
end
|
|
67
|
+
|
|
68
|
+
#
|
|
69
|
+
# Disable SSL Certificate verification
|
|
70
|
+
#
|
|
71
|
+
# @return [String] Powershell code to disable SSL verification
|
|
72
|
+
# checks.
|
|
73
|
+
def self.ignore_ssl_certificate
|
|
74
|
+
'[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true};'
|
|
75
|
+
end
|
|
67
76
|
end
|
|
68
77
|
end
|
|
69
78
|
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# -*- coding: binary -*-
|
|
2
|
+
|
|
3
|
+
module Rex
|
|
4
|
+
module Java
|
|
5
|
+
module Serialization
|
|
6
|
+
# This class provides a builder to help in the construction of
|
|
7
|
+
# Java serialized contents.
|
|
8
|
+
class Builder
|
|
9
|
+
|
|
10
|
+
# Creates a Rex::Java::Serialization::Model::NewArray
|
|
11
|
+
#
|
|
12
|
+
# @param opts [Hash{Symbol => <Rex::Java::Serialization::Model::NewClassDesc, String, Array>}]
|
|
13
|
+
# @option opts [Rex::Java::Serialization::Model::NewClassDesc] :description
|
|
14
|
+
# @option opts [String] :values_type
|
|
15
|
+
# @option opts [Array] :values
|
|
16
|
+
# @return [Rex::Java::Serialization::Model::NewArray]
|
|
17
|
+
# @see #new_class
|
|
18
|
+
def new_array(opts = {})
|
|
19
|
+
class_desc = opts[:description] || new_class(opts)
|
|
20
|
+
type = opts[:values_type] || ''
|
|
21
|
+
values = opts[:values] || []
|
|
22
|
+
|
|
23
|
+
array = Rex::Java::Serialization::Model::NewArray.new
|
|
24
|
+
array.array_description = Rex::Java::Serialization::Model::ClassDesc.new
|
|
25
|
+
array.array_description.description = class_desc
|
|
26
|
+
array.type = type
|
|
27
|
+
array.values = values
|
|
28
|
+
|
|
29
|
+
array
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Creates a Rex::Java::Serialization::Model::NewObject
|
|
33
|
+
#
|
|
34
|
+
# @param opts [Hash{Symbol => <Rex::Java::Serialization::Model::NewClassDesc, Array>}]
|
|
35
|
+
# @option opts [Rex::Java::Serialization::Model::NewClassDesc] :description
|
|
36
|
+
# @option opts [Array] :data
|
|
37
|
+
# @return [Rex::Java::Serialization::Model::NewObject]
|
|
38
|
+
# @see #new_class
|
|
39
|
+
def new_object(opts = {})
|
|
40
|
+
class_desc = opts[:description] || new_class(opts)
|
|
41
|
+
data = opts[:data] || []
|
|
42
|
+
|
|
43
|
+
object = Rex::Java::Serialization::Model::NewObject.new
|
|
44
|
+
object.class_desc = Rex::Java::Serialization::Model::ClassDesc.new
|
|
45
|
+
object.class_desc.description = class_desc
|
|
46
|
+
object.class_data = data
|
|
47
|
+
|
|
48
|
+
object
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Creates a Rex::Java::Serialization::Model::NewClassDesc
|
|
52
|
+
#
|
|
53
|
+
# @param opts [Hash{Symbol => <Rex::Java::Serialization::Model::NewClassDesc, Array>}]
|
|
54
|
+
# @option opts [String] :name
|
|
55
|
+
# @option opts [Fixnum] :serial
|
|
56
|
+
# @option opts [Fixnum] :flags
|
|
57
|
+
# @option opts [Array] :fields
|
|
58
|
+
# @option opts [Array] :annotations
|
|
59
|
+
# @option opts [Rex::Java::Serialization::Model::Element] :super_class
|
|
60
|
+
# @return [Rex::Java::Serialization::Model::NewClassDesc]
|
|
61
|
+
def new_class(opts = {})
|
|
62
|
+
class_name = opts[:name] || ''
|
|
63
|
+
serial_version = opts[:serial] || 0
|
|
64
|
+
flags = opts[:flags] || 2
|
|
65
|
+
fields = opts[:fields] || []
|
|
66
|
+
annotations = opts[:annotations] || [Rex::Java::Serialization::Model::NullReference.new,
|
|
67
|
+
Rex::Java::Serialization::Model::EndBlockData.new]
|
|
68
|
+
super_class = opts[:super_class] || Rex::Java::Serialization::Model::NullReference.new
|
|
69
|
+
|
|
70
|
+
class_desc = Rex::Java::Serialization::Model::NewClassDesc.new
|
|
71
|
+
class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, class_name)
|
|
72
|
+
class_desc.serial_version = serial_version
|
|
73
|
+
class_desc.flags = flags
|
|
74
|
+
class_desc.fields = []
|
|
75
|
+
|
|
76
|
+
fields.each do |f|
|
|
77
|
+
field = Rex::Java::Serialization::Model::Field.new
|
|
78
|
+
field.type = f[0]
|
|
79
|
+
field.name = Rex::Java::Serialization::Model::Utf.new(nil, f[1])
|
|
80
|
+
field.field_type = Rex::Java::Serialization::Model::Utf.new(nil, f[2]) if f[2]
|
|
81
|
+
class_desc.fields << field
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new
|
|
85
|
+
class_desc.class_annotation.contents = annotations
|
|
86
|
+
class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new
|
|
87
|
+
class_desc.super_class.description = super_class
|
|
88
|
+
|
|
89
|
+
class_desc
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
# -*- coding: binary -*-
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
3
|
+
module Rex
|
|
4
|
+
module Java
|
|
5
|
+
module Serialization
|
|
6
|
+
module Model
|
|
7
|
+
|
|
8
|
+
autoload :Annotation, 'rex/java/serialization/model/annotation'
|
|
9
|
+
autoload :BlockDataLong, 'rex/java/serialization/model/block_data_long'
|
|
10
|
+
autoload :BlockData, 'rex/java/serialization/model/block_data'
|
|
11
|
+
autoload :ClassDesc, 'rex/java/serialization/model/class_desc'
|
|
12
|
+
autoload :Contents, 'rex/java/serialization/model/contents'
|
|
13
|
+
autoload :Element, 'rex/java/serialization/model/element'
|
|
14
|
+
autoload :EndBlockData, 'rex/java/serialization/model/end_block_data'
|
|
15
|
+
autoload :Field, 'rex/java/serialization/model/field'
|
|
16
|
+
autoload :LongUtf, 'rex/java/serialization/model/long_utf'
|
|
17
|
+
autoload :NewArray, 'rex/java/serialization/model/new_array'
|
|
18
|
+
autoload :NewClassDesc, 'rex/java/serialization/model/new_class_desc'
|
|
19
|
+
autoload :NewEnum, 'rex/java/serialization/model/new_enum'
|
|
20
|
+
autoload :NewObject, 'rex/java/serialization/model/new_object'
|
|
21
|
+
autoload :NullReference, 'rex/java/serialization/model/null_reference'
|
|
22
|
+
autoload :Reference, 'rex/java/serialization/model/reference'
|
|
23
|
+
autoload :Reset, 'rex/java/serialization/model/reset'
|
|
24
|
+
autoload :Stream, 'rex/java/serialization/model/stream'
|
|
25
|
+
autoload :Utf, 'rex/java/serialization/model/utf'
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
@@ -29,7 +29,7 @@ module Rex
|
|
|
29
29
|
loop do
|
|
30
30
|
content = decode_content(io, stream)
|
|
31
31
|
self.contents << content
|
|
32
|
-
return self if content.
|
|
32
|
+
return self if content.kind_of?(EndBlockData)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
self
|
|
@@ -66,4 +66,4 @@ module Rex
|
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
|
-
end
|
|
69
|
+
end
|
|
@@ -55,7 +55,7 @@ module Rex
|
|
|
55
55
|
# @return [String] if serialization succeeds
|
|
56
56
|
# @raise [RuntimeError] if serialization doesn't succeed
|
|
57
57
|
def encode
|
|
58
|
-
unless name.
|
|
58
|
+
unless name.kind_of?(Rex::Java::Serialization::Model::Utf)
|
|
59
59
|
raise ::RuntimeError, 'Failed to serialize Field'
|
|
60
60
|
end
|
|
61
61
|
|
|
@@ -169,4 +169,4 @@ module Rex
|
|
|
169
169
|
end
|
|
170
170
|
end
|
|
171
171
|
end
|
|
172
|
-
end
|
|
172
|
+
end
|
|
@@ -52,7 +52,7 @@ module Rex
|
|
|
52
52
|
# @return [String] if serialization succeeds
|
|
53
53
|
# @raise [RuntimeError] if serialization doesn't succeed
|
|
54
54
|
def encode
|
|
55
|
-
unless array_description.
|
|
55
|
+
unless array_description.kind_of?(ClassDesc)
|
|
56
56
|
raise ::RuntimeError, 'Failed to serialize NewArray'
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -103,12 +103,17 @@ module Rex
|
|
|
103
103
|
raise ::RuntimeError, 'Empty NewArray description'
|
|
104
104
|
end
|
|
105
105
|
|
|
106
|
-
unless array_description.
|
|
106
|
+
unless array_description.kind_of?(ClassDesc)
|
|
107
107
|
raise ::RuntimeError, 'Unsupported NewArray description class'
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
desc = array_description.description
|
|
111
111
|
|
|
112
|
+
if desc.class == Reference
|
|
113
|
+
ref = desc.handle - BASE_WIRE_HANDLE
|
|
114
|
+
desc = stream.references[ref]
|
|
115
|
+
end
|
|
116
|
+
|
|
112
117
|
unless desc.class_name.contents[0] == '[' # Array
|
|
113
118
|
raise ::RuntimeError, 'Unsupported NewArray description'
|
|
114
119
|
end
|
|
@@ -222,4 +227,4 @@ module Rex
|
|
|
222
227
|
end
|
|
223
228
|
end
|
|
224
229
|
end
|
|
225
|
-
end
|
|
230
|
+
end
|
|
@@ -66,8 +66,8 @@ module Rex
|
|
|
66
66
|
# @return [String] if serialization succeeds
|
|
67
67
|
# @raise [RuntimeError] if serialization doesn't succeed
|
|
68
68
|
def encode
|
|
69
|
-
unless class_name.class == Rex::Java::Serialization::Model::Utf
|
|
70
|
-
class_annotation.class == Rex::Java::Serialization::Model::Annotation
|
|
69
|
+
unless class_name.class == Rex::Java::Serialization::Model::Utf ||
|
|
70
|
+
class_annotation.class == Rex::Java::Serialization::Model::Annotation ||
|
|
71
71
|
super_class.class == Rex::Java::Serialization::Model::ClassDesc
|
|
72
72
|
raise ::RuntimeError, 'Filed to serialize NewClassDesc'
|
|
73
73
|
end
|
|
@@ -152,4 +152,4 @@ module Rex
|
|
|
152
152
|
end
|
|
153
153
|
end
|
|
154
154
|
end
|
|
155
|
-
end
|
|
155
|
+
end
|
|
@@ -41,8 +41,8 @@ module Rex
|
|
|
41
41
|
# @return [String] if serialization succeeds
|
|
42
42
|
# @raise [RuntimeError] if serialization doesn't succeed
|
|
43
43
|
def encode
|
|
44
|
-
unless enum_description.
|
|
45
|
-
|
|
44
|
+
unless enum_description.kind_of?(ClassDesc) &&
|
|
45
|
+
constant_name.kind_of?(Utf)
|
|
46
46
|
raise ::RuntimeError, 'Failed to serialize EnumDescription'
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -68,7 +68,7 @@ module Rex
|
|
|
68
68
|
# @raise [RuntimeError] if deserialization doesn't succed
|
|
69
69
|
def decode_constant_name(io)
|
|
70
70
|
content = decode_content(io, stream)
|
|
71
|
-
raise ::RuntimeError, 'Failed to unserialize NewEnum' unless content.
|
|
71
|
+
raise ::RuntimeError, 'Failed to unserialize NewEnum' unless content.kind_of?(Rex::Java::Serialization::Model::Utf)
|
|
72
72
|
|
|
73
73
|
content
|
|
74
74
|
end
|
|
@@ -76,4 +76,4 @@ module Rex
|
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
|
-
end
|
|
79
|
+
end
|
|
@@ -32,9 +32,10 @@ module Rex
|
|
|
32
32
|
self.class_desc = ClassDesc.decode(io, stream)
|
|
33
33
|
stream.add_reference(self) unless stream.nil?
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
case class_desc.description
|
|
36
|
+
when NewClassDesc
|
|
36
37
|
self.class_data = decode_class_data(io, class_desc.description)
|
|
37
|
-
|
|
38
|
+
when Reference
|
|
38
39
|
ref = class_desc.description.handle - BASE_WIRE_HANDLE
|
|
39
40
|
self.class_data = decode_class_data(io, stream.references[ref])
|
|
40
41
|
end
|
|
@@ -47,7 +48,7 @@ module Rex
|
|
|
47
48
|
# @return [String] if serialization succeeds
|
|
48
49
|
# @raise [RuntimeError] if serialization doesn't succeed
|
|
49
50
|
def encode
|
|
50
|
-
unless class_desc.
|
|
51
|
+
unless class_desc.kind_of?(ClassDesc)
|
|
51
52
|
raise ::RuntimeError, 'Failed to serialize NewObject'
|
|
52
53
|
end
|
|
53
54
|
|
|
@@ -55,7 +56,7 @@ module Rex
|
|
|
55
56
|
encoded << class_desc.encode
|
|
56
57
|
|
|
57
58
|
class_data.each do |value|
|
|
58
|
-
if value.
|
|
59
|
+
if value.kind_of?(Array)
|
|
59
60
|
encoded << encode_value(value)
|
|
60
61
|
else
|
|
61
62
|
encoded << encode_content(value)
|
|
@@ -70,15 +71,16 @@ module Rex
|
|
|
70
71
|
# @return [String]
|
|
71
72
|
def to_s
|
|
72
73
|
str = ''
|
|
73
|
-
|
|
74
|
+
case class_desc.description
|
|
75
|
+
when NewClassDesc
|
|
74
76
|
str << class_desc.description.class_name.to_s
|
|
75
|
-
|
|
77
|
+
when Reference
|
|
76
78
|
str << (class_desc.description.handle - BASE_WIRE_HANDLE).to_s(16)
|
|
77
79
|
end
|
|
78
80
|
|
|
79
81
|
str << ' => { '
|
|
80
|
-
|
|
81
|
-
str <<
|
|
82
|
+
data_str = class_data.collect { |data| data.to_s }
|
|
83
|
+
str << data_str.join(', ')
|
|
82
84
|
str << ' }'
|
|
83
85
|
end
|
|
84
86
|
|
|
@@ -94,7 +96,12 @@ module Rex
|
|
|
94
96
|
values = []
|
|
95
97
|
|
|
96
98
|
unless my_class_desc.super_class.description.class == NullReference
|
|
97
|
-
|
|
99
|
+
if my_class_desc.super_class.description.class == Reference
|
|
100
|
+
ref = my_class_desc.super_class.description.handle - BASE_WIRE_HANDLE
|
|
101
|
+
values += decode_class_data(io, stream.references[ref])
|
|
102
|
+
else
|
|
103
|
+
values += decode_class_data(io, my_class_desc.super_class.description)
|
|
104
|
+
end
|
|
98
105
|
end
|
|
99
106
|
|
|
100
107
|
values += decode_class_fields(io, my_class_desc)
|
|
@@ -220,4 +227,4 @@ module Rex
|
|
|
220
227
|
end
|
|
221
228
|
end
|
|
222
229
|
end
|
|
223
|
-
end
|
|
230
|
+
end
|
data/lib/rex/ole/direntry.rb
CHANGED
|
File without changes
|
data/lib/rex/ole/samples/dir.rb
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -293,7 +293,7 @@ module Rex
|
|
|
293
293
|
# XXX: Actually implement more of these
|
|
294
294
|
def process_service(service,banner)
|
|
295
295
|
meth = "process_service_#{service.gsub("-","_")}"
|
|
296
|
-
if self.respond_to?
|
|
296
|
+
if self.respond_to?(meth, true)
|
|
297
297
|
self.send meth, banner
|
|
298
298
|
else
|
|
299
299
|
return (first_line banner)
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# -*- coding: binary -*-
|
|
2
|
+
module Rex
|
|
3
|
+
module Parser
|
|
4
|
+
###
|
|
5
|
+
#
|
|
6
|
+
# This class parses the contents of an NTFS partition file.
|
|
7
|
+
# Author : Danil Bazin <danil.bazin[at]hsc.fr> @danilbaz
|
|
8
|
+
#
|
|
9
|
+
###
|
|
10
|
+
class NTFS
|
|
11
|
+
#
|
|
12
|
+
# Initialize the NTFS class with an already open file handler
|
|
13
|
+
#
|
|
14
|
+
DATA_ATTRIBUTE_ID = 128
|
|
15
|
+
INDEX_ROOT_ID = 144
|
|
16
|
+
INDEX_ALLOCATION_ID = 160
|
|
17
|
+
def initialize(file_handler)
|
|
18
|
+
@file_handler = file_handler
|
|
19
|
+
data = @file_handler.read(4096)
|
|
20
|
+
# Boot sector reading
|
|
21
|
+
@bytes_per_sector = data[11, 2].unpack('v')[0]
|
|
22
|
+
@sector_per_cluster = data[13].unpack('C')[0]
|
|
23
|
+
@cluster_per_mft_record = data[64].unpack('c')[0]
|
|
24
|
+
if @cluster_per_mft_record < 0
|
|
25
|
+
@bytes_per_mft_record = 2**(-@cluster_per_mft_record)
|
|
26
|
+
@cluster_per_mft_record = @bytes_per_mft_record.to_f / @bytes_per_sector / @sector_per_cluster
|
|
27
|
+
else
|
|
28
|
+
@bytes_per_mft_record = @bytes_per_sector * @sector_per_cluster * @cluster_per_mft_record
|
|
29
|
+
end
|
|
30
|
+
@bytes_per_cluster = @sector_per_cluster * @bytes_per_sector
|
|
31
|
+
@mft_logical_cluster_number = data[48, 8].unpack('Q<')[0]
|
|
32
|
+
@mft_offset = @mft_logical_cluster_number * @sector_per_cluster * @bytes_per_sector
|
|
33
|
+
@file_handler.seek(@mft_offset)
|
|
34
|
+
@mft = @file_handler.read(@bytes_per_mft_record)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#
|
|
38
|
+
# Gather the MFT entry corresponding to his number
|
|
39
|
+
#
|
|
40
|
+
def mft_record_from_mft_num(mft_num)
|
|
41
|
+
mft_num_offset = mft_num * @cluster_per_mft_record
|
|
42
|
+
mft_data_attribute = mft_record_attribute(@mft)[DATA_ATTRIBUTE_ID]['data']
|
|
43
|
+
cluster_from_attribute_non_resident(mft_data_attribute, mft_num_offset, @bytes_per_mft_record)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# Get the size of the file in the $FILENAME (64) attribute
|
|
48
|
+
#
|
|
49
|
+
def real_size_from_filenameattribute(attribute)
|
|
50
|
+
filename_attribute = attribute
|
|
51
|
+
filename_attribute[48, 8].unpack('Q<')[0]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
# Gather the name of the file from the $FILENAME (64) attribute
|
|
56
|
+
#
|
|
57
|
+
def filename_from_filenameattribute(attribute)
|
|
58
|
+
filename_attribute = attribute
|
|
59
|
+
length_of_name = filename_attribute[64].ord
|
|
60
|
+
# uft16 *2
|
|
61
|
+
d = ::Encoding::Converter.new('UTF-16LE', 'UTF-8')
|
|
62
|
+
d.convert(filename_attribute[66, (length_of_name * 2)])
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# Get the file from the MFT number
|
|
67
|
+
# The size must be gived because the $FILENAME attribute
|
|
68
|
+
# in the MFT entry does not contain it
|
|
69
|
+
# The file is in $DATA (128) Attribute
|
|
70
|
+
#
|
|
71
|
+
def file_content_from_mft_num(mft_num, size)
|
|
72
|
+
mft_record = mft_record_from_mft_num(mft_num)
|
|
73
|
+
attribute_list = mft_record_attribute(mft_record)
|
|
74
|
+
if attribute_list[DATA_ATTRIBUTE_ID]['resident']
|
|
75
|
+
return attribute_list[DATA_ATTRIBUTE_ID]['data']
|
|
76
|
+
else
|
|
77
|
+
data_attribute = attribute_list[DATA_ATTRIBUTE_ID]['data']
|
|
78
|
+
return cluster_from_attribute_non_resident(data_attribute)[0, size]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
#
|
|
83
|
+
# parse one index record and return the name, MFT number and size of the file
|
|
84
|
+
#
|
|
85
|
+
def parse_index(index_entry)
|
|
86
|
+
res = {}
|
|
87
|
+
filename_size = index_entry[10, 2].unpack('v')[0]
|
|
88
|
+
filename_attribute = index_entry[16, filename_size]
|
|
89
|
+
# Should be 8 bytes but it doesn't work
|
|
90
|
+
# mft_offset = index_entry[0.unpack('Q<',:8])[0]
|
|
91
|
+
# work with 4 bytes
|
|
92
|
+
mft_offset = index_entry[0, 4].unpack('V')[0]
|
|
93
|
+
res[filename_from_filenameattribute(filename_attribute)] = {
|
|
94
|
+
'mft_offset' => mft_offset,
|
|
95
|
+
'file_size' => real_size_from_filenameattribute(filename_attribute) }
|
|
96
|
+
res
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
#
|
|
100
|
+
# parse index_record in $INDEX_ROOT and recursively index_record in
|
|
101
|
+
# INDEX_ALLOCATION
|
|
102
|
+
#
|
|
103
|
+
def parse_index_list(index_record, index_allocation_attribute)
|
|
104
|
+
offset_index_entry_list = index_record[0, 4].unpack('V')[0]
|
|
105
|
+
index_size = index_record[offset_index_entry_list + 8, 2].unpack('v')[0]
|
|
106
|
+
index_size_in_bytes = index_size * @bytes_per_cluster
|
|
107
|
+
index_entry = index_record[offset_index_entry_list, index_size]
|
|
108
|
+
res = {}
|
|
109
|
+
while index_entry[12, 4].unpack('V')[0] & 2 != 2
|
|
110
|
+
res.update(parse_index(index_entry))
|
|
111
|
+
# if son
|
|
112
|
+
if index_entry[12, 4].unpack('V')[0] & 1 == 1
|
|
113
|
+
# should be 8 bytes length
|
|
114
|
+
vcn = index_entry[-8, 4].unpack('V')[0]
|
|
115
|
+
vcn_in_bytes = vcn * @bytes_per_cluster
|
|
116
|
+
res_son = parse_index_list(index_allocation_attribute[vcn_in_bytes + 24, index_size_in_bytes], index_allocation_attribute)
|
|
117
|
+
res.update(res_son)
|
|
118
|
+
end
|
|
119
|
+
offset_index_entry_list += index_size
|
|
120
|
+
index_size = index_record[offset_index_entry_list + 8, 2].unpack('v')[0]
|
|
121
|
+
index_size_in_bytes = index_size * @bytes_per_cluster
|
|
122
|
+
index_entry = index_record [offset_index_entry_list, index_size]
|
|
123
|
+
end
|
|
124
|
+
# if son on the last
|
|
125
|
+
if index_entry[12, 4].unpack('V')[0] & 1 == 1
|
|
126
|
+
# should be 8 bytes length
|
|
127
|
+
vcn = index_entry[-8, 4].unpack('V')[0]
|
|
128
|
+
vcn_in_bytes = vcn * @bytes_per_cluster
|
|
129
|
+
res_son = parse_index_list(index_allocation_attribute[vcn_in_bytes + 24, index_size_in_bytes], index_allocation_attribute)
|
|
130
|
+
res.update(res_son)
|
|
131
|
+
end
|
|
132
|
+
res
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
#
|
|
136
|
+
# return the list of files in attribute directory and their MFT number and size
|
|
137
|
+
#
|
|
138
|
+
def index_list_from_attributes(attributes)
|
|
139
|
+
index_root_attribute = attributes[INDEX_ROOT_ID]
|
|
140
|
+
index_record = index_root_attribute[16, index_root_attribute.length - 16]
|
|
141
|
+
if attributes.key?(INDEX_ALLOCATION_ID)
|
|
142
|
+
return parse_index_list(index_record, attributes[INDEX_ALLOCATION_ID])
|
|
143
|
+
else
|
|
144
|
+
return parse_index_list(index_record, '')
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def cluster_from_attribute_non_resident(attribute, cluster_num = 0, size_max = ((2**31) - 1))
|
|
149
|
+
lowvcn = attribute[16, 8].unpack('Q<')[0]
|
|
150
|
+
highvcn = attribute[24, 8].unpack('Q<')[0]
|
|
151
|
+
offset = attribute[32, 2].unpack('v')[0]
|
|
152
|
+
real_size = attribute[48, 8].unpack('Q<')[0]
|
|
153
|
+
attribut = ''
|
|
154
|
+
run_list_num = lowvcn
|
|
155
|
+
old_offset = 0
|
|
156
|
+
while run_list_num <= highvcn
|
|
157
|
+
first_runlist_byte = attribute[offset].ord
|
|
158
|
+
run_offset_size = first_runlist_byte >> 4
|
|
159
|
+
run_length_size = first_runlist_byte & 15
|
|
160
|
+
run_length = attribute[offset + 1, run_length_size]
|
|
161
|
+
run_length += "\x00" * (8 - run_length_size)
|
|
162
|
+
run_length = run_length.unpack('Q<')[0]
|
|
163
|
+
|
|
164
|
+
offset_run_offset = offset + 1 + run_length_size
|
|
165
|
+
run_offset = attribute[offset_run_offset, run_offset_size]
|
|
166
|
+
if run_offset[-1].ord & 128 == 128
|
|
167
|
+
run_offset += "\xFF" * (8 - run_offset_size)
|
|
168
|
+
else
|
|
169
|
+
run_offset += "\x00" * (8 - run_offset_size)
|
|
170
|
+
end
|
|
171
|
+
run_offset = run_offset.unpack('q<')[0]
|
|
172
|
+
#offset relative to previous offset
|
|
173
|
+
run_offset += old_offset
|
|
174
|
+
|
|
175
|
+
size_wanted = [run_length * @bytes_per_cluster, size_max - attribut.length].min
|
|
176
|
+
if cluster_num + (size_max / @bytes_per_cluster) >= run_list_num && (cluster_num < run_length + run_list_num)
|
|
177
|
+
run_list_offset_in_cluster = run_offset + [cluster_num - run_list_num, 0].max
|
|
178
|
+
run_list_offset = (run_list_offset_in_cluster) * @bytes_per_cluster
|
|
179
|
+
run_list_offset = run_list_offset.to_i
|
|
180
|
+
@file_handler.seek(run_list_offset)
|
|
181
|
+
|
|
182
|
+
data = ''
|
|
183
|
+
while data.length < size_wanted
|
|
184
|
+
data << @file_handler.read(size_wanted - data.length)
|
|
185
|
+
end
|
|
186
|
+
attribut << data
|
|
187
|
+
end
|
|
188
|
+
offset += run_offset_size + run_length_size + 1
|
|
189
|
+
run_list_num += run_length
|
|
190
|
+
old_offset = run_offset
|
|
191
|
+
end
|
|
192
|
+
attribut = attribut[0, real_size]
|
|
193
|
+
attribut
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
#
|
|
197
|
+
# return the attribute list from the MFT record
|
|
198
|
+
# deal with resident and non resident attributes (but not $DATA due to performance issue)
|
|
199
|
+
#
|
|
200
|
+
def mft_record_attribute(mft_record)
|
|
201
|
+
attribute_list_offset = mft_record[20, 2].unpack('C')[0]
|
|
202
|
+
curs = attribute_list_offset
|
|
203
|
+
attribute_identifier = mft_record[curs, 4].unpack('V')[0]
|
|
204
|
+
res = {}
|
|
205
|
+
while attribute_identifier != 0xFFFFFFFF
|
|
206
|
+
# attribute_size=mft_record[curs + 4, 4].unpack('V')[0]
|
|
207
|
+
# should be on 4 bytes but doesnt work
|
|
208
|
+
attribute_size = mft_record[curs + 4, 2].unpack('v')[0]
|
|
209
|
+
# resident
|
|
210
|
+
if mft_record[curs + 8] == "\x00"
|
|
211
|
+
content_size = mft_record[curs + 16, 4].unpack('V')[0]
|
|
212
|
+
content_offset = mft_record[curs + 20, 2].unpack('v')[0]
|
|
213
|
+
res[attribute_identifier] = mft_record[curs + content_offset, content_size]
|
|
214
|
+
else
|
|
215
|
+
# non resident
|
|
216
|
+
if attribute_identifier == DATA_ATTRIBUTE_ID
|
|
217
|
+
res[attribute_identifier] = mft_record[curs, attribute_size]
|
|
218
|
+
else
|
|
219
|
+
res[attribute_identifier] = cluster_from_attribute_non_resident(mft_record[curs, attribute_size])
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
if attribute_identifier == DATA_ATTRIBUTE_ID
|
|
223
|
+
res[attribute_identifier] = {
|
|
224
|
+
'data' => res[attribute_identifier],
|
|
225
|
+
'resident' => mft_record[curs + 8] == "\x00" }
|
|
226
|
+
end
|
|
227
|
+
curs += attribute_size
|
|
228
|
+
attribute_identifier = mft_record[curs, 4].unpack('V')[0]
|
|
229
|
+
end
|
|
230
|
+
res
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
#
|
|
234
|
+
# return the file path in the NTFS partition
|
|
235
|
+
#
|
|
236
|
+
def file(path)
|
|
237
|
+
repertory = mft_record_from_mft_num(5)
|
|
238
|
+
index_entry = {}
|
|
239
|
+
path.split('\\').each do |r|
|
|
240
|
+
attributes = mft_record_attribute(repertory)
|
|
241
|
+
index = index_list_from_attributes(attributes)
|
|
242
|
+
unless index.key?(r)
|
|
243
|
+
fail ArgumentError, 'File path does not exist', caller
|
|
244
|
+
end
|
|
245
|
+
index_entry = index[r]
|
|
246
|
+
repertory = mft_record_from_mft_num(index_entry['mft_offset'])
|
|
247
|
+
end
|
|
248
|
+
file_content_from_mft_num(index_entry['mft_offset'], index_entry['file_size'])
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|