Introducing Compromise Checker! An easy tool to check the NTLM hashes from HaveIBeenPwned against AD

Hopefully everyone reading this is aware of the amazing HaveIBeenPwned project by Troy Hunt.  As of today, NTLM hashes are officially available for download of all compromised passwords seen in this project.  This is great for checking against your Active Directory environment to see whether or not your users are using passwords that are known to be compromised.  I threw together a quick tool that can get all of the NTLM hashes from your AD environment using DSInternals, and then check to see which (if any) are listed in the download from HIBP.

While this is a fairly simple concept, the shear size of the download from HIBP presents a number of problems when performing this type of searching.  This application is specifically designed to avoid reading the entire HIBP file into memory; as that could negatively affect the computer it is being run on.  Because of the amount of data it has to process, you should expect it to take at least a few hours – no matter how small your AD environment is.  That being said, it uses even less memory than most of the other processes running on your computer (especially Chrome); so multi-tasking shouldn’t be an issue.

Check out the source code here:, and download the pre-compiled project and installer from here:

About thegeekkid

10 thoughts on “Introducing Compromise Checker! An easy tool to check the NTLM hashes from HaveIBeenPwned against AD

  1. What are the system requirements to run this? I’m using Server 2008 and Powershell 5.1 installed. When I run the program I can see part of an an error:

    “Import-Module: The specified module ‘DSInternals’ was not loaded because no…”

    A few minutes later the program stops and says there are no compromised passwords. Yet I know of one test account that was set with a compromised password.

    1. Hey… sorry for the late response, somehow I totally missed this comment. It should run on 2008 with Powershell 5.1, but I’ve only officially tested it on Server 2016 and Windows 10. Do you happen to have the full “Import-Module” error? It looks like it failed to load the DSInternals module that gets installed during the application’s first run, and that is the module that it uses to get the hashes from AD. It could also be an AntiMalware program blocking it, since that should be suspicious behavior to any decent heuristics engine. You could check C:\Program Files\WindowsPowerShell\Modules\DSInternals and see if the folder exists and has the module files in it. According to their specs, it should run on 5.0+; so if you are seeing files in that folder, I would check your AV/AM to see if it has quarantined any of the files. -Brian

  2. Hi Brian
    Thanks for creating this tool, it all seems so simple. However, I just cannot make it run. I have the DSInternal 3.2.1 module installed, plus its in the directory referenced on the DSInternals github site too.
    Initially I was getting the same error as Richard, but after forcing the DSInternals module install that error has gone away.
    I now get the following exception:
    ************** Exception Text **************
    System.IO.FileNotFoundException: Could not find file ‘C:\ProgramData\SemrauSecurity\CompromiseCheck\adExport.txt’.
    File name: ‘C:\ProgramData\SemrauSecurity\CompromiseCheck\adExport.txt’
    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
    at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean checkHost)
    at System.IO.File.InternalReadAllText(String path, Encoding encoding, Boolean checkHost)
    at System.IO.File.ReadAllText(String path)
    at CompromiseCheck.Form1.ReadAD()
    at CompromiseCheck.Form1.button2_Click(Object sender, EventArgs e)
    at System.Windows.Forms.Control.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.ButtonBase.WndProc(Message& m)
    at System.Windows.Forms.Button.WndProc(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

    Can you offer any advice as to what I am missing?

    1. Hi Steve,

      Sorry about the late response… I guess I need to check the comments more often! C:\ProgramData\SemrauSecurity\CompromiseCheck\adExport.txt is the file that gets generated from DSInternals. When the program first starts to run, a powershell window should pop up and ask about changing the execution policy, and then show a progress bar for replicating Active Directory objects… did that come up? If not, do you have a group policy that would stop PowerShell from changing the execution policy on that computer?? If so, that would stop DSInternals from being able to replicate the hashes so that the Compromise Checker can search through them.


  3. Solution for this DSInternalProblem:

    You can set the Restriction Policy to Unrestricted for the time of the use.

    Open Powershell and Type:
    Set-ExecutionPolicy Unrestricted

    If you get asked, answer with “A”.

    Then run the Ckecker as Admin.

    This did solve it for me.
    After you are done, set the ExecutionPolicy back to Restricted.
    Set-ExecutionPolicy Restricted

  4. Interesting… it is calling an ExecutionPolicy elevation as it is running (Powershell should prompt you to confirm the override when it does that). I’ll have to look into what that isn’t working on some systems. Thanks for sharing! 🙂 -Brian

  5. Hi thegeekkid,

    It seems to not work properly anymore. When i start the Tool without Admin, it works trough but doesn’t show any results. If i start it as Admin, it wont run and says that there’s no DSinternals installed, but it is, i checked it twice.

    I think something is broken.



    1. Hey Gino,

      Thanks for the heads up, and sorry about the late response (I was out of the office for a week, so I had to catch up on my paid work before I could look into this – lol). Yep, I’m seeing the same results as you are… what’s weird is that if I use my smaller sample-set from the hashes that I use for testing, it doesn’t display the same behavior. I’ll be looking into it, but since I’ll have to work from the full set of hashes, it might take me a little bit of time to figure out what is going on. :/

  6. Good Day TheGeekKid,

    Did you had the time to look into?

    Would be nice if it get’s fixed! We are looking forward for it 🙂



Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.