1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
/* smb_parser.c
*
* This file contains functions to parse SMB (version 2 and 3) headers.
*
* File begun on 2018-11-13
*
* Created by:
* - Théo Bertin (theo.bertin@advens.fr)
*
* With:
* - François Bernard (francois.bernard@isen.yncrea.fr)
* - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
*
* This file is part of rsyslog.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config.h"
#include "parsers.h"
/* SMB2 opCodes */
#define SMB2_NEGOTIATE 0x00
#define SMB2_SESSIONSET 0x01
#define SMB2_SESSIONLOGOFF 0x02
#define SMB2_TREECONNECT 0x03
#define SMB2_TREEDISCONNECT 0x04
#define SMB2_CREATE 0x05
#define SMB2_CLOSE 0x06
#define SMB2_FLUSH 0x07
#define SMB2_READ 0x08
#define SMB2_WRITE 0x09
#define SMB2_LOCK 0x0a
#define SMB2_IOCTL 0x0b
#define SMB2_CANCEL 0x0c
#define SMB2_KEEPALIVE 0x0d
#define SMB2_FIND 0x0e
#define SMB2_NOTIFY 0x0f
#define SMB2_GETINFO 0x10
#define SMB2_SETINFO 0x11
#define SMB2_BREAK 0x12
struct smb_header_s {
uint32_t version;
uint16_t headerLength;
uint16_t padding1;
uint32_t ntStatus;
uint16_t opCode;
uint16_t padding2;
uint32_t flags;
uint32_t chainOffset;
uint32_t comSeqNumber[2];
uint32_t processID;
uint32_t treeID;
uint32_t userID[2];
uint32_t signature[4];
};
typedef struct smb_header_s smb_header_t;
static char flagCodes[5] = "RPCS";
/*
* This function parses the bytes in the received packet to extract SMB2 metadata.
*
* its parameters are:
* - a pointer on the list of bytes representing the packet
* the beginning of the header will be checked by the function
* - the size of the list passed as first parameter
* - a pointer on a json_object, containing all the metadata recovered so far
* this is also where SMB2 metadata will be added
*
* This function returns a structure containing the data unprocessed by this parser
* or the ones after (as a list of bytes), and the length of this data.
*/
data_ret_t *smb_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
DBGPRINTF("smb_parse\n");
DBGPRINTF("packet size %d\n", pktSize);
int pktSizeCpy = pktSize;
const uchar *packetCpy = packet;
while (pktSizeCpy > 0) {
/* don't check packetCpy[0] to include SMB version byte at the beginning */
if (packetCpy[1] == 'S') {
if (packetCpy[2] == 'M') {
if (packetCpy[3] == 'B') {
break;
}
}
}
packetCpy++, pktSizeCpy--;
}
if ((int)pktSizeCpy < 64) {
DBGPRINTF("SMB packet too small : %d\n", pktSizeCpy);
RETURN_DATA_AFTER(0)
}
/* Union to prevent cast from uchar to smb_header_t */
union {
const uchar *pck;
smb_header_t *hdr;
} smb_header_to_char;
smb_header_to_char.pck = packetCpy;
smb_header_t *smb_header = smb_header_to_char.hdr;
char flags[5] = {0};
uint64_t seqNum, userID;
uint8_t version;
version = (smb_header->version == 0xFF) ? 1 : 2;
seqNum = smb_header->comSeqNumber[0] | smb_header->comSeqNumber[1] << 16;
userID = smb_header->userID[0] | smb_header->userID[1] << 16;
uint8_t i, pos = 0;
for (i = 0; i < 4; ++i) {
if (smb_header->flags & (0x01 << i))
flags[pos++] = flagCodes[i];
}
json_object_object_add(jparent, "SMB_version", json_object_new_int(version));
json_object_object_add(jparent, "SMB_NTstatus", json_object_new_int64(smb_header->ntStatus));
json_object_object_add(jparent, "SMB_operation", json_object_new_int(smb_header->opCode));
json_object_object_add(jparent, "SMB_flags", json_object_new_string(flags));
json_object_object_add(jparent, "SMB_seqNumber", json_object_new_int64(seqNum));
json_object_object_add(jparent, "SMB_processID", json_object_new_int64(smb_header->processID));
json_object_object_add(jparent, "SMB_treeID", json_object_new_int64(smb_header->treeID));
json_object_object_add(jparent, "SMB_userID", json_object_new_int64(userID));
RETURN_DATA_AFTER(0)
}
|