Introduction
Recently, I came across a technique that allows bypassing Windows Defender’s detection mechanisms specifically designed to identify LSASS (Local Security Authority Subsystem Service) dumps.
I embarked on a quest to uncover the root cause of this particular technique. This method posed a serious security vulnerability that has been in the latest version of Windows (Windows 11).
My investigation aims to shed light on its implications and understand why it has not been addressed in the current iteration of the operating system.
Ok, Let’s see the technique:
Dumping Windows Creds
Attackers often attempt to access Windows credentials using a well-known tool called “mimikatz.”
This tool offers various methods to extract data from the memory of the “lsass” process, allowing attackers to crack password hashes. However, most security products can detect “mimikatz”, so attackers need to find ways to conceal its use or resort to alternative techniques.
One effective technique involves leveraging internal Windows libraries to extract sensitive credential data from the Local Security Authority Subsystem Service (LSASS). This process allows for the retrieval of authentication information, which plays a crucial role in the security architecture of the Windows operating system.
In contrast, advanced security solutions like Endpoint Detection and Response (EDR) systems and antivirus software are specifically trying to identify and combat these sophisticated techniques.
For example, Windows has a fascinating library called “comsvcs.dll”. This powerful tool serves as a Living Off the Land Binaries and Scripts (LOLBAS) for credential access tools. It’s intriguing how such components can play a crucial role in various cybersecurity scenarios!
This library exports a function called “MiniDumpW“, which allows for taking a dump from the lsass process memory. An attacker can utilize this function to access credentials using “rundll32.”
PS C:\Windows\system32> rundll32 C:\windows\system32\comsvcs.dll MiniDump %LSASS_PID% dump.bin full

EDR and AV tools are undeniably capable of detecting this attack, thanks to their comprehensive and well-defined set of rules specifically designed to identify such threats. Like the below rule that is for Splunk. As you see the rule checks if a process uses “comsvcs.dll” with the “MiniDump” argument.
| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where `process_rundll32` Processes.process=*comsvcs.dll* Processes.process IN ("*MiniDump*") by Processes.user Processes.parent_process_name Processes.process_name Processes.original_file_name Processes.process Processes.dest
| `drop_dm_object_name(Processes)`
| `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`
| `dump_lsass_via_comsvcs_dll_filter`
At this point, the mouse-and-cat game began. Attackers use the ordinal number of the exported function instead of its name.
PS C:\Windows\system32> rundll32 C:\windows\system32\comsvcs.dll '#24' %LSASS_PID% dump.bin full
Now The detection rule has been successfully updated, bringing exciting new improvements! 😀
| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where `process_rundll32` Processes.process=*comsvcs.dll* Processes.process IN ("*MiniDump*","*#24*") by Processes.user Processes.parent_process_name Processes.process_name Processes.original_file_name Processes.process Processes.dest
| `drop_dm_object_name(Processes)`
| `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`
| `dump_lsass_via_comsvcs_dll_filter`
At this stage, security products are robust and proficient in identifying this specific method of attack. However, it is important to recognize that attackers may still exploit certain programming bugs or vulnerabilities, finding ways to circumvent even the most advanced security measures.
The latest approach to using this method to evade antivirus and endpoint detection and response systems is particularly intriguing.
Let’s see it:
rundll32 C:\windows\system32\comsvcs.dll,#-9999999999999999999999999999999976 %LSASS_PID% dump.bin full
In this technique, the attacker uses a large negative number that triggers the call to ordinal number 24.
In this technique, the attacker can successfully get a dump from the lsass memory and also doesn’t detected by security products.
The question is: How did this happen?
I rolled up my sleeves, ready to get my hands dirty and fully immerse myself in finding the answer to this question.
Reverse Engineering
To understand the problem, I started reversing the rundll32 DLL to see how the big negative number converts to 24. I discovered that the rundll32 checks the arguments passed to the called function. If the passed argument starts with a # sign(0x23), rundll32 identifies that the user provided an ordinal value.

Now rundll32 uses from “wtoi” function to convert the ordinal number from an ASCII number to an integer value.

rundll32 passes the argument “-9999999999999999999999999999999976” to the function “wtoi”, and when “wtoi” is called, it returns the value 24 (0x18).

