mirror of https://github.com/OISF/suricata
smb and dcerpc work
parent
bf72331849
commit
ecaa701bdf
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Open Information Security Foundation
|
||||
* app-layer-dcerpc.c
|
||||
*
|
||||
* \author Kirby Kuehl <kkuehl@gmail.com>
|
||||
*/
|
||||
#include "eidps-common.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "decode.h"
|
||||
#include "threads.h"
|
||||
|
||||
#include "util-print.h"
|
||||
#include "util-pool.h"
|
||||
|
||||
#include "stream-tcp-private.h"
|
||||
#include "stream-tcp-reassemble.h"
|
||||
#include "stream.h"
|
||||
|
||||
#include "app-layer-protos.h"
|
||||
#include "app-layer-parser.h"
|
||||
|
||||
#include "util-binsearch.h"
|
||||
#include "util-unittest.h"
|
||||
|
||||
#include "app-layer-dcerpc.h"
|
||||
|
||||
|
||||
enum {
|
||||
DCERPC_FIELD_NONE = 0,
|
||||
DCERPC_PARSE_DCERPC_HEADER,
|
||||
DCERPC_PARSE_DCERPC_BIND,
|
||||
DCERPC_PARSE_DCERPC_BIND_ACK,
|
||||
DCERPC_PARSE_DCERPC_REQUEST,
|
||||
/* must be last */
|
||||
DCERPC_FIELD_MAX,
|
||||
};
|
||||
|
||||
static int DCERPCParseHeader(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
|
||||
DCERPCState *sstate = (DCERPCState *)dcerpc_state;
|
||||
uint8_t *p = input;
|
||||
// hexdump(p, input_len);
|
||||
if (input_len) {
|
||||
switch (sstate->bytesprocessed) {
|
||||
case 0:
|
||||
if (input_len >= DCERPC_HDR_LEN + 1) {
|
||||
if (*p != 5) return 1;
|
||||
if (!(*(p + 1 ) == 0 || (*(p + 1) == 1))) return 2;
|
||||
sstate->dcerpc.rpc_vers = *p;
|
||||
sstate->dcerpc.rpc_vers_minor = *(p + 1);
|
||||
sstate->dcerpc.type = *(p + 2);
|
||||
sstate->dcerpc.pfc_flags = *(p + 3);
|
||||
sstate->dcerpc.packed_drep[0] = *(p + 4);
|
||||
sstate->dcerpc.packed_drep[1] = *(p + 5);
|
||||
sstate->dcerpc.packed_drep[2] = *(p + 6);
|
||||
sstate->dcerpc.packed_drep[3] = *(p + 7);
|
||||
sstate->dcerpc.frag_length |= *(p + 8) << 8;
|
||||
sstate->dcerpc.frag_length |= *(p + 9);
|
||||
sstate->dcerpc.auth_length |= *(p + 10) << 8;
|
||||
sstate->dcerpc.auth_length |= *(p + 11);
|
||||
sstate->dcerpc.call_id |= *(p + 12) << 24;
|
||||
sstate->dcerpc.call_id |= *(p + 13) << 16;
|
||||
sstate->dcerpc.call_id |= *(p + 14) << 8;
|
||||
sstate->dcerpc.call_id |= *(p + 15);
|
||||
return 1;
|
||||
break;
|
||||
} else {
|
||||
sstate->dcerpc.rpc_vers = *(p++);
|
||||
if (sstate->dcerpc.rpc_vers != 5) return 2;
|
||||
if (!(--input_len)) break;
|
||||
}
|
||||
case 1:
|
||||
sstate->dcerpc.rpc_vers_minor = *(p++);
|
||||
if ((sstate->dcerpc.rpc_vers_minor != 0) ||
|
||||
(sstate->dcerpc.rpc_vers_minor != 1)) return 3;
|
||||
if (!(--input_len)) break;
|
||||
case 2:
|
||||
sstate->dcerpc.type = *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 3:
|
||||
sstate->dcerpc.pfc_flags = *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 4:
|
||||
sstate->dcerpc.packed_drep[0] = *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 5:
|
||||
sstate->dcerpc.packed_drep[1] = *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 6:
|
||||
sstate->dcerpc.packed_drep[2] = *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 7:
|
||||
sstate->dcerpc.packed_drep[3] = *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 8:
|
||||
sstate->dcerpc.frag_length |= *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 9:
|
||||
sstate->dcerpc.frag_length |= *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 10:
|
||||
sstate->dcerpc.auth_length |= *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 11:
|
||||
sstate->dcerpc.auth_length |= *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 12:
|
||||
sstate->dcerpc.call_id |= *(p++) << 24;
|
||||
if (!(--input_len)) break;
|
||||
case 13:
|
||||
sstate->dcerpc.call_id |= *(p++) << 16;
|
||||
if (!(--input_len)) break;
|
||||
case 14:
|
||||
sstate->dcerpc.call_id |= *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 15:
|
||||
sstate->dcerpc.call_id |= *(p++);
|
||||
--input_len;
|
||||
break;
|
||||
default: // SHOULD NEVER OCCUR
|
||||
printf("Odd\n");
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
sstate->bytesprocessed += (p - input);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DCERPCParse(void *dcerpc_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
|
||||
// DCERPCState *sstate = (DCERPCState *)dcerpc_state;
|
||||
uint16_t max_fields = 3;
|
||||
uint16_t u = 0;
|
||||
uint32_t offset = 0;
|
||||
|
||||
if (pstate == NULL)
|
||||
return -1;
|
||||
|
||||
for (u = pstate->parse_field; u < max_fields; u++) {
|
||||
printf("DCERPCParse: u %" PRIu32 "\n", u);
|
||||
switch(u) {
|
||||
case 0:
|
||||
{
|
||||
int r = AlpParseFieldBySize(output, pstate, DCERPC_PARSE_DCERPC_HEADER, DCERPC_HDR_LEN, input, input_len, &offset);
|
||||
|
||||
if (r == 0) {
|
||||
pstate->parse_field = 0;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pstate->parse_field = 0;
|
||||
pstate->flags |= APP_LAYER_PARSER_DONE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void *DCERPCStateAlloc(void) {
|
||||
void *s = malloc(sizeof(DCERPCState));
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(s, 0, sizeof(DCERPCState));
|
||||
return s;
|
||||
}
|
||||
|
||||
static void DCERPCStateFree(void *s) {
|
||||
if (s) {
|
||||
free(s);
|
||||
s = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterDCERPCParsers(void) {
|
||||
AppLayerRegisterProto("dcerpc", ALPROTO_DCERPC, STREAM_TOSERVER, DCERPCParse);
|
||||
AppLayerRegisterProto("dcerpc", ALPROTO_DCERPC, STREAM_TOCLIENT, DCERPCParse);
|
||||
AppLayerRegisterParser("dcerpc.hdr", ALPROTO_DCERPC, DCERPC_PARSE_DCERPC_HEADER, DCERPCParseHeader, "dcerpc");
|
||||
AppLayerRegisterStateFuncs(ALPROTO_DCERPC, DCERPCStateAlloc, DCERPCStateFree);
|
||||
}
|
||||
|
||||
/* UNITTESTS */
|
||||
#ifdef UNITTESTS
|
||||
|
||||
|
||||
int DCERPCParserTest01(void) {
|
||||
int result = 1;
|
||||
Flow f;
|
||||
uint8_t dcerpcbuf[] = "\x05\x00\x0b\x03\x10\x00\x00\x00\x48\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\xd0\x16\xd0\x16\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00"
|
||||
"\x01\x00\xb8\x4a\x9f\x4d\x1c\x7d\xcf\x11\x86\x1e\x00\x20\xaf\x6e\x7c\x57"
|
||||
"\x00\x00\x00\x00\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10"
|
||||
"\x48\x60\x02\x00\x00\x00";
|
||||
|
||||
uint32_t dcerpclen = sizeof(dcerpcbuf) - 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_DCERPC, STREAM_TOSERVER|STREAM_EOF, dcerpcbuf, dcerpclen, FALSE);
|
||||
if (r != 0) {
|
||||
printf("dcerpc header check returned %" PRId32 ", expected 0: ", r);
|
||||
result = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
DCERPCState *dcerpc_state = ssn.aldata[AlpGetStateIdx(ALPROTO_DCERPC)];
|
||||
if (dcerpc_state == NULL) {
|
||||
printf("no dcerpc state: ");
|
||||
result = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (dcerpc_state->dcerpc.rpc_vers != 5) {
|
||||
printf("expected dcerpc version 0x05, got 0x%02x : ",
|
||||
dcerpc_state->dcerpc.rpc_vers);
|
||||
result = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (dcerpc_state->dcerpc.type != BIND) {
|
||||
printf("expected dcerpc type 0x%02x , got 0x%02x : ", BIND, dcerpc_state->dcerpc.type);
|
||||
result = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
return result;
|
||||
}
|
||||
|
||||
void DCERPCParserRegisterTests(void) {
|
||||
printf("DCERPCParserRegisterTests\n");
|
||||
UtRegisterTest("DCERPCParserTest01", DCERPCParserTest01, 1);
|
||||
}
|
||||
#endif
|
||||
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Open Information Security Foundation
|
||||
* app-layer-dcerpc.h
|
||||
*
|
||||
* \author Kirby Kuehl <kkuehl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef APPLAYERDCERPC_H_
|
||||
#define APPLAYERDCERPC_H_
|
||||
#include "app-layer-protos.h"
|
||||
#include "app-layer-parser.h"
|
||||
#include "flow.h"
|
||||
|
||||
void RegisterDCERPCParsers(void);
|
||||
void DCERPCParserTests(void);
|
||||
void DCERPCParserRegisterTests(void);
|
||||
|
||||
// http://www.opengroup.org/onlinepubs/9629399/chap12.htm#tagcjh_17_06
|
||||
#define REQUEST 0
|
||||
#define PING 1
|
||||
#define RESPONSE 2
|
||||
#define FAULT 3
|
||||
#define WORKING 4
|
||||
#define NOCALL 5
|
||||
#define REJECT 6
|
||||
#define ACK 7
|
||||
#define CL_CANCEL 8
|
||||
#define FACK 9
|
||||
#define CANCEL_ACK 10
|
||||
#define BIND 11
|
||||
#define BIND_ACK 12
|
||||
#define BIND_NAK 13
|
||||
#define ALTER_CONTEXT 14
|
||||
#define ALTER_CONTEXT_RESP 15
|
||||
#define SHUTDOWN 17
|
||||
#define CO_CANCEL 18
|
||||
#define ORPHANED 19
|
||||
#if 0
|
||||
typedef struct {
|
||||
uint8_t rpc_vers; /* 4 RPC protocol major version (4 LSB only)*/
|
||||
uint8_t ptype; /* Packet type (5 LSB only) */
|
||||
uint8_t flags1; /* Packet flags */
|
||||
uint8_t flags2; /* Packet flags */
|
||||
uint8_t drep[3]; /* Data representation format label */
|
||||
uint8_t serial_hi; /* High byte of serial number */
|
||||
uuid_t object; /* Object identifier */
|
||||
uuid_t if_id; /* Interface identifier */
|
||||
uuid_t act_id; /* Activity identifier */
|
||||
unsigned long server_boot;/* Server boot time */
|
||||
unsigned long if_vers; /* Interface version */
|
||||
unsigned long seqnum; /* Sequence number */
|
||||
unsigned short opnum; /* Operation number */
|
||||
unsigned short ihint; /* Interface hint */
|
||||
unsigned short ahint; /* Activity hint */
|
||||
unsigned short len; /* Length of packet body */
|
||||
unsigned short fragnum; /* Fragment number */
|
||||
unsigned small auth_proto; /* Authentication protocol identifier*/
|
||||
unsigned small serial_lo; /* Low byte of serial number */
|
||||
} dc_rpc_cl_pkt_hdr_t;
|
||||
#endif
|
||||
|
||||
#define RESERVED_01 0x01
|
||||
#define LASTFRAG 0x02
|
||||
#define FRAG 0x04
|
||||
#define NOFACK 0x08
|
||||
#define MAYBE 0x10
|
||||
#define IDEMPOTENT 0x20
|
||||
#define BROADCAST 0x40
|
||||
#define RESERVED_80 0x80
|
||||
|
||||
#define CANCEL_PENDING 0x02
|
||||
#define RESERVED_04 0x04
|
||||
#define RESERVED_10 0x10
|
||||
#define RESERVED_20 0x20
|
||||
#define RESERVED_40 0x40
|
||||
#define RESERVED_80 0x80
|
||||
|
||||
typedef struct dcerpc_hdr_ {
|
||||
uint8_t rpc_vers; /* 00:01 RPC version should be 5 */
|
||||
uint8_t rpc_vers_minor; /* 01:01 minor version */
|
||||
uint8_t type; /* 02:01 packet type */
|
||||
uint8_t pfc_flags; /* 03:01 flags (see PFC_... ) */
|
||||
uint8_t packed_drep[4]; /* 04:04 NDR data representation format label */
|
||||
uint16_t frag_length; /* 08:02 total length of fragment */
|
||||
uint16_t auth_length; /* 10:02 length of auth_value */
|
||||
uint32_t call_id; /* 12:04 call identifier */
|
||||
}dcerpc_t;
|
||||
|
||||
#define DCERPC_HDR_LEN 16
|
||||
|
||||
typedef struct DCERPCState_ {
|
||||
dcerpc_t dcerpc;
|
||||
uint16_t bytesprocessed;
|
||||
}DCERPCState;
|
||||
|
||||
|
||||
#define PFC_FIRST_FRAG 0x01/* First fragment */
|
||||
#define PFC_LAST_FRAG 0x02/* Last fragment */
|
||||
#define PFC_PENDING_CANCEL 0x04/* Cancel was pending at sender */
|
||||
#define PFC_RESERVED_1 0x08
|
||||
#define PFC_CONC_MPX 0x10/* supports concurrent multiplexing
|
||||
* of a single connection. */
|
||||
#define PFC_DID_NOT_EXECUTE 0x20/* only meaningful on `fault' packet;
|
||||
* if true, guaranteed call did not
|
||||
* execute. */
|
||||
#define PFC_MAYBE 0x40/* `maybe' call semantics requested */
|
||||
#define PFC_OBJECT_UUID 0x80/* if true, a non-nil object UUID
|
||||
* was specified in the handle, and
|
||||
* is present in the optional object
|
||||
* field. If false, the object field
|
||||
* is omitted. */
|
||||
#define REASON_NOT_SPECIFIED 0
|
||||
#define TEMPORARY_CONGESTION 1
|
||||
#define LOCAL_LIMIT_EXCEEDED 2
|
||||
#define CALLED_PADDR_UNKNOWN 3 /* not used */
|
||||
#define PROTOCOL_VERSION_NOT_SUPPORTED 4
|
||||
#define DEFAULT_CONTEXT_NOT_SUPPORTED 5 /* not used */
|
||||
#define USER_DATA_NOT_READABLE 6 /* not used */
|
||||
#define NO_PSAP_AVAILABLE 7 /* not used */
|
||||
|
||||
#endif /* APPLAYERDCERPC_H_ */
|
||||
|
@ -0,0 +1,597 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Open Information Security Foundation
|
||||
* app-layer-smb.c
|
||||
*
|
||||
* \author Kirby Kuehl <kkuehl@gmail.com>
|
||||
*/
|
||||
#include "eidps-common.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "decode.h"
|
||||
#include "threads.h"
|
||||
|
||||
#include "util-print.h"
|
||||
#include "util-pool.h"
|
||||
|
||||
#include "stream-tcp-private.h"
|
||||
#include "stream-tcp-reassemble.h"
|
||||
#include "stream.h"
|
||||
|
||||
#include "app-layer-protos.h"
|
||||
#include "app-layer-parser.h"
|
||||
|
||||
#include "util-binsearch.h"
|
||||
#include "util-unittest.h"
|
||||
|
||||
#include "app-layer-smb.h"
|
||||
|
||||
enum {
|
||||
SMB_FIELD_NONE = 0,
|
||||
SMB_PARSE_NBSS_HEADER,
|
||||
SMB_PARSE_SMB_HEADER,
|
||||
SMB_PARSE_GET_WORDCOUNT,
|
||||
SMB_PARSE_WORDCOUNT,
|
||||
SMB_PARSE_GET_BYTECOUNT,
|
||||
SMB_PARSE_BYTECOUNT,
|
||||
/* must be last */
|
||||
SMB_FIELD_MAX,
|
||||
};
|
||||
|
||||
void hexdump(const void *buf, size_t len) {
|
||||
/* dumps len bytes of *buf to stdout. Looks like:
|
||||
* [0000] 75 6E 6B 6E 6F 77 6E 20
|
||||
* 30 FF 00 00 00 00 39 00 unknown 0.....9.
|
||||
* (in a single line of course)
|
||||
*/
|
||||
|
||||
const unsigned char *p = buf;
|
||||
unsigned char c;
|
||||
size_t n;
|
||||
char bytestr[4] = { 0 };
|
||||
char addrstr[10] = { 0 };
|
||||
char hexstr[16 * 3 + 5] = { 0 };
|
||||
char charstr[16 * 1 + 5] = { 0 };
|
||||
for (n = 1; n <= len; n++) {
|
||||
if (n % 16 == 1) {
|
||||
/* store address for this line */
|
||||
#if __WORDSIZE == 64
|
||||
snprintf(addrstr, sizeof(addrstr), "%.4lx",
|
||||
((uint64_t)p-(uint64_t)buf) );
|
||||
#else
|
||||
snprintf(addrstr, sizeof(addrstr), "%.4x", ((uint32_t) p
|
||||
- (uint32_t) buf));
|
||||
#endif
|
||||
}
|
||||
|
||||
c = *p;
|
||||
if (isalnum(c) == 0) {
|
||||
c = '.';
|
||||
}
|
||||
|
||||
/* store hex str (for left side) */
|
||||
snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
|
||||
strncat(hexstr, bytestr, sizeof(hexstr) - strlen(hexstr) - 1);
|
||||
|
||||
/* store char str (for right side) */
|
||||
snprintf(bytestr, sizeof(bytestr), "%c", c);
|
||||
strncat(charstr, bytestr, sizeof(charstr) - strlen(charstr) - 1);
|
||||
|
||||
if (n % 16 == 0) {
|
||||
/* line completed */
|
||||
printf("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
|
||||
hexstr[0] = 0;
|
||||
charstr[0] = 0;
|
||||
} else if (n % 8 == 0) {
|
||||
/* half line: add whitespaces */
|
||||
strncat(hexstr, " ", sizeof(hexstr) - strlen(hexstr) - 1);
|
||||
strncat(charstr, " ", sizeof(charstr) - strlen(charstr) - 1);
|
||||
}
|
||||
p++; /* next byte */
|
||||
}
|
||||
|
||||
if (strlen(hexstr) > 0) {
|
||||
/* print rest of buffer if not empty */
|
||||
printf("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
|
||||
}
|
||||
}
|
||||
|
||||
static int SMBParseAndX(void *smb_state, AppLayerParserState *pstate,
|
||||
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
|
||||
SMBState *sstate = (SMBState *) smb_state;
|
||||
uint8_t *p = input;
|
||||
switch (sstate->andx.andxbytesprocessed) {
|
||||
case 0:
|
||||
sstate->andx.andxcommand = *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 2:
|
||||
p++; // Reserved
|
||||
if (!(--input_len)) break;
|
||||
case 3:
|
||||
sstate->andx.andxoffset |= *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 4:
|
||||
sstate->andx.andxoffset |= *(p++);
|
||||
if (!(--input_len)) break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain SMB WordCount which is 2 times the value.
|
||||
* Reset bytecount.bytecountbytes to 0.
|
||||
* Determine if this is an SMB AndX Command
|
||||
*/
|
||||
static int SMBGetWordCount(void *smb_state, AppLayerParserState *pstate,
|
||||
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
|
||||
if (input_len) {
|
||||
SMBState *sstate = (SMBState *) smb_state;
|
||||
sstate->wordcount.wordcount = *(input) * 2;
|
||||
sstate->bytesprocessed++;
|
||||
sstate->bytecount.bytecountbytes = 0;
|
||||
sstate->andx.isandx = isAndX(sstate);
|
||||
printf("Wordcount (%u):\n", sstate->wordcount.wordcount);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain SMB Bytecount. Handle the corner obfuscation case where a packet boundary
|
||||
* is after the first bytecount byte.
|
||||
*/
|
||||
static int SMBGetByteCount(void *smb_state, AppLayerParserState *pstate,
|
||||
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
|
||||
if (input_len) {
|
||||
SMBState *sstate = (SMBState *) smb_state;
|
||||
uint8_t *p = input;
|
||||
switch(sstate->bytecount.bytecountbytes) {
|
||||
case 0:
|
||||
sstate->bytecount.bytecount = *(p++) << 8;
|
||||
sstate->bytecount.bytecountbytes++;
|
||||
if (!(--input_len)) break;
|
||||
case 1:
|
||||
sstate->bytecount.bytecount |= *(p++);
|
||||
sstate->bytecount.bytecountbytes++;
|
||||
printf("Bytecount %u\n", sstate->bytecount.bytecount);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
sstate->bytesprocessed += (p - input);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SMBParseWordCount(void *smb_state, AppLayerParserState *pstate,
|
||||
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
|
||||
SMBState *sstate = (SMBState *) smb_state;
|
||||
uint8_t *p = input;
|
||||
while (sstate->wordcount.wordcount-- && input_len--) {
|
||||
if (sstate->andx.isandx) {
|
||||
SMBParseAndX(smb_state, pstate, input, input_len, output);
|
||||
}
|
||||
printf("0x%02x\n", *(p++));
|
||||
}
|
||||
sstate->bytesprocessed += (p - input);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SMBParseByteCount(void *smb_state, AppLayerParserState *pstate,
|
||||
uint8_t *input, uint32_t input_len, AppLayerParserResult *output) {
|
||||
SMBState *sstate = (SMBState *) smb_state;
|
||||
uint8_t *p = input;
|
||||
while (sstate->bytecount.bytecount-- && input_len--) {
|
||||
printf("0x%02x\n", *(p++));
|
||||
}
|
||||
sstate->bytesprocessed += (p - input);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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) {
|
||||
switch (sstate->bytesprocessed) {
|
||||
case 0:
|
||||
if (input_len >= NBSS_HDR_LEN) {
|
||||
sstate->nbss.type = *p;
|
||||
sstate->nbss.length = (*(p + 1) & 0x01) << 16;
|
||||
sstate->nbss.length |= *(p + 2) << 8;
|
||||
sstate->nbss.length |= *(p + 3);
|
||||
input_len -= NBSS_HDR_LEN;
|
||||
sstate->bytesprocessed += NBSS_HDR_LEN;
|
||||
return 0;
|
||||
} else {
|
||||
sstate->nbss.type = *(p++);
|
||||
if (!(--input_len)) break;
|
||||
}
|
||||
case 1:
|
||||
sstate->nbss.length = (*(p++) & 0x01) << 16;
|
||||
if (!(--input_len)) break;
|
||||
case 2:
|
||||
sstate->nbss.length |= *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 3:
|
||||
sstate->nbss.length |= *(p++);
|
||||
--input_len;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
sstate->bytesprocessed += (p - input);
|
||||
}
|
||||
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) {
|
||||
switch (sstate->bytesprocessed) {
|
||||
case 4:
|
||||
if (input_len >= SMB_HDR_LEN) {
|
||||
//if (sstate->nbss.type != NBSS_SESSION_MESSAGE) return 1;
|
||||
//if (sstate->nbss.length < MINIMUM_SMB_LEN) return 2;
|
||||
if (memcmp(p, "\xff\x53\x4d\x42", 4) != 0) {
|
||||
printf("SMB Header did not validate\n");
|
||||
return 3;
|
||||
}
|
||||
sstate->smb.command = *(p + 4);
|
||||
sstate->smb.status = *(p + 5) << 24;
|
||||
sstate->smb.status |= *(p + 6) << 16;
|
||||
sstate->smb.status |= *(p + 7) << 8;
|
||||
sstate->smb.status |= *(p + 8);
|
||||
sstate->smb.flags = *(p + 9);
|
||||
sstate->smb.flags2 = *(p + 10) << 8;
|
||||
sstate->smb.flags2 |= *(p + 11);
|
||||
sstate->smb.pidhigh = *(p + 12) << 8;
|
||||
sstate->smb.pidhigh |= *(p + 13);
|
||||
sstate->smb.securitysignature = (uint64_t) *(p + 14) << 56;
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p + 15) << 48;
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p + 16) << 40;
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p + 17) << 32;
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p + 18) << 24;
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p + 19) << 16;
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p + 20) << 8;
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p + 21);
|
||||
sstate->smb.tid = *(p + 24) << 8;
|
||||
sstate->smb.tid |= *(p + 25);
|
||||
sstate->smb.pid = *(p + 26) << 8;
|
||||
sstate->smb.pid |= *(p + 27);
|
||||
sstate->smb.uid = *(p + 28) << 8;
|
||||
sstate->smb.uid |= *(p + 29);
|
||||
sstate->smb.mid = *(p + 30) << 8;
|
||||
sstate->smb.mid |= *(p + 31);
|
||||
input_len -= (SMB_HDR_LEN + 1);
|
||||
sstate->bytesprocessed += (SMB_HDR_LEN + 1);
|
||||
return 1;
|
||||
break;
|
||||
} else {
|
||||
//sstate->smb.protocol[0] = *(p++);
|
||||
if (*(p++) != 0xff)
|
||||
return 4;
|
||||
if (!(--input_len)) break;
|
||||
}
|
||||
case 5:
|
||||
//sstate->smb.protocol[1] = *(p++);
|
||||
if (*(p++) != 'S')
|
||||
return 5;
|
||||
if (!(--input_len)) break;
|
||||
case 6:
|
||||
//sstate->smb.protocol[2] = *(p++);
|
||||
if (*(p++) != 'M')
|
||||
return 6;
|
||||
if (!(--input_len)) break;
|
||||
case 7:
|
||||
//sstate->smb.protocol[3] = *(p++);
|
||||
if (*(p++) != 'B')
|
||||
return 7;
|
||||
if (!(--input_len)) break;
|
||||
case 8:
|
||||
sstate->smb.command = *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 9:
|
||||
sstate->smb.status = *(p++) << 24;
|
||||
if (!(--input_len)) break;
|
||||
case 10:
|
||||
sstate->smb.status |= *(p++) << 16;
|
||||
if (!(--input_len)) break;
|
||||
case 11:
|
||||
sstate->smb.status |= *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 12:
|
||||
sstate->smb.status |= *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 13:
|
||||
sstate->smb.flags = *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 14:
|
||||
sstate->smb.flags2 = *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 15:
|
||||
sstate->smb.flags2 |= *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 16:
|
||||
sstate->smb.pidhigh = *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 17:
|
||||
sstate->smb.pidhigh |= *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 18:
|
||||
sstate->smb.securitysignature = (uint64_t) *(p++) << 56;
|
||||
if (!(--input_len)) break;
|
||||
case 19:
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p++) << 48;
|
||||
if (!(--input_len)) break;
|
||||
case 20:
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p++) << 40;
|
||||
if (!(--input_len)) break;
|
||||
case 21:
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p++) << 32;
|
||||
if (!(--input_len)) break;
|
||||
case 22:
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p++) << 24;
|
||||
if (!(--input_len)) break;
|
||||
case 23:
|
||||
sstate->smb.securitysignature |=(uint64_t) *(p++) << 16;
|
||||
if (!(--input_len)) break;
|
||||
case 24:
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 25:
|
||||
sstate->smb.securitysignature |= (uint64_t) *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 26:
|
||||
p++; // UNUSED
|
||||
if (!(--input_len)) break;
|
||||
case 27:
|
||||
p++; // UNUSED
|
||||
if (!(--input_len)) break;
|
||||
case 28:
|
||||
sstate->smb.tid = *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 29:
|
||||
sstate->smb.tid |= *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 30:
|
||||
sstate->smb.pid = *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 31:
|
||||
sstate->smb.pid |= *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 32:
|
||||
sstate->smb.uid = *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 33:
|
||||
sstate->smb.uid |= *(p++);
|
||||
if (!(--input_len)) break;
|
||||
case 34:
|
||||
sstate->smb.mid = *(p++) << 8;
|
||||
if (!(--input_len)) break;
|
||||
case 35:
|
||||
sstate->smb.mid |= *(p++);
|
||||
--input_len;
|
||||
break;
|
||||
default: // SHOULD NEVER OCCUR
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
if (pstate == NULL)
|
||||
return -1;
|
||||
|
||||
for (u = pstate->parse_field; u < max_fields; u++) {
|
||||
printf("SMBParse: u %" PRIu32 "\n", u);
|
||||
switch (u) {
|
||||
case 0: {
|
||||
int r = AlpParseFieldBySize(output, pstate, SMB_PARSE_NBSS_HEADER,
|
||||
NBSS_HDR_LEN, input, input_len, &offset);
|
||||
|
||||
if (r == 0) {
|
||||
pstate->parse_field = 0;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
uint8_t *data = input + offset;
|
||||
uint32_t data_len = input_len - offset;
|
||||
if (sstate->nbss.type == NBSS_SESSION_MESSAGE) {
|
||||
int r = AlpParseFieldBySize(output, pstate, SMB_PARSE_SMB_HEADER,
|
||||
SMB_HDR_LEN, data, data_len, &offset);
|
||||
if (r == 0) {
|
||||
pstate->parse_field = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
uint8_t *data = input + offset;
|
||||
uint32_t data_len = input_len - offset;
|
||||
int r = AlpParseFieldBySize(output, pstate, SMB_PARSE_GET_WORDCOUNT,
|
||||
1, data, data_len, &offset);
|
||||
if (r == 0) {
|
||||
pstate->parse_field = 2;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
uint8_t *data = input + offset;
|
||||
uint32_t data_len = input_len - offset;
|
||||
printf("wordcount %d\n", sstate->wordcount.wordcount);
|
||||
|
||||
int r = AlpParseFieldBySize(output, pstate, SMB_PARSE_WORDCOUNT,
|
||||
sstate->wordcount.wordcount, data, data_len, &offset);
|
||||
if (r == 0) {
|
||||
pstate->parse_field = 3;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
uint8_t *data = input + offset;
|
||||
uint32_t data_len = input_len - offset;
|
||||
|
||||
int r = AlpParseFieldBySize(output, pstate, SMB_PARSE_GET_BYTECOUNT,
|
||||
2, data, data_len, &offset);
|
||||
if (r == 0) {
|
||||
pstate->parse_field = 4;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
uint8_t *data = input + offset;
|
||||
uint32_t data_len = input_len - offset;
|
||||
|
||||
int r = AlpParseFieldBySize(output, pstate, SMB_PARSE_BYTECOUNT,
|
||||
sstate->bytecount.bytecount, data, data_len, &offset);
|
||||
if (r == 0) {
|
||||
pstate->parse_field = 5;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pstate->parse_field = 0;
|
||||
pstate->flags |= APP_LAYER_PARSER_DONE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int isAndX(SMBState *smb_state) {
|
||||
switch (smb_state->smb.command) {
|
||||
case SMB_NO_SECONDARY_ANDX_COMMAND:
|
||||
case SMB_COM_LOCKING_ANDX:
|
||||
case SMB_COM_OPEN_ANDX:
|
||||
case SMB_COM_READ_ANDX:
|
||||
case SMB_COM_WRITE_ANDX:
|
||||
case SMB_COM_SESSION_SETUP_ANDX:
|
||||
case SMB_COM_LOGOFF_ANDX:
|
||||
case SMB_COM_TREE_CONNECT_ANDX:
|
||||
case SMB_COM_NT_CREATE_ANDX:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void *SMBStateAlloc(void) {
|
||||
void *s = malloc(sizeof(SMBState));
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(s, 0, sizeof(SMBState));
|
||||
return s;
|
||||
}
|
||||
|
||||
static void SMBStateFree(void *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,
|
||||
NBSSParseHeader, "smb");
|
||||
AppLayerRegisterParser("smb.hdr", ALPROTO_SMB, SMB_PARSE_SMB_HEADER,
|
||||
SMBParseHeader, "smb");
|
||||
AppLayerRegisterParser("smb.getwordcount", ALPROTO_SMB, SMB_PARSE_GET_WORDCOUNT,
|
||||
SMBGetWordCount, "smb");
|
||||
AppLayerRegisterParser("smb.wordcount", ALPROTO_SMB, SMB_PARSE_WORDCOUNT,
|
||||
SMBParseWordCount, "smb");
|
||||
AppLayerRegisterParser("smb.getbytecount", ALPROTO_SMB, SMB_PARSE_GET_BYTECOUNT,
|
||||
SMBGetByteCount, "smb");
|
||||
AppLayerRegisterParser("smb.bytecount", ALPROTO_SMB, SMB_PARSE_BYTECOUNT,
|
||||
SMBParseByteCount, "smb");
|
||||
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) {
|
||||
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) {
|
||||
printf("no smb state: ");
|
||||
result = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
printf("expected SMB command 0x%02x , got 0x%02x : ", SMB_COM_NEGOTIATE, smb_state->smb.command);
|
||||
result = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
return result;
|
||||
}
|
||||
|
||||
void SMBParserRegisterTests(void) {
|
||||
printf("SMBParserRegisterTests\n");
|
||||
UtRegisterTest("SMBParserTest01", SMBParserTest01, 1);
|
||||
}
|
||||
#endif
|
||||
|
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Open Information Security Foundation
|
||||
* app-layer-smb.h
|
||||
*
|
||||
* \author Kirby Kuehl <kkuehl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef APPLAYERSMB_H_
|
||||
#define APPLAYERSMB_H_
|
||||
#include "app-layer-protos.h"
|
||||
#include "app-layer-parser.h"
|
||||
#include "flow.h"
|
||||
#include "stream.h"
|
||||
#include <stdint.h>
|
||||
/*
|
||||
http://ubiqx.org/cifs/rfc-draft/rfc1002.html#s4.3
|
||||
All session packets are of the following general structure:
|
||||
|
||||
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| TYPE | FLAGS | LENGTH |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
/ TRAILER (Packet Type Dependent) /
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
The TYPE, FLAGS, and LENGTH fields are present in every session
|
||||
packet.
|
||||
*/
|
||||
#define NBSS_SESSION_MESSAGE 0x00
|
||||
#define NBSS_SESSION_REQUEST 0x81
|
||||
#define NBSS_POSITIVE_SESSION_RESPONSE 0x82
|
||||
#define NBSS_NEGATIVE_SESSION_RESPONSE 0x83
|
||||
#define NBSS_RETARGET_SESSION_RESPONSE 0x84
|
||||
#define NBSS_SESSION_KEEP_ALIVE 0x85
|
||||
|
||||
typedef struct nbss_hdr_ {
|
||||
uint8_t type;
|
||||
uint8_t flags;
|
||||
uint32_t length;
|
||||
}nbss_hdr_t, *pnbss_hdr_t;
|
||||
#define NBSS_HDR_LEN 4
|
||||
|
||||
typedef struct smb_hdr_ {
|
||||
uint8_t protocol[4];
|
||||
uint8_t command;
|
||||
uint32_t status;
|
||||
uint8_t flags;
|
||||
uint16_t flags2;
|
||||
uint16_t pidhigh;
|
||||
uint64_t securitysignature;
|
||||
uint16_t unused;
|
||||
uint16_t tid;
|
||||
uint16_t pid;
|
||||
uint16_t uid;
|
||||
uint16_t mid;
|
||||
}smb_hdr_t, *psmb_hdr_t;
|
||||
#define SMB_HDR_LEN 32
|
||||
#define MINIMUM_SMB_LEN 35
|
||||
#define NBSS_SMB_HDRS_LEN 36
|
||||
|
||||
typedef struct wordcount_ {
|
||||
uint8_t wordcount;
|
||||
uint8_t *words;
|
||||
}wordcount_t, *pwordcount_t;
|
||||
|
||||
typedef struct bytecount_ {
|
||||
uint8_t bytecountbytes;
|
||||
uint16_t bytecount;
|
||||
uint8_t *bytes;
|
||||
}bytecount_t, *pbytyecount_t;
|
||||
|
||||
typedef struct andxcount_ {
|
||||
uint8_t isandx;
|
||||
uint8_t andxcommand;
|
||||
uint16_t andxoffset;
|
||||
uint16_t andxbytesprocessed;
|
||||
}andx_t, *pandx_t;
|
||||
|
||||
typedef struct SMBState_ {
|
||||
nbss_hdr_t nbss;
|
||||
smb_hdr_t smb;
|
||||
wordcount_t wordcount;
|
||||
bytecount_t bytecount;
|
||||
andx_t andx;
|
||||
uint16_t bytesprocessed;
|
||||
}SMBState;
|
||||
|
||||
#define SMB_FLAGS_SERVER_TO_REDIR 0x80
|
||||
#define SMB_NO_SECONDARY_ANDX_COMMAND 0xff
|
||||
|
||||
/* http://msdn.microsoft.com/en-us/library/dd327674.aspx */
|
||||
#define SMB_COM_CREATE_DIRECTORY 0x00
|
||||
#define SMB_COM_DELETE_DIRECTORY 0x01
|
||||
#define SMB_COM_OPEN 0x02
|
||||
#define SMB_COM_CREATE 0x03
|
||||
#define SMB_COM_CLOSE 0x04
|
||||
#define SMB_COM_FLUSH 0x05
|
||||
#define SMB_COM_DELETE 0x06
|
||||
#define SMB_COM_RENAME 0x07
|
||||
#define SMB_COM_QUERY_INFORMATION 0x08
|
||||
#define SMB_COM_SET_INFORMATION 0x09
|
||||
#define SMB_COM_READ 0x0A
|
||||
#define SMB_COM_WRITE 0x0B
|
||||
#define SMB_COM_LOCK_BYTE_RANGE 0x0C
|
||||
#define SMB_COM_UNLOCK_BYTE_RANGE 0x0D
|
||||
#define SMB_COM_CREATE_TEMPORARY 0x0E
|
||||
#define SMB_COM_CREATE_NEW 0x0F
|
||||
#define SMB_COM_CHECK_DIRECTORY 0x10
|
||||
#define SMB_COM_PROCESS_EXIT 0x11
|
||||
#define SMB_COM_SEEK 0x12
|
||||
#define SMB_COM_LOCK_AND_READ 0x13
|
||||
#define SMB_COM_WRITE_AND_UNLOCK 0x14
|
||||
#define SMB_COM_READ_RAW 0x1A
|
||||
#define SMB_COM_READ_MPX 0x1B
|
||||
#define SMB_COM_READ_MPX_SECONDARY 0x1C
|
||||
#define SMB_COM_WRITE_RAW 0x1D
|
||||
#define SMB_COM_WRITE_MPX 0x1E
|
||||
#define SMB_COM_WRITE_COMPLETE 0x20
|
||||
#define SMB_COM_SET_INFORMATION2 0x22
|
||||
#define SMB_COM_QUERY_INFORMATION2 0x23
|
||||
#define SMB_COM_LOCKING_ANDX 0x24
|
||||
#define SMB_COM_TRANSACTION 0x25
|
||||
#define SMB_COM_TRANSACTION_SECONDARY 0x26
|
||||
#define SMB_COM_IOCTL 0x27
|
||||
#define SMB_COM_IOCTL_SECONDARY 0x28
|
||||
#define SMB_COM_COPY 0x29
|
||||
#define SMB_COM_MOVE 0x2A
|
||||
#define SMB_COM_ECHO 0x2B
|
||||
#define SMB_COM_WRITE_AND_CLOSE 0x2C
|
||||
#define SMB_COM_OPEN_ANDX 0x2D
|
||||
#define SMB_COM_READ_ANDX 0x2E
|
||||
#define SMB_COM_WRITE_ANDX 0x2F
|
||||
#define SMB_COM_CLOSE_AND_TREE_DISC 0x31
|
||||
#define SMB_COM_TRANSACTION2 0x32
|
||||
#define SMB_COM_TRANSACTION2_SECONDARY 0x33
|
||||
#define SMB_COM_FIND_CLOSE2 0x34
|
||||
#define SMB_COM_FIND_NOTIFY_CLOSE 0x35
|
||||
#define SMB_COM_TREE_CONNECT 0x70
|
||||
#define SMB_COM_TREE_DISCONNECT 0x71
|
||||
#define SMB_COM_NEGOTIATE 0x72
|
||||
#define SMB_COM_SESSION_SETUP_ANDX 0x73
|
||||
#define SMB_COM_LOGOFF_ANDX 0x74
|
||||
#define SMB_COM_TREE_CONNECT_ANDX 0x75
|
||||
#define SMB_COM_QUERY_INFORMATION_DISK 0x80
|
||||
#define SMB_COM_SEARCH 0x81
|
||||
#define SMB_COM_FIND 0x82
|
||||
#define SMB_COM_FIND_UNIQUE 0x83
|
||||
#define SMB_COM_NT_TRANSACT 0xA0
|
||||
#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
|
||||
#define SMB_COM_NT_CREATE_ANDX 0xA2
|
||||
#define SMB_COM_NT_CANCEL 0xA4
|
||||
#define SMB_COM_NT_RENAME 0xA5
|
||||
#define SMB_COM_OPEN_PRINT_FILE 0xC0
|
||||
#define SMB_COM_WRITE_PRINT_FILE 0xC1
|
||||
#define SMB_COM_CLOSE_PRINT_FILE 0xC2
|
||||
#define SMB_COM_GET_PRINT_QUEUE 0xC3
|
||||
|
||||
void RegisterSMBParsers(void);
|
||||
void SMBParserRegisterTests(void);
|
||||
int isAndX(SMBState *smb_state);
|
||||
|
||||
|
||||
#endif /* APPLAYERSMB_H_ */
|
Loading…
Reference in New Issue