Skip to content

Commit dee89bd

Browse files
committed
Merge branch 'rapid7' into feature/travis-ci.org
Conflicts: README.md
2 parents baffd09 + 8a4fb07 commit dee89bd

27 files changed

+857
-103
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
.yardoc
77
# Mac OS X files
88
.DS_Store
9+
# simplecov coverage data
10+
coverage
911
data/meterpreter/ext_server_pivot.dll
1012
data/meterpreter/ext_server_pivot.x64.dll
1113
doc

Gemfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,7 @@ end
2424
group :test do
2525
# testing framework
2626
gem 'rspec'
27+
# code coverage for tests
28+
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
29+
gem 'simplecov', '0.5.4', :require => false
2730
end

Gemfile.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ GEM
4545
rspec-expectations (2.11.3)
4646
diff-lcs (~> 1.1.3)
4747
rspec-mocks (2.11.3)
48+
simplecov (0.5.4)
49+
multi_json (~> 1.0.3)
50+
simplecov-html (~> 0.5.3)
51+
simplecov-html (0.5.3)
4852
slop (3.3.3)
4953
tzinfo (0.3.33)
5054
yard (0.8.2.1)
@@ -60,4 +64,5 @@ DEPENDENCIES
6064
rake
6165
redcarpet
6266
rspec
67+
simplecov (= 0.5.4)
6368
yard

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.png)](https://travis-ci.org/rapid7/metasploit-framework)
2+
Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.png)](https://travis-ci.org/rapid7/metasploit-framework) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/rapid7/metasploit-framework)
33
==
44
The Metasploit Framework is released under a BSD-style license. See
55
COPYING for more details.

lib/msf/core/exploit/realport.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def realport_recv_banner(port=0, timeout=30, max_data=4096)
133133
banner
134134
end
135135

136-
def realport_send(port=0, data)
136+
def realport_send(port=0, data="")
137137
sock.put( [port].pack("C") + data )
138138
end
139139

lib/msf/core/exploit/winrm.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,12 @@ def target_url
323323
end
324324
end
325325

326+
def wmi_namespace
327+
return datastore['NAMESPACE'] if datastore['NAMESPACE']
328+
return @namespace_override if @namespace_override
329+
return "/root/cimv2/"
330+
end
331+
326332

327333
private
328334

@@ -433,7 +439,7 @@ def winrm_header(data)
433439
def winrm_uri_action(type)
434440
case type
435441
when "wql"
436-
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*</w:ResourceURI>
442+
return %Q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/wmi#{wmi_namespace}*</w:ResourceURI>
437443
<a:Action mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action>}
438444
when "create_shell"
439445
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>

lib/msf/core/module_manager/loading.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,4 @@ def load_modules(path, options={})
109109

110110
count_by_type
111111
end
112-
end
112+
end

lib/msf/core/modules/error.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Base error class for all error under {Msf::Modules}
2+
class Msf::Modules::Error < StandardError
3+
def initialize(attributes={})
4+
@module_path = attributes[:module_path]
5+
@module_reference_name = attributes[:module_reference_name]
6+
7+
message_parts = []
8+
message_parts << "Failed to load module"
9+
10+
if module_reference_name or module_path
11+
clause_parts = []
12+
13+
if module_reference_name
14+
clause_parts << module_reference_name
15+
end
16+
17+
if module_path
18+
clause_parts << "from #{module_path}"
19+
end
20+
21+
clause = clause_parts.join(' ')
22+
message_parts << "(#{clause})"
23+
end
24+
25+
causal_message = attributes[:causal_message]
26+
27+
if causal_message
28+
message_parts << "due to #{causal_message}"
29+
end
30+
31+
message = message_parts.join(' ')
32+
33+
super(message)
34+
end
35+
36+
attr_reader :module_reference_name
37+
attr_reader :module_path
38+
end

lib/msf/core/modules/loader/base.rb

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#
44
require 'msf/core/modules/loader'
55
require 'msf/core/modules/namespace'
6+
require 'msf/core/modules/metasploit_class_compatibility_error'
67
require 'msf/core/modules/version_compatibility_error'
78

89
# Responsible for loading modules for {Msf::ModuleManager}.
@@ -117,12 +118,17 @@ def load_module(parent_path, type, module_reference_name, options={})
117118

118119
metasploit_class = nil
119120

