Back

Executing .NET Methods with RunDotNetDll32

For DerbyCon 2017 I released a mini red team toolkit in the form of a .Net DLL named WheresMyImplant.  Since then I’ve been expanding its functionality to continue development on it. As part of the effort I needed a way to quickly execute .NET methods from an existing DLL.  However, to the best of my knowledge there was no nice way of doing that without using PowerShell or .net SmokeTest. So I created RunDotNetDll32 for that purpose.

In this blog I’ll provide an overview of what RunDotNetDll32 does and some common usage examples.

Introduction to RunDotNetDll32

Below is a basic example command showing how to use PowerShell to load the .NET DLL WheresMyImplant.dll so that the DumpSAM() function can be executed to recover local password hashes.

[System.Reflection.Assembly]::Load("WheresMyImplant.dll")
[WheresMyImplant.Implant]::DumpSAM()
[System.Reflection.Assembly]::Unload("WheresMyImplant.dll")

As you can see, PowerShell can be a great medium for executing .NET methods reflectively.  However, this can become a bit cumbersome during testing and isn’t ideal for executing client side.

Enter RunDotNetDll32; this executable has one purpose, to duplicate the functionality of rundll32 for .Net assemblies. Syntactically it is very similar to rundll32.exe. For example, if you wanted to execute the pre-mimikatz trick of locking the workstation and keylogging the winlogon process, it would start with the following command:

rundll32.exe User32.dll,LockWorkStation

Where the syntax is:

rundll32.exe $ASSEMBLY,$ENTRYPOINT $ARGUMENTS

With RunDotNetDll32 the syntax had to be slightly modified to the following:

rundotnetdll32.exe $ASSEMBLY,$NAMESPACE,$CLASS,$METHOD $ARGUMENTS

For example, to run the SAM hashdump from WheresMyImplant you could use the command below:

rundotnetdll32.exe WheresMyImplant.dll,WheresMyImplant,Implant,DumpSAM
----------
Namespace: WheresMyImplant
Class: Implant
Method: DumpSAM
Arguments:
----------
[+] Running as SYSTEM
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::

Similarly, the MiniDump method can be run from WheresMyImplant:

rundotnetdll32.exe WheresMyImplant.dll,WheresMyImplant,Implant,MiniDump 552,lsass.dmp
----------
Namespace: WheresMyImplant
Class: Implant
Method: MiniDump
Arguments: 552 lsass.dmp
----------
[+] Received Handle: 512
[+] Dump File Created

Enumerating Namespaces, Classes and Methods

It was pointed out to me early on that it’s not intuitive to have to remember every namespace, class, and method in an assembly. So the functionality to list namespaces, classes, and methods was rolled in.

Below are some basic examples:

Listing Namespaces

rundotnetdll32.exe WheresMyImplant.dll list namespaces 

WheresMyImplant

Listing Classes

rundotnetdll32.exe WheresMyImplant.dll list classes

WheresMyImplant
        [TRUNCATED]
        RunCommandPrompt
        ntdll
        LSASecrets
        InjectDll
        MyInstall
        Implant
        BaseSQL
        RunXPCmdShell
        Advapi32
        [TRUNCATED]

Listing Methods

rundotnetdll32.exe WheresMyImplant.dll list methods WheresMyImplant Implant

WheresMyImplant
        Implant
                RunCMD
                RunPowerShell
                RunXpCmdShell
                InjectShellCode
                InjectShellCodeWMIFSB64
                InjectDll
                InjectDllWMIFS
                InjectPeFile
                InjectPeString
                InjectPeWMIFS
                InjectPeWMIFSRemote
                Empire
                Tokenvator
                BypassUac
                DumpLsa
                DumpSAM
                DumpDomainCache
                DumpVault
                DumpVaultCLI
                ReadProcessMemory
                CheckCCNumber
                MiniDump
                PSExec
                WirelessPreSharedKey
                [TRUNCATED]

I made this program for myself and the team, but hopefully it will be useful to blue and red team members developing .NET applications.  If you have any bugs or commits let me know.  Both are welcome.

Back

Dumping Active Directory Domain Info – in Go!

I’ve used NetSPI PowerShell tools and the PowerView toolset to dump information from Active Directory during almost every internal penetration test I’ve done. These tools are a great starting point for gaining insight into an Active Directory environment. Go seems to be gaining popularity for its performance and scalability, so I tried to replicate some of the functionality in my favorite PowerShell tools. goddi (go dump domain info) dumps domain users, groups, domain controllers, and more in CSV output. And it runs on Windows and Linux!

Before going any further, I want to thank Scott Sutherland (@_nullbind) for his help and mentorship. This work is based off of internal tools he created and none of it would be possible without him! This tool is also based on work from Antti Rantasaari, Eric Gruber (@egru), Will Schroeder (@harmj0y), and the PowerView authors.

So Why Go?

Go is fast and supports cross platform compilation. During testing, goddi managed to cut execution time down to a matter of seconds when compared to its PowerShell counterparts. Go binaries can also be built for Windows, Linux, and MacOS all on the same system. The full list of OS and architecture combinations are listed in the go GitHub repo. At the time of this blog’s release, goddi has been tested on Windows (10 and 8.1) and Kali Linux.

That isn’t to say that there aren’t any drawbacks with a Go implementation. The Microsoft ADSI API is much more flexible to work with, especially when creating LDAP queries to run under the current user’s security context. goddi requires domain credentials to be explicitly provided on the command line. This can be especially annoying in scenarios where a user’s credentials may not be known. If you get access to a box with local Administrator, but don’t have domain credentials yet, you can run PSExec to get local system. With local system, you can check if you have domain user privileges and then run PowerShell in this current context without domain credentials. This functionality is on the roadmap for future development.

Features

Check out the GitHub repo for an up to date list of features. goddi dumps…

  • Domain users
  • Users in privileged user groups (DA, EA, FA)
  • Users with passwords not set to expire
  • User accounts that have been locked or disabled
  • Machine accounts with passwords older than 45 days
  • Domain Computers
  • Domain Controllers
  • Sites and Subnets
  • SPNs
  • Trusted domain relationships
  • Domain Groups
  • Domain OUs
  • Domain Account Policy
  • Domain deligation users
  • Domain GPOs
  • Domain FSMO roles
  • LAPS passwords
  • GPP passwords

Run goddi with the example command below. The CSV output is dumped in the “csv” folder in the current working directory.

goddi-windows-amd64.exe -username=juser -password="Fall2017!" -domain="demo.local" -dc="10.2.9.220" -unsafe

Goddi

Roadmap

In the future, I would love to see if I can get this tool to operate closer to the ADSI model. Being able to run the tool in the user’s current context would be preferable from a testing standpoint. I would also like to improve how GPP passwords are gathered. Network shares to the target DC are mapped and mounted with the net use and mount commands. While GPP cpassword searching works with these commands, I have not gotten the chance to add robust error handling for corner cases when dealing with underlying OS errors.

GitHub Repo

Check out the goddi GitHub repo for install and usage instructions. I’ll be updating the features list and roadmap there. Comments and commits are welcome! I’m not a Go expert, so I would appreciate any constructive feedback.

Discover how NetSPI ASM solution helps organizations identify, inventory, and reduce risk to both known and unknown assets.

X