Intercepting Password Changes With Function Hooking

Last week, Mubix published a malicious Windows password filter DLL (http://carnal0wnage.attackresearch.com/2013/09/stealing-passwords-every-time-they.html). The idea is simple, by installing this password filter, he can intercept the clear text credential whenever a user changes their password. There are two caveats with installing this password filter:

  1. You must restart the computer for it to take affect
  2. It will show up as an autorun and a loaded DLL in lsass.exe which may be noticed

I’ve been playing around with function hooks lately and thought this would be a great demonstration of their usefulness. The idea is that you hook the PasswordChangeNotify function in the default Windows password filter (rassfm.dll). Anytime PasswordChangeNotify is called, it will be rerouted to my malicious PasswordChangeNotify function, which will write the password to disk and return execution back to the original PasswordChangeNotify function.

To do this, I will write the function hooking code in a DLL and reflectively inject the DLL in to lsass.exe using Invoke-ReflectivePEInjection. The benefit to this approach is that no binaries are written to disk, no suspicious DLL’s are loaded in lsass, no registry changes are made, and no reboot is required.

Since I know not everybody is familiar with writing a function hook, I’ll explain the code (which can be found here: https://github.com/clymb3r/Misc-Windows-Hacking/tree/master/HookPasswordChange):

  • Invoke-ReflectivePEInjection is used to inject the malicious hooking DLL in to lsass.

.\Invoke-ReflectivePEInjection –pepath .\HookPasswordChange.dll –procname lsass

  • Invoke-ReflectivePEInjection calls the function VoidFunc in the reflectively loaded DLL, which installs the function hook. The function hook overwrites the first 12 bytes of PasswordChangeNotify with instructions to jump to another location.

The hook also allocates some RWX memory that holds byte code that returns execution flow to rassfm!PasswordChangeNotify (more on this later).

  • Rassfm!PasswordChangeNotify is called; it immediately executes the following assembly which diverts execution to my malicious PasswordChangeNotifyHook function.
Disassembly of PasswordChangeNotify after being hooked. The instructions after jmp rax disassemble incorrectly after hooking, but all the code after the hook is intact.

Disassembly of PasswordChangeNotify after being hooked. The instructions after jmp rax disassemble incorrectly after hooking, but all the code after the hook is intact.

  • PasswordChangeNotifyHook is a function written in c++, and it takes the same parameters as rassfm!PasswordChangeNotify function. This function takes the username and password and writes it to disk (or does something else that you program such as sending the output to a web site).
  • Now it is time to return execution flow back to the real PasswordChangeNotify. PasswordChangeNotifyHook casts the memory address of the RWX memory allocated earlier to be a function pointer to a function with the same signature as rassfm!PasswordChangeNotify and calls this function pointer.
  • The RWX memory contains the first 3 instructions (15 bytes worth of byte code) that we overwrote in rassfm!PasswordChangeNotify. Now that those instructions have been executed, load the memory address of PasswordChangeNotify+0xf to the EAX and jump to it. Execution flow has now been successfully returned to rassfm!PasswordChangeNotify.
Disassembly of the RWX memory I allocate which ends up returning execution to PasswordChangeNotify.

Disassembly of the RWX memory I allocate which ends up returning execution to PasswordChangeNotify.

Originally I wanted to write inline asm in the PasswordChangeNotifyHook function to return control flow to rassfm!PasswordChangeNotify but unfortunately Visual Studio doesn’t support inline asm for x64 or Itanium, only x86. This is why I had to allocate RWX memory to put the byte code in and trigger it by calling a function pointer.

Note that this is a proof of concept. I have tested it on Windows Server 2012 but it should work on 2008R2 as well. The code can be found at: https://github.com/clymb3r/Misc-Windows-Hacking/tree/master/HookPasswordChange.

The Invoke-ReflectivePEInjection script which is used to load the hook DLL can be found at: https://github.com/clymb3r/PowerShell/tree/master/Invoke-ReflectivePEInjection.

Tagged with: , ,
Posted in Hacking, PowerShell
7 comments on “Intercepting Password Changes With Function Hooking
  1. Awesome post! Few questions about function hooking:

    Without doing an Internet search, how can you tell that “rassfm” is the dll that contains PasswordChangeNotify?
    How can you tell that you overwrote 3 instructions? (when you did mov rax, ADDRESS and jmp rax) – that looks like just 2 instructions
    The first VirtualProtect, you allocated 50 bytes and the second time you called it you allocated 100?

    • clymb3r says:

      1.) To find the Windows defaults, I looked up the registry key that contains the password reset libraries to load (Mubix has this key on his blog, and MSFT documents it). I ran dumpbin /exports c:\windows\system32\rassfm.dll to list the exported functions in rassfm.dll, and PasswordChangeNotify was exported so I can hook it.
      2.) Only write 2 instructions, but what you need to look at is how many bytes you are writing in to memory. I am writing a total of 12 bytes to memory for my 2 instructions. 12 bytes overwrites the first 2 instructions in PasswordChangeNotify, plus part of the third. You can see the instruction sizes if you attach a debugger in windbg and disassemble the code.
      3.) When you call VirtualAlloc/VirtualProtect it does it on a per-page level which is like 2k in Windows, so those sizes (50, 100, whatever) are kinda arbitrary and don’t really matter. I’m allocating more space than I’m using (I write like 20 bytes to memory).

  2. Hi

    I am Mangesh I want password filter to implement at our setup. Below is the configuration of the system. Currently Password filter not working.

    I am using Windows Server 2008 R2 64 bit.
    I copy all four files in Windows\SysWow64 folder which is available in the below link

    https://github.com/clymb3r/Misc-Windows-Hacking/tree/master/HookPasswordChange/Release

    Also make the entry in Registry
    I) [HKLM]\SYSTEM\CurrentControlSet\Control\Lsa\Notification Packages\HookPasswordChange

    I also make log file in c:\windows\Temp\logFile.txt and c:\windows\Temp\passwords.txt

    currently registry only one value is present which is HookPasswordChange

    Please tell me is there any configuration is pending from my side. If you have any document regarding how to configure above password filter please share it to me.

    I am very thankful to you if you are share the procedure how to configure the password filter.

    Regards,

    Mangesh Bhanage

  3. clymb3r says:

    It sounds like you want to implement a legitimate password filter. This is a tutorial on maliciously hijacking an existing password filter using function hooking. If you want to learn how to build real password filters your best bet is probably MSDN. I have no experience doing such a thing.

  4. J says:

    This is awesome and it works very well, however the servers we go against don’t have the rassfm, only scecli. Do you have a a c++ program for that dll?

    • clymb3r says:

      Sorry, I missed this message. I don’t have c++ for that DLL. What version of Windows are you running on? I just did this for Windows server 2012 as a proof-of-concept, but I’m thinking about making a better more universal LSASS function hook.

      • J says:

        Server 2008 R2. It works great with my servers, just what I want to put it on won’t have that rassfm dll :/ I was also leaning more towards a better solution, but I’m just not sure how much time I want to invest.

Leave a comment