121+
module_content = read_module_content(parent_path, type, module_reference_name)
122+
123+
if module_content.empty?
124+
# read_module_content is responsible for calling {#load_error}, so just return here.
125+
return false
126+
end
127+
120128
loaded = namespace_module_transaction(type + "/" + module_reference_name, :reload => reload) { |namespace_module|
121129
# set the parent_path so that the module can be reloaded with #load_module
122130
namespace_module.parent_path = parent_path
123131

124-
module_content = read_module_content(parent_path, type, module_reference_name)
125-
126132
begin
127133
namespace_module.module_eval_with_lexical_scope(module_content, module_path)
128134
# handle interrupts as pass-throughs unlike other Exceptions so users can bail with Ctrl+C
@@ -133,45 +139,33 @@ def load_module(parent_path, type, module_reference_name, options={})
133139
begin
134140
namespace_module.version_compatible!(module_path, module_reference_name)
135141
rescue Msf::Modules::VersionCompatibilityError => version_compatibility_error
136-
error_message = "Failed to load module (#{module_path}) due to error and #{version_compatibility_error}"
142+
load_error(module_path, version_compatibility_error)
137143
else
138-
error_message = "#{error.class} #{error}"
144+
load_error(module_path, error)
139145
end
140146

141-
# record the error message without the backtrace for the console
142-
module_manager.module_load_error_by_path[module_path] = error_message
143-
144-
error_message_with_backtrace = "#{error_message}:\n#{error.backtrace.join("\n")}"
145-
elog(error_message_with_backtrace)
146-
147147
return false
148148
end
149149

150150
begin
151151
namespace_module.version_compatible!(module_path, module_reference_name)
152152
rescue Msf::Modules::VersionCompatibilityError => version_compatibility_error
153-
error_message = version_compatibility_error.to_s
154-
155-
elog(error_message)
156-
module_manager.module_load_error_by_path[module_path] = error_message
153+
load_error(module_path, version_compatibility_error)
157154

158155
return false
159156
end
160157

161-
metasploit_class = namespace_module.metasploit_class
162-
163-
unless metasploit_class
164-
error_message = "Missing Metasploit class constant"
165-
166-
elog(error_message)
167-
module_manager.module_load_error_by_path[module_path] = error_message
158+
begin
159+
metasploit_class = namespace_module.metasploit_class!(module_path, module_reference_name)
160+
rescue Msf::Modules::MetasploitClassCompatibilityError => error
161+
load_error(module_path, error)
168162

169-
return false
163+
return false
170164
end
171165

172166
unless usable?(metasploit_class)
173167
ilog(
174-
"Skipping module #{module_reference_name} under #{parent_path} because is_usable returned false.",
168+
"Skipping module (#{module_reference_name} from #{module_path}) because is_usable returned false.",
175169
'core',
176170
LEV_1
177171
)
@@ -409,6 +403,29 @@ def each_module_reference_name(path)
409403
raise ::NotImplementedError
410404
end
411405

406+
# Records the load error to {Msf::ModuleManager::Loading#module_load_error_by_path} and the log.
407+
#
408+
# @param [String] module_path Path to the module as returned by {#module_path}.
409+
# @param [Exception, #class, #to_s, #backtrace] error the error that cause the module not to load.
410+
# @return [void]
411+
#
412+
# @see #module_path
413+
def load_error(module_path, error)
414+
# module_load_error_by_path does not get the backtrace because the value is echoed to the msfconsole where
415+
# backtraces should not appear.
416+
module_manager.module_load_error_by_path[module_path] = "#{error.class} #{error}"
417+
418+
log_lines = []
419+
log_lines << "#{module_path} failed to load due to the following error:"
420+
log_lines << error.class.to_s
421+
log_lines << error.to_s
422+
log_lines << "Call stack:"
423+
log_lines += error.backtrace
424+
425+
log_message = log_lines.join("\n")
426+
elog(log_message)
427+
end
428+
412429
# @return [Msf::ModuleManager] The module manager for which this loader is loading modules.
413430
attr_reader :module_manager
414431

lib/msf/core/modules/loader/directory.rb

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,17 @@ def read_module_content(parent_path, type, module_reference_name)
7575

7676
module_content = ''
7777

78-
# force to read in binary mode so Pro modules won't be truncated on Windows
79-
File.open(full_path, 'rb') do |f|
80-
# Pass the size of the file as it leads to faster reads due to fewer buffer resizes. Greatest effect on Windows.
81-
# @see http://www.ruby-forum.com/topic/209005
82-
# @see https://github.com/ruby/ruby/blob/ruby_1_8_7/io.c#L1205
83-
# @see https://github.com/ruby/ruby/blob/ruby_1_9_3/io.c#L2038
84-
module_content = f.read(f.stat.size)
78+
begin
79+
# force to read in binary mode so Pro modules won't be truncated on Windows
80+
File.open(full_path, 'rb') do |f|
81+
# Pass the size of the file as it leads to faster reads due to fewer buffer resizes. Greatest effect on Windows.
82+
# @see http://www.ruby-forum.com/topic/209005
83+
# @see https://github.com/ruby/ruby/blob/ruby_1_8_7/io.c#L1205
84+
# @see https://github.com/ruby/ruby/blob/ruby_1_9_3/io.c#L2038
85+
module_content = f.read(f.stat.size)
86+
end
87+
rescue Errno::ENOENT => error
88+
load_error(full_path, error)
8589
end
8690

8791
module_content

0 commit comments

Comments
 (0)