dcerpc request smb transact and fix for dcerpc bindack

remotes/origin/master-1.0.x
Kirby Kuehl 17 years ago committed by Victor Julien
parent 8f00718b0d
commit 90b42232fa

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009 Open Information Security Foundation * Copyright (c) 2009,2010 Open Information Security Foundation
* app-layer-dcerpc.h * app-layer-dcerpc.h
* *
* \author Kirby Kuehl <kkuehl@gmail.com> * \author Kirby Kuehl <kkuehl@gmail.com>
@ -11,6 +11,7 @@
#include "app-layer-parser.h" #include "app-layer-parser.h"
#include "flow.h" #include "flow.h"
#include "queue.h" #include "queue.h"
#include <byteswap.h>
void RegisterDCERPCParsers(void); void RegisterDCERPCParsers(void);
void DCERPCParserTests(void); void DCERPCParserTests(void);
@ -115,6 +116,7 @@ typedef struct DCERPCState_ {
TAILQ_HEAD(, uuid_entry) uuid_list; TAILQ_HEAD(, uuid_entry) uuid_list;
uint16_t secondaryaddrlen; uint16_t secondaryaddrlen;
uint16_t secondaryaddrlenleft; uint16_t secondaryaddrlenleft;
uint16_t opnum;
}DCERPCState; }DCERPCState;

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009 Open Information Security Foundation * Copyright (c) 2009, 2010 Open Information Security Foundation
* app-layer-smb.c * app-layer-smb.c
* *
* \author Kirby Kuehl <kkuehl@gmail.com> * \author Kirby Kuehl <kkuehl@gmail.com>
@ -39,6 +39,7 @@ enum {
}; };
#if 0 #if 0
/* \brief hexdump function from libdnet, used for debugging only */
void hexdump(const void *buf, size_t len) { void hexdump(const void *buf, size_t len) {
/* dumps len bytes of *buf to stdout. Looks like: /* dumps len bytes of *buf to stdout. Looks like:
* [0000] 75 6E 6B 6E 6F 77 6E 20 * [0000] 75 6E 6B 6E 6F 77 6E 20
@ -102,8 +103,9 @@ void hexdump(const void *buf, size_t len) {
* \brief SMB Write AndX Request Parsing * \brief SMB Write AndX Request Parsing
*/ */
/* For WriteAndX we need to get writeandxdataoffset */ /* For WriteAndX we need to get writeandxdataoffset */
static uint32_t SMBParseWriteAndX(Flow *f, void *smb_state, AppLayerParserState *pstate, static uint32_t SMBParseWriteAndX(Flow *f, void *smb_state,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
SCEnter(); SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
@ -112,14 +114,14 @@ static uint32_t SMBParseWriteAndX(Flow *f, void *smb_state, AppLayerParserState
sstate->andx.paddingparsed = 0; sstate->andx.paddingparsed = 0;
if (input_len >= 28) { if (input_len >= 28) {
sstate->andx.andxcommand = *p; sstate->andx.andxcommand = *p;
sstate->andx.andxoffset = *(p+2) << 8; sstate->andx.andxoffset = *(p + 2);
sstate->andx.andxoffset |= *(p+3); sstate->andx.andxoffset |= *(p + 3) << 8;
sstate->andx.datalength = *(p+18) << 16; sstate->andx.datalength = *(p + 18);
sstate->andx.datalength |= *(p+19) << 24; sstate->andx.datalength |= *(p + 19) << 8;
sstate->andx.datalength |= *(p+20) << 8; sstate->andx.datalength |= *(p + 20) << 16;
sstate->andx.datalength |= *(p+21); sstate->andx.datalength |= *(p + 21) << 24;
sstate->andx.dataoffset = *(p+22) << 8; sstate->andx.dataoffset = *(p + 22);
sstate->andx.dataoffset|= *(p+23); sstate->andx.dataoffset |= *(p + 23) << 8;
sstate->andx.dataoffset |= (uint64_t) * (p + 24) << 56; sstate->andx.dataoffset |= (uint64_t) * (p + 24) << 56;
sstate->andx.dataoffset |= (uint64_t) * (p + 25) << 48; sstate->andx.dataoffset |= (uint64_t) * (p + 25) << 48;
sstate->andx.dataoffset |= (uint64_t) * (p + 26) << 40; sstate->andx.dataoffset |= (uint64_t) * (p + 26) << 40;
@ -128,104 +130,131 @@ static uint32_t SMBParseWriteAndX(Flow *f, void *smb_state, AppLayerParserState
SCReturnUInt(28U); SCReturnUInt(28U);
} else { } else {
sstate->andx.andxcommand = *(p++); sstate->andx.andxcommand = *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
} }
case 1: case 1:
p++; // Reserved p++; // Reserved
if (!(--input_len)) break; if (!(--input_len))
break;
case 2: case 2:
sstate->andx.andxoffset = *(p++) << 8; sstate->andx.andxoffset = *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 3: case 3:
sstate->andx.andxoffset |= *(p++); sstate->andx.andxoffset |= *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 4: case 4:
// SMB_COM_WRITE_ANDX Fid 1 // SMB_COM_WRITE_ANDX Fid 1
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 5: case 5:
// SMB_COM_WRITE_ANDX Fid 2 // SMB_COM_WRITE_ANDX Fid 2
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 6: case 6:
// SMB_COM_WRITE_ANDX Offset 1 // SMB_COM_WRITE_ANDX Offset 1
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 7: case 7:
// SMB_COM_WRITE_ANDX Offset 2 // SMB_COM_WRITE_ANDX Offset 2
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 8: case 8:
// SMB_COM_WRITE_ANDX Offset 3 // SMB_COM_WRITE_ANDX Offset 3
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 9: case 9:
// SMB_COM_WRITE_ANDX Offset 4 // SMB_COM_WRITE_ANDX Offset 4
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 10: case 10:
// SMB_COM_WRITE_ANDX Reserved 1 // SMB_COM_WRITE_ANDX Reserved 1
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 11: case 11:
// SMB_COM_WRITE_ANDX Reserved 2 // SMB_COM_WRITE_ANDX Reserved 2
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 12: case 12:
// SMB_COM_WRITE_ANDX Reserved 3 // SMB_COM_WRITE_ANDX Reserved 3
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 13: case 13:
// SMB_COM_WRITE_ANDX Reserved 4 // SMB_COM_WRITE_ANDX Reserved 4
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 14: case 14:
// SMB_COM_WRITE_ANDX WriteMode 1 // SMB_COM_WRITE_ANDX WriteMode 1
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 15: case 15:
// SMB_COM_WRITE_ANDX WriteMode 2 // SMB_COM_WRITE_ANDX WriteMode 2
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 16: case 16:
// SMB_COM_WRITE_ANDX BytesRemaining 1 // SMB_COM_WRITE_ANDX BytesRemaining 1
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 17: case 17:
// SMB_COM_WRITE_ANDX BytesRemaining 2 // SMB_COM_WRITE_ANDX BytesRemaining 2
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 18: case 18:
// DataLengthHigh 1 // DataLengthHigh 1
sstate->andx.datalength = *(p++) << 16; sstate->andx.datalength = *(p++) << 16;
if (!(--input_len)) break; if (!(--input_len))
break;
case 19: case 19:
// DataLengthHigh 2 // DataLengthHigh 2
sstate->andx.datalength |= *(p++) << 24; sstate->andx.datalength |= *(p++) << 24;
if (!(--input_len)) break; if (!(--input_len))
break;
case 20: case 20:
// DataLength 1 // DataLength 1
sstate->andx.datalength |= *(p++) << 8; sstate->andx.datalength |= *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 21: case 21:
// DataLength 2 // DataLength 2
sstate->andx.datalength |= *(p++); sstate->andx.datalength |= *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 22: case 22:
sstate->andx.dataoffset = *(p++) << 8; sstate->andx.dataoffset = *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 23: case 23:
sstate->andx.dataoffset |= *(p++); sstate->andx.dataoffset |= *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 24: case 24:
sstate->andx.dataoffset |= (uint64_t) * (p++) << 56; sstate->andx.dataoffset |= (uint64_t) * (p++) << 56;
if (!(--input_len)) break; if (!(--input_len))
break;
case 25: case 25:
sstate->andx.dataoffset |= (uint64_t) * (p++) << 48; sstate->andx.dataoffset |= (uint64_t) * (p++) << 48;
if (!(--input_len)) break; if (!(--input_len))
break;
case 26: case 26:
sstate->andx.dataoffset |= (uint64_t) * (p++) << 40; sstate->andx.dataoffset |= (uint64_t) * (p++) << 40;
if (!(--input_len)) break; if (!(--input_len))
break;
case 27: case 27:
sstate->andx.dataoffset |= (uint64_t) * (p++) << 32; sstate->andx.dataoffset |= (uint64_t) * (p++) << 32;
--input_len; --input_len;
@ -238,8 +267,9 @@ static uint32_t SMBParseWriteAndX(Flow *f, void *smb_state, AppLayerParserState
/** /**
* \brief SMB Read AndX Response Parsing * \brief SMB Read AndX Response Parsing
*/ */
static uint32_t SMBParseReadAndX(Flow *f, void *smb_state, AppLayerParserState *pstate, static uint32_t SMBParseReadAndX(Flow *f, void *smb_state,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
SCEnter(); SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
@ -248,81 +278,99 @@ static uint32_t SMBParseReadAndX(Flow *f, void *smb_state, AppLayerParserState *
sstate->andx.paddingparsed = 0; sstate->andx.paddingparsed = 0;
if (input_len >= 24) { if (input_len >= 24) {
sstate->andx.andxcommand = *p; sstate->andx.andxcommand = *p;
sstate->andx.andxoffset = *(p+2) << 8; sstate->andx.andxoffset = *(p + 2);
sstate->andx.andxoffset |= *(p+3); sstate->andx.andxoffset |= *(p + 3) << 8;
sstate->andx.datalength = *(p+10) << 8; sstate->andx.datalength = *(p + 10);
sstate->andx.datalength |= *(p+11); sstate->andx.datalength |= *(p + 11) << 8;
sstate->andx.dataoffset = *(p+12) << 8; sstate->andx.dataoffset = *(p + 12);
sstate->andx.dataoffset |= *(p+13); sstate->andx.dataoffset |= *(p + 13) << 8;
sstate->andx.datalength |= (uint64_t) *(p+14) << 56; sstate->andx.datalength |= (uint64_t) * (p + 14) << 32;
sstate->andx.datalength |= (uint64_t) *(p+15) << 48; sstate->andx.datalength |= (uint64_t) * (p + 15) << 40;
sstate->andx.datalength |= (uint64_t) *(p+16) << 40; sstate->andx.datalength |= (uint64_t) * (p + 16) << 48;
sstate->andx.datalength |= (uint64_t) *(p+17) << 32; sstate->andx.datalength |= (uint64_t) * (p + 17) << 56;
sstate->bytesprocessed += 24; sstate->bytesprocessed += 24;
SCReturnUInt(24U); SCReturnUInt(24U);
} else { } else {
sstate->andx.andxcommand = *(p++); sstate->andx.andxcommand = *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
} }
case 1: case 1:
p++; // Reserved p++; // Reserved
if (!(--input_len)) break; if (!(--input_len))
break;
case 2: case 2:
sstate->andx.andxoffset |= *(p++) << 8;
if (!(--input_len)) break;
case 3:
sstate->andx.andxoffset |= *(p++); sstate->andx.andxoffset |= *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 3:
sstate->andx.andxoffset |= *(p++) << 8;
if (!(--input_len))
break;
case 4: case 4:
// SMB_COM_READ_ANDX Remaining Reserved must be 0xff // SMB_COM_READ_ANDX Remaining Reserved must be 0xff
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 5: case 5:
// SMB_COM_READ_ANDX Remaining Reserved must be 0xff // SMB_COM_READ_ANDX Remaining Reserved must be 0xff
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 6: case 6:
// SMB_COM_READ_ANDX DataCompactionMode 1 // SMB_COM_READ_ANDX DataCompactionMode 1
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 7: case 7:
// SMB_COM_READ_ANDX DataCompactionMode 1 // SMB_COM_READ_ANDX DataCompactionMode 1
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 8: case 8:
// SMB_COM_READ_ANDX Reserved // SMB_COM_READ_ANDX Reserved
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 9: case 9:
// SMB_COM_READ_ANDX Reserved // SMB_COM_READ_ANDX Reserved
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 10: case 10:
sstate->andx.datalength = *(p++) << 8; sstate->andx.datalength = *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 11: case 11:
sstate->andx.datalength |= *(p++); sstate->andx.datalength |= *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 12: case 12:
sstate->andx.dataoffset = *(p++) << 8; sstate->andx.dataoffset = *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 13: case 13:
sstate->andx.dataoffset|= *(p++); sstate->andx.dataoffset |= *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 14: case 14:
sstate->andx.datalength |= *(p++) << 24;
if (!(--input_len)) break;
case 15:
sstate->andx.datalength |= *(p++) << 16; sstate->andx.datalength |= *(p++) << 16;
if (!(--input_len)) break; if (!(--input_len))
break;
case 15:
sstate->andx.datalength |= *(p++) << 24;
if (!(--input_len))
break;
case 16: case 16:
// SMB_COM_READ_ANDX Reserved // SMB_COM_READ_ANDX Reserved
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 17: case 17:
// SMB_COM_READ_ANDX Reserved // SMB_COM_READ_ANDX Reserved
p++; p++;
if (!(--input_len)) break; if (!(--input_len))
break;
case 18: case 18:
// SMB_COM_READ_ANDX Reserved // SMB_COM_READ_ANDX Reserved
p++; p++;
@ -333,6 +381,170 @@ static uint32_t SMBParseReadAndX(Flow *f, void *smb_state, AppLayerParserState *
SCReturnUInt((uint32_t)(p - input)); SCReturnUInt((uint32_t)(p - input));
} }
static uint32_t SMBParseTransact(Flow *f, void *smb_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
SCEnter();
SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input;
switch (sstate->andx.andxbytesprocessed) {
case 0:
sstate->andx.paddingparsed = 0;
if (input_len >= 27) {
sstate->andx.datalength = *(p + 22);
sstate->andx.datalength |= *(p + 23) << 8;
sstate->andx.dataoffset = *(p + 24);
sstate->andx.dataoffset |= *(p + 25) << 8;
sstate->andx.datalength |= (uint64_t) * (p + 14) << 56;
sstate->andx.datalength |= (uint64_t) * (p + 15) << 48;
sstate->andx.datalength |= (uint64_t) * (p + 16) << 40;
sstate->andx.datalength |= (uint64_t) * (p + 17) << 32;
sstate->bytesprocessed += 24;
SCReturnUInt(24U);
} else {
/* total parameter count 1 */
p++;
if (!(--input_len))
break;
}
case 1:
/* total parameter count 2 */
p++;
if (!(--input_len))
break;
case 2:
/* total data count 1 */
p++;
if (!(--input_len))
break;
case 3:
/* total data count 2 */
p++;
if (!(--input_len))
break;
case 4:
/* max parameter count 1 */
p++;
if (!(--input_len))
break;
case 5:
/* max parameter count 2 */
p++;
if (!(--input_len))
break;
case 6:
/* max data count 1 */
p++;
if (!(--input_len))
break;
case 7:
/* max data count 2 */
p++;
if (!(--input_len))
break;
case 8:
/* max setup count */
p++;
if (!(--input_len))
break;
case 9:
/* Reserved */
p++;
if (!(--input_len))
break;
case 10:
/* Flags */
p++;
if (!(--input_len))
break;
case 11:
/* Flags */
p++;
if (!(--input_len))
break;
case 12:
/* Timeout */
p++;
if (!(--input_len))
break;
case 13:
/* Timeout */
p++;
if (!(--input_len))
break;
case 14:
/* Timeout */
p++;
if (!(--input_len))
break;
case 15:
/* Timeout */
p++;
if (!(--input_len))
break;
case 16:
/* Reserved */
p++;
if (!(--input_len))
break;
case 17:
/* Reserved */
p++;
if (!(--input_len))
break;
case 18:
/* Parameter Count */
p++;
if (!(--input_len))
break;
case 19:
/* Parameter Count */
p++;
if (!(--input_len))
break;
case 20:
/* Parameter Offset */
p++;
if (!(--input_len))
break;
case 21:
/* Parameter Offset */
p++;
if (!(--input_len))
break;
case 22:
/* Data Count */
sstate->andx.datalength = *(p++);
if (!(--input_len))
break;
case 23:
/* Data Count */
sstate->andx.datalength |= *(p++) << 8;
if (!(--input_len))
break;
case 24:
/* Data Offset */
sstate->andx.dataoffset = *(p++);
if (!(--input_len))
break;
case 25:
/* Data Offset */
sstate->andx.dataoffset |= *(p++) << 8;
if (!(--input_len))
case 26:
/* Setup Count */
p++;
if (!(--input_len))
case 27:
/* Reserved */
p++;
--input_len;
break;
}
sstate->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
}
/** /**
* Handle variable length padding for WriteAndX and ReadAndX * Handle variable length padding for WriteAndX and ReadAndX
*/ */
@ -341,10 +553,13 @@ static uint32_t PaddingParser(void *smb_state, AppLayerParserState *pstate,
SCEnter(); SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
while ((uint32_t)(sstate->bytesprocessed + (p - input)) < sstate->andx.dataoffset && sstate->bytecount.bytecount-- && input_len--) { while ((uint32_t)(sstate->bytesprocessed + (p - input))
< sstate->andx.dataoffset && sstate->bytecount.bytecount--
&& input_len--) {
p++; p++;
} }
if ((uint32_t)(sstate->bytesprocessed + (p - input)) == sstate->andx.dataoffset) { if ((uint32_t)(sstate->bytesprocessed + (p - input))
== sstate->andx.dataoffset) {
sstate->andx.paddingparsed = 1; sstate->andx.paddingparsed = 1;
} }
sstate->bytesprocessed += (p - input); sstate->bytesprocessed += (p - input);
@ -362,7 +577,8 @@ static uint32_t DataParser(void *smb_state, AppLayerParserState *pstate,
uint8_t *p = input; uint8_t *p = input;
if (sstate->andx.paddingparsed) { if (sstate->andx.paddingparsed) {
while (sstate->andx.datalength-- && sstate->bytecount.bytecount-- && input_len--) { while (sstate->andx.datalength-- && sstate->bytecount.bytecount--
&& input_len--) {
SCLogDebug("0x%02x ", *p); SCLogDebug("0x%02x ", *p);
p++; p++;
} }
@ -371,15 +587,14 @@ static uint32_t DataParser(void *smb_state, AppLayerParserState *pstate,
SCReturnUInt((uint32_t)(p - input)); SCReturnUInt((uint32_t)(p - input));
} }
/** /**
* \brief Obtain SMB WordCount which is 2 times the value. * \brief Obtain SMB WordCount which is 2 times the value.
* Reset bytecount.bytecountbytes to 0. * Reset bytecount.bytecountbytes to 0.
* Determine if this is an SMB AndX Command * Determine if this is an SMB AndX Command
*/ */
static uint32_t SMBGetWordCount(Flow *f, void *smb_state, AppLayerParserState *pstate, static uint32_t SMBGetWordCount(Flow *f, void *smb_state,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
{ AppLayerParserResult *output) {
SCEnter(); SCEnter();
if (input_len) { if (input_len) {
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
@ -398,20 +613,20 @@ static uint32_t SMBGetWordCount(Flow *f, void *smb_state, AppLayerParserState *p
* is after the first bytecount byte. * is after the first bytecount byte.
*/ */
static uint32_t SMBGetByteCount(Flow *f, void *smb_state, AppLayerParserState *pstate, static uint32_t SMBGetByteCount(Flow *f, void *smb_state,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
{ AppLayerParserResult *output) {
SCEnter(); SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
if (input_len && sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN + if (input_len && sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN + 1
1 + sstate->wordcount.wordcount) { + sstate->wordcount.wordcount) {
sstate->bytecount.bytecount = *(p++); sstate->bytecount.bytecount = *(p++);
sstate->bytesprocessed++; sstate->bytesprocessed++;
--input_len; --input_len;
} }
if (input_len && sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN + if (input_len && sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN + 2
2 + sstate->wordcount.wordcount) { + sstate->wordcount.wordcount) {
sstate->bytecount.bytecount |= *(p++) << 8; sstate->bytecount.bytecount |= *(p++) << 8;
sstate->bytesprocessed++; sstate->bytesprocessed++;
SCLogDebug("Bytecount %u", sstate->bytecount.bytecount); SCLogDebug("Bytecount %u", sstate->bytecount.bytecount);
@ -424,22 +639,34 @@ static uint32_t SMBGetByteCount(Flow *f, void *smb_state, AppLayerParserState *p
* \brief SMBParseWordCount parses the SMB Wordcount portion of the SMB Transaction. * \brief SMBParseWordCount parses the SMB Wordcount portion of the SMB Transaction.
* until sstate->wordcount.wordcount bytes are parsed. * until sstate->wordcount.wordcount bytes are parsed.
*/ */
static uint32_t SMBParseWordCount(Flow *f, void *smb_state, AppLayerParserState *pstate, static uint32_t SMBParseWordCount(Flow *f, void *smb_state,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
{ AppLayerParserResult *output) {
SCEnter(); SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
uint32_t retval = 0; uint32_t retval = 0;
uint32_t parsed = 0; uint32_t parsed = 0;
if ((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) && sstate->smb.command == SMB_COM_READ_ANDX) { if ((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) && sstate->smb.command
retval = SMBParseReadAndX(f, sstate, pstate, input + parsed, input_len, output); == SMB_COM_READ_ANDX) {
retval = SMBParseReadAndX(f, sstate, pstate, input + parsed, input_len,
output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
sstate->wordcount.wordcount -= retval; sstate->wordcount.wordcount -= retval;
SCReturnUInt(retval); SCReturnUInt(retval);
} else if (((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) == 0) && sstate->smb.command == SMB_COM_WRITE_ANDX) { } else if (((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) == 0)
retval = SMBParseWriteAndX(f, sstate, pstate, input + parsed, input_len, output); && sstate->smb.command == SMB_COM_WRITE_ANDX) {
retval = SMBParseWriteAndX(f, sstate, pstate, input + parsed,
input_len, output);
parsed += retval;
input_len -= retval;
sstate->wordcount.wordcount -= retval;
SCReturnUInt(retval);
} else if ((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR)
&& sstate->smb.command == SMB_COM_TRANSACTION) {
retval = SMBParseTransact(f, sstate, pstate, input + parsed, input_len,
output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
sstate->wordcount.wordcount -= retval; sstate->wordcount.wordcount -= retval;
@ -459,23 +686,28 @@ static uint32_t SMBParseWordCount(Flow *f, void *smb_state, AppLayerParserState
* until sstate->bytecount.bytecount bytes are parsed. * until sstate->bytecount.bytecount bytes are parsed.
*/ */
static uint32_t SMBParseByteCount(Flow *f, void *smb_state, AppLayerParserState *pstate, static uint32_t SMBParseByteCount(Flow *f, void *smb_state,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
{ AppLayerParserResult *output) {
SCEnter(); SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
uint32_t retval = 0; uint32_t retval = 0;
uint32_t parsed = 0; uint32_t parsed = 0;
if (((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) && sstate->smb.command == SMB_COM_READ_ANDX) || if (((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) && sstate->smb.command
(((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) == 0) && sstate->smb.command == SMB_COM_WRITE_ANDX)) { == SMB_COM_READ_ANDX) || (((sstate->smb.flags
& SMB_FLAGS_SERVER_TO_REDIR) == 0) && sstate->smb.command
== SMB_COM_WRITE_ANDX) ||
(sstate->smb.command == SMB_COM_TRANSACTION)) {
if (sstate->andx.paddingparsed == 0) { if (sstate->andx.paddingparsed == 0) {
retval = PaddingParser(sstate, pstate, input + parsed, input_len, output); retval = PaddingParser(sstate, pstate, input + parsed, input_len,
output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
} }
if (sstate->andx.datalength) { if (sstate->andx.datalength) {
retval = DataParser(sstate, pstate, input + parsed, input_len, output); retval = DataParser(sstate, pstate, input + parsed, input_len,
output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
} }
@ -493,9 +725,9 @@ static uint32_t SMBParseByteCount(Flow *f, void *smb_state, AppLayerParserState
SCReturnUInt((uint32_t)(p - input)); SCReturnUInt((uint32_t)(p - input));
} }
static uint32_t NBSSParseHeader(Flow *f, void *smb_state, AppLayerParserState *pstate, static uint32_t NBSSParseHeader(Flow *f, void *smb_state,
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
{ AppLayerParserResult *output) {
SCEnter(); SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
@ -514,14 +746,17 @@ static uint32_t NBSSParseHeader(Flow *f, void *smb_state, AppLayerParserState *p
SCReturnUInt(4U); SCReturnUInt(4U);
} else { } else {
sstate->nbss.type = *(p++); sstate->nbss.type = *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
} }
case 1: case 1:
sstate->nbss.length = (*(p++) & 0x01) << 16; sstate->nbss.length = (*(p++) & 0x01) << 16;
if (!(--input_len)) break; if (!(--input_len))
break;
case 2: case 2:
sstate->nbss.length |= *(p++) << 8; sstate->nbss.length |= *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 3: case 3:
sstate->nbss.length |= *(p++); sstate->nbss.length |= *(p++);
--input_len; --input_len;
@ -532,9 +767,12 @@ static uint32_t NBSSParseHeader(Flow *f, void *smb_state, AppLayerParserState *p
SCReturnUInt((uint32_t)(p - input)); SCReturnUInt((uint32_t)(p - input));
} }
static uint32_t SMBParseHeader(Flow *f, void *smb_state, AppLayerParserState *pstate, /**
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) * \brief SMBParseHeader parses and validates the 32 byte SMB Header
{ */
static uint32_t SMBParseHeader(Flow *f, void *smb_state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
AppLayerParserResult *output) {
SCEnter(); SCEnter();
SMBState *sstate = (SMBState *) smb_state; SMBState *sstate = (SMBState *) smb_state;
uint8_t *p = input; uint8_t *p = input;
@ -579,104 +817,135 @@ static uint32_t SMBParseHeader(Flow *f, void *smb_state, AppLayerParserState *ps
//sstate->smb.protocol[0] = *(p++); //sstate->smb.protocol[0] = *(p++);
if (*(p++) != 0xff) if (*(p++) != 0xff)
SCReturnInt(0); SCReturnInt(0);
if (!(--input_len)) break; if (!(--input_len))
break;
} }
case 5: case 5:
//sstate->smb.protocol[1] = *(p++); //sstate->smb.protocol[1] = *(p++);
if (*(p++) != 'S') if (*(p++) != 'S')
SCReturnInt(0); SCReturnInt(0);
if (!(--input_len)) break; if (!(--input_len))
break;
case 6: case 6:
//sstate->smb.protocol[2] = *(p++); //sstate->smb.protocol[2] = *(p++);
if (*(p++) != 'M') if (*(p++) != 'M')
SCReturnInt(0); SCReturnInt(0);
if (!(--input_len)) break; if (!(--input_len))
break;
case 7: case 7:
//sstate->smb.protocol[3] = *(p++); //sstate->smb.protocol[3] = *(p++);
if (*(p++) != 'B') if (*(p++) != 'B')
SCReturnInt(0); SCReturnInt(0);
if (!(--input_len)) break; if (!(--input_len))
break;
case 8: case 8:
sstate->smb.command = *(p++); sstate->smb.command = *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 9: case 9:
sstate->smb.status = *(p++) << 24; sstate->smb.status = *(p++) << 24;
if (!(--input_len)) break; if (!(--input_len))
break;
case 10: case 10:
sstate->smb.status |= *(p++) << 16; sstate->smb.status |= *(p++) << 16;
if (!(--input_len)) break; if (!(--input_len))
break;
case 11: case 11:
sstate->smb.status |= *(p++) << 8; sstate->smb.status |= *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 12: case 12:
sstate->smb.status |= *(p++); sstate->smb.status |= *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 13: case 13:
sstate->smb.flags = *(p++); sstate->smb.flags = *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 14: case 14:
sstate->smb.flags2 = *(p++) << 8; sstate->smb.flags2 = *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 15: case 15:
sstate->smb.flags2 |= *(p++); sstate->smb.flags2 |= *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 16: case 16:
sstate->smb.pidhigh = *(p++) << 8; sstate->smb.pidhigh = *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 17: case 17:
sstate->smb.pidhigh |= *(p++); sstate->smb.pidhigh |= *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 18: case 18:
sstate->smb.securitysignature = (uint64_t) * (p++) << 56; sstate->smb.securitysignature = (uint64_t) * (p++) << 56;
if (!(--input_len)) break; if (!(--input_len))
break;
case 19: case 19:
sstate->smb.securitysignature |= (uint64_t) * (p++) << 48; sstate->smb.securitysignature |= (uint64_t) * (p++) << 48;
if (!(--input_len)) break; if (!(--input_len))
break;
case 20: case 20:
sstate->smb.securitysignature |= (uint64_t) * (p++) << 40; sstate->smb.securitysignature |= (uint64_t) * (p++) << 40;
if (!(--input_len)) break; if (!(--input_len))
break;
case 21: case 21:
sstate->smb.securitysignature |= (uint64_t) * (p++) << 32; sstate->smb.securitysignature |= (uint64_t) * (p++) << 32;
if (!(--input_len)) break; if (!(--input_len))
break;
case 22: case 22:
sstate->smb.securitysignature |= (uint64_t) * (p++) << 24; sstate->smb.securitysignature |= (uint64_t) * (p++) << 24;
if (!(--input_len)) break; if (!(--input_len))
break;
case 23: case 23:
sstate->smb.securitysignature |= (uint64_t) * (p++) << 16; sstate->smb.securitysignature |= (uint64_t) * (p++) << 16;
if (!(--input_len)) break; if (!(--input_len))
break;
case 24: case 24:
sstate->smb.securitysignature |= (uint64_t) * (p++) << 8; sstate->smb.securitysignature |= (uint64_t) * (p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 25: case 25:
sstate->smb.securitysignature |= (uint64_t) * (p++); sstate->smb.securitysignature |= (uint64_t) * (p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 26: case 26:
p++; // UNUSED p++; // UNUSED
if (!(--input_len)) break; if (!(--input_len))
break;
case 27: case 27:
p++; // UNUSED p++; // UNUSED
if (!(--input_len)) break; if (!(--input_len))
break;
case 28: case 28:
sstate->smb.tid = *(p++) << 8; sstate->smb.tid = *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 29: case 29:
sstate->smb.tid |= *(p++); sstate->smb.tid |= *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 30: case 30:
sstate->smb.pid = *(p++) << 8; sstate->smb.pid = *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 31: case 31:
sstate->smb.pid |= *(p++); sstate->smb.pid |= *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 32: case 32:
sstate->smb.uid = *(p++) << 8; sstate->smb.uid = *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 33: case 33:
sstate->smb.uid |= *(p++); sstate->smb.uid |= *(p++);
if (!(--input_len)) break; if (!(--input_len))
break;
case 34: case 34:
sstate->smb.mid = *(p++) << 8; sstate->smb.mid = *(p++) << 8;
if (!(--input_len)) break; if (!(--input_len))
break;
case 35: case 35:
sstate->smb.mid |= *(p++); sstate->smb.mid |= *(p++);
--input_len; --input_len;
@ -688,8 +957,7 @@ static uint32_t SMBParseHeader(Flow *f, void *smb_state, AppLayerParserState *ps
} }
static int SMBParse(Flow *f, void *smb_state, AppLayerParserState *pstate, static int SMBParse(Flow *f, 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;
@ -700,71 +968,74 @@ static int SMBParse(Flow *f, void *smb_state, AppLayerParserState *pstate,
SCReturnInt(-1); SCReturnInt(-1);
while (sstate->bytesprocessed < NBSS_HDR_LEN) { while (sstate->bytesprocessed < NBSS_HDR_LEN) {
retval = NBSSParseHeader(f, smb_state, pstate, input, input_len, retval
= NBSSParseHeader(f, smb_state, pstate, input, input_len,
output); output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
SCLogDebug("NBSS Header (%u/%u) Type 0x%02x Length 0x%04x parsed %ld input_len %u", SCLogDebug(
"NBSS Header (%u/%u) Type 0x%02x Length 0x%04x parsed %ld input_len %u",
sstate->bytesprocessed, NBSS_HDR_LEN, sstate->nbss.type, sstate->bytesprocessed, NBSS_HDR_LEN, sstate->nbss.type,
sstate->nbss.length, parsed, input_len); sstate->nbss.length, parsed, input_len);
} }
switch (sstate->nbss.type) { switch (sstate->nbss.type) {
case NBSS_SESSION_MESSAGE: case NBSS_SESSION_MESSAGE:
while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN && while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN
sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN)) { && sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN)) {
retval = SMBParseHeader(f, smb_state, pstate, input + retval = SMBParseHeader(f, smb_state, pstate, input + parsed,
parsed, input_len, output); input_len, output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
SCLogDebug("SMB Header (%u/%u) Command 0x%02x parsed %ld input_len %u", SCLogDebug(
"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);
} }
do { do {
if (input_len && (sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN)) { if (input_len && (sstate->bytesprocessed == NBSS_HDR_LEN
retval = SMBGetWordCount(f, smb_state, pstate, + SMB_HDR_LEN)) {
input + parsed, input_len, retval = SMBGetWordCount(f, smb_state, pstate, input + parsed,
output); input_len, output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
SCLogDebug("wordcount (%u) parsed %ld input_len %u", SCLogDebug("wordcount (%u) parsed %ld input_len %u",
sstate->wordcount.wordcount, parsed, input_len); sstate->wordcount.wordcount, parsed, input_len);
} }
while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN + SMB_HDR_LEN + 1 && while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN
sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN + 1 + SMB_HDR_LEN + 1 && sstate->bytesprocessed < NBSS_HDR_LEN
+ sstate->wordcount.wordcount)) { + SMB_HDR_LEN + 1 + sstate->wordcount.wordcount)) {
retval = SMBParseWordCount(f, smb_state, pstate, retval = SMBParseWordCount(f, smb_state, pstate,
input + parsed, input_len, input + parsed, input_len, output);
output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
} }
while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN + SMB_HDR_LEN + while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN
1 + sstate->wordcount.wordcount && sstate->bytesprocessed < NBSS_HDR_LEN + + SMB_HDR_LEN + 1 + sstate->wordcount.wordcount
SMB_HDR_LEN + 3 + sstate->wordcount.wordcount)) { && sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN + 3
retval = SMBGetByteCount(f, smb_state, pstate, + sstate->wordcount.wordcount)) {
input + parsed, input_len, retval = SMBGetByteCount(f, smb_state, pstate, input + parsed,
output); input_len, output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
} }
while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN + while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN
SMB_HDR_LEN + 3 + sstate->wordcount.wordcount && + SMB_HDR_LEN + 3 + sstate->wordcount.wordcount
sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN + 3 && sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN + 3
+ sstate->wordcount.wordcount + sstate->bytecount.bytecount)) { + sstate->wordcount.wordcount
+ sstate->bytecount.bytecount)) {
retval = SMBParseByteCount(f, smb_state, pstate, retval = SMBParseByteCount(f, smb_state, pstate,
input + parsed, input_len, input + parsed, input_len, output);
output);
parsed += retval; parsed += retval;
input_len -= retval; input_len -= retval;
} }
} while (sstate->andx.andxcommand != SMB_NO_SECONDARY_ANDX_COMMAND && input_len); } while (sstate->andx.andxcommand != SMB_NO_SECONDARY_ANDX_COMMAND
&& input_len);
break; break;
default: default:
break; break;
@ -883,7 +1154,6 @@ int SMBParserTest01(void) {
goto end; goto end;
} }
end: end:
return result; return result;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009 Open Information Security Foundation * Copyright (c) 2009,2010 Open Information Security Foundation
* app-layer-smb.h * app-layer-smb.h
* *
* \author Kirby Kuehl <kkuehl@gmail.com> * \author Kirby Kuehl <kkuehl@gmail.com>

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009 Open Information Security Foundation * Copyright (c) 2009,2010 Open Information Security Foundation
* app-layer-smb.c * app-layer-smb.c
* *
* \author Kirby Kuehl <kkuehl@gmail.com> * \author Kirby Kuehl <kkuehl@gmail.com>

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009 Open Information Security Foundation * Copyright (c) 2009,2010 Open Information Security Foundation
* app-layer-smb2.h * app-layer-smb2.h
* *
* \author Kirby Kuehl <kkuehl@gmail.com> * \author Kirby Kuehl <kkuehl@gmail.com>

Loading…
Cancel
Save