Remote Overflow Analysis of Windows Workstation Service
Note: eeye digital security, a world-renowned security organization, announced its discovery of buffer overflow defects in the Windows Workstation Service on the http://www.eeye.com site homepage on November 11. This vulnerability involves the basic services that most Windows operating systems rely on for normal operation and can be remotely exploited. The relevant TCP ports are 139 and 445. The announcement of this defect has an impact on the Windows operating system security system. However, as CNNs puts forward, "attacks are the best way to test network security", the critical defects of each operating system, their attack exploitation code, and subsequent worms, all force manufacturers to accelerate the launch of security solutions, and the security of these services will also be improved. This attack and defense cycle will be accompanied by the lifecycle of any mainstream operating system.
This article describes how the CNNs R & D department uses the technology to analyze this vulnerability. Time rush, there are any errors and deficiencies, welcome to exchange: snake@cnns.net
//////////////////////////////////////// //////////////////////////////////////// ///////////////////////////
Eeye announced a remote overflow vulnerability in Windows workstation in November 11. This is another basic service of Microsoft and has serious defects in attacks.
This article will analyze how to exploit this vulnerability.
According to some public information of eeye, The vulnerability lies in the vsprintf call of wkssvc. dll. It is inferred that the length of the input buffer is not checked. The netvalidatename function can be used for direct attacks.
The following environment is:
Client: Win2k, which establishes an IPC $ connection with the server and then interacts with netvalidatename to trigger overflow. The specific sample code will not be posted, and packetstorm and other sites have published a lot...
Server: attacked end (Simplified Chinese Win2k + SP3)
Start windbg and trace the related functions. It starts with the call of the rpcrt4.dll's NDRC servercall2. in this short period of time, there is no way to look at and digest it. If you ignore it, continue to trace it...
Then there are some calls. Including the call of the NDRC serverinitializenew, the call of the NDRC pointerunmarshell and the call of the NDRC conformantstringunmarshall. You can ignore the call and keep track of the call. The machine has actually restarted n times. It doesn't matter, it's a virtual machine. :)
The following is an analysis of the error function. Some initialization actions are ignored. In short, the error occurs here, And the use is also used when the function is returned ..
. Text: 76724cd7; int _ stdcall sub_76724cd7 (handle hfile, Int, INT)
. Text: 76724cd7 sub_76724cd7 proc near; Code xref: sub_76724db5 + 20 p
. Text: 76724cd7
. Text: 76724cd7 var_81a = byte PTR-81ah
. Text: 76724cd7 var_819 = byte PTR-819 H
. Text: 76724cd7 buffer = byte PTR-818 H
. Text: 76724cd7 var_817 = byte PTR-817 H
. Text: 76724cd7 numberofbyteswritten = dword ptr-14 h
. Text: 76724cd7 systemtime = _ systemtime PTR-10 h
. Text: 76724cd7 hfile = dword ptr 8
. Text: 76724cd7 arg_4 = dword ptr 0ch
. Text: 76724cd7 arg_8 = dword ptr 10 h
. Text: 76724cd7
. Text: 76724cd7 push EBP
. Text: 76724cd8 mov EBP, ESP
. Text: 76724cda sub ESP, 818 h ;//!! Only 0x818 = 2072 bytes are allocated to all variables.
. Text: 76724ce0 CMP [EBP + hfile], 0; // determine whether the file handle is invalid
. Text: 76724ce4 JZ locret_76724db1; // If yes, return
. Text: 76724cea push EDI
. Text: 76724ceb mov EDI, offset unk_7672760
. Text: 76724cf0 push ESI
. Text: 76724cf1 push EDI; lpcriticalsection
. Text: 76724cf2 call DS: entercriticalsection; // enter the critical space
. Text: 76724cf8 xor esi, ESI
. Text: 76724cfa CMP dword_76727a3c, ESI; Determine whether to print time information
. Text: 76724d00 JZ short loc_76724d3c
. Text: 76724d02 Lea eax, [EBP + systemtime]; the output of the time information string is as follows.
. Text: 76724d05 push eax; lpsystemtime
. Text: 76724d06 call DS: getlocaltime
. Text: 76724d0c movzx eax, [EBP + systemtime. wsecond]
. Text: 76724d10 push eax
. Text: 76724d11 movzx eax, [EBP + systemtime. wminute]
. Text: 76724d15 push eax
. Text: 76724d16 movzx eax, [EBP + systemtime. whour]
. Text: 76724d1a push eax
. Text: 76724d1b movzx eax, [EBP + systemtime. wday]
. Text: 76724d1f push eax
. Text: 76724d20 movzx eax, [EBP + systemtime. wmonth]
. Text: 76724d24 push eax
. Text: 76724d25 Lea eax, [EBP + buffer]
. Text: 76724d2b push offset a02u02u02u02; "% 02u/% 02u % 02u: % 02u: % 02u"
. Text: 76724d30 push eax
. Text: 76724d31 call DS: sprintf; // at first, format the time string...
. Text: 76724d37 add ESP, 1ch
. Text: 76724d3a mov ESI, eax
. Text: 76724d3c
. Text: 76724d3c loc_76724d3c:; Code xref: sub_76724cd7 + 29j
. Text: 76724d3c push [EBP + arg_8]
. Text: 76724d3f Lea eax, [EBP + ESI + buffer]; get the output buffer address, here is the esi-0x818
. Text: 76724d3f; ESI is the adjusted output pointer. If the time information is printed,
. Text: 76724d3f; then = the length of the time string. Otherwise, = 0.
. Text: 76724d46 push [EBP + arg_4]; The format here is:
. Text: 76724d46; netpvalidatename: checking to see if % WS is valid as type % d name.
. Text: 76724d46;
. Text: 76724d46; *** note that the parameters are % WS and % d.
. Text: 76724d46; % ws .... Troublesome conversion. Hey, there is still a solution.
. Text: 76724d46;
. Text: 76724d49 push eax
. Text: 76724d4a call DS: vsprintf; overflow occurs here
. Text: 76724d50 add ESP, 0ch
. Text: 76724d53 add ESI, eax; check whether ESI + eax = 0. If there is no output, mark it as 0
. Text: 76724d55 JZ short loc_76724d6d
. Text: 76724d57 CMP [EBP + ESI + var_819], 0ah. If you do not press enter, make a flag .. :(
. Text: 76724d57;
. Text: 76724d5f jnz short loc_76724d6d
. Text: 76724d61 mov dword_76727a3c, 1
. Text: 76724d6b JMP short loc_76724d78; it is fun to add a carriage return to the beginning of the output buffer,
. Text: 76724d6b;
. Text: 76724d6d; where where?
. Text: 76724d6d
. Text: 76724d6d loc_76724d6d:; Code xref: sub_76724cd7 + 7ej
. Text: 76724d6d; sub_76724cd7 + 88j
. Text: 76724d6d XOR eax, eax
. Text: 76724d6f test eax, eax
. Text: 76724d71 mov dword_76727a3c, eax
. Text: 76724d76 JZ short loc_76724d91
. Text: 76724d78
. Text: 76724d78 loc_76724d78:; Code xref: sub_76724cd7 + 94j
. Text: 76724d78 mov [EBP + ESI + var_819], 0dh; it is fun to add a carriage return to the beginning of the output buffer,
. Text: 76724d78;
. Text: 76724d80 mov [EBP + ESI + buffer], 0ah
. Text: 76724d88 and [EBP + ESI + var_817], 0
. Text: 76724d90 Inc ESI
. Text: 76724d91
. Text: 76724d91 loc_76724d91:; Code xref: sub_76724cd7 + 9fj
. Text: 76724d91 Lea eax, [EBP + numberofbyteswritten]
. Text: 76724d94 push 0; lpoverlapped
. Text: 76724d94; write the file here.
. Text: 76724d94; note that the 4th parameters of writefile
. Text: 76724d94; lpnumberofbyteswritten is in
. Text: 76724d94; ebp-14 location, will rewrite buffer, so,
. Text: 76724d94; Be careful if shellcode is put there.
. Text: 76724d94; the data at this position is now ..
. Text: 76724d96 push eax; lpnumberofbyteswritten
. Text: 76724d97 Lea eax, [EBP + buffer]
. Text: 76724d9d push ESI; nnumberofbytestowrite
. Text: 76724d9e push eax; lpbuffer
. Text: 76724d9f push [EBP + hfile]; hfile
. Text: 76724da2 call DS: writefile
. Text: 76724da8 push EDI; lpcriticalsection
. Text: 76724da9 call DS: leavecriticalsection; here leavecriticalsection. Fortunately, the EDI parameter has not been changed.
. Text: 76724da9; otherwise, it will be much more troublesome during the attack.
. Text: 76724daf pop ESI
. Text: 76724db0 pop EDI
. Text: 76724db1
. Text: 76724db1 locret_76724db1:; Code xref: sub_76724cd7 + DJ
. Text: 76724db1 leave
. Text: 76724db2 retn 0ch; OK, function return, hey, after processing, we will execute our shellcode.
. Text: 76724db2 sub_76724cd7 endp
. Text: 76724db2
. Text: 76724db5
According to the above analysis, the parameter % ws of the program in vsprintf is formatted, and the 2nd parameters of netvalidatename are used as input. After formatting, the data is output to the stack, stack Overflow occurs when the content is too long.
Analyze the possibility of attacks.
1. This function checks the validity of the file handle. If % WINDIR %/debug/netsetup. log cannot be opened, this function cannot be executed. Therefore, if the connected account does not have the permission to open the file when the server executes the file record, subsequent attacks cannot be carried out. Unless the server permission settings are incorrect, or the FAT32 file format, there is no way to restrict the permissions. Hey hey...
2. when the input length is not long, a stack overflow occurs. Fill in the jmp esp content at the overflow point (approximately 0x818-12), and then, at the beginning of the next address, write shellcode to run the code.
3. when the input length is very long, Windows's structured exception protection will be triggered. If the data is large enough to overwrite the exception structure, you can also achieve redirection. However, at this time, it is dangerous, and the system can no longer be exceeded for 2nd times, because at the beginning of the function, the system enters the critical section and exits. In this case, the critical variable is not released.
4. netvalidatename: Buffer of the 2nd parameters. Unicode is input. % WS is converted back to the ANSI string when vsprintf is used. The vsprintf called here is a function of the same name as msvcrt. dll, rather than a function in the libc standard library. This vsprintf can not be converted to 100% during conversion. After tracking, we found that wctomb function is called for execution. At the end, even if it can be converted, the final output may be 0. The Standard visible string can be converted, but the data in the Multi-byte language is not that good. That is to say, the code to be executed can only be within visible characters for the moment, and the rest should be carefully constructed. More details need to be studied in detail. (Conclusion: there is still a long way to go to implement multilingual attack code ...)
5. In the input buffer, the data at the position of 0x818-12-0x14-strlen ("netpvalidatename: checking to see if") will be rewritten by the writefile parameter. Therefore, the shellcode is damaged.
6. If this attack uses exitthread after Shellcode Execution is complete, it should be able to be overflows infinitely...
In short, I have analyzed a lot of things above. Writing specific general attack programs is just a matter of time. It seems that there are no more technical difficulties and skills, and there is nothing to say. I hope that the implemented hero will carefully publish attack tools and codes. This article only analyzes them from a technical point of view. This kind of "spam code" is actually relatively easy to defend against, you only need to convert vsprintf to vsnprintf to avoid similar problems !.
Another attack method of eeye is the netaddalternatecomputername attack, which is effective in the NTFS format. I didn't see it. It can be in XP, but I don't have this function in 2 K, I wonder if XP can attack 2 k... If you are free, try again.
* ** Postscript ***
I really don't know how to evaluate this vulnerability. Microsoft's software, the server and workstation services provide powerful service functions. However, such a serious vulnerability exists .... Be careful when writing your own programs, especially the widely used programs.
Snake. 2003/11/17 morning.
Connection: http://www.cnns.net/news/db/3796.htm