KeePass + Password File + PowerShell = Brute Force Attack Goodness
PowerShell and KeePass Brute Force Password Reclamation
Happy New Year from Grumpy Admin!
Well now the nice holiday season is over, coming back to work with a thump is not nice…. it just makes me grumpy.
I was a bit busy before the holiday, so I did not get to write this to how I wanted to, so I thought I leave it off for the New Year.
Well last year, I meet an interesting problem! Which lead me for my own selfish reason to write a small PowerShell tool for cracking KeePass Files.
I got locked out of an old KeePass file, it might of had the credentials that we needed at the time, but no one in the office could remember the password, after many attempts we like most people in IT do, we gave up and reinstalled the same service after resetting the password.
However, this got me thinking… There lots of chatter of using cleaver memory forensic methods to recover the key and to find the key etc, but putting Dark Code on our system was not an option plus to be honest, Grumpy Admin isn’t that smart or astute when it comes to hacking! I know the basics and enough to be an effective junior blue team member but I don’t confess to being a rockstar like some.
My google Fu skills could find very few brute force tools out there for KeePass and nothing that says brute force KeePass and PowerShell. This is not good enough for me! Typically a lot of tools are written in Python but I wanted a PowerShell script.
I saw some code for accessing a KeyPass file via PowerShell. I have also seen code, and can write simple code that can read files like a big list of Passwords… why not just mix the two and have some sweet KeyPass brute force fun. It seems so simple, I am shocked I couldn’t find such a thing out there already. Maybe there is, I would like to find it!
PowerShell…. KeePass and Large Password list, seriously what could go wrong! Let give it try!
Let us get the simple thing done. I am often using password lists to crack passwords/ Test passwords for strength as they say… i’m a CISSP got to be ethical right!
Like a LOT of people, I grab Daniel Miesslers sec list from github – this provides me a large base files with lots of changes of having the correct password. Well as they say people choose bad passwords!
https://github.com/danielmiessler/SecLists
ps… under passwords section as he has lots of other things like fuzzers and stuff but the bottom line is “More passwords than you can shake a kangaroo at”!
I downloaded just a single password file with about a million passwords – and Grumpy Admin being lazy, and this is a simple first version of this new simple tool, we only parse and brute force against one file. I use simple because, well it is a brute force tool – the bottom of the food chain in infosec world… but still a tools a tool and more to the point I lean about connecting PowerShell to KeePass
Next, I created a test keepass file! With a password that is hopefully in the List… This will prove the brute force works! The password I have chosen from my test_password file is vjjk3p
This password is simple and will prove that the brute force works and exists in the password file!
Next I need to fire up my PowerShell editor – Now for small scripts, I normally just author them directly in notepad. However, for slightly more in-depth scripts and like most other people I of course use the ISE.
Then if I have an objective I want to achieve in a script, I like to plan my scripts/programs very simply, helps me get my logic correct!
load keepass access code load password file load first password loop open keepass file with password if opens dump all data else load next password and goto loop
Therefore, I have a now have a plan; let us hope I keep to it, as Grumpy Admin does have a tendency to wander off base.
Cut and Paste a basic new function in and let us start to create this basic tool! The birth!
Now my Google efforts showed me that I need to load the following two files as [reflection.assembly]
KeePass.exe KeePass.XmlSerializer.dll
So the code will look like this…
[Reflection.Assembly]::LoadFile("KeePass.exe") [Reflection.Assembly]::LoadFile("KeePass.XmlSerializers.dll")
This is a good start, if we are in the KeyPass directory, but if we not it will throw an error unless your KeePass binaries are in the system path. So let’s modify this function, give it a name and supply, a path as a param and use that in the loading of the KeePass functions from the KeePass binaries.
You should of noticed that I used the Mandatory=$true
This is a good start – but generally, when you are trying to do stuff, you should have some error handling code – A good way of doing is to put it inside of a TRY CATCH framework! I also throw the output to Null so we not bothered with misc. messages
Excellent work so far Grumpy Admin – Grab a Coffee! Ah that’s better, lets finish tidying this function up! We are sending a path to a something, so let validate that path. We could use the PowerShell cmdlet Test-Path! Let do this in a simple If statement so our completed function will now look like this
Next on our mini program roadmap is the load password file function/methods!
There are a couple way of doing this – Initially, when I was prototyping my code I was using Get-Content and it was very very very very slow and what was worse was it caused massive memory growth! This clearly was not viable method.
A quick Google and I find that I can create a File Stream object, just like what we used to do in VB etc but in .net J Check this MSDN page
https://msdn.microsoft.com/en-us/library/system.io.streamreader(v=vs.110).aspx
So my simple base code would be something like
$pwdfile = New-Object System.IO.StreamReader -Arg C:\Software\pwdlist.txt while ($password = $pwdfile.ReadLine()){ #check password against the file code } $pwdfile.close()
Now we have a base function so let us construct this new logic into a function as well, also testing the path is valid for the password file, this time lets specify a default file if it could not be found as hopefully it will ship with the script!
This is good, but I have a look that will take a while to munch through a large password file, I had better add some user feedback…
Now without do a free line check, on the password file, I can’t determine the length, without a length I can’t determine a percentage. At this stage I determine that
I want it to output something every 1000 keys – just to let people know it is still doing something don’t want them thinking it’s not working…
So some simple basic maths = if I mod the number by a 1000 and it = 0 I have a test for each 1000 keys/passwords checked! Also it might be funky to tell people how long we been in the loop for!
We can use the good old fashion Diagnostics.stopwatch code and methods here! Here some more MSDN linky goodness from Grumpy Admin!
https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch(v=vs.110).aspx
So here this function called – load-passwordfile
Next, we need the heart of the code! We need the open KeyPass with the password file code! Now as we are going to be calling this logic code from within our while loop and the password needs to be passing a variable to the code. Which I have loving called $x.
However, before we get to that, we actually need to open out KeePass file
As ever, here is another link to where I borrowed this bit of code about using KeyPass and PowerShell. As Grumpy Admin always says – why reinvent the wheel!
http://cyber-defense.sans.org/blog/2015/08/13/powershell-for-keepass-sample-script/comment-page-1/
$Database = new-object KeePassLib.PwDatabase $IOConnectionInfo = New-Object KeePassLib.Serialization.IOConnectionInfo I actually need to specify the database file that we are going to try to open using the path property on the IOConnectionInfo object we just created! $IOconnectionInfo.Path = "test.kdbx"
This is sounds like we need to create and use a check-kdbxfile function
Excellent… Now we need to control scope of variables and the likes or we can get in the realms of things being called and not being accessible, so let’s control the scope by controlling the execution and creating a starting function!
I move our loading binary code in to our new start function and our IO connection object creation code into this function as well. With this preamble sorted, it means we can now finish our testing logic.
Which shall be a wonderful function called try-key and this is where I use my little buddy from earlier $x… As you can see, I had to jump, to write supporting functions to get the logic correct!
So how do we specify a key and try to open a database! Simple look here!
$Key = new-object KeePassLib.Keys.CompositeKey $Key.AddUserKey((New-Object KeePassLib.Keys.KcpPassword("PASSWORD HERE GUYS"))); $Database.Open($IOConnectionInfo,$Key,$null)
If it open a KeePass database it simply throws and error, which means we can reliably test is the brute force attempted failed or worked.
The next phase is, if we manage to open the KeyPass file with our CompositeKey, we can extract all the information from the KeyPass file!!!
Therefore, here is the simple brute force function
function try-key($x){ $Key = new-object KeePassLib.Keys.CompositeKey $Key.AddUserKey((New-Object KeePassLib.Keys.KcpPassword($x))); try{ $Database.Open($IOConnectionInfo,$Key,$null) $items="" Write-Warning "Master Password Found = $x " write-output "=================" $Items = $Database.RootGroup.GetObjects($true, $true) foreach($Item in $Items) { write-output Title=$($Item.Strings.ReadSafe("Title")) write-output UserName=$($Item.Strings.ReadSafe("UserName")) write-output Password=$($Item.Strings.ReadSafe("Password")) write-output URL=$($Item.Strings.ReadSafe("URL")) write-output Note=$($Item.Strings.ReadSafe("Note")) write-output "=================" } $Database.Close() break } catch{ } }
And the proof of the pudding as they say!
I have do some simple tidying up of the script up and put it on GIT hub. I hope to be using GIT Hub a bit more; as well, I need to improve my profile online. Feel free to recommend me for a https://mvp.microsoft.com/. I have as much chance of being an MVP as my pet Tortoise Sheldon has of reaching blackbelt in Kung-Fu!
Well I guess this is actually perhaps my first public complete tool, as with all my code and blogs it is really badly written and the likes… but it works sadly we didn’t use a common password for our locked out KeyPass but I do have a method of testing the strength of KeyPass file now…
https://github.com/wevans311082/PoshKPBrute
Hazzy