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.

Dictionary files (.dctx)

This is not a very important research really. Just a ‘blurb’ of what I observed during my quick tests.

So…

First of all, I noticed that .dctx files are being handled by this program:

  • C:\Windows\System32\IME\shared\IMEWDBLD.EXE

These are dictionary files (source) and are compiled to some other binary format (.dctc AFAICT). These dictionaries seem to be heavily used (and needed?) for Asian languages, so most of info on them can be found online on forums discussing Japanese and Chinese language keyboard input.

Examples: here, and here.

When you open a .dctx file on Windows 10 you will be presented with this dialog box:

When we click OK, we will see another dialog box:

I have not figured out what that means, but it seems to be a highly prevalent error and many users report it. I couldn’t bypass it despite toying around with various parameters embedded inside my test .dctx file. I tried to use variations of English language (US vs. UK), different encoding, etc., but it always comes back with the same error.

Also, after looking at IMEWDBLD.EXE, I noticed that it takes a -v <logfile> command line argument (where -v stands for -verbose, I guess). Using it during testing is a better alternative to that non-descriptive dialog box shown above. After trying to open the very same .dctx with IMEWDBLD.EXE and -v flag enabled I observed this in the ouput of the log file:

Error: Encountered fatal error(0x80070057:The parameter is incorrect.).
Error: There is a problem with the dictionary file. Please try to download again.

Unfortunately, this error is very prevalent inside the binary (IMEWDBLD.EXE), so I didn’t spend too much time trying to figure it out. Okay, if you must know, 0x80070057 stands for an invalid argument. Would be really handy to know which argument triggered it… hmm…..

So, that’s it really.

If you want to play around, this is a minimalistic sample .dctx file you can try to import on your Windows 10 system. Download, and double click. That’s it.

Bonus

I think the IME components are not very well researched and can potentially offer mechanisms that will allow for less-known attacks focused on:

  • persistence
  • bypassing security controls
  • RCE

Why?

They seem to be developed for a niche (but not negligible due to number!) group of users in Asia (Japanese, Chinese), and most likely have been poorly tested. The last IME-related research I could find is here.

Why?

If you look at IMEWDBLD.EXE binary you will notice a bunch of flags that are not documented anywhere on the internet. Hence, they could be limited to a test environment at MS, or only taken into account on OS versions that require IME. The lower the scope, the lower the testing priority. A.K.A. if it is not documented on the Internet, then it’s likely internal.

Some food for a thought:

  • HKLM\SOFTWARE\Microsoft\IME\PlugInDict
  • EncryptAllPlugInDict
  • DisableAllPlugInDict

Command line arguments for IMEWDBLD.EXE:

  • -encrypt <unknown>
  • -pluginguid <guid>
  • -w <unknown>
  • -pm <unknown>
  • -v <logfile> – saves the verbose info to logfile
  • -nofilter <unknown>
  • -testing <unknown>