A forum for reverse engineering, OS internals and malware analysis 

Forum for announcements and questions about tools and software.
 #28833  by EP_X0FF
 Thu Jul 07, 2016 2:18 pm
Continuous digging into WinSxS internals give me some surprising results, so I decided to share it, despite previous statements.

First I would like to recommend you old and seems abandoned blog -> https://blogs.msdn.microsoft.com/junfeng/

It is one of the Fusion (aka WinSxS or aka both) developers. I found answer why all this sxs stuff so dramatically remembers me dotnet framework. They share same dev teams, same ideas and same design. Well and same design failures.

SxS all based on various things like parsing manifests xml, manipulating Windows loader behavior and other mostly boring stuff. Introduced to fight against Dll Hell problem, and looking on WinSxS folder size on various computers, it is now Dll Hell problem itself.

Manifest, what do you know about it? Xml shit with dependencies your program will load (+plus sometimes MS put here undocumented backdoors to fix UAC but it is our secret), also here located specific program settings like support of HighDPI and other non-interesting stuff.

Probably all your experience with manifest was about enabling visual styles, using the below manifest from MSDN examples:
Code: Select all
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="*"
    name="CompanyName.ProductName.YourApplication"
    type="win32"
/>
<description>Your application description here.</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="*"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
</assembly>
the most interesting part here is dependency block. It tell Windows loader to select proper dll for the given component named "Microsoft.Windows.Common-Controls". This will force Windows load comctrl32.dll from WinSxS folder of given type, version and language, instead of file in system32, which is here for compatibility reasons.

How does it will load? Obviously Loader/WinSxS will built path to dll, judging on manifest data and then do load library it, from WinSxS store you might think (that huge directory systemroot\winsxs).

Not so fast!

Before doing so, Windows will check if special feature called "DotLocal" can be used. DotLocal is a algorithm comming from old good days of Windows 2000, yeah so old. It is local dll redirection technique. It behavior was altered few times since Win2k, but it is still here, in modern fresh OS, in Windows 10 RS1. More information about it history -> https://blogs.msdn.microsoft.com/junfen ... direction/. Is it documented? Yes and no, documentation isn't complete and contradictory.

To put it simple.

If ApplicationName.exe.local exists as directory - Windows will try to find assembly components inside it. It they found - Windows will load it. Feeling some dotnet influence here?

How does it related to bypassing UAC and elevating to NtAuthority\System?

Windows autoelevated components such a sysprep (pity app, so much love from malware) has a GUI and they use comctl32.dll. What a surprise!

Lets profile it (you maybe surprised but this thing is something Microsoft unable to do last 7 years).

Image

In red - Windows check if DotLocal redirection available. Nope.
In green - Windows access WinSXS store, because DotLocal unavailable.

So we:
1) Creating sysprep.exe.local directory.
2) Creating assembly component folder.
3) Copying payload as comctl32.dll into final component folder.

In the end we have something like this:
Code: Select all
C:\windows\system32\sysprep\sysprep.exe.local\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.14379.0_none_2d155300bdac0920\comctl32.dll
Trigger sysprep.exe - our code loaded because we enabled DotLocal and we have High IL, because sysprep autoelevate=true and executionlevel=requireAdministrator.

We have multiple autoelevated application with GUI. You know what to do.

Now next part, with all this stuff time to make some fun from UAC itself.

As you know this thing is running as service - NT AUTHORITY\SYSTEM. Can we hijack UAC itself, using above described method? Do you remember that annoying popups from this "not security boundary" feature which it bombards to users? It has GUI and it is inside consent.exe, located in the system32. You maybe don't know but appinfo.dll really loves consent.exe, doing so much hardcore checks (AipVerifyConsent), something like "Is it you consent.exe? I mean are you really from Microsoft?" Yes, shut the fuck up and load me. Btw, since latest RS1 builds UAC window now has new design. New UAC window design - it was really what was required to do with UAC.

