Possible anti-sandbox trick using SetSystemTimeAdjustment API

Update

Just to expand on the forensic side of things – the time adjustment value, if changed, does not survive the reboot; i.e the adjustment value is not stored anywhere (e.g. in Registry).

Old post

Today I was browsing some of my archives and (re-)discovered a program written by my ex-coworker before Tue Feb 10 20:20:38 2004 (thx PE compilation time ;). The program was written with QA test automation in mind, but when I ran it today on my win7 VM I realized that the very same trick could be used to affect the inner working of the sandbox systems, or even disturb some reversing work…

The program is simple; it allows the user to modify the ‘adjustment’ value for the Windows Clock.

What does it mean?

Googling around I found this post that explains the inner workings of this mechanism better than I could ever do myself. The magic API is called SetSystemTimeAdjustment; it’s good to know that it internally calls NtSetSystemInformation with a SystemTimeAdjustmentInformation parameter. Sandbox programmers please take a notice.

As per the MSDN article:

The GetSystemTimeAdjustment and SetSystemTimeAdjustment functions support algorithms that synchronize the time-of-day clock, reported via GetSystemTime and GetLocalTime, with another time source using a periodic time adjustment.

Okay, enough theory.

After I ran the program and adjusted the ‘adjustment’ (pun intended) setting to the ‘max’ my clock went completely crazy:

(btw. this is tested and recorded on win7; win10 clock is such a ‘paradigm shift’ in the user interface that I can’t even begin to describe my despair…)

Running timeout 10 command suddenly doesn’t work as it should. It exits immediately or almost instantly and shows some funny values on the screen (kinda integer overflow ;). Same goes for timeout 100, 1000, 10000…

Interestingly, running ping 127.0.0.1 doesn’t cause any issues.

And this is because timeout is using a _time API function that is being checked every 100 ms. If we adjust the clock to run faster the _time function will produce the result that is immediately much higher than expected under normal circumstances (so, delta between the start value and next value is big enough o satisfy the exit condition); as a result, the timeout program will quit. Ping is using a call to Sleep (1000) API in a loop (between the pings, the number of which is default 3 and can be changed by the -n command line argument), and that’s why it is not affected.

So, the conclusion can be that if any program ran by a sandbox on the test system is relying on a difference between two sequential values returned by any of the time function relying on the adjustment (GetSystemTime , GetLocalTime, _time, etc.) – it will be affected. Sandboxes that don’t run any ‘worker’ programs on the guest system can sleep well, but… don’t they all run auto clickers (for GUI programs) these days? And these must rely on some delays/time functions. Hmm… As usual, a subject for a further research. I also wonder if changing the settings will affect existing software and potentially introduce some interesting race conditions or at least DoS. The good news is that use of this API requires admin privileges,

Beyond good ol’ Run key, Part 89

What would be Windows without all these hidden, test, debugging features?

I loathe Windows 10 for many reasons and so far do not plan installing it on my computer, but I do welcome all its updates and changes as they provide a fertile soil for research of any sort. New persistence tricks are of course pretty high on my list and I especially welcome these ones that ‘break’ something new.

Such is the case of the persistence trick I am going to cover today: persistence within Metro Apps.

Despite the Metro Apps no longer being plain vanilla PE files they still need to be loaded.

The task of loading them is delegated to WWAhost.exe that launches respective Metro App when we click the app’s icon. For instance, loading and launching Netflix App that you install from the Microsoft Store leads to the following process being created:

  • “C:\WINDOWS\system32\wwahost.exe” -ServerName:Netflix.App.wwa

and the current directory of the app is set to:

  • C:\Program Files\WindowsApps\4DF9E0F8.Netflix_6.81.325.0_x86__mcm4njqhnhss8\

I am not that familiar with Metro App internals yet, so I got curious about their loading process and started poking around this particular host process. I quickly discovered that it leverages the good old IFEO key and tests for a presence of an entry called ‘WWAInject’.

Ah, how nice…  seeing IFEO and ‘inject’ in the same sentence (a.k.a. one Procmon log row) can only lead to one conclusion: this is probably a new persistence trick!

So…

I added:

  • HKLM\SOFTWARE\Microsoft\Windows NT\
    CurrentVersion\Image File Execution Options\
    wwahost.exe\WWAInject=<DLL>

and pointed it to my test DLL.

Then I launched the test Metro App… and… nothing.

Not only it didn’t launch properly, it actually crashed.

Hmm…

Looking at the Procmon logs I discovered that the Access denied was reported for my DLL when the application was loaded. The fact it was accessed was a good sign. The fact it didn’t load… a bit of a disappointment. It then hit me. Metro App are sandboxed and use various mechanisms to restrict access of the protected apps to the local system.

After checking the OS libraries’ rights that are obviously loaded by the wwahost.exe without any problem I noticed that on a file system level they grant access to the following entities:

  • APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(RX)
  • APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(RX)

I cheated and used icacls with its /save and /restore options to copy the OS library rights to my DLL:

  • icacls C:\Windows\System32\rpcss.dll /save c:\test\foo

and then (after editing the name of the DLL) inside the ‘foo’ file to test.dll:

  • icacls C:\test\ /restore c:\test\foo

Now the DLL file has all the rights identical with C:\Windows\System32\rpcss.dll and can be loaded via the WWAInject entry with no problem. No more crashes, and the DLL does whatever I want it to.