Bug #88 » 0001-bug-88-validate-dcerpc-header.patch
src/app-layer-dcerpc-common.h | ||
---|---|---|
} 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 printUUID(char *type, struct uuid_entry *uuid);
|
||
src/app-layer-dcerpc.c | ||
---|---|---|
* 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
|
||
* 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();
|
||
uint8_t *p = input;
|
||
if (input_len) {
|
||
switch (dcerpc->bytesprocessed) {
|
||
case 0:
|
||
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_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.pfc_flags = *(p + 3);
|
||
dcerpc->dcerpchdr.packed_drep[0] = *(p + 4);
|
||
... | ... | |
dcerpc->dcerpchdr.call_id |= *(p + 15) << 24;
|
||
}
|
||
dcerpc->bytesprocessed = DCERPC_HDR_LEN;
|
||
SCReturnUInt(16U);
|
||
SCReturnInt(16);
|
||
break;
|
||
} else {
|
||
dcerpc->dcerpchdr.rpc_vers = *(p++);
|
||
// if dcerpc->dcerpchdr.rpc_vers != 5) SCReturnInt(2);
|
||
if (!(--input_len))
|
||
break;
|
||
}
|
||
case 1:
|
||
dcerpc->dcerpchdr.rpc_vers_minor = *(p++);
|
||
// if ((sdcerpc->dcerpchdr.rpc_vers_minor != 0) ||
|
||
// (dcerpc->dcerpchdr.rpc_vers_minor != 1)) SCReturnInt(3);
|
||
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);
|
||
}
|
||
if (!(--input_len))
|
||
break;
|
||
case 2:
|
||
... | ... | |
}
|
||
}
|
||
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();
|
||
uint32_t retval = 0;
|
||
uint32_t parsed = 0;
|
||
int hdrretval = 0;
|
||
while (dcerpc->bytesprocessed < DCERPC_HDR_LEN && input_len) {
|
||
retval = DCERPCParseHeader(dcerpc, input, input_len);
|
||
parsed += retval;
|
||
input_len -= retval;
|
||
hdrretval = DCERPCParseHeader(dcerpc, input, input_len);
|
||
if (hdrretval == -1) {
|
||
dcerpc->bytesprocessed = 0;
|
||
SCReturnInt(-1);
|
||
} else {
|
||
parsed += hdrretval;
|
||
input_len -= hdrretval;
|
||
}
|
||
}
|
||
SCLogDebug("Done with DCERPCParseHeader bytesprocessed %u/%u left %u\n",
|
||
dcerpc->bytesprocessed, dcerpc->dcerpchdr.frag_length, input_len);
|
||
... | ... | |
dcerpc->bytesprocessed = 0;
|
||
break;
|
||
}
|
||
SCReturnUInt(parsed);
|
||
SCReturnInt(parsed);
|
||
}
|
||
static int DCERPCParse(Flow *f, void *dcerpc_state,
|
||
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
|
||
AppLayerParserResult *output) {
|
||
SCEnter();
|
||
int32_t retval = 0;
|
||
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)
|
||
SCReturnInt(-1);
|
||
src/app-layer-nbss.h | ||
---|---|---|
uint8_t flags;
|
||
uint32_t length;
|
||
}NBSSHdr;
|
||
#define NBSS_HDR_LEN 4U
|
||
#define NBSS_HDR_LEN 4
|
||
#endif /* APPLAYERNBSS_H_ */
|
src/app-layer-smb.c | ||
---|---|---|
SMBState *sstate = (SMBState *) smb_state;
|
||
uint8_t *p = input;
|
||
/* Check for validity of dataoffset */
|
||
if ((sstate->bytesprocessed - NBSS_HDR_LEN) > sstate->andx.dataoffset) {
|
||
if ((uint64_t)(sstate->bytesprocessed - NBSS_HDR_LEN) > sstate->andx.dataoffset) {
|
||
sstate->andx.paddingparsed = 1;
|
||
SCReturnUInt((uint32_t)(p - input));
|
||
}
|
||
while (((sstate->bytesprocessed - NBSS_HDR_LEN) + (p - input))
|
||
while (((uint64_t)(sstate->bytesprocessed - NBSS_HDR_LEN) + (p - input))
|
||
< sstate->andx.dataoffset && sstate->bytecount.bytecountleft--
|
||
&& input_len--) {
|
||
SCLogDebug("0x%02x ", *p);
|
||
p++;
|
||
}
|
||
if (((sstate->bytesprocessed - NBSS_HDR_LEN) + (p - input))
|
||
if (((uint64_t)(sstate->bytesprocessed - NBSS_HDR_LEN) + (p - input))
|
||
== sstate->andx.dataoffset) {
|
||
sstate->andx.paddingparsed = 1;
|
||
}
|
||
... | ... | |
/**
|
||
* \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) {
|
||
SCEnter();
|
||
SMBState *sstate = (SMBState *) smb_state;
|
||
uint32_t parsed = 0;
|
||
int32_t parsed = 0;
|
||
if (sstate->andx.paddingparsed) {
|
||
parsed = DCERPCParser(&sstate->dcerpc, input, input_len);
|
||
sstate->bytesprocessed += parsed;
|
||
sstate->bytecount.bytecountleft -= parsed;
|
||
input_len -= parsed;
|
||
parsed = DCERPCParser(&sstate->dcerpc, input, input_len);
|
||
if (parsed == -1) {
|
||
SCReturnInt(-1);
|
||
} else {
|
||
sstate->bytesprocessed += parsed;
|
||
sstate->bytecount.bytecountleft -= parsed;
|
||
input_len -= parsed;
|
||
}
|
||
}
|
||
SCReturnUInt(parsed);
|
||
SCReturnInt(parsed);
|
||
}
|
||
/**
|
||
... | ... | |
SCEnter();
|
||
SMBState *sstate = (SMBState *) smb_state;
|
||
uint8_t *p = input;
|
||
uint32_t retval = 0;
|
||
int32_t retval = 0;
|
||
uint32_t parsed = 0;
|
||
if (((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) && sstate->smb.command
|
||
== SMB_COM_READ_ANDX) || (((sstate->smb.flags
|
||
... | ... | |
if (sstate->andx.datalength && input_len) {
|
||
retval = DataParser(sstate, pstate, input + parsed, input_len,
|
||
output);
|
||
parsed += retval;
|
||
input_len -= retval;
|
||
if (retval != -1) {
|
||
parsed += 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);
|
||
}
|
||
... | ... | |
p++;
|
||
}
|
||
sstate->bytesprocessed += (p - input);
|
||
SCReturnUInt((uint32_t)(p - input));
|
||
SCReturnUInt((p - input));
|
||
}
|
||
static uint32_t NBSSParseHeader(Flow *f, void *smb_state,
|
||
... | ... | |
/**
|
||
* \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,
|
||
AppLayerParserResult *output) {
|
||
SCEnter();
|
||
... | ... | |
if (input_len >= SMB_HDR_LEN) {
|
||
if (memcmp(p, "\xff\x53\x4d\x42", 4) != 0) {
|
||
SCLogDebug("SMB Header did not validate");
|
||
SCReturnUInt(0);
|
||
SCReturnInt(-1);
|
||
}
|
||
sstate->smb.command = *(p + 4);
|
||
sstate->smb.status = *(p + 5) << 24;
|
||
... | ... | |
sstate->smb.mid = *(p + 30) << 8;
|
||
sstate->smb.mid |= *(p + 31);
|
||
sstate->bytesprocessed += SMB_HDR_LEN;
|
||
SCReturnUInt(32U);
|
||
SCReturnInt(32);
|
||
break;
|
||
} else {
|
||
//sstate->smb.protocol[0] = *(p++);
|
||
if (*(p++) != 0xff)
|
||
SCReturnInt(0);
|
||
SCReturnInt(-1);
|
||
if (!(--input_len))
|
||
break;
|
||
}
|
||
case 5:
|
||
//sstate->smb.protocol[1] = *(p++);
|
||
if (*(p++) != 'S')
|
||
SCReturnInt(0);
|
||
SCReturnInt(-1);
|
||
if (!(--input_len))
|
||
break;
|
||
case 6:
|
||
//sstate->smb.protocol[2] = *(p++);
|
||
if (*(p++) != 'M')
|
||
SCReturnInt(0);
|
||
SCReturnInt(-1);
|
||
if (!(--input_len))
|
||
break;
|
||
case 7:
|
||
//sstate->smb.protocol[3] = *(p++);
|
||
if (*(p++) != 'B')
|
||
SCReturnInt(0);
|
||
SCReturnInt(-1);
|
||
if (!(--input_len))
|
||
break;
|
||
case 8:
|
||
... | ... | |
}
|
||
}
|
||
sstate->bytesprocessed += (p - input);
|
||
SCReturnUInt((uint32_t)(p - input));
|
||
SCReturnInt((p - input));
|
||
}
|
||
static int SMBParse(Flow *f, void *smb_state, AppLayerParserState *pstate,
|
||
... | ... | |
&& sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN)) {
|
||
retval = SMBParseHeader(f, smb_state, pstate, input + parsed,
|
||
input_len, output);
|
||
if (retval) {
|
||
if (retval == -1) {
|
||
SCLogDebug("Error parsing SMB Header\n");
|
||
sstate->bytesprocessed = 0;
|
||
SCReturnInt(1);
|
||
} else {
|
||
parsed += retval;
|
||
input_len -= retval;
|
||
SCLogDebug(
|
||
"SMB Header (%u/%u) Command 0x%02x parsed %ld input_len %u",
|
||
sstate->bytesprocessed, NBSS_HDR_LEN + SMB_HDR_LEN,
|
||
sstate->smb.command, parsed, input_len);
|
||
} else if (input_len) {
|
||
SCLogDebug("Error parsing SMB Word Count\n");
|
||
parsed += input_len;
|
||
input_len = 0;
|
||
}
|
||
}
|
||
src/app-layer-smb.h | ||
---|---|---|
uint16_t uid;
|
||
uint16_t mid;
|
||
}SMBHdr;
|
||
#define SMB_HDR_LEN 32U
|
||
#define MINIMUM_SMB_LEN 35U
|
||
#define NBSS_SMB_HDRS_LEN 36U
|
||
#define SMB_HDR_LEN 32
|
||
#define MINIMUM_SMB_LEN 35
|
||
#define NBSS_SMB_HDRS_LEN 36
|
||
typedef struct wordcount_ {
|
||
uint8_t wordcount;
|