Stuffing up the WINDIR env. var. with THE SPACE

I love revisiting the ‘there is nothing else to be found there anymore’ cases and I described this process here.

Recently, I’ve been thinking of the WINDIR environment variable. I have already covered a few cases where WoW executables could be forced to execute any executable of our choice after the WINDIR environment variable modification, but it crossed my mind that we may try something new…

If you google what the environment variable maximum length is you will discover it is (allegedly) 32,767 characters. Luckily, Raymond Chan wrote this post that gives us a bit more (reliable) insight.

So, my thinking was … if I can force the WINDIR environment variable to fill-in the whole space used by the environment variables…. then in cases where it is used to expand a path (f.ex. for the 64-bit executable from the WoW 32-bit executable level as in cases I linked to above), there may be some path truncation happening that will render the ‘expanded’ version of the path in some unpredictable way… That is, I was hoping that if the WINDIR is long enough f.ex. close to the alleged maximum length of 32K characters, then the rest of the path would be truncated, potentially giving us an opportunity to literally run any executable on the system this way…

That didn’t happen 🙁

After playing around with it I eventually gave up. No truncation occurred, and while results were dependent on the WoW executable I tested (msra.exe, w32tm.exe, launchtm.exe), I have not identified a way to exploit this in any way.

However…

I do want to showcase one interesting observation from this attempt.

The msra.exe was a very interesting study.

I generated a batch file that was nearly 65K in size. It’s just a rather lengthy SET WINDIR=<~64K spaces>..\..\windows\notepad.exe.

So, I ran it from cmd.exe terminal, and then executed c:\WINDOWS\SysWOW64\msra.exe.

To my surprise, the program ran! Despite the fact that the WINDIR environment variable was far bigger than the alleged maximum environment block size!

Secondly, while it took a few seconds for the msra.exe to load, it did eventually show an interesting message box as an indication of an error:

The lessons learned is that the environment block can be far larger than 32K!

Using System Informer/Process Hacker we can look at the msra.exe process environment block, and here it is — a WINDIR variable taking ~64K:

(you can select all, copy it to clipboard, then paste it in Notepad, save file and check file size).

What this example teaches is that you should trust, but verify.

And it’s still possible I missed something and WINDIR or many other environment variables can be abused to do things no one ever considered…

SilentProcessExit – quick look under the hood

There is a relatively old, but well-known debugging mechanism called SilentProcessExit. It is documented on Microsoft site, and there are many blogs talking about it (@Oddvarmoe has a very good into post about it and you should have a glance before you continue reading below).

I was curious how it works under the hood, and this post is about it. What motivated me to look at it in a first place was the fact that I saw a potential to abuse it to spawn arbitrary processes via svchost.exe / werfault.exe combo – with them acting as ancestor/parent processes to our program of choice e.g.:

I was curious if I could do it _without_ setting up Registry Settings under HKLM. If it worked, we would have yet another evasion possibility.

The function triggering this activity is called RtlReportSilentProcessExit and it is called from ntdll.dll before programs terminate.

If SilentProcessExit Registry settings are set up properly for the exiting program (either via gflags.exe tool, or manually), the aforementioned API will ‘talk’ to WER Service. As a result, the latter will launch a predefined Monitoring program as per the SilentProcessExit Registry settings (if configured).

I speculated, that if I can find out how the RtlReportSilentProcessExit API works, and in particular, how it talks to the WER service, I will be able to either force it to launch my program of choice, or at least rip its code to ‘talk’ to the WER service myself, and most importantly (and hopefully) – w/o the SilentProcessExit Registry Settings in place.

After a lot of spelunking, I realized a few things:

  • RtlReportSilentProcessExit is talking to WER services via ALPC; Alex Ionescu (no surprises here) covered (PDF Warning) this mechanism on a high level a few years ago.
  • Th ALPC port is named \WindowsErrorReportingServicePort
  • The ALPC interaction that RtlReportSilentProcessExit initiates just tells WER to handle the SilentProcessExit and provided the Process ID; I was really expecting to have more influence over this bit 🙁
  • The WER Service that the RtlReportSilentProcessExit API talks to is hosted by svchost.exe:
    • WerSvc = C:\Windows\System32\svchost.exe -k WerSvcGroup
    • It loads the %SystemRoot%\System32\WerSvc.dll
  • After looking at WerSvc.dll I confirmed that the HKLM Registry settings required for SilentProcessExit to work are mandatory 🙁
  • The WerSvc.dll handler extracts a file name of an executable that is exiting, then checks an associated IFEO Registry key, and if GlobalFlag value name exists and has a flag 0x200 set, it will launch the werfault.exe – the latter will execute the predefined Monitoring Process

So… the conclusion is this: we can trigger execution of this mechanism via RtlReportSilentProcessExit without exiting the program, and the svchost.exe/werfault.exe combo will launch the Monitoring Program of your choice, but you do need these Registry settings in place (GlobalFlag and Monitoring Program).

At the moment I can’t think of any practical use for it, but I guess it’s good to know why the Monitoring Program process is spawn by the werfault.exe.