Created
August 4, 2017 07:45
-
-
Save qistoph/3ff171c1d429b9b9ca0dad9de87e9538 to your computer and use it in GitHub Desktop.
Search a list of hashes for your KeePass stored passwords
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# Search a list of hashes for your KeePass stored passwords | |
# e.g. https://haveibeenpwned.com/Passwords | |
# Chris van Marle 2017 | |
# License: GNU GPLv3 | |
use strict; | |
use warnings; | |
use Data::Dumper; | |
use XML::XPath; | |
use Digest::SHA qw(sha1 sha1_hex); | |
use Fcntl qw(SEEK_SET SEEK_CUR SEEK_END); | |
$|++; | |
my $shafile = "pwned-passwords-1.0.txt"; | |
my $linelen = 2*20 + 2; # 20 bytes SHA in hex + \r\n | |
print "Reading SHA file\n"; | |
my $fSHA; | |
open($fSHA, $shafile) || die("Couldn't open sha file ($shafile): $!"); | |
seek($fSHA, 0, SEEK_END); | |
my $endPos = tell($fSHA); | |
my $totalLines = ($endPos / $linelen)-1; | |
print "Reading KeePass file\n"; | |
my $xp = new XML::XPath(filename => 'KeePass.xml'); | |
my $nodeset = $xp->findnodes('/KeePassFile/Root//Group/Entry'); # Find Entry's in Group (not for example History) that have a Password field | |
print "Entries in KeePass file: "; | |
print $nodeset->size()."\n"; | |
foreach my $node ($nodeset->get_nodelist) { | |
my $title = $node->findvalue('String[Key/text()="Title"]/Value'); | |
my $uuid = $node->findvalue('UUID'); | |
my $pass = $node->findvalue('String[Key/text()="Password"]/Value'); | |
next if($pass eq ''); | |
my $hash = uc(sha1_hex($pass)); | |
my $found = find(0, $totalLines, $hash); | |
if($found) { | |
printf("%s - %s: ", $title, $pass); | |
print $found ? "FOUND\n" : "not found\n"; | |
} | |
} | |
sub readnr { | |
my $linenr = shift; | |
seek($fSHA, $linenr * $linelen, SEEK_SET); | |
my $val = <$fSHA>; | |
$val =~ s/\s+$//; | |
return $val; | |
} | |
sub find { | |
my ($startLine, $endLine, $target) = @_; | |
my $midLine = int(($endLine - $startLine) / 2 + $startLine); | |
#print "$startLine - $midLine - $endLine\n"; | |
my $startValue = readnr($startLine); | |
#print "startValue: $startValue\n"; | |
my $res1 = $target cmp $startValue; | |
#print "res1: $res1\n"; | |
return 1 if ($res1 == 0); | |
return 0 if ($res1 < 0); | |
my $endValue = readnr($endLine); | |
#print "endValue: $endValue\n"; | |
my $res2 = $target cmp $endValue; | |
#print "res2: $res2\n"; | |
return 1 if($res2 == 0); | |
return 0 if($res2 > 0); | |
my $midValue = readnr($midLine); | |
#print "midValue: $midValue\n"; | |
my $resM = $target cmp $midValue; | |
return 1 if($resM == 0); | |
return 0 if($startLine == $midLine or $endLine == $midLine); | |
return find($startLine, $midLine, $target) if($resM < 0); | |
return find($midLine, $endLine, $target) if($resM > 0); | |
die "Invalid state!"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment