Preface

The CVE-2008-4250 vulnerability we are studying this time is in the NetpwPathCanonicalize function of the netapi32.dll file. The cause is due to a developer's negligence and lack of rigor in string movement operations, failing to strictly check for out-of-bounds situations.

Static Analysis

The function we are researching this time is the same as before, which is the path character function used to splice and normalize path characters in the NetpwPathCanonicalize function. The call location of this function is at 0x5FDDA15B in the NetpwPathCanonicalize function:

Untitled

Entering the sub_5FDDA180 function, starting from the 0x5FDDA1E0 position, we can see that the program uses the wcscat() function to splice the paths, and the spliced path will be placed in the local variable Destination. Next, a loop operation is used (green thick arrow) to check whether there are any slash "/" characters in the spliced string, and if so, convert them to backslash "\":

Screenshot 2024-03-19 at 6.37.32 PM.png

After the conversion is completed, the program will push Destination, i.e., the converted path string, as the only parameter onto the stack and call the sub_5FDDA26B function, and it is this function that has the overflow problem:

Screenshot 2024-03-19 at 6.42.21 PM.png

In fact, the function of this function is to implement the simplification problem we mentioned in the last lesson, removing a single dot representing the current directory level and removing two dots representing the parent directory, as well as removing the directory name in front of the two dots. The location for implementing this functionality is at 0x5FDDA2F3 in this function. After obtaining the relevant character positions (mainly the "\" pointers in the path string), the program uses the wcscpy() function to implement this simplification function:

Screenshot 2024-04-11 at 10.30.00 AM.png

The problem lies in the process after simplifying the two dots:

Screenshot 2024-04-11 at 10.30.49 AM.png

After calling the wcscpy() function, the value of edi will be decremented by 2. Since it is currently operating on wide characters, subtracting 2 actually means getting the character before the current slash. Then it compares whether this character is "\", and if not, it determines whether the current pointer position is equal to arg_0, i.e., the starting address of the string to be simplified. If they are equal, it means it has reached the boundary and cannot search forward anymore. If they are not equal, it continuously calls the decrement operation twice to continue searching forward for "\":

Screenshot 2024-04-11 at 10.31.07 AM.png

Until "\" is found. In fact, what is being searched for here is the "\" in front of the previous directory name. Since it does not timely determine whether the calculation result is less than or equal to arg_0 when edi-2, but directly determines whether it is equal to arg_0, this causes the value after edi-2 to be able to be less than arg_0. The following statements will execute forward search for "\", causing the current pointer position to never be equal to arg_0, leading the program to perform search operations in unknown memory areas, thus exceeding the current buffer range. Once "\" is found and the simplification condition is met, the wcscpy() function will execute the copy function and overwrite the return address, thus creating the risk of overflow.

The following diagram can be used to illustrate this situation:

Untitled

First, when the program finds a form like "A..", it will use three pointers p1, p2, and p3 for marking. Next, it will use wcscpy(p3, p1) to perform string copy operations. After the copy is completed, the p3 pointer will be decremented by 2 to reach the position of the previous character. Since it has already gone out of bounds at this point, and the out-of-bounds comparison method used by the program is to compare with the starting address of the string, as long as it is not equal to (less than or greater than) the starting address, it is considered not out of bounds until it is equal to the starting address to be considered at the boundary position. However, since the address is already less than the boundary value at this point, the program will never consider an out-of-bounds situation to have occurred. At this point, the program will continue to search forward for "\", and the content of the target memory area being searched is unknown until "\" is found. It will stop there, set that position as p3, and consider the path characters between p1 and p3 to be newly simplified. Therefore, it will continue to call wcscpy(p3, p1) to perform string copy operations, resulting in the return address being overwritten, leading to the occurrence of overflow.