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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rex/exploitation/egghunter.rb +4 -6
  3. data/lib/rex/exploitation/powershell/psh_methods.rb +9 -0
  4. data/lib/rex/java/serialization.rb +2 -1
  5. data/lib/rex/java/serialization/builder.rb +94 -0
  6. data/lib/rex/java/serialization/model.rb +29 -18
  7. data/lib/rex/java/serialization/model/annotation.rb +2 -2
  8. data/lib/rex/java/serialization/model/field.rb +2 -2
  9. data/lib/rex/java/serialization/model/new_array.rb +8 -3
  10. data/lib/rex/java/serialization/model/new_class_desc.rb +3 -3
  11. data/lib/rex/java/serialization/model/new_enum.rb +4 -4
  12. data/lib/rex/java/serialization/model/new_object.rb +17 -10
  13. data/lib/rex/ole/direntry.rb +1 -1
  14. data/lib/rex/ole/samples/create_ole.rb +0 -0
  15. data/lib/rex/ole/samples/dir.rb +0 -0
  16. data/lib/rex/ole/samples/dump_stream.rb +0 -0
  17. data/lib/rex/ole/samples/ole_info.rb +0 -0
  18. data/lib/rex/parser/foundstone_nokogiri.rb +1 -1
  19. data/lib/rex/parser/fs/ntfs.rb +252 -0
  20. data/lib/rex/parser/openvas_nokogiri.rb +2 -0
  21. data/lib/rex/payloads/win32/kernel.rb +3 -3
  22. data/lib/rex/post/meterpreter/client_core.rb +172 -64
  23. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +3 -2
  24. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +12 -10
  25. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb +64 -37
  26. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +8 -2
  27. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +15 -3
  28. data/lib/rex/post/meterpreter/packet.rb +41 -38
  29. data/lib/rex/post/meterpreter/packet_dispatcher.rb +7 -1
  30. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +17 -4
  31. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +11 -4
  32. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +1 -1
  33. data/lib/rex/proto.rb +2 -0
  34. data/lib/rex/proto/acpp.rb +17 -0
  35. data/lib/rex/proto/acpp/client.rb +29 -0
  36. data/lib/rex/proto/acpp/message.rb +183 -0
  37. data/lib/rex/proto/http/client.rb +1 -2
  38. data/lib/rex/proto/iax2/call.rb +22 -3
  39. data/lib/rex/proto/iax2/client.rb +1 -0
  40. data/lib/rex/proto/kerberos.rb +13 -0
  41. data/lib/rex/proto/kerberos/client.rb +213 -0
  42. data/lib/rex/proto/kerberos/credential_cache.rb +19 -0
  43. data/lib/rex/proto/kerberos/credential_cache/cache.rb +81 -0
  44. data/lib/rex/proto/kerberos/credential_cache/credential.rb +151 -0
  45. data/lib/rex/proto/kerberos/credential_cache/element.rb +49 -0
  46. data/lib/rex/proto/kerberos/credential_cache/key_block.rb +62 -0
  47. data/lib/rex/proto/kerberos/credential_cache/principal.rb +70 -0
  48. data/lib/rex/proto/kerberos/credential_cache/time.rb +69 -0
  49. data/lib/rex/proto/kerberos/crypto.rb +21 -0
  50. data/lib/rex/proto/kerberos/crypto/rc4_hmac.rb +65 -0
  51. data/lib/rex/proto/kerberos/crypto/rsa_md5.rb +15 -0
  52. data/lib/rex/proto/kerberos/model.rb +133 -0
  53. data/lib/rex/proto/kerberos/model/ap_req.rb +98 -0
  54. data/lib/rex/proto/kerberos/model/authenticator.rb +143 -0
  55. data/lib/rex/proto/kerberos/model/authorization_data.rb +85 -0
  56. data/lib/rex/proto/kerberos/model/checksum.rb +59 -0
  57. data/lib/rex/proto/kerberos/model/element.rb +67 -0
  58. data/lib/rex/proto/kerberos/model/enc_kdc_response.rb +215 -0
  59. data/lib/rex/proto/kerberos/model/encrypted_data.rb +171 -0
  60. data/lib/rex/proto/kerberos/model/encryption_key.rb +106 -0
  61. data/lib/rex/proto/kerberos/model/kdc_request.rb +166 -0
  62. data/lib/rex/proto/kerberos/model/kdc_request_body.rb +315 -0
  63. data/lib/rex/proto/kerberos/model/kdc_response.rb +141 -0
  64. data/lib/rex/proto/kerberos/model/krb_error.rb +219 -0
  65. data/lib/rex/proto/kerberos/model/last_request.rb +82 -0
  66. data/lib/rex/proto/kerberos/model/pre_auth_data.rb +104 -0
  67. data/lib/rex/proto/kerberos/model/pre_auth_enc_time_stamp.rb +126 -0
  68. data/lib/rex/proto/kerberos/model/pre_auth_pac_request.rb +81 -0
  69. data/lib/rex/proto/kerberos/model/principal_name.rb +116 -0
  70. data/lib/rex/proto/kerberos/model/ticket.rb +151 -0
  71. data/lib/rex/proto/kerberos/pac.rb +36 -0
  72. data/lib/rex/proto/kerberos/pac/client_info.rb +53 -0
  73. data/lib/rex/proto/kerberos/pac/element.rb +52 -0
  74. data/lib/rex/proto/kerberos/pac/logon_info.rb +566 -0
  75. data/lib/rex/proto/kerberos/pac/priv_svr_checksum.rb +29 -0
  76. data/lib/rex/proto/kerberos/pac/server_checksum.rb +30 -0
  77. data/lib/rex/proto/kerberos/pac/type.rb +121 -0
  78. data/lib/rex/proto/rmi.rb +7 -0
  79. data/lib/rex/proto/rmi/model.rb +31 -0
  80. data/lib/rex/proto/rmi/model/call.rb +60 -0
  81. data/lib/rex/proto/rmi/model/continuation.rb +76 -0
  82. data/lib/rex/proto/rmi/model/dgc_ack.rb +62 -0
  83. data/lib/rex/proto/rmi/model/element.rb +143 -0
  84. data/lib/rex/proto/rmi/model/output_header.rb +86 -0
  85. data/lib/rex/proto/rmi/model/ping.rb +41 -0
  86. data/lib/rex/proto/rmi/model/ping_ack.rb +41 -0
  87. data/lib/rex/proto/rmi/model/protocol_ack.rb +100 -0
  88. data/lib/rex/proto/rmi/model/return_data.rb +60 -0
  89. data/lib/rex/socket.rb +9 -1
  90. data/lib/rex/socket/tcp_server.rb +3 -0
  91. data/lib/rex/ui/text/dispatcher_shell.rb +4 -4
  92. data/lib/rex/ui/text/output/tee.rb +2 -0
  93. data/lib/rex/zip/samples/comment.rb +0 -0
  94. data/lib/rex/zip/samples/mkwar.rb +0 -0
  95. data/lib/rex/zip/samples/mkzip.rb +0 -0
  96. data/lib/rex/zip/samples/recursive.rb +0 -0
  97. data/rex.gemspec +1 -1
  98. metadata +56 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 31837db98ac01dead4073a5d9785ee8c3885772a
