Skip to content

Add Windows Time Provider persistence module#21522

Open
M4nu02 wants to merge 2 commits into
rapid7:masterfrom
M4nu02:windows-timeprovider-persistence
Open

Add Windows Time Provider persistence module#21522
M4nu02 wants to merge 2 commits into
rapid7:masterfrom
M4nu02:windows-timeprovider-persistence

Conversation

@M4nu02
Copy link
Copy Markdown
Contributor

@M4nu02 M4nu02 commented Jun 1, 2026

Adds a new persistence module that registers a custom Time Provider DLL under the W32Time service registry key. The service loads the DLL at startup, providing persistence across reboots. Requires Administrator or SYSTEM privileges.

Fixes #20825

Verification

  • Start msfconsole
  • Get an Admin or SYSTEM shell
  • use exploit/windows/persistence/time_provider
  • set SESSION [SESSION]
  • run
  • Reboot the machine
  • You should get a shell

The classic technique as described in several blogs only registers the DLL under W32Time, resulting in a LocalService shell. I modified the ObjectName registry key to LocalSystem, granting an immediate SYSTEM shell upon reboot and allowing the payload to execute reliably from any directory.

Adds a new persistence module that registers a custom Time
Provider DLL under the W32Time service registry key. The
service loads the DLL at startup, providing persistence
across reboots. Requires Administrator or SYSTEM privileges.

Fixes rapid7#20825
Copy link
Copy Markdown
Contributor

@jvoisin jvoisin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a sneaky one

'Emanuele Cervelli',
],
'Platform' => [ 'win' ],
'Arch' => [ARCH_X64, ARCH_X86],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it arch-independent-ish? Windows runs on ARM as well now :)

Comment on lines +150 to +157
stop_result = service_stop('W32Time')
start_result = service_start('W32Time')

if stop_result.zero? && start_result.zero?
print_good('W32Time service restarted successfully')
else
print_warning("Unable to restart W32Time cleanly (stop=#{stop_result}, start=#{start_result}).")
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lib/msf/core/post/windows/services.rb has a service_restart method

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's good to know, thanks.

Refactor the W32Time persistence module to utilize the built-in
Msf::Post::Windows::Services#service_restart method. This replaces
the custom `restart_w32time` helper function.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

New Persistence Technique: Windows Time Provider

3 participants