|
|
|
|
@ -193,9 +193,9 @@ static int SMBParseByteCount(void *smb_state, AppLayerParserState *pstate,
|
|
|
|
|
#define DEBUG 1
|
|
|
|
|
static int NBSSParseHeader(void *smb_state, AppLayerParserState *pstate,
|
|
|
|
|
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
|
|
|
|
|
SMBState *sstate = (SMBState *) smb_state;
|
|
|
|
|
uint8_t *p = input;
|
|
|
|
|
if (input_len && sstate->bytesprocessed < NBSS_HDR_LEN - 1) {
|
|
|
|
|
SMBState *sstate = (SMBState *) smb_state;
|
|
|
|
|
uint8_t *p = input;
|
|
|
|
|
if (input_len && sstate->bytesprocessed < NBSS_HDR_LEN - 1) {
|
|
|
|
|
switch (sstate->bytesprocessed) {
|
|
|
|
|
case 0:
|
|
|
|
|
if (input_len >= NBSS_HDR_LEN) {
|
|
|
|
|
@ -225,16 +225,16 @@ if (input_len && sstate->bytesprocessed < NBSS_HDR_LEN - 1) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sstate->bytesprocessed += (p - input);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int SMBParseHeader(void *smb_state, AppLayerParserState *pstate,
|
|
|
|
|
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
|
|
|
|
|
SMBState *sstate = (SMBState *) smb_state;
|
|
|
|
|
uint8_t *p = input;
|
|
|
|
|
hexdump(p, input_len);
|
|
|
|
|
if (input_len) {
|
|
|
|
|
SMBState *sstate = (SMBState *) smb_state;
|
|
|
|
|
uint8_t *p = input;
|
|
|
|
|
hexdump(p, input_len);
|
|
|
|
|
if (input_len) {
|
|
|
|
|
switch (sstate->bytesprocessed) {
|
|
|
|
|
case 4:
|
|
|
|
|
if (input_len >= SMB_HDR_LEN) {
|
|
|
|
|
@ -383,25 +383,26 @@ if (input_len) {
|
|
|
|
|
default: // SHOULD NEVER OCCUR
|
|
|
|
|
return 8;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sstate->bytesprocessed += (p - input);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
sstate->bytesprocessed += (p - input);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int SMBParse(void *smb_state, AppLayerParserState *pstate,
|
|
|
|
|
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
|
|
|
|
|
SMBState *sstate = (SMBState *) smb_state;
|
|
|
|
|
uint16_t max_fields = 3;
|
|
|
|
|
uint16_t u = 0;
|
|
|
|
|
uint32_t offset = 0;
|
|
|
|
|
SMBState *sstate = (SMBState *) smb_state;
|
|
|
|
|
uint16_t max_fields = 3;
|
|
|
|
|
uint16_t u = 0;
|
|
|
|
|
uint32_t offset = 0;
|
|
|
|
|
|
|
|
|
|
if (pstate == NULL)
|
|
|
|
|
if (pstate == NULL)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
for (u = pstate->parse_field; u < max_fields; u++) {
|
|
|
|
|
for (u = pstate->parse_field; u < max_fields; u++) {
|
|
|
|
|
printf("SMBParse: u %" PRIu32 "\n", u);
|
|
|
|
|
switch (u) {
|
|
|
|
|
case 0: {
|
|
|
|
|
case 0:
|
|
|
|
|
{
|
|
|
|
|
int r = AlpParseFieldBySize(output, pstate, SMB_PARSE_NBSS_HEADER,
|
|
|
|
|
NBSS_HDR_LEN, input, input_len, &offset);
|
|
|
|
|
|
|
|
|
|
@ -411,7 +412,8 @@ for (u = pstate->parse_field; u < max_fields; u++) {
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 1: {
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
uint8_t *data = input + offset;
|
|
|
|
|
uint32_t data_len = input_len - offset;
|
|
|
|
|
if (sstate->nbss.type == NBSS_SESSION_MESSAGE) {
|
|
|
|
|
@ -424,7 +426,8 @@ for (u = pstate->parse_field; u < max_fields; u++) {
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 2: {
|
|
|
|
|
case 2:
|
|
|
|
|
{
|
|
|
|
|
uint8_t *data = input + offset;
|
|
|
|
|
uint32_t data_len = input_len - offset;
|
|
|
|
|
int r = AlpParseFieldBySize(output, pstate, SMB_PARSE_GET_WORDCOUNT,
|
|
|
|
|
@ -435,7 +438,8 @@ for (u = pstate->parse_field; u < max_fields; u++) {
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 3: {
|
|
|
|
|
case 3:
|
|
|
|
|
{
|
|
|
|
|
uint8_t *data = input + offset;
|
|
|
|
|
uint32_t data_len = input_len - offset;
|
|
|
|
|
printf("wordcount %d\n", sstate->wordcount.wordcount);
|
|
|
|
|
@ -448,7 +452,8 @@ for (u = pstate->parse_field; u < max_fields; u++) {
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 4: {
|
|
|
|
|
case 4:
|
|
|
|
|
{
|
|
|
|
|
uint8_t *data = input + offset;
|
|
|
|
|
uint32_t data_len = input_len - offset;
|
|
|
|
|
|
|
|
|
|
@ -460,7 +465,8 @@ for (u = pstate->parse_field; u < max_fields; u++) {
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 5: {
|
|
|
|
|
case 5:
|
|
|
|
|
{
|
|
|
|
|
uint8_t *data = input + offset;
|
|
|
|
|
uint32_t data_len = input_len - offset;
|
|
|
|
|
|
|
|
|
|
@ -472,12 +478,12 @@ for (u = pstate->parse_field; u < max_fields; u++) {
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pstate->parse_field = 0;
|
|
|
|
|
pstate->flags |= APP_LAYER_PARSER_DONE;
|
|
|
|
|
return 1;
|
|
|
|
|
pstate->parse_field = 0;
|
|
|
|
|
pstate->flags |= APP_LAYER_PARSER_DONE;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int isAndX(SMBState *smb_state) {
|
|
|
|
|
@ -498,100 +504,100 @@ int isAndX(SMBState *smb_state) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *SMBStateAlloc(void) {
|
|
|
|
|
void *s = malloc(sizeof(SMBState));
|
|
|
|
|
if (s == NULL)
|
|
|
|
|
void *s = malloc(sizeof(SMBState));
|
|
|
|
|
if (s == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
memset(s, 0, sizeof(SMBState));
|
|
|
|
|
return s;
|
|
|
|
|
memset(s, 0, sizeof(SMBState));
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void SMBStateFree(void *s) {
|
|
|
|
|
if (s) {
|
|
|
|
|
if (s) {
|
|
|
|
|
free(s);
|
|
|
|
|
s = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RegisterSMBParsers(void) {
|
|
|
|
|
AppLayerRegisterProto("smb", ALPROTO_SMB, STREAM_TOSERVER, SMBParse);
|
|
|
|
|
AppLayerRegisterProto("smb", ALPROTO_SMB, STREAM_TOCLIENT, SMBParse);
|
|
|
|
|
AppLayerRegisterParser("nbss.hdr", ALPROTO_SMB, SMB_PARSE_NBSS_HEADER,
|
|
|
|
|
AppLayerRegisterProto("smb", ALPROTO_SMB, STREAM_TOSERVER, SMBParse);
|
|
|
|
|
AppLayerRegisterProto("smb", ALPROTO_SMB, STREAM_TOCLIENT, SMBParse);
|
|
|
|
|
AppLayerRegisterParser("nbss.hdr", ALPROTO_SMB, SMB_PARSE_NBSS_HEADER,
|
|
|
|
|
NBSSParseHeader, "smb");
|
|
|
|
|
AppLayerRegisterParser("smb.hdr", ALPROTO_SMB, SMB_PARSE_SMB_HEADER,
|
|
|
|
|
AppLayerRegisterParser("smb.hdr", ALPROTO_SMB, SMB_PARSE_SMB_HEADER,
|
|
|
|
|
SMBParseHeader, "smb");
|
|
|
|
|
AppLayerRegisterParser("smb.getwordcount", ALPROTO_SMB, SMB_PARSE_GET_WORDCOUNT,
|
|
|
|
|
AppLayerRegisterParser("smb.getwordcount", ALPROTO_SMB, SMB_PARSE_GET_WORDCOUNT,
|
|
|
|
|
SMBGetWordCount, "smb");
|
|
|
|
|
AppLayerRegisterParser("smb.wordcount", ALPROTO_SMB, SMB_PARSE_WORDCOUNT,
|
|
|
|
|
AppLayerRegisterParser("smb.wordcount", ALPROTO_SMB, SMB_PARSE_WORDCOUNT,
|
|
|
|
|
SMBParseWordCount, "smb");
|
|
|
|
|
AppLayerRegisterParser("smb.getbytecount", ALPROTO_SMB, SMB_PARSE_GET_BYTECOUNT,
|
|
|
|
|
AppLayerRegisterParser("smb.getbytecount", ALPROTO_SMB, SMB_PARSE_GET_BYTECOUNT,
|
|
|
|
|
SMBGetByteCount, "smb");
|
|
|
|
|
AppLayerRegisterParser("smb.bytecount", ALPROTO_SMB, SMB_PARSE_BYTECOUNT,
|
|
|
|
|
AppLayerRegisterParser("smb.bytecount", ALPROTO_SMB, SMB_PARSE_BYTECOUNT,
|
|
|
|
|
SMBParseByteCount, "smb");
|
|
|
|
|
AppLayerRegisterStateFuncs(ALPROTO_SMB, SMBStateAlloc, SMBStateFree);
|
|
|
|
|
AppLayerRegisterStateFuncs(ALPROTO_SMB, SMBStateAlloc, SMBStateFree);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* UNITTESTS */
|
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
|
|
|
|
|
|
int SMBParserTest01(void) {
|
|
|
|
|
int result = 1;
|
|
|
|
|
Flow f;
|
|
|
|
|
uint8_t smbbuf[] = "\x00\x00\x00\x85\xff\x53\x4d\x42\x72\x00\x00\x00\x00"
|
|
|
|
|
"\x18\x53\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x00\x00"
|
|
|
|
|
"\x00\x62\x00\x02\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20"
|
|
|
|
|
"\x31\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00\x02\x57\x69\x6e\x64\x6f\x77\x73"
|
|
|
|
|
"\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00\x02\x4c"
|
|
|
|
|
"\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54"
|
|
|
|
|
"\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00";
|
|
|
|
|
|
|
|
|
|
uint32_t smblen = sizeof(smbbuf) - 1;
|
|
|
|
|
TcpSession ssn;
|
|
|
|
|
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_SMB, STREAM_TOSERVER|STREAM_EOF, smbbuf, smblen, FALSE);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
int result = 1;
|
|
|
|
|
Flow f;
|
|
|
|
|
uint8_t smbbuf[] = "\x00\x00\x00\x85\xff\x53\x4d\x42\x72\x00\x00\x00\x00"
|
|
|
|
|
"\x18\x53\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x00\x00"
|
|
|
|
|
"\x00\x62\x00\x02\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20"
|
|
|
|
|
"\x31\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00\x02\x57\x69\x6e\x64\x6f\x77\x73"
|
|
|
|
|
"\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00\x02\x4c"
|
|
|
|
|
"\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54"
|
|
|
|
|
"\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00";
|
|
|
|
|
|
|
|
|
|
uint32_t smblen = sizeof(smbbuf) - 1;
|
|
|
|
|
TcpSession ssn;
|
|
|
|
|
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_SMB, STREAM_TOSERVER|STREAM_EOF, smbbuf, smblen, FALSE);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
printf("smb header check returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SMBState *smb_state = ssn.aldata[AlpGetStateIdx(ALPROTO_SMB)];
|
|
|
|
|
if (smb_state == NULL) {
|
|
|
|
|
SMBState *smb_state = ssn.aldata[AlpGetStateIdx(ALPROTO_SMB)];
|
|
|
|
|
if (smb_state == NULL) {
|
|
|
|
|
printf("no smb state: ");
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (smb_state->nbss.type != NBSS_SESSION_MESSAGE) {
|
|
|
|
|
if (smb_state->nbss.type != NBSS_SESSION_MESSAGE) {
|
|
|
|
|
printf("expected nbss type 0x%02x , got 0x%02x : ", NBSS_SESSION_MESSAGE, smb_state->nbss.type);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (smb_state->nbss.length != 133) {
|
|
|
|
|
if (smb_state->nbss.length != 133) {
|
|
|
|
|
printf("expected nbss length 0x%02x , got 0x%02x : ", 133, smb_state->nbss.length);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (smb_state->smb.command != SMB_COM_NEGOTIATE) {
|
|
|
|
|
if (smb_state->smb.command != SMB_COM_NEGOTIATE) {
|
|
|
|
|
printf("expected SMB command 0x%02x , got 0x%02x : ", SMB_COM_NEGOTIATE, smb_state->smb.command);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
return result;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SMBParserRegisterTests(void) {
|
|
|
|
|
printf("SMBParserRegisterTests\n");
|
|
|
|
|
UtRegisterTest("SMBParserTest01", SMBParserTest01, 1);
|
|
|
|
|
printf("SMBParserRegisterTests\n");
|
|
|
|
|
UtRegisterTest("SMBParserTest01", SMBParserTest01, 1);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|