|
|
|
@ -1067,10 +1067,10 @@ static int DCERPCParseHeader(DCERPC *dcerpc, uint8_t *input, uint32_t input_len)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
case 15:
|
|
|
|
dcerpc->dcerpchdr.call_id |= *(p++);
|
|
|
|
dcerpc->dcerpchdr.call_id |= *(p++);
|
|
|
|
if (dcerpc->dcerpchdr.packed_drep[0] == 0x01) {
|
|
|
|
if (dcerpc->dcerpchdr.packed_drep[0] == 0x10) {
|
|
|
|
SCByteSwap16(dcerpc->dcerpchdr.frag_length);
|
|
|
|
dcerpc->dcerpchdr.frag_length = SCByteSwap16(dcerpc->dcerpchdr.frag_length);
|
|
|
|
SCByteSwap16(dcerpc->dcerpchdr.auth_length);
|
|
|
|
dcerpc->dcerpchdr.auth_length = SCByteSwap16(dcerpc->dcerpchdr.auth_length);
|
|
|
|
SCByteSwap32(dcerpc->dcerpchdr.call_id);
|
|
|
|
dcerpc->dcerpchdr.call_id = SCByteSwap32(dcerpc->dcerpchdr.call_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--input_len;
|
|
|
|
--input_len;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
@ -1354,6 +1354,10 @@ int32_t DCERPCParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) {
|
|
|
|
SCLogDebug("DCERPC Type 0x%02x not implemented yet", dcerpc->dcerpchdr.type);
|
|
|
|
SCLogDebug("DCERPC Type 0x%02x not implemented yet", dcerpc->dcerpchdr.type);
|
|
|
|
dcerpc->bytesprocessed = 0;
|
|
|
|
dcerpc->bytesprocessed = 0;
|
|
|
|
dcerpc->pdu_fragged = 0;
|
|
|
|
dcerpc->pdu_fragged = 0;
|
|
|
|
|
|
|
|
/* reset type to REQUEST. Yeah, that's cool. Just like how we would
|
|
|
|
|
|
|
|
* otherwise behave if this is the first dce payload the parser is
|
|
|
|
|
|
|
|
* seeing */
|
|
|
|
|
|
|
|
dcerpc->dcerpchdr.type = 0;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -3852,6 +3856,92 @@ end:
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* \test DCERPC fragmented PDU.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
int DCERPCParserTest07(void) {
|
|
|
|
|
|
|
|
int result = 1;
|
|
|
|
|
|
|
|
Flow f;
|
|
|
|
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t fault[] = {
|
|
|
|
|
|
|
|
0x05, 0x00, 0x03, 0x03, 0x10, 0x00, 0x00, 0x00,
|
|
|
|
|
|
|
|
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
|
|
|
|
|
|
|
0xf7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32_t fault_len = sizeof(fault);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t request1[] = {
|
|
|
|
|
|
|
|
0x05, 0x00
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32_t request1_len = sizeof(request1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t request2[] = {
|
|
|
|
|
|
|
|
0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00,
|
|
|
|
|
|
|
|
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00,
|
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02,
|
|
|
|
|
|
|
|
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
|
|
|
|
|
|
|
0x0B, 0x0C
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32_t request2_len = sizeof(request2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TcpSession ssn;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_DCERPC, STREAM_TOSERVER|STREAM_START,
|
|
|
|
|
|
|
|
fault, fault_len);
|
|
|
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
|
|
|
printf("dcerpc header check returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DCERPCState *dcerpc_state = f.aldata[AlpGetStateIdx(ALPROTO_DCERPC)];
|
|
|
|
|
|
|
|
if (dcerpc_state == NULL) {
|
|
|
|
|
|
|
|
printf("no dcerpc state: ");
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_DCERPC, STREAM_TOSERVER,
|
|
|
|
|
|
|
|
request1, request1_len);
|
|
|
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
|
|
|
printf("dcerpc header check returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result &= (dcerpc_state->dcerpc.bytesprocessed == 2);
|
|
|
|
|
|
|
|
result &= (dcerpc_state->dcerpc.dcerpcrequest.stub_data_buffer == NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_DCERPC, STREAM_TOSERVER,
|
|
|
|
|
|
|
|
request2, request2_len);
|
|
|
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
|
|
|
printf("dcerpc header check returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result &= (dcerpc_state->dcerpc.bytesprocessed == 0);
|
|
|
|
|
|
|
|
result &= (dcerpc_state->dcerpc.dcerpcrequest.stub_data_buffer != NULL &&
|
|
|
|
|
|
|
|
dcerpc_state->dcerpc.dcerpcrequest.stub_data_buffer_len == 12);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DCERPCParserRegisterTests(void) {
|
|
|
|
void DCERPCParserRegisterTests(void) {
|
|
|
|
printf("DCERPCParserRegisterTests\n");
|
|
|
|
printf("DCERPCParserRegisterTests\n");
|
|
|
|
UtRegisterTest("DCERPCParserTest01", DCERPCParserTest01, 1);
|
|
|
|
UtRegisterTest("DCERPCParserTest01", DCERPCParserTest01, 1);
|
|
|
|
@ -3860,6 +3950,7 @@ void DCERPCParserRegisterTests(void) {
|
|
|
|
UtRegisterTest("DCERPCParserTest04", DCERPCParserTest04, 1);
|
|
|
|
UtRegisterTest("DCERPCParserTest04", DCERPCParserTest04, 1);
|
|
|
|
UtRegisterTest("DCERPCParserTest05", DCERPCParserTest05, 1);
|
|
|
|
UtRegisterTest("DCERPCParserTest05", DCERPCParserTest05, 1);
|
|
|
|
UtRegisterTest("DCERPCParserTest06", DCERPCParserTest06, 1);
|
|
|
|
UtRegisterTest("DCERPCParserTest06", DCERPCParserTest06, 1);
|
|
|
|
|
|
|
|
UtRegisterTest("DCERPCParserTest07", DCERPCParserTest07, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|