We need to load into UAC service and keep it workable, consent.exe imports ONE function from comctl32.dll - TaskDialogIndirect with fixed ordinal, doesn't change since Windows 7. We can forward it to nowhere, (but not to system32\comctl32.dll because it doesn't have it) or try to load real comctl32 from winsxs and call it from here. This doesn't really matter.

Another consent.exe specific problem we need to solve. Since this trash spawns everytime elevation take place IFileOperation used as delivery interface can fail during creating sub directories/copying file. Why? Because Windows will look inside DotLocal directory during interface autoelevation and if nothing found here it will stop loading. And we are risking to face completely unworkable UAC, where you will be unable start anything with admin rights.

Solution is simple - enable DotLocal redirection only after all preparation is done. So you create some directory named consent.exe.shit, create sub directory for assembly component, copy here your file and only after this -> rename consent.exe.shit to consent.exe.local, this enabling DotLocal for application.

Have no idea if this can be done more easily with Wusa, Windows 10 banned it /extract option, so I don't even look on Wusa now.

So in the end consent.exe loads your payload because of DotLocal and executes it with NtAuthority\System rights. Your code is passing execution next, so consent.exe can normally show it dialog and UAC can elevate(or not elevate) user programs. Everytime when UAC will be triggered - your code will be triggered also. Very cool and easy.

Example: we are running eventvwr.exe because it will launch "mmc.exe evenvwr.msc" (mmc.exe is whitelisted for autoelevation with known snap-in - so no UAC dialogs even show), which trigger consent.exe and load our code. Windows 10 RS1, most secured version of Windows? Pfff.

Image

Where it will work: everywhere since Windows 7 up to latest available RS1 build 14379.
What integrity level do we need: medium as on any default Windows setup.
What UAC level do we need for IFileOperation: default as on any default Windows setup.
Affected applications: every using WinSxS components.

This implemented in UACMe v2.5 as method 21 (sysprep) and method 22 (special for consent).

Update 08/07/16

Another post about DotLocal
http://www.hexacorn.com/blog/2015/01/09 ... y-part-23/

which points to the same blog as source I mentioned.

Update 10/07/16
Special update for twitter security experts, who are digging into demagogy.

Where it will work: everywhere since Windows 7 up to latest available RS1 build 14385.
What integrity level do we need: medium as on any default Windows setup.
What UAC level do we need for IFileOperation: default as on any default Windows setup.
Affected applications: every using WinSxS components.
User Account: admin as on any default Windows setup.
 #28872  by EP_X0FF
 Wed Jul 13, 2016 8:37 am
Preamble

UACMe v2.5.1 will be the last official release. Any further updates will only include bugfixes and information regarding changes in Windows.

Those demagogues with "not a security boundary" can close this browser tab now - nothing interesting to you, go play with your toys/mantras.

Decision to stop development comes from:

1) Starting from December 2014 until July 2016 we have successfully identified and reproduced something like 99% of UAC bypass methods used by ITW malware and based on AutoElevation Microsoft backdoor. Nothing really left. Malware developers mostly show total incompetence in this subject, having multiple different working methods they still copy-paste old useless crap and idiocy with virus like EPO.

2) It is boring. The same and same methods just working with different environment.

3) Uncovered methods more than enough to bypass UAC everywhere from Windows 7 up to Windows 10 RS1.

4) Microsoft unwilling to fix root of the problem and only produce partial and sometimes not working fixes.

Root of the problem

1) Default user account is Admin.
2) Default UAC settings are not enough to prevent malware from silent autoelevation.
3) Ways to write to the system directories exist (IFileOperation, WUSA, InfDefaultInstall in past, IFileOperation in present)
4) Exist security-through-obscurity mechanisms (e.g. ISecurityEditor, SxS).

Here is the promised "guide" with live examples. Most of it inspired by Captain Obvious. This guilde assumes you are following this thread from the beginning and familiar with UAC internals/ways to bypass/MS fixes listed here.

UAC bypass "guide"

Target OS

We are looking on upcoming Windows 10 RS1 as target. For older systems - multiple methods already implemented in UACMe and I think it's more than enough.
Architecture is x64, as dominant. Build - 14388.

