Skip to content

Commit 8fe8ee9

Browse files
committed
first shot at letting scriptable.rb handle local exploits
1 parent a270cc6 commit 8fe8ee9

File tree

1 file changed

+54
-12
lines changed

1 file changed

+54
-12
lines changed

lib/msf/base/sessions/scriptable.rb

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,66 @@ def execute_file
5858
#
5959
def execute_script(script_name, *args)
6060
mod = framework.modules.create(script_name)
61-
if (mod and mod.type == "post")
61+
if mod
6262
# Don't report module run events here as it will be taken care of
6363
# in +Post.run_simple+
64+
# meterpreter scripts don't need SESSION, but it's not gonna hurt
6465
opts = { 'SESSION' => self.sid }
6566
args.each do |arg|
6667
k,v = arg.split("=", 2)
6768
opts[k] = v
6869
end
69-
mod.run_simple(
70-
# Run with whatever the default stance is for now. At some
71-
# point in the future, we'll probably want a way to force a
72-
# module to run in the background
73-
#'RunAsJob' => true,
74-
'LocalInput' => self.user_input,
75-
'LocalOutput' => self.user_output,
76-
'Options' => opts
77-
)
78-
else
70+
if mod.type == "post"
71+
mod.run_simple(
72+
# Run with whatever the default stance is for now. At some
73+
# point in the future, we'll probably want a way to force a
74+
# module to run in the background
75+
#'RunAsJob' => true,
76+
'LocalInput' => self.user_input,
77+
'LocalOutput' => self.user_output,
78+
'Options' => opts
79+
)
80+
elsif mod.type == "exploit"
81+
# well it must be a local, we're not currently supporting anything else
82+
if mod.category == "local"
83+
# get a copy of the session exploit's datastore if we can
84+
original_exploit_datastore = self.exploit.datastore || {}
85+
copy_of_orig_exploit_datastore = original_exploit_datastore.dup
86+
# we don't want to inherit a couple things, like AutoRunScript's
87+
to_neuter = ['AutoRunScript', 'InitialAutoRunScript']
88+
to_neuter.each { |setting| copy_of_orig_exploit_datastore.delete(setting) }
89+
# @TODO: if opts are the same, we don't need another handler, set
90+
# DisablePayloadHandler => true in that case?
91+
92+
# merge in any opts that were passed in, defaulting to the
93+
# copy of the datastore (of the exploit) that spawned the session
94+
local_exploit_opts = copy_of_orig_exploit_datastore.merge(opts)
95+
96+
# try to run this local exploit, which is likely to be exception prone
97+
begin
98+
new_session = mod.exploit_simple(
99+
'Payload' => local_exploit_opts['PAYLOAD'],
100+
'LocalInput' => self.user_input,
101+
'LocalOutput' => self.user_output,
102+
'Options' => local_exploit_opts
103+
)
104+
rescue ::Interrupt
105+
raise $!
106+
rescue ::Exception => e
107+
print_error("Local exploit exception (#{mod.refname}): #{e.class} #{e}")
108+
if(e.class.to_s != 'Msf::OptionValidateError')
109+
print_error("Call stack:")
110+
e.backtrace.each do |line|
111+
break if line =~ /lib.msf.base.simple/
112+
print_error(" #{line}")
113+
end
114+
end
115+
end # end rescue
116+
117+
end # end if local
118+
end # end if exploit
119+
120+
else # else no mod
79121
full_path = self.class.find_script_path(script_name)
80122

81123
# No path found? Weak.
@@ -85,7 +127,7 @@ def execute_script(script_name, *args)
85127
end
86128
framework.events.on_session_script_run(self, full_path)
87129
execute_file(full_path, args)
88-
end
130+
end # end if mod
89131
end
90132

91133
end

0 commit comments

Comments
 (0)