A standalone DLL that exports databases in cleartext once injected in the KeePass process.
Heavily inspired by the great KeeFarce, KeeThief and KeePassHax projects.
A few years ago, @denandz released KeeFarce, the first offensive tool designed to extract KeePass databases in cleartex. It works by injecting a DLL into the running process, then walks the heap using ClrMD to find the necessary objects and invoke KeePass's builtin export method using reflection. Its only downside at the time was that multiple files needed to be dropped on the target (the extraction DLL + ClrMD DLL + the injector + a bootstrap DLL).
A year later, @tifkin_ and @harmj0y released an in-depth review of offensive techniques targeting KeePass (while not available on harmj0y's blog anymore, the articles can be found on Wayback Machine: part 1, part 2). It resulted in the release of KeeThief, a tool able to decrypt KeePass' masterkey (including when alternative authentication method are used). It worked so well that KeePass developpers added a parameter to mitigate this technique (it can be disabled by editing KeePass configuration file if the user have enough rights, which is pretty common).
These tools quickly became my go-to during penetration testing, but they soon became obsolete as their injection techniques (namely, the famous Win32 APIs gang of VirtualAllocEx, WriteProcessMemory, CreateRemoteThread, WriteProcessMemory, etc) now immediately triggers detection. @snovvcrash addressed this issue by forking KeeThief (now in a private repo, but still accessible here) to improve the injection mechanism with D/Invoke, writing a great article detailing the process he followed. As this demonstrated the faisability of maintaining KeeThief, I find it difficult to implement with other injection techniques, as KeeThief's code is tightly linked to its injector.
@holly-cracker also released KeePassHax, which comes as a single DLL and only uses reflection to decrypt KeePass' masterkey. Inspired by this work, I decided to do the same with KeeFarce and write my own KeePass extraction tool with the following features:
- Self-sufficient ⇒ no interaction needed with the injector's code to work.
- Only uses builtin .NET libraries (in particular, no ClrMD) ⇒ better compatibility + single-file to make the injection easier.
- Exports the database ⇒ same as KeeFarce, no need to retrieve the .kdbx nor using a custom KeePass built to input the recovered masterkey.
As the code solely relies on .NET Framework with no external dependency, it should compile easily on Visual Studio 2015 and higher.
Once the KeePassReborn.dll is compiled, you will need to inject it by yourself in the targeted KeePass process.
As I personally find it easier to stealthily inject shellcode than DLL in a remote process, the first thing I typically start with is generating a position-independent shellcode from our DLL. It appears that @odzhan and @TheWover's donut project perfectly suits our needs !
We compile donut from a commit in the dev branch, as it fixes an issue in application domain management that would prevent us from performing reflection in the default domain.
git clone https://github.com/TheWover/donut/
cd donut
git checkout 9d781d8da571eb1499122fc0e2d6e89e5a43603c
We can easily build from Visual Studio's x64 Native Tools Command Prompt with nmake utility:
nmake -f Makefile.msvc
Generating the shellcode is as simple as:
.\donut.exe "C:\KeeFarceReborn\KeePassReborn\bin\Release\KeeFarceReborn.dll" -c KeeFarceReborn.Program -m Main -e 1
[ Donut shellcode generator v0.9.3
[ Copyright (c) 2019 TheWover, Odzhan
[ Instance type : Embedded
[ Module file : "C:\KeeFarceReborn\KeePassReborn\bin\Release\KeeFarceReborn.dll"
[ Entropy : None
[ File type : .NET DLL
[ Class : KeeFarceReborn.Program
[ Method : Main
[ Target CPU : x86+amd64
[ AMSI/WDLP : continue
[ Shellcode : "loader.bin"
Note that
-e 1
is necessary to disable entropy, otherwise the injected process won't be in the default application domain.
Let's compress it using PowerShell for easier integration in the injector's code:
$bytes = [System.IO.File]::ReadAllBytes("C:\donut\loader.bin")
[System.IO.MemoryStream] $outStream = New-Object System.IO.MemoryStream
$deflateStream = New-Object System.IO.Compression.DeflateStream($outStream, [System.IO.Compression.CompressionLevel]::Optimal)
$deflateStream.Write($bytes, 0, $bytes.Length)
$deflateStream.Dispose()
$outBytes = $outStream.ToArray()
$outStream.Dispose()
$b64 = [System.Convert]::ToBase64String($outBytes)
Write-Output $b64 | clip
You now have a payload ready to be injected with your favourite technique. If you don't know what to do now, I suggest you check ired.team Code & Process Injection page to get familiar with the concept, then have a look into direct syscalls and D/Invoke which will probably do the job in most cases. @SEKTOR7's malware development courses are full of great learnings if you can afford them.
As an example, let's inject our payload using snovvcrash's VeraCryptThief code (itself inspired by SEKTOR7 courses) that make use of D/Invoke. To demonstrate, I copied his project in the SampleInjector folder, we only need to paste our compressed shellcode then compile in x64.
While it still bypasses Defender at the moment (november 2022), tinkering your own injector will of course be needed in order to bypass modern EDRs. This sample injector is just here to demonstrate that everything behaves as expected.
By running .\SampleInjector.exe alongside an open KeePass database, you will see debug messages being printed in MessageBox (which should obviously be removed when used in a real penetration testing scenario) then find the exported database in the current user's %APPDATA% (choosed by default, as KeePass will be sure to have write access). The exported XML file can later be imported in any KeePass database without asking for a password.
If the export functionnality is disabled by policy, it can still be enabled by editing the KeePass.config.xml :
<Policy> <Export>true</Export> </Policy>
While the main issue concerning KeePass extraction tools detection is injectors, in-memory scan may also trigger alerts when analyzing the shellcode. You will probably have to obfuscate and/or encrypt the shellcode to use with your injector.
Also, the Assembly.Load
method used to perform reflection may be considered as a malicious behavior. I noticed that KeePass itself was sometimes using it for legitimate purposes so I guess most antiviral solutions won't flag it. If you have insights on this, feel free to let me know.
- KeeFarce Reborn only relies on .NET Framework with no external dependency, so it should be fairly compatible with most targets.
- By default, KeeFarce Reborn's Visual Studio solution targets .NET 4.6 (installed by default on Windows 10) but can be retargeted edited.
- If .NET Framework is not installed on the target system, you can still set it up manually from command line using
DISM.exe
. - I only tested x64 payloads injection, but this should work as well with 32 bits architectures.
- Check in details what parts of the DLL can trigger EDRs
- Provide an obfuscated version of the DLL
- Add option to log events into a file to debug while attacking a target, without using noisy message boxes
Pull requests are welcome. Feel free to open an issue or DM me on Twitter to suggest improvement.
Bits of code where taken from the KeeFarce, KeeThief and KeePassHax projects.
The sample injection mechanism was directely taken from snovvcrash's projects.