Attack surface and components

It is greatly reduced in comparison to previous versions and even with Windows 10 TH1. Still lots of way to compromise this pseudo-security mechanism.

g_lpIncludedSystemDirs
Handled by appinfo!AipInitializeSecureWindowsDirectories.
Application examined by UAC checked to be inside these directories.
Code: Select all
%systemroot%\system32, contains most of x64 autoelevated applications 
%systemroot%\syswow64 contains wow64 versions of autoelevated applications
g_lpExemptedAutoApproveExes
Handled by appinfo!AipInitializeSecureWindowsDirectories
Application examined by UAC checked to be exactly this file and location.
Code: Select all
%systemroot%\inetsrv, contain InetMgr.exe (when IIS installed)
%systemroot%\sysprep, contain Sysprep.exe
g_lpIncludedPFDirs
Handled by appinfo!AipInitializeSecurePFDirectories
Application examined by UAC checked to be inside these directories.
Code: Select all
"Windows Defender"
"Windows Journal"
"Windows Media Player"
"Windows Multipoint Server"
Note: Windows Defender uses FileSystem filter to deny write attempts to it folder, thus making it exploitation (in this way) impossible.

g_lpAutoApproveEXEList
Handled by AiIsEXESafeToAutoApprove
Application examined by UAC checked to be one of these files.
Code: Select all
"cttunesvr.exe"
"inetmgr.exe"
"migsetup.exe"
"mmc.exe"
"oobe.exe"
"pkgmgr.exe"
"provisionshare.exe"
"provisionstorage.exe"
"spinstall.exe"
"winsat.exe"
Note: starting from Windows 10 RS1 14371 build this list verified by newly added routine appinfo!AipIsValidAutoApprovalEXE, thus making it direct exploitation further impossible.

Microsoft Snap-in files. Does not have public symbol name. Assume it is sort of g_lpApprovedMSCList
Handled by appinfo!AiIsEXESafeToAutoApprove
mmc.exe examined by UAC to have parameter from this list and snap-in is verified.
Code: Select all
"adfs.msc"
"admgmt.msc"
"adrmsadmin.msc"
"adsiedit.msc"
"appsrv.msc"
"appsrv64.msc"
"azman.msc"
"certmgr.msc"
"certsrv.msc"
"certtmpl.msc"
"ciadmin.msc"
"ciadv.msc"
"cluadmin.msc"
"comexp.msc"
"compmgmt.msc"
"da6to4.msc"
"daiphttps.msc"
"daipsecdos.msc"
"daisatap.msc"
"damgmt.msc"
"datrdr.msc"
"datrds.msc"
"devmgmt.msc"
"dfsgui.msc"
"dfsmgmt.msc"
"dhcpmgmt.msc"
"diskmgmt.msc"
"dnsmgmt.msc"
"domain.msc"
"dsa.msc"
"dssite.msc"
"eventvwr.msc"
"failoverclusters.snapinhelper.msc"
"fsmgmt.msc"
"fsrm.msc"
"fxsadmin.msc"
"gpedit.msc"
"gpmc.msc"
"gpme.msc"
"gptedit.msc"
"hcscfg.msc"
"idmumgmt.msc"
"iis.msc"
"iis6.msc"
"ilr.msc"
"ipaddrmgmt.msc"
"lsdiag.msc"
"lusrmgr.msc"
"napclcfg.msc"
"nfsmgmt.msc"
"nps.msc"
"ntwkmgmt.msc"
"ocsp.msc"
"perfmon.msc"
"pkiview.msc"
"pkmgmt.msc"
"printmanagement.msc"
"remoteprograms.msc"
"rrasmgmt.msc"
"rsadmin.msc"
"rsop.msc"
"sanmmc.msc"
"sbmgr.msc"
"scanmanagement.msc"
"schmmgmt.msc"
"secpol.msc"
"services.msc"
"storagemgmt.msc"
"storexpl.msc"
"tapimgmt.msc"
"taskschd.msc"
"tpm.msc"
"tsadmin.msc"
"tsconfig.msc"
"tsgateway.msc"
"virtmgmt.msc"
"wbadmin.msc"
"wdsmgmt.msc"
"wf.msc"
"winsmgmt.msc"
"wmimgmt.msc"
"wsrm.msc"
AutoElevation checking.
Compare manifest element autoElevate value to "true"
Originally implemented in appinfo!AipCheckFusion called by appinfo!AiIsEXESafeToAutoApprove

