Patch Diffing: Windows NTLM Elevation of Privilege Vulnerability (CVE-2025-54918)

I’ve just started looking at the NTLM privilege escalation patch from September 2025. I’m documenting my progress as I go, so these are my initial notes and not a polished blog post!

From the advisory, found this KB5065426 article for Windows 11 Version 24H2 (x64) and downloaded the download the file information for cumulative update from that KB article (link here). Looking at the changed files, it seems these three files are relating to NTLM: ntlanman.dll, ntlmshared.dll, and ntlanui2.dll. I’m looking at these files at this time since they are executables (DLL, SYS, or EXE etc.) while other NTLM related files appear to be non-executable. To understand more about this process, please read my previous blog post here.

To start with, I think I should be looking at ntlmshared.dll. So, I downloaded the patched and unpatched versions from WinBindex. The patched version, 10.0.26100.5074 is from this month, September 2025 and the unpatched version, 10.0.26100.4768 is from July 2025.

TO reduce the number changes that we need to review, we should be looking at the unpatched version closest to the patched version and 10.0.26100.4768 seems to be the closest one as it seems this file wasn’t modified in August 2025.

I exported these two files after finishing the Auto analysis in Ghidra and used BinDiff to spot the differences (changed functions). Looking at the Matched Functions, these two functions seem to have changed (not sure if they contain the patch yet!) – “MsvpLm20GetNtlm3ChallengeResponse” and MsvpAvlGetTimestamp() (Name in the primary / unpatched file is sub_180009B98).

  • Regarding sub_180009b98, looking at address 0x180009b98 in Ghidra, it shows a totally different function MsvpAvlGet() instead of MsvpAvlGetTimestamp(). Why is BinDiff doing this?

I’m now taking a look at “MsvpLm20GetNtlm3ChallengeResponse” as the name appears to be intuitive. There are more functions listed under Primary Unmatched and Secondary Unmatched, but I will come back to that later.

Update – 09/25/2025 @ 8:44 PM AEST

  • Just a reminder to myself (and you if you happen to be like me) that it’s important to check if we have a PDB for the file we’re analysing and if it’s up to date. So here I was looking at this function MsvpLm20GetNtlm3ChallengeResponse() in Ghidra thinking how to decipher its function signature (prototype). The function’s pseudo code obviously looked garbage, so I started looking at all API calls this function makes. I couldn’t find prototype for this function or any function that this function calls to in any of the header files under “C:\Program Files (x86)\Windows Kits” (except for the standard API call “NtQuerySystemTime()”
  • Likely because these are undocumented / internal function that Microsoft doesn’t provide symbols for these internal / undocumented functions.
  • I had already looked at Ghidra’s symbol servers settings yesterday and was convinced it’s all good BUT then I looked at the PDB for ntlmshared.dll in C:\Symbols and noticed that it was last modified in 2024.
    • So, I went back to Ghidra -> Load PDB -> Advanced and saw the Ntlmshared.pdb was already loaded but then I clicked Search All and found one remote PDB on Microsoft’s symbol server… So, I loaded it and voila all of the function names that this MsvpLm20GetNtlm3ChallengeResponse() function calls to were resolved and the code was a bit more readable than before!
    • Still need to figure out the function signature/prototype though!

Okay, What haven’t disclosed yet! 😀

  • Someone has already leaked old Windows source code on Github here and you can see the function definition there for MsvpLm20GetNtlm3ChallengeResponse() in nlmain.c file. BUT I’m not looking at at this time on purpose 🙂
  • The patch seems to be all about validating the timestamp of NTLM related messages? because calls to functions like MsvpAvlGetTimestamp() and NtQuerySystemTime() are not there in the vulnerable version (of ntlshared.dll)

BinDiff –> Secondary Unmatched Functions shows new functions added to the patched file:

After taking a quick look at changes in this MsvpLm20GetNtlm3ChallengeResponse() function, I have a feeling that the patch might not be in this file. So, I just diffed the patched and unpatched msv1_0.dll files and see so many changes here. Could the actual or main patch be here?

Update – 10/11/2025 @ 5:58 PM AEST

I spent a few hours today understanding NTLM (v1, v2, ESS and EAP etc.) but just a high-level overview as opposed to deep dive.

I’m now facing two questions:

  1. Is this vulnerability in NTLMv1 or NTLMv2?
    • It seems to be in NTLMv2 as the past advisories for NTLM mentioned NTLMv1 when the vulnerability was in NTLMv1.
  2. Which DLL has the patch?
    • Since the vulnerability is relating to improper authentication in Windows NTLM, I think I should look at Msv1_0.dll since MSV1_0 authentication package is the one that handles user authentication (Ref: NTLM User Authentication). I hope I’m on the right track 😬.

If that’s the case, if you look at the BinDiff screenshot for msv1_0.dll above, some of the changed functions look promising. I skimmed through just one of them and the code seems complex as it’s more than 1300+ lines of code.

I will spend some time going through some of these functions and try make them more readable by trying to fix variable data types and function signature/prototype etc.

  • The MS-NLMP doc has details about NTLM structures. Could be useful
  • Also, the leaked source code would be helpful too make the code more readable?

Leave a comment