To find the root cause, we should further investigate “wtoi” located in “msvcrt.dll”.
In the “wtoi” function we can see that first, it checks whether the number is negative or positive.
It checks this by comparing the first character of the ASCII number.

After that, the “wtoi” function starts to convert the ASCII number to an integer, character by character.
It reads a character from the leftmost string number then converts it to its decimal value does some mathematical operation on it and repeats this operation until reaches the end of the string to create the final integer.

As you see in the below picture, the function uses a multiplication and addition operation.
The “r14d” keeps the base which in our case is “10” and the “ecx” holds the decimal digit of the converted digit.

The formula is something like below:
final_number = (digit + base) * final_number
The problem at hand lies in the fact that this function fails to validate the length of the input string before proceeding with its calculations. As a result, the function continues to process characters until it eventually reaches the end of the string. In this particular case, one would expect that the output number would exceed the maximum value allowed, leading to an overflow. However, this overflow does not happen, which raises concerns about the accuracy and reliability of the function’s operation.
The function addresses the overflow issue by checking the length of the final result. The “wtoi” function is designed to convert an input string into a signed 4-byte integer value. While the result is always 4 bytes, the problem arises because the result is a signed value. When an overflow occurs, the sign bit changes, leading to an incorrect final number.
Let’s see the result of our sample:

I continued the converter loop until we reached the last three digits of the large negative number. During each step, the result is held in the RDI register, and the current value is “0x3FFFFFFF,” with the sign bit still set to zero. Now, let’s examine the next step of the loop, where we calculate the final “9.”

As you can see, the least 32 bits of the RDI register are 0xFFFFFFFF, which indicates a value of -1 due to the sign bit. Overflow in wtoi.
Therefore, all four bytes are full, and we have two additional digits: 76.
At the end of this covert operation, we have the number: “0xFFFFFFE8“:

Now we have the signed integer 0xFFFFFFE8, represented in Two’s complement form.
Upon conversion, we determine that this number equates to “-24” Thus, the ultimate result of transforming “9999999999999999999999999999999976” is confidently stated as “-24” It’s important to note, however, that our original number carries a negative sign, denoted as “-9999999999999999999999999999999976” Consequently, the wtoi function will accurately negate the result during its final calculation, ensuring precise and reliable outcomes.
-(-24): +24

You can see that the neg instruction converted 0xFFFFFFE8 to 0x18 (24 in decimal). This allows the attacker to call the ordinal number 24, which corresponds to the “MiniDump” function, effectively bypassing the security product.
This is how an Overflow in wtoi leads attackers to bypass AVs.
But when we look at the Microsoft document for the Overflow in “wtoi” function, it says:
When the functions overflow with large negative integral values,
LONG_MIN
is returned.atoi
and_wtoi
returnINT_MAX
andINT_MIN
on these conditions.
I wrote a simple code to find the reason and compiled it on Windows with Visual Studio.
Visual Studio 2019
Windows SDK 10.0
Windows 10 version 22H2 build 19045.4894

As you can see, the result matches the Microsoft document. But why does wtoi in my code handle overflow, while the one in msvcrt does not?
I found out the reason in the linked libraries. I compare the import table of the rundll32 and my executable.

This is the rundll32 import table. As you see the wtoi function is imported from the msvcrt.dll library.

Also, you see the test executable import table. in this case, the wtoi is imported from the api-ms-win-crt-convert.dll which is a part of the Windows Universal C Runtime library.
Conclusion
The Microsoft Visual C Runtime (MSVCRT) library is older than the Universal C Runtime (UCRT), and it is my understanding that the wtoi function within MSVCRT has overflowed in wtoi. This flaw can lead to erroneous conversions when handling wide string inputs that exceed the bounds of the target integer type. Fortunately, Microsoft addressed this security issue in the UCRT, which is a more modern and robust library designed to provide safer and more consistent runtime support across various Windows applications. The updated implementation of wtoi within the UCRT incorporates safeguards against such overflow problems, greatly enhancing the security and reliability of the function.
Overflow in wtoi.
Why hasn’t Microsoft updated their DLLs to use the UCRT instead of the MSVCRT library?
Thanks for details about this problem
من تست کردم ولی کسپر گرفت.
به هر حال ممکنه یه سریا بگیرن ولی هدف این کار این بود که در مورد مشکل wtoi صحبت بشه
tnx