bug 88 validate dcerpc header

remotes/origin/master-1.0.x
Kirby Kuehl 16 years ago committed by Victor Julien
parent 9e4da4f8e7
commit bea30a6db6

@ -169,7 +169,7 @@ typedef struct DCERPC_ {
} p_cont_elem_t; } p_cont_elem_t;
*/ */
uint32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len); int32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len);
void hexdump(const void *buf, size_t len); void hexdump(const void *buf, size_t len);
void printUUID(char *type, struct uuid_entry *uuid); void printUUID(char *type, struct uuid_entry *uuid);

@ -858,18 +858,24 @@ static uint32_t StubDataParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_le
* A fast path for normal decoding is used when there is enough bytes * A fast path for normal decoding is used when there is enough bytes
* present to parse the entire header. A slow path is used to parse * present to parse the entire header. A slow path is used to parse
* fragmented packets. * fragmented packets.
* \retval -1 if DCEPRC Header does not validate
* \retval Number of bytes processed
*/ */
static uint32_t DCERPCParseHeader(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) { static int DCERPCParseHeader(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter(); SCEnter();
uint8_t *p = input; uint8_t *p = input;
if (input_len) { if (input_len) {
switch (dcerpc->bytesprocessed) { switch (dcerpc->bytesprocessed) {
case 0: case 0:
if (input_len >= DCERPC_HDR_LEN) { if (input_len >= DCERPC_HDR_LEN) {
//if (*p != 5) SCReturnUInt();
//if (!(*(p + 1 ) == 0 || (*(p + 1) == 1))) SCReturnInt(0);
dcerpc->dcerpchdr.rpc_vers = *p; dcerpc->dcerpchdr.rpc_vers = *p;
dcerpc->dcerpchdr.rpc_vers_minor = *(p + 1); dcerpc->dcerpchdr.rpc_vers_minor = *(p + 1);
if ((dcerpc->dcerpchdr.rpc_vers != 5) ||
((dcerpc->dcerpchdr.rpc_vers_minor != 0) &&
(dcerpc->dcerpchdr.rpc_vers_minor != 1))) {
SCLogDebug("DCERPC Header did not validate");
SCReturnInt(-1);
}
dcerpc->dcerpchdr.type = *(p + 2); dcerpc->dcerpchdr.type = *(p + 2);
dcerpc->dcerpchdr.pfc_flags = *(p + 3); dcerpc->dcerpchdr.pfc_flags = *(p + 3);
dcerpc->dcerpchdr.packed_drep[0] = *(p + 4); dcerpc->dcerpchdr.packed_drep[0] = *(p + 4);
@ -896,18 +902,21 @@ static uint32_t DCERPCParseHeader(DCERPC *dcerpc, uint8_t *input, uint32_t input
dcerpc->dcerpchdr.call_id |= *(p + 15) << 24; dcerpc->dcerpchdr.call_id |= *(p + 15) << 24;
} }
dcerpc->bytesprocessed = DCERPC_HDR_LEN; dcerpc->bytesprocessed = DCERPC_HDR_LEN;
SCReturnUInt(16U); SCReturnInt(16);
break; break;
} else { } else {
dcerpc->dcerpchdr.rpc_vers = *(p++); dcerpc->dcerpchdr.rpc_vers = *(p++);
// if dcerpc->dcerpchdr.rpc_vers != 5) SCReturnInt(2);
if (!(--input_len)) if (!(--input_len))
break; break;
} }
case 1: case 1:
dcerpc->dcerpchdr.rpc_vers_minor = *(p++); dcerpc->dcerpchdr.rpc_vers_minor = *(p++);
// if ((sdcerpc->dcerpchdr.rpc_vers_minor != 0) || if ((dcerpc->dcerpchdr.rpc_vers != 5) ||
// (dcerpc->dcerpchdr.rpc_vers_minor != 1)) SCReturnInt(3); ((dcerpc->dcerpchdr.rpc_vers_minor != 0) &&
(dcerpc->dcerpchdr.rpc_vers_minor != 1))) {
SCLogDebug("DCERPC Header did not validate");
SCReturnInt(-1);
}
if (!(--input_len)) if (!(--input_len))
break; break;
case 2: case 2:
@ -974,17 +983,24 @@ static uint32_t DCERPCParseHeader(DCERPC *dcerpc, uint8_t *input, uint32_t input
} }
} }
dcerpc->bytesprocessed += (p - input); dcerpc->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input)); SCReturnInt((p - input));
} }
uint32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) { int32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
SCEnter(); SCEnter();
uint32_t retval = 0; uint32_t retval = 0;
uint32_t parsed = 0; uint32_t parsed = 0;
int hdrretval = 0;
while (dcerpc->bytesprocessed < DCERPC_HDR_LEN && input_len) { while (dcerpc->bytesprocessed < DCERPC_HDR_LEN && input_len) {
retval = DCERPCParseHeader(dcerpc, input, input_len); hdrretval = DCERPCParseHeader(dcerpc, input, input_len);
parsed += retval; if (hdrretval == -1) {
input_len -= retval; dcerpc->bytesprocessed = 0;
SCReturnInt(-1);
} else {
parsed += hdrretval;
input_len -= hdrretval;
}
} }
SCLogDebug("Done with DCERPCParseHeader bytesprocessed %u/%u left %u\n", SCLogDebug("Done with DCERPCParseHeader bytesprocessed %u/%u left %u\n",
dcerpc->bytesprocessed, dcerpc->dcerpchdr.frag_length, input_len); dcerpc->bytesprocessed, dcerpc->dcerpchdr.frag_length, input_len);
@ -1198,18 +1214,20 @@ uint32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
dcerpc->bytesprocessed = 0; dcerpc->bytesprocessed = 0;
break; break;
} }
SCReturnUInt(parsed); SCReturnInt(parsed);
} }
static int DCERPCParse(Flow *f, void *dcerpc_state, static int DCERPCParse(Flow *f, void *dcerpc_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) { AppLayerParserResult *output) {
SCEnter(); SCEnter();
int32_t retval = 0;
DCERPCState *sstate = (DCERPCState *) dcerpc_state; DCERPCState *sstate = (DCERPCState *) dcerpc_state;
DCERPCParser(&sstate->dcerpc, input, input_len); retval = DCERPCParser(&sstate->dcerpc, input, input_len);
if (retval == -1) {
SCReturnInt(-1);
}
if (pstate == NULL) if (pstate == NULL)
SCReturnInt(-1); SCReturnInt(-1);

@ -508,17 +508,17 @@ static uint32_t PaddingParser(void *smb_state, AppLayerParserState *pstate,
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
/* Check for validity of dataoffset */ /* Check for validity of dataoffset */
if ((uint32_t)(sstate->bytesprocessed - NBSS_HDR_LEN) > sstate->andx.dataoffset) { if ((uint64_t)(sstate->bytesprocessed - NBSS_HDR_LEN) > sstate->andx.dataoffset) {
sstate->andx.paddingparsed = 1; sstate->andx.paddingparsed = 1;
SCReturnUInt((uint32_t)(p - input)); SCReturnUInt((uint32_t)(p - input));
} }
while (((uint32_t)(sstate->bytesprocessed - NBSS_HDR_LEN) + (p - input)) while (((uint64_t)(sstate->bytesprocessed - NBSS_HDR_LEN) + (p - input))
< sstate->andx.dataoffset && sstate->bytecount.bytecountleft-- < sstate->andx.dataoffset && sstate->bytecount.bytecountleft--
&& input_len--) { && input_len--) {
SCLogDebug("0x%02x ", *p); SCLogDebug("0x%02x ", *p);
p++; p++;
} }
if (((uint32_t)(sstate->bytesprocessed - NBSS_HDR_LEN) + (p - input)) if (((uint64_t)(sstate->bytesprocessed - NBSS_HDR_LEN) + (p - input))
== sstate->andx.dataoffset) { == sstate->andx.dataoffset) {
sstate->andx.paddingparsed = 1; sstate->andx.paddingparsed = 1;
} }
@ -528,20 +528,25 @@ static uint32_t PaddingParser(void *smb_state, AppLayerParserState *pstate,
/** /**
* \brief Parse WriteAndX and ReadAndX Data * \brief Parse WriteAndX and ReadAndX Data
* \todo Hand off to DCERPC parser for DCERPC over SMB * \retval -1 f DCERPCParser does not validate
* \retval Number of bytes processed
*/ */
static uint32_t DataParser(void *smb_state, AppLayerParserState *pstate, static int32_t DataParser(void *smb_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
SCEnter(); SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint32_t parsed = 0; int32_t parsed = 0;
if (sstate->andx.paddingparsed) { if (sstate->andx.paddingparsed) {
parsed = DCERPCParser(&sstate->dcerpc, input, input_len); parsed = DCERPCParser(&sstate->dcerpc, input, input_len);
if (parsed == -1) {
SCReturnInt(-1);
} else {
sstate->bytesprocessed += parsed; sstate->bytesprocessed += parsed;
sstate->bytecount.bytecountleft -= parsed; sstate->bytecount.bytecountleft -= parsed;
input_len -= parsed; input_len -= parsed;
} }
SCReturnUInt(parsed); }
SCReturnInt(parsed);
} }
/** /**
@ -655,7 +660,7 @@ static uint32_t SMBParseByteCount(Flow *f, void *smb_state,
SCEnter(); SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
uint32_t retval = 0; int32_t retval = 0;
uint32_t parsed = 0; uint32_t parsed = 0;
if (((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) && sstate->smb.command if (((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) && sstate->smb.command
== SMB_COM_READ_ANDX) || (((sstate->smb.flags == SMB_COM_READ_ANDX) || (((sstate->smb.flags
@ -672,8 +677,19 @@ static uint32_t SMBParseByteCount(Flow *f, void *smb_state,
if (sstate->andx.datalength && input_len) { if (sstate->andx.datalength && input_len) {
retval = DataParser(sstate, pstate, input + parsed, input_len, retval = DataParser(sstate, pstate, input + parsed, input_len,
output); output);
if (retval != -1) {
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
} else { /* Did not Validate as DCERPC over SMB */
while (sstate->bytecount.bytecountleft-- && input_len--) {
SCLogDebug("0x%02x bytecount %u/%u input_len %u", *p,
sstate->bytecount.bytecountleft,
sstate->bytecount.bytecount, input_len);
p++;
}
sstate->bytesprocessed += (p - input);
SCReturnUInt((p - input));
}
} }
SCReturnUInt(retval); SCReturnUInt(retval);
} }
@ -685,7 +701,7 @@ static uint32_t SMBParseByteCount(Flow *f, void *smb_state,
p++; p++;
} }
sstate->bytesprocessed += (p - input); sstate->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input)); SCReturnUInt((p - input));
} }
static uint32_t NBSSParseHeader(Flow *f, void *smb_state, static uint32_t NBSSParseHeader(Flow *f, void *smb_state,
@ -733,7 +749,7 @@ static uint32_t NBSSParseHeader(Flow *f, void *smb_state,
/** /**
* \brief SMBParseHeader parses and validates the 32 byte SMB Header * \brief SMBParseHeader parses and validates the 32 byte SMB Header
*/ */
static uint32_t SMBParseHeader(Flow *f, void *smb_state, static int SMBParseHeader(Flow *f, void *smb_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) { AppLayerParserResult *output) {
SCEnter(); SCEnter();
@ -745,7 +761,7 @@ static uint32_t SMBParseHeader(Flow *f, void *smb_state,
if (input_len >= SMB_HDR_LEN) { if (input_len >= SMB_HDR_LEN) {
if (memcmp(p, "\xff\x53\x4d\x42", 4) != 0) { if (memcmp(p, "\xff\x53\x4d\x42", 4) != 0) {
SCLogDebug("SMB Header did not validate"); SCLogDebug("SMB Header did not validate");
SCReturnUInt(0); SCReturnInt(-1);
} }
sstate->smb.command = *(p + 4); sstate->smb.command = *(p + 4);
sstate->smb.status = *(p + 5) << 24; sstate->smb.status = *(p + 5) << 24;
@ -774,31 +790,27 @@ static uint32_t SMBParseHeader(Flow *f, void *smb_state,
sstate->smb.mid = *(p + 30) << 8; sstate->smb.mid = *(p + 30) << 8;
sstate->smb.mid |= *(p + 31); sstate->smb.mid |= *(p + 31);
sstate->bytesprocessed += SMB_HDR_LEN; sstate->bytesprocessed += SMB_HDR_LEN;
SCReturnUInt(32U); SCReturnInt(32);
break; break;
} else { } else {
//sstate->smb.protocol[0] = *(p++);
if (*(p++) != 0xff) if (*(p++) != 0xff)
SCReturnInt(0); SCReturnInt(-1);
if (!(--input_len)) if (!(--input_len))
break; break;
} }
case 5: case 5:
//sstate->smb.protocol[1] = *(p++);
if (*(p++) != 'S') if (*(p++) != 'S')
SCReturnInt(0); SCReturnInt(-1);
if (!(--input_len)) if (!(--input_len))
break; break;
case 6: case 6:
//sstate->smb.protocol[2] = *(p++);
if (*(p++) != 'M') if (*(p++) != 'M')
SCReturnInt(0); SCReturnInt(-1);
if (!(--input_len)) if (!(--input_len))
break; break;
case 7: case 7:
//sstate->smb.protocol[3] = *(p++);
if (*(p++) != 'B') if (*(p++) != 'B')
SCReturnInt(0); SCReturnInt(-1);
if (!(--input_len)) if (!(--input_len))
break; break;
case 8: case 8:
@ -916,7 +928,7 @@ static uint32_t SMBParseHeader(Flow *f, void *smb_state,
} }
} }
sstate->bytesprocessed += (p - input); sstate->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input)); SCReturnInt((p - input));
} }
static int SMBParse(Flow *f, void *smb_state, AppLayerParserState *pstate, static int SMBParse(Flow *f, void *smb_state, AppLayerParserState *pstate,
@ -952,17 +964,17 @@ static int SMBParse(Flow *f, void *smb_state, AppLayerParserState *pstate,
&& sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN)) { && sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN)) {
retval = SMBParseHeader(f, smb_state, pstate, input + parsed, retval = SMBParseHeader(f, smb_state, pstate, input + parsed,
input_len, output); input_len, output);
if (retval) { if (retval == -1) {
SCLogDebug("Error parsing SMB Header\n");
sstate->bytesprocessed = 0;
SCReturnInt(1);
} else {
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
SCLogDebug( SCLogDebug(
"SMB Header (%u/%u) Command 0x%02x parsed %ld input_len %u", "SMB Header (%u/%u) Command 0x%02x parsed %ld input_len %u",
sstate->bytesprocessed, NBSS_HDR_LEN + SMB_HDR_LEN, sstate->bytesprocessed, NBSS_HDR_LEN + SMB_HDR_LEN,
sstate->smb.command, parsed, input_len); sstate->smb.command, parsed, input_len);
} else if (input_len) {
SCLogDebug("Error parsing SMB Word Count\n");
parsed += input_len;
input_len = 0;
} }
} }

Loading…
Cancel
Save