The Background Story
Throughout 2021 a thought had been bouncing around in my head: why hasn’t anyone reimplemented MiniDumpWriteDump?
For those who are not yet familiar, the Win32 API MiniDumpWriteDump() has been available in Windows since at least Windows NT and was originally implemented to provide process snapshots for debugging purposes.
From an offensive security perspective, pentesters have been using it for a LONG time to dump the LSASS (Local Security Authority Subsystem Service) process for offline cached password and NTLM hash extraction with Mimikatz and its derivatives. Little did I know, someone had already done such a thing, and technically it wasn’t the first reimplementation.
Although it’s my own fault for living under a rock and not keeping a constant eye on Twitter, it’s entirely possible that the first MiniDumpWriteDump() reimplementation for offensive purposes had made some fanfare without grabbing my attention. Instead, I started down the process of trying to reimplement it myself, before giving up thanks to Michael Rand.
In this blog we’ll examine this Win32 API call, and walk through the [naïve] process I took to consider a reimplementation of MiniDumpWriteDump().
The Rabbit Hole
Somewhere around August or September in 2021, I finally had decided the persistent thought was enough and began to look at the MiniDumpWriteDump() API call in IDA. I had taken a peripheral look at it in the past, but never decided it was worth the time to reverse the API call.
I use my Windows 7 R&D system, assuming that the compiled version of MiniDumpWriteDump() wouldn’t have additional complexities introduced from newer compilers or anti-exploit methods as my Windows 10 LTSC R&D system might possess.
The first thing I did was load C:\Windows\System32\dbghelp.dll into IDA, and open the exported MiniDumpWriteDump() function. Without considering cross-referenced function calls, we can start to get a rough idea about how large the function is by viewing a Flowchart of the exported function:
That doesn’t look too terrible at first, but then we’ll expand to get a chart of all the Cross-references (Xrefs) from our function call, just to get a rough idea of how much binary code we’ll actually need to be reviewing. For those of you who haven’t done this before, when you see an “Xrefs From” chart that looks like the following, you’re in for a lot of work:
Although we were able to get debugging symbols imported from Microsoft when loading DbgHelp.dll, it wasn’t obvious what the Cross-referenced function calls (e.g. function calls LEAVING MiniDumpWriteDump() were doing. It was, however, obvious fairly quickly by the
call qword ptr [rax]
statements that we were likely dealing with C++ code that did not have easy-to-access class definitions:
First Reimplementation Of MiniDumpWriteDump()
I was wandering around in my vegetable garden, grumbling to myself about how much effort it would be to reimplement MiniDumpWriteDump() from reversing the Windows DLL, and continuously asked myself “who would have done this already?”
Then it dawned on me: ReactOS: a complete reimplementation of the NTOS Kernel from scratch that started development in 2001 or so, with binary compatibility across the Win32 API space. I was enamored at how cool such a thing could end up becoming, and they even had demos of running Quake III Arena!
I rushed inside and started searching for the source code. It was pretty easy since it’s hosted on GitHub. Searching through the main project, we found this fella: https://github.com/reactos/reactos/blob/3fa57b8ff7fcee47b8e2ed869aecaf4515603f3f/dll/win32/dbghelp/minidump.c#L942
With access to the source code, I started copying over code into Visual Studio to build a testing application. It wasn’t easy to get the copied code to build, because I had to copy over many supporting functions and custom structs, as well as identify the necessary Windows header files (or add the structs manually). As I was going through the process of fighting compiler errors, I found that ReactOS may present different internal OS objects than you’d find natively in Windows, in particular with regards to thread objects being returned for easier enumeration of thread stacks. After troubleshooting all of this, I was able to take a very rudimentary snapshot of LSASS on my testing system at around 2 MB of process memory. However, the initial pass did not have the necessary memory regions where credentials were stored.
Although it did take several days of spare time to get a build, I hadn’t spent enough time manually reviewing the code I was trying to get built. This was a pretty big error on my part, and it all came from the false belief that “nobody has done this for offensive security purposes yet”. We’ll get to that later, but at this point, I was running into a wall, largely due to my own patience, but also because we have to work on non-R&D projects at White Oak! But I was struggling to get the code to export much more than 2 MB of process memory, so I returned to searching to see if I could find other reimplementations of MiniDumpWriteDump().
Windows NT Leaked Source Code Living On GitHub?
I wish I could provide a direct link to what I found, but instead, I’ll provide a link to the DMCA Takedown notice:
During my searches, I came across references to Open NT OS, which apparently used to be hosted on an external Subversion (SVN) site and have an entire community. The developer had become tired of answering questions all the time and decided to close shop. Based on what was still lingering on old forums about this community, Open NT OS made use of copyrighted NT 4.0 source code leaked a decade ago to create an “updated” version of NT OS.
This had been the first time I heard of this, but a few more searches found that the source code had been moved to GitHub several years ago. The ironic part is that Microsoft (having purchased GitHub) was hosting its own source code, originally leaked to the world, and subsequently used (in violation of copyright) as part of a community project.
When I stumbled across this, I had assumed that Microsoft must have known GitHub was hosting that project. According to the DMCA takedown request above, it looks like they must have recently figured it out. What’s confusing to me is why the forked versions of the removed repository are still live (as of writing this blog), but I digress.
Regardless, peeking at Microsoft’s ancient implementation of MiniDumpWriteDump() for 32-bit Windows NT 4.0 wasn’t any more helpful. So I returned to the ReactOS implementation before taking a break from R&D to run a few Purple Team assessments.
Part One Summary
In this blog, we took a brief look at the MiniDumpWriteDump() Win32 API, and considered options for reimplementation for the purposes of avoiding AV and EDR prevention. When starting this research, little did I know that there was already one project released that did exactly this, nor was I aware that there was another one about to be released.
In the next blog, we’ll continue the story and walk through the two projects currently available as Cobalt Strike Beacon Object Files. And we’ll wrap the story up by discussing how we adapted one of these projects to be loadable with .NET Reflection methods!
Stay tuned, here’s MiniDumpDotNet Part 2.
More From White Oak Security
White Oak Security is a highly skilled and knowledgeable cyber security testing company that works hard to get into the minds of opponents to help protect those we serve from malicious threats through expertise, integrity, and passion.
For more expert pentesting posts, check out our blog page.