CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/test/functional/framework/msfconsole_spec.rb
Views: 11623
1
$:.unshift(File.join(File.dirname(__FILE__)))
2
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', 'lib'))
3
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
4
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'test', 'lib'))
5
6
require 'fileutils'
7
require 'msf_matchers'
8
require 'msf_test_case'
9
10
module MsfTest
11
include MsfTest::MsfMatchers
12
13
## This spec exists to help us describe the behavior of msfconsole - TODO
14
15
describe "Msfconsole" do
16
###
17
# Setup!
18
###
19
20
before :all do
21
@working_directory = File.dirname(__FILE__)
22
23
## Static specs will make use of RC files here
24
@static_resource_directory = "#{@working_directory}/msftest/resource"
25
26
## Directories for the generated specs
27
@temp_directory = "#{@working_directory}/msfconsole_specs"
28
@temp_input_directory = "#{@temp_directory}/generated_rc"
29
30
## Where all output from the runs will go
31
@temp_output_directory = "#{@temp_directory}/output"
32
33
## Create a framework object
34
@framework = ::Msf::Simple::Framework.create
35
end
36
37
before :each do
38
end
39
40
after :each do
41
end
42
43
after :all do
44
## Clean up
45
# FileUtils.rm_rf(@temp_directory)
46
end
47
48
###
49
# Static Test cases!
50
###
51
52
it "should start and let us run help" do
53
data = start_console_and_run_rc("help", "#{@static_resource_directory}/help.rc")
54
55
success_strings = [
56
'help',
57
'Database Backend Commands',
58
'Core Commands'
59
]
60
failure_strings = [] | generic_failure_strings
61
failure_exception_strings = [] | generic_failure_exception_strings
62
63
data.should contain_all_successes(success_strings)
64
data.should contain_no_failures_except(failure_strings, failure_exception_strings)
65
end
66
67
it "should generate a meterpreter session against a vulnerable win32 host" do
68
## Set input & output to something sane
69
input = Rex::Ui::Text::Input::Stdio.new
70
output = Rex::Ui::Text::Output::File.new("temp.output")
71
session = generate_x86_meterpreter_session(input, output)
72
73
session.should_not be_nil
74
75
if session
76
session.load_stdapi
77
session.run_cmd("help")
78
else
79
flunk "Error interacting with session"
80
end
81
end
82
83
###
84
# Dynamic Test Cases!!
85
###
86
87
@working_directory = File.dirname(__FILE__)
88
89
## Directories for the generated specs
90
@temp_directory = "#{@working_directory}/msfconsole_specs"
91
@temp_input_directory = "#{@temp_directory}/generated_rc"
92
93
## Where all output from the runs will go
94
@temp_output_directory = "#{@temp_directory}/output"
95
96
if File.directory? @temp_directory
97
FileUtils.rm_rf(@temp_directory)
98
end
99
100
Dir.mkdir(@temp_directory)
101
Dir.mkdir(@temp_input_directory)
102
Dir.mkdir(@temp_output_directory)
103
104
Dir.glob("#{@working_directory}/msftest/*.msftest").each do |filename|
105
## Parse this test case
106
test_case = MsfTestCase.new(filename)
107
puts "Found #{test_case.name} in: #{filename}"
108
109
## Write the commands back to a temporary RC file
110
puts "Writing #{@temp_input_directory}/#{test_case.name}.rc"
111
File.open("#{@temp_input_directory}/#{test_case.name}.rc", 'w') { |f| f.puts test_case.commands }
112
113
## Create the rspec Test Case
114
it "should #{test_case.name}" do
115
## Gather the success / failure strings, and combine with the generics
116
success_strings = test_case.expected_successes
117
failure_strings = test_case.expected_failures | generic_failure_strings
118
failure_exception_strings = test_case.expected_failure_exceptions | generic_failure_exception_strings
119
120
## run the commands
121
data = start_console_and_run_rc(test_case.name, "#{@temp_input_directory}/#{test_case.name}.rc")
122
123
## check the output
124
data.should contain_all_successes(success_strings)
125
data.should contain_no_failures_except(failure_strings, failure_exception_strings)
126
127
## Clean up
128
# File.delete("#{@temp_input_directory}/#{test_case.name}.rc")
129
# File.delete("#{@temp_output_directory}/#{test_case.name}")
130
end
131
end
132
133
###
134
# Test case helpers:
135
###
136
def generic_success_strings
137
[]
138
end
139
140
def generic_failure_strings
141
['fatal', 'fail', 'error', 'exception']
142
end
143
144
def generic_failure_exception_strings
145
[]
146
end
147
148
def start_console_and_run_rc(name, rc_file, database_file = false)
149
output_file = "#{@temp_output_directory}/#{name}"
150
151
if database_file
152
msfconsole_string = "ruby #{@working_directory}/../../../msfconsole -o #{output_file} -r #{rc_file} -y #{database_file}"
153
else
154
msfconsole_string = "ruby #{@working_directory}/../../../msfconsole -o #{output_file} -r #{rc_file}"
155
end
156
157
system("#{msfconsole_string}")
158
159
data = hlp_file_to_string("#{output_file}")
160
end
161
162
def generate_x86_meterpreter_session(input, output)
163
## Setup for win32
164
exploit_name = 'windows/smb/psexec'
165
payload_name = 'windows/meterpreter/bind_tcp'
166
167
## Fire it off against a known-vulnerable host
168
session = @framework.exploits.create(exploit_name).exploit_simple(
169
'Options' => { 'RHOST' => "vulnerable", "SMBUser" => "administrator", "SMBPass" => "" },
170
'Payload' => payload_name,
171
'LocalInput' => input,
172
'LocalOutput' => output
173
)
174
175
## If a session came back, try to interact with it.
176
if session
177
return session
178
else
179
return nil
180
end
181
end
182
183
def generate_win64_meterpreter_session(input, output)
184
raise "Not Implemented"
185
end
186
187
def generate_java_meterpreter_session(input, output)
188
raise "Not Implemented"
189
end
190
191
def generate_php_meterpreter_session(input, output)
192
raise "Not Implemented"
193
end
194
195
def hlp_file_to_string(filename)
196
data = ""
197
f = File.open(filename, "r")
198
f.each_line do |line|
199
data += line
200
end
201
return data
202
end
203
end
204
end
205
206