AutoElevated COM interfaces, see note.
http://www.kernelmode.info/forum/viewto ... =13&t=3687

Everything from above vulnerable to dll-hijacking. So much effort to nothing in result.

Utilities
1) Microsoft Dependency Walker (http://dependencywalker.com/, or from newest SDK)
2) Microsoft Sysinternals Process Monitor (https://technet.microsoft.com/en-us/sys ... nitor.aspx)
3) Any dissassembler capable to work with x64 binaries
4) Your own made injector dll x64/x86-32 which will be used for fast application tests.

Profiling
Take all autoelevated applications and put them into profiling. Sounds already boring? Yes it is.

1) Check if application has manifest with dll redirection, examples sysprep.exe/inetmgr.exe
2) Run DependencyWalker as admin, load autoelevated application, set all flags in profile section and run. After it exit - carefuly examine output logs, looking for dll load attempts, their path and conditions (who load them).
3) Run Process Monitor, setup filter by process name to examined application. Select FileSystem/Process And Thread Activity. Enable advanced output. Run target application. Find a missing dll file load attempts.

Live example #1. WOW64 executables.

Profiling wow64 Wusa.exe (autoelevate=true)

ProcMon output.
Image

From this picture you see that wow64 wusa.exe attempt to read wow64 logger dll which does not exist on disk, this is generic behavior for wow64 executables. Can we use it bypass UAC? Yes. See lhc645 initial wow64 logger blogpost from 2010 To exploit this and bypass UAC -> place your x64 injector dll to the system32 root (not syswow64). Now every wow64 application will execute your code -> every autoelevated wow64 too.

Notice rpcss.dll failed read attempt. Figure out it doesn't actually loaded by wusa.exe

Turn on Registry in ProcMon and profile again, look for suspicious registry entries in HKCU application attempt to read. Sometimes Microsoft binaries looks for special keys to load additional dlls.

This example was so-called rough attempt.


Live example #2. Exploiting g_lpAutoApproveEXEList

Carefully profile every executable from this list. If nothing found, put all of them into disassembler and figure out what they do.

I will show you simple example with PkgMgr.exe - Vista legacy package manager, which is whitelisted by Windows and represents another UAC bypass.
Preliminary ProcMon/Depends results shows - nothing suspicious, pkgmgr indeed load everything that exists and in system folders. So we go to the next stage.

Put pkgmgr.exe into disassembler. Immediately at windows main we can see the following code:
Code: Select all
  v21 = StartDism(v38, &v37, &v65);
    v9 = v21;
    if ( v21 < 0 )
    {
      v22 = "Failed to start dism.exe.";
      goto LABEL_63;
    }
Nice catch, so package manager is actually gate to dism.exe, located in the same system32 folder, but not autoelevated.

However since PkgMgr.exe autoelevated his child process also will have High IL.

We need to figure out how to start dism.exe from Package Manager and how to hijack Dism.exe

ProcMon to the rescue.

Image

Congratulations, we just found another UAC bypass. Dism.exe attempt to load non-existent dll from system32 and when failed load it from Dism subdirectory.

Now we need to figure out how to launch dism from Package Manager.

MSDN to the rescue.

https://technet.microsoft.com/en-US/lib ... s.10).aspx
/n: answer_file
Specifies the file name of the unattended installation answer file
In other words we need to run PkgMgr.exe /n:OurFile, this will be transfered to dism and trigger our code.
As file, take any shit from any KB you can found. I will use this one very small and simple.

Save it as AnyShit.xml %somewhere%
Code: Select all
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
    <servicing>
        <package action="install">
            <assemblyIdentity  name="Package_1_for_KB929761" version="6.0.1.1" language="neutral" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35"/>
            <source location="%configsetroot%\Windows6.0-KB929761-x86.CAB" />
        </package>
     </servicing>
</unattend>
Place payload x64 dll to the system as dismcore.dll and run pkgmgr.exe /n:%somewhere%\AnyShit.xml

Result:
Image (uacme #23)

Live example #3 Exploiting g_lpAutoApproveEXEList and Microsoft Management Console

mmc.exe handled by UAC in tricky way. It is autoelevated only when known snap-in used (purpose - less irritation of user when it works with admin tools).
List of snap-ins is huge and you have to profile it all. Itself snap-in is just text configuration file, however you cannot edit it, as it won't be verified.

So we will profile mmc with snap-ins and look on the ProcMon/Depends output.

Image

Notice DotLocal (as everywhere with GUI), MFC Local dlls (you will be surprised but previous Windows versions tried to load them as code). Look on this strange failed attempts -> DSPARSE.DLL and wbemcomn.dll

Could this be used to UAC bypass? Placing DSPARSE.DLL to the systemroot\system32\wbem result:

Image

Same with wbemcomn.dll (uacme #20).

Live example #4. DOTNET DLL HELL

Dotnet do you like it? Fast easy way to create application with support of modern technologies. So why not? Microsoft don't really trust dotnet applications to be autoelevated. From all scope I found only few mmc snap-ins using dotnet and one dotnet application in Windows 2012 R2 -> Server Manager.

Lets begin our dotnet journey with helloworld C# application. I actually like C# and writting programs on it. Surprise?

Simple HelloWorld from MSDN.
Code: Select all
using System;
namespace HelloWorld
{
    class Hello 
    {
        static void Main() 
        {
            Console.WriteLine("Hello World!");
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}
Compile it as x64 release with other default settings. Run it in Depends and ProcMon.

Image

Image

What the fuck is this?

Image

But I never asked for this. I just wanted to run HelloWorld, why it started using Version.dll from current directory?

Another examples from different dotnet programs:
Code: Select all
00:00:48.657: LoadLibraryExW("C:\Windows\Microsoft.Net\assembly\GAC_MSIL\MIGUIControls\v4.0_1.0.0.0__31bf3856ad364e35\ntdll.dll", 0x0000000000000000, LOAD_WITH_ALTERED_SEARCH_PATH) called from "c:\windows\microsoft.net\framework64\v4.0.30319\CLR.DLL" at address 0x00007FFA2FF49F74 by thread 11.
00:00:48.657: LoadLibraryExW("C:\Windows\Microsoft.Net\assembly\GAC_MSIL\MIGUIControls\v4.0_1.0.0.0__31bf3856ad364e35\ntdll.dll", 0x0000000000000000, LOAD_WITH_ALTERED_SEARCH_PATH) returned NULL by thread 11. Error: The specified module could not be found (126).
Code: Select all
00:00:43.313: LoadLibraryExW("C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\oleaut32.dll", 0x0000000000000000, 0x00001000) called from "c:\windows\microsoft.net\framework64\v4.0.30319\CLR.DLL" at address 0x00007FFA2FF49F74 by thread 1.
00:00:43.313: LoadLibraryExW("C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\oleaut32.dll", 0x0000000000000000, 0x00001000) returned NULL by thread 1. Error: The specified module could not be found (126).
Code: Select all
00:00:44.844: LoadLibraryExW("C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\shell32.dll", 0x0000000000000000, 0x00001000) called from "c:\windows\microsoft.net\framework64\v4.0.30319\CLR.DLL" at address 0x00007FFA2FF49F74 by thread 1.
00:00:44.844: LoadLibraryExW("C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\shell32.dll", 0x0000000000000000, 0x00001000) returned NULL by thread 1. Error: The specified module could not be found (126).
Code: Select all
00:00:01.890: LoadLibraryExW("C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscoree.dll", 0x0000000000000000, LOAD_WITH_ALTERED_SEARCH_PATH) called from "c:\windows\microsoft.net\framework64\v4.0.30319\CLR.DLL" at address 0x00007FFA28788D00 by thread 1.
00:00:01.890: LoadLibraryExW("C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscoree.dll", 0x0000000000000000, LOAD_WITH_ALTERED_SEARCH_PATH) returned NULL by thread 1. Error: The specified module could not be found (126).
00:00:01.906: LoadLibraryExA("mscoree.dll", 0x0000000000000000, 0x00000000) called from "c:\windows\microsoft.net\framework64\v4.0.30319\CLR.DLL" at address 0x00007FFA28817CC9 by thread 1.
Can we use this to bypass UAC? Definitely Yes.

Lets find what dotnet components we can exploit this way and look on their Dotnet DLL Hell.

You maybe already guessed who are these components. This huge bloatware dotnet powered EventViewer, TaskScheduler. Just profile first of it.

mmc.exe eventvwr.msc
Image

Ok, lets drop our oleaut32.dll for example to dotnet framework directory.

Image

No comments. In fact you can use multiple dll names. It will load and execute everything.

Task Scheduler Snap-in, multiple hijacking variants.

Image

Other dotnet powered console snap-ins vulnerable as well.

Epilogie

Everything from above can be found in 2-10 minutes of simple Windows binaries profiling. Seems impossible to do for Microsoft.

UAC is a pseudo-security feature.

Do not trust UAC in admin account even in Windows 10 RS1, as it easily can be fooled by malware.

Do not sit under admin -> set password for admin account and use account without admin privileges. Force UAC to show you everything -> give it max settings. Yes, it is a pain in the ass - but blame Microsoft and their marketing (defending themselves with blog posts full of demagogy) not system itself. It is their fault not Windows.

Users have this Windows setup -> Windows Defender ON, updates on, UAC default, account default admin. Will this prevent malware from install? No. Malware will be delivered to user undetected by built-in AV, will be executed and self-elevated through UAC bypass to the high integrity level (or like in case of consent directly to system privileges) and from it fuck user. Really nice perspective. Remember simplicity is always better.
 #28895  by EP_X0FF
 Sat Jul 16, 2016 5:59 am
As I said above I now will only update information regarding Windows changes and UACMe in general.

Readme updated with Windows 10 RS1 14390 information, Cymmetria Patchwork and discontinuation notice.

https://raw.githubusercontent.com/hfire ... /README.md
 #28906  by EP_X0FF
 Tue Jul 19, 2016 5:09 am
Windows 10 RS1 build 14393 does not contain any UAC improvements or fixes.

Special note for guys who copy-paste from this thread to the different forums: give a credit to the place from where you steal "your" information.
 #28918  by flir
 Thu Jul 21, 2016 7:14 am
Thanks EP_XOFF, this is very informative, cheers! appreciate all the efforts into research, analysis and development in these flaws and for UACme. I've enjoyed all your discoveries over time! Keep up the good work and stay active! your a great asset to the community.
 #29058  by EP_X0FF
 Wed Aug 17, 2016 7:54 am
Nice attempt to give a WHITEFLAG from MS.
There are really only two effectively distinct settings for the UAC slider
https://blogs.msdn.microsoft.com/oldnew ... 0/?p=94105

It is Captain Obvious blogpost which shows how much technically author understand in subject. Not so much. What a surprise, I was better opinion about this author.

First of all, remember this and stop giving accent to it: You don't need injects anywhere. Unless they won't change this in Windows builds sometime in future.
Second: expect in future usage of this blogpost (with completely incompetent technical statement) as another answer-on-everything link in any kind of discussions about UAC.

A: "Hey UAC sucks, here is my exploit for default settings"
B: "UAC is not security boundary"
A: "But it works"
B: "RTFM https://blogs.msdn.microsoft.com/oldnew ... 0/?p=94105"

Do you ever wonder why MS is so fucked up last few years?
  • 1
  • 10
  • 11
  • 12
  • 13
  • 14