Beyond good ol’ Run key, Part 60

Today I’ll describe a little secret – a stealthy autostart key that is not very well-known and is very reliable since it is used by… well… the Windows Update.

Yup, it’s a pretty handy one…

This is the key:

  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Setup\ServiceStartup

It has two interesting properties:

  • It can be used as a persistence mechanism
  • It can also mysteriously make files re-appear on the system as the mechanism is used to update files and as such, the entries are being used to copy files during the system start (by the ‘svchost.exe -k netsvcs’ process)

This is an example entry:

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Setup\ServiceStartup\malware.dll
"RegistrationFlags"=dword:00000001
"CacheFile"="C:\\test\\malware.dll"
"TargetFile"="C:\\WINDOWS\\system32\\malware.dll"

The entry will force the file:

  • C:\test\malware.dll

to be loaded.

It will be also copied to:

  • C:\WINDOWS\system32\malware.dll

Note that you can also simply ignore the copying and drop the file anywhere, and just point ‘CacheFile’ and ‘TargetFile’ to it.

If you look at the first screenshot you will notice the Procmon logs show a reference to the ’20MUIFixUp’ entry.

Interestingly, this entry can be used to just copy files, so adding a reg combo as below:

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Setup\ServiceStartup\malware.dll
"20MUIFixUp"=dword:00000001
"CacheFile"="C:\\test\\malware.dll"
"TargetFile"="C:\\WINDOWS\\system32\\malware.dll"

will create ‘C:\WINDOWS\system32\malware.dll’ anytime you boot the system (but the file won’t be loaded/executed). The’ 20MUIFixUp’ entry in the Registry will be deleted afterwards (so it needs to be re-created).

Interestingly, the information about the loaded DLLs can be found inside the Windows Update log file:

  • c:\WINDOWS\WindowsUpdate.log

Here’s an excerpt:

Misc    Registering binary: C:\WINDOWS\system32\regsvr32.exe  /s "C:\WINDOWS\system32\malware.dll"
Misc    FATAL: Self registration of C:\WINDOWS\system32\malware.dll failed, error = 0x8024D007
Setup    FATAL: Failed to register C:\WINDOWS\system32\malware.dll: error 0x8024d007
Setup    FATAL: ProcessDelayedCopies failed: 0x8024d007
Service    FATAL: Failed to fix up registration at service startup: 0x8024d007

My test DLL was not prepared correctly (missing exported ‘DllInstall’ – see below), but the DLL still loads.

At least on Windows XP.

Okay, what about newer versions of Windows?

First, let’s fix my DLL.

To do so, I actually add two exported functions:

  • DllInstall, and
  • DllRegisterServer.

Why?

Because the ‘RegistrationFlags’ parameter can be equal either to ‘1’ or ‘2’.

If it is 1, the ‘DllInstall’ API will be called. Otherwise, it will be the ‘DllRegisterServer’ API.

When these DLLs are loaded and respective functions are called the Windows Update service logs the appropriate information to the ‘WindowsUpdate.log’ file – let’s have a look at the two examples:

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Setup\ServiceStartup\malware.dll
"RegistrationFlags"=dword:00000001
"CacheFile"="C:\\test\\malware.dll"
"TargetFile"="C:\\test\\malware.dll"

and

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Setup\ServiceStartup\malware.dll
"RegistrationFlags"=dword:00000002
"CacheFile"="C:\\test\\malware.dll"
"TargetFile"="C:\\test\\malware.dll"

When Windows Update service is restarted, you will get the following log entries inside the WindowsUpdate.log:

"RegistrationFlags"=dword:00000001
Misc    Registering binary: C:\Windows\system32\regsvr32.exe  /s "C:\test\malware.dll"
Agent      * WU client version 7.6.7600.256
Agent      * Base directory: C:\Windows\SoftwareDistribution
Agent      * Access type: No proxy
Agent      * Network state: Connected

"RegistrationFlags"=dword:00000002
Misc    Registering binary: C:\Windows\system32\regsvr32.exe  /s /n /i "c:\test\malware.dll"
Agent      * WU client version 7.6.7600.256
Agent      * Base directory: C:\Windows\SoftwareDistribution
Agent      * Access type: No proxy
Agent      * Network state: Connected

The trick works like a charm for Windows 7. I don’t see it working on Windows 10 though, but perhaps it has to be triggered some other way.