4
- data.tar.gz: 0976f856604fdeee60805d11fe36faeee0e4656b
3
+ metadata.gz: 5cc2f7d9e9457482ffe5b8935f8b93c4e57560cc
4
+ data.tar.gz: b6e6ee56e59286b54a62d28540e92fa6363dd6ae
5
5
  SHA512:
6
- metadata.gz: f35c3bb765efa30161a507f41e8e1016296bacb8bb8b80eb0220c8cfc18092957f479f3ea17b1994fc4e38e58e60eed8bcb3e545f6a3f62cebe54a44afca9099
7
- data.tar.gz: 89e3d3600fd209b95a8bf231df5d4ab8d839ca6b1b8e1178e23b676cddf1d1afd7461985c2689b54d71d437fb3839e12497c9f7bde7b5f1f9a59a1655fda82ed
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
- if searchforward.to_s.downcase == 'false'
70
- # go backwards
71
- flippage = "\n\txor dl,dl"
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
@@ -51,4 +51,5 @@ module Rex
51
51
  end
52
52
  end
53
53
 
54
- require 'rex/java/serialization/model'
54
+ require 'rex/java/serialization/model'
55
+ require 'rex/java/serialization/builder'
@@ -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
- require 'rex/java/serialization/model/element'
4
- require 'rex/java/serialization/model/null_reference'
5
- require 'rex/java/serialization/model/reference'
6
- require 'rex/java/serialization/model/reset'
7
- require 'rex/java/serialization/model/utf'
8
- require 'rex/java/serialization/model/long_utf'
9
- require 'rex/java/serialization/model/block_data'
10
- require 'rex/java/serialization/model/block_data_long'
11
- require 'rex/java/serialization/model/end_block_data'
12
- require 'rex/java/serialization/model/contents'
13
- require 'rex/java/serialization/model/new_enum'
14
- require 'rex/java/serialization/model/field'
15
- require 'rex/java/serialization/model/new_array'
16
- require 'rex/java/serialization/model/annotation'
17
- require 'rex/java/serialization/model/class_desc'
18
- require 'rex/java/serialization/model/new_class_desc'
19
- require 'rex/java/serialization/model/new_object'
20
- require 'rex/java/serialization/model/stream'
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.class == EndBlockData
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.class == Rex::Java::Serialization::Model::Utf
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.class == ClassDesc
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.class == ClassDesc
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.class == ClassDesc &&
45
- constant_name.class == Utf
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.class == Rex::Java::Serialization::Model::Utf
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
- if class_desc.description.class == NewClassDesc
35
+ case class_desc.description
36
+ when NewClassDesc
36
37
  self.class_data = decode_class_data(io, class_desc.description)
37
- elsif class_desc.description.class == Reference
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.class == ClassDesc
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.class == Array
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
- if class_desc.description.class == NewClassDesc
74
+ case class_desc.description
75
+ when NewClassDesc
74
76
  str << class_desc.description.class_name.to_s
75
- elsif class_desc.description.class == Reference
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
- data = class_data.collect { |data| data.to_s }
81
- str << data.join(', ')
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
- values += decode_class_data(io, my_class_desc.super_class.description)
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
@@ -96,7 +96,7 @@ class DirEntry
96
96
  return de
97
97
  end
98
98
  @children.each { |cde|
99
- ret = find_by_sid(cde, sid)
99
+ ret = find_by_sid(sid, cde)
100
100
  if (ret)
101
101
  return ret
102
102
  end
File without changes
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? meth
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