0x01 MS08-067 Vulnerability Principle
The MS08-067 vulnerability is triggered when the NetPathCanonicalize function in the Server service program is called through the MSRPC over SMB channel. When the NetPathCanonicalize function remotely accesses other hosts, it will call the NetpwPathCanonicalize function to standardize the remote access path, and in the NetpwPathCanonicalize function Existing logic errors can cause the stack buffer to be overflowed and obtain remote code execution (Remote Code Execution).
The so-called path standardization is to convert the [/] in the path string to [\], while removing the relative path [.\] and [..\]. Such as:
**/*/./** => **\*\** **\*\..\** => **\**
In the operation of path standardization, the service program checks the address space of the path string with logical loopholes. By carefully designing the input path, the attacker can copy the contents of the path string to the address space (low address) before the path string when the function removes the [..\] string, to cover the return address of the function, and execute arbitrary code the goal of.
Path processing flow
The NetpwPathCanonicalize function does not directly perform input path and normalization, but continues to call the lower-level function CanonicalizePathName to organize the path, normalize the path string to be sorted, and then save it in the pre-allocated output path buffer buffer.
Path processing flow:
1. Check the first character of the path to be sorted;
2. Call the wcslen function of msvcrt.dll module to calculate the path length;
3. Call the wcscat function of msvcrt.dll module to copy all the paths to be sorted to the newly applied memory.
4. Call the wcscpy function, remove the first relative path representing the parent directory in the path to be sorted and copy it to strTemp, such as:
\******\..\..\*** => \..\***
5. Call wcscpy cyclically until the path is finished.
Here we know that when copying in a standardized way, look for the [..\] string representing the parent directory and the previous [\] string, remove this paragraph and copy the new path.
As shown in the figure, the first relative path was removed during the first check and copied to the buffer
However, when the [..\] string is at the front of the path string, then the previous [\] is outside the buffer, which is where the forward (low address) overflow occurs.
What needs to be clear is that Microsoft has made a preliminary defense against buffer overflows that may occur in string copying during path normalization.
Every time you copy a string to the buffer, whether you use wcsccpy or wcscat, always compare the length of the source string before copying to ensure that the length is less than a certain value (207), otherwise the copy will not continue. This strategy Ensure that the buffer does not overflow to a high address, that is, no problem occurs when the current function returns.
But note that when looking for the [\] character in front of the [..\] string in the parent directory in the normalized representation of the path, the program does a judgment and boundary check: if the address of the current comparison character is the same as the source string address, it means The entire string has been searched, and the program will stop searching.
However, it only misses one case, that is, when the parent directory relative path [..\] string is at the beginning of the source string, the string to be compared at the beginning of the search ([\] to [..\]) Located outside the buffer, this caused the copied string to overflow to the lower address, causing the return address of the function wcscpy to be overwritten.
0x02 vulnerability restoration analysis
Target machine: Windows2003 SP0 EN
Vulnerable component: netapi32.dll
Tools: IDA Pro, OllyDbg
Select the Windows XP SP3 EN system host as the analysis environment, locate the system module netapi32.dll (path C:\Windows\system32) containing the security vulnerability and the process svchost.exe that calls the vulnerability service Server. The target process command line is:
Open netapi32.dll with IDA pro and find the NetpwPathCanonicalize letter where the vulnerability is located (the address in the stack will be different each time you run it, but the address of each function is the same), as shown in the book:
Looking at the function flowchart, you can see that this function does not directly normalize the input path, but continues to call the lower-level function CanonicalizePathName
However, the CanonicalizePathName function was not found in the actual operation, and a variety of materials indicate that the CanonicalizePathName function should be called for normalization.
IDA analysis of NetpwPathCanonicalize function code (F5 + finishing + main code):
The function declaration is as follows:
DWORD NetpwPathCanonicalize( LPWSTR PathName, //Need a standardized path LPWSTR Outbuf, //Buffer that stores the standardized pat DWORD OutbufLen, //Buffer length LPWSTR Prefix, //Optional parameter, useful when PathName is a relative path LPDWORD PathType, //Storage path type DWORD Flags // Reserved, 0 )
View the process pid whose command line parameter is svchost.exe -k netsvcs through wmic:
Open OllyDbg, click file->attach, and attach to the svchost.exe process:
View->Executable modules, double-click netapi32, right-click in the cpu command window and select Search for to find exec(label) in current module, find the function NetpwPathCanonicalize, the address is 71C#44A3E, set a breakpoint here:
Track the vulnerability trigger process
Go back to the CPU command window and run the program, then the attacker Metasploit loads the ms08_067_netapi module and exploits:
The svchost program in the analysis environment will be interrupted at the entry address of the NetpwPathCanonicalize function. The incoming parameters of this function are as follows:
esp [esp] * Comment * 00ECF924 02248D34; Point to the path to be sorted 00ECF928 022321D8; Point to the output path buffer 00ECF92C 000003F1; output buffer length 00ECF930 02248FB0; Point to the prefix, the value is \x5C\x00, that is, unicode ‘\’ 00ECF934 02248FB4; Point to the path type, the value is 0x1001 00ECF938 00000000; WORD Flags reserved, the value is 0
Combined with IDA pro’s process analysis of NetpwPathCanonicalize, the next-level function CanonPathName will be called at the address, and a breakpoint will be set at this address:
Run to this breakpoint, and then trace the function CanonPathName, the incoming parameters are as follows:
00F0F8FC 00157570 ;Point to prefix, the value is \x5C\00, which is Unicode "\" 00F0F900 001572F4; point to the path to be sorted 00F0F904 02132E80; buffer pointing to the output path 00F0F908 000003F9; The length of the output buffer 00F0F90C 00000000; WORD Flag reserved word, the value is 0
It can be seen from the parameter passing of the above two functions that the CanonPathName function organizes the path, and then saves it in the pre-allocated output path buffer.
Path structure to be sorted
Check the structure of the path to be sorted in the OD. The path is a Unicode string, starting with [\x5C\x00] (Unicode character “\”) and ending with [\x00\x00], with some random upper and lower case letters in the middle. The long undisplayable character is the encoded shellcode, the most important of which is the relative path of the two parent directories [….\] linked together.
The path is a Unicode string, starting with [\x5C\x00] (Unicode character “\”) and ending with [\x00\x00], with some random upper and lower case letters in the middle, and a longer period of undisplayable characters is passed The most critical part of the encoded shellcode is the two connected [\..\..\], which is the relative path of the parent directory.
The entire path to be sorted looks like:
Pre-operation before arranging paths
Set a memory access breakpoint on the 4 bytes at the memory address 000C0F50 where the path to be sorted is located:
Press F9 to run, it will be interrupted 3 times, the first two are to check the first character of the path to be sorted and call the wcslen function, and the third is to call the wcscat function. Analyze two parameters in the third incoming stack:
The first is strDestination, which points to a memory space starting with [\x5c\x00]; the second is strSource, which points to the content after the first two bytes [\x5c\x00] of the path to be sorted.
The program copies all the paths to be sorted to strDestination, which is 0x001572F6. Set a breakpoint in this 4 bytes and select “Hardware, on access” DWord as the type.
Copy path to buffer
Press F9 to continue running. The fourth interruption is at 0x77BD4010. The memory shows that the first two characters of src have been copied to the back of [\x5C\x00] of dest. This is because the two bytes have set breakpoints:
The fifth interrupt is at 0x71C#44B1C, located in the wcscat function. The memory shows that src has been copied to dest, as shown in the figure:
rst path normalization
Press F9 to run, stop at memory 0x77bd4d36 after multiple interruptions, and you can see from the stack that it belongs to the wcscpy function. Call this function here for the first path normalization. As shown:
The current parameter src value is 0x00EC6E0, which points to [..*]; the parameter strDestination value is 0x00ECF4DC, which points to the first character in temp [\]. Obviously, the path standardization this time is to discard the content between the first character [\] and the first [..\] relative path in the path to be sorted.
At this time, the source address src of wcscpy is in the edx register, pointing to [..*]; the destination address dest is in the ecx register, pointing to the first character [\] of the path to be sorted, as shown in the figure:
Therefore, the string copy operation this time is to remove the first relative path that represents the parent directory, that is, the content between the first [\] and the first [..\] in the path to be sorted becomes a useless path. abandon. After the operation is completed, the path character in temp is like [..*].
After the first normalization, the path to be sorted looks like:
Because there is still [..\], another standardization is needed, and this second standardization is where the mystery lies.
Second path normalization
Since the wcscpy function is called every time the path is normalized, the hardware breakpoint of 0x00ECF4DC will be deleted and the breakpoint will be set directly at the entry address of the wcscpy function at 0x77BD4D28.
After pressing F9 to run, interrupt at the entry 0x77BD4D28 of the wcscpy function, and call the parameters passed in the wcscpy function:
esp [esp] * Comment * 00ECF4AC 00ECF494 Destination address, the value of the memory area pointed to is \x5c\x00, that is [\] 00ECF4B0 00ECF4E2 Source address, pointing to the last slash of the second relative path [\..\]
Under normal circumstances, this normalization process will perform the same operation as the first time, removing the second relative path [..\] to complete the second path normalization. But there is an unexpected situation here. The first address of temp is 0x00ECF4DC, and the destination address dest of this string copy operation is 0x00ECF494, before temp, as shown in the figure:
Also note that the stack pointer ESP value is 0x00ECF4A8, which points to the return address of the wcscpy function 0x71C52FD4. ESP to the copy destination dest address 0x00ECF494 only has 0x14 bytes, so if the function wcscpy continues to execute, it will overwrite the return address of the wcscpy function with the source string src.
After executing the retn command, you can see that the return address becomes 0x0100129E, and the instruction at this address is:
00100129E FFD6 call esi
Execute the call esi (ES=0x00F0F4DE) instruction, and just point EIP to the 8th byte empty instruction constructed in the string to be copied as far as possible, followed by [\xeb\x62] (jmp 0x62), this jmp instruction skips the middle Random string, pointing to the encoded Shellcode, as shown in the figure:
So here is due to a [\] (0x5C) at memory 0x00F0F494, which overflows the path to be processed when processing the parent relative path [..\], thus overwriting the string to the location of the return address of the function wcscpy , Jump to shellcode to cause remote code execution.
As mentioned earlier, when [..\] is at the beginning of the source string, when the search is started, the compared characters are outside the buffer, which leads to a forward overflow.