RunDLL32.exe Obscurity

RunDLL Wierdness

While working on building a couple new simulation modules for ATTACKIFY, we came across an interesting feature within rundll32.exe. When creating some test DLL files we created exported functions with the following names:

snippet_image

So at this point our DLL has two exported functions named MyFunction and MyFunctionA (this was originally just testing). The first function, MyFunction could contain potentially malicious code, however in this case it only displays a message box to indicate where you are in the execution.

So let’s run the new DLL with rundll32.exe and execute the exported function by name, MyFunction, and see what happens.

runbutnot_image

Well that’s is interesting rundll32.exe is executing the function MyFunctionA instead of the specified MyFunction as seen in the command line. As mentioned before we were testing something else when we came across this problem and couldn not figure out why rundll32.exe was not running the function we specified as it seemed to run just fine with other tools that are not rundll32.exe. So inorder to successfully execute the function we want, we can use something that is not rundll32.exe like a custom tool or PowerShell.

Our snippet for PowerShell can be something as simple as:

ps_code_image

Running the above PowerShell script successfully executes our function specified in the DLL as compared to rundll32.exe:

ps_code_image

What can we do with this?

Not all that much, however, something attackers/malware writers/red teamers could use this technique to potentially hide their malicious functionality from some basic analysis for a moment or two longer. An attacker can create 3 exported functions with the same name but ending two harmless functions with the the W or A suffix.

for example: FuncW() and FuncA() could contain non-malicious code and Func() would contain the malicious functionality

The idea would be that if the suspicious DLL is manually analysed using rundll32.exe the observed function will run the non-malicious functionality because of the strange behaviour, thus protecting the malicious code from being run and easily analysed. Obviously this not fool proof, but if only basic analysis is performed, this would easily circumvent the malicious code from being observed or detected as one of the harmless functions would run not the malicious one via rundll32.exe.

Why does rundll32.exe do that?

There is not a lot of information or research on this particular behaviour that we could find before writing this up. We do however suspect that it has to do with Microsoft Windows wide/Unicode and ANSI character compatibility support. So it seems like default behaviour is for rundll32.exe to fist check for wide/ANSI character supported functions before defaulting to the command-line specified function.

We found this mini write up on rundll32: https://www.hexacorn.com/blog/2019/09/28/rundll32-api-calling/

Then we also found a similar example of our finding here: https://github.com/gtworek/PSBits/tree/master/NoRunDll

Rundll32 and Ordinal Values

It is possible to force rundll32.exe to still run the specific function, just not by the exported function name. To do this one can use the ordinal value and tell rundll32.exe to execute the function at position #1, #2, #3 etc. So we can load the DLL up in a DLL Export View that will list all the available function names and the ordinal value for each function (you could also just brute-force the values starting from 1):

export_view_image

rundll32.exe <dllFile>, #1

As you can see the function in question has an ordinal value of 1, we can now simply instruct rundll32.exe to execute the correct exported function without getting tricked up by the naming obscurity issue:

rundll_rdinal_image

Lessons

I guess the lessons here include:

- Know your tools and what they are doing, what they are not doing and the tools limitations
- Make sure you thouroughly perform analysis and dont rely on basic testing
- Dig a little deeper and use the right tools

Simulation Module

We have already implemented a module to simulate the behaviour for you. The module will drop a DLL file to the endpoint, run the exported function that will spawn calc.exe and then when run with rundll32.exe will prompt the user to try harder! We also leave a copy of the artefact for you to manually play with.

Contact Us

Interested to find out more about ATTACKIFY?

Contact