2 * Routines for ETW Dissection
4 * Copyright 2020, Odysseus Yang
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 /* Dissector based on ETW Trace
14 * https://docs.microsoft.com/en-us/windows/win32/etw/event-tracing-portal
19 #include <epan/packet.h>
20 #include <wiretap/wtap.h>
22 void proto_register_etw(void);
23 void proto_reg_handoff_etw(void);
25 static dissector_handle_t etw_handle
;
28 static int hf_etw_size
;
29 static int hf_etw_header_type
;
30 static int hf_etw_header_flag_extended_info
;
31 static int hf_etw_header_flag_private_session
;
32 static int hf_etw_header_flag_string_only
;
33 static int hf_etw_header_flag_trace_message
;
34 static int hf_etw_header_flag_no_cputime
;
35 static int hf_etw_header_flag_32_bit_header
;
36 static int hf_etw_header_flag_64_bit_header
;
37 static int hf_etw_header_flag_decode_guid
;
38 static int hf_etw_header_flag_classic_header
;
39 static int hf_etw_header_flag_processor_index
;
40 static int hf_etw_flags
;
41 static int hf_etw_event_property
;
42 static int hf_etw_event_property_xml
;
43 static int hf_etw_event_property_forwarded_xml
;
44 static int hf_etw_event_property_legacy_eventlog
;
45 static int hf_etw_event_property_legacy_reloggable
;
46 static int hf_etw_thread_id
;
47 static int hf_etw_process_id
;
48 static int hf_etw_time_stamp
;
49 static int hf_etw_provider_id
;
50 static int hf_etw_buffer_context_processor_number
;
51 static int hf_etw_buffer_context_alignment
;
52 static int hf_etw_buffer_context_logger_id
;
53 static int hf_etw_message_length
;
54 static int hf_etw_provider_name_length
;
55 static int hf_etw_provider_name
;
56 static int hf_etw_message
;
57 static int hf_etw_user_data_length
;
58 static int hf_etw_descriptor_id
;
59 static int hf_etw_descriptor_version
;
60 static int hf_etw_descriptor_channel
;
61 static int hf_etw_descriptor_level
;
62 static int hf_etw_descriptor_opcode
;
63 static int hf_etw_descriptor_task
;
64 static int hf_etw_descriptor_keywords
;
65 static int hf_etw_processor_time
;
66 static int hf_etw_activity_id
;
68 static int ett_etw_header
;
69 static int ett_etw_descriptor
;
70 static int ett_etw_buffer_context
;
71 static int ett_etw_header_flags
;
72 static int ett_etw_event_property_types
;
74 static dissector_handle_t mbim_dissector
;
76 static e_guid_t mbim_net_providerid
= { 0xA42FE227, 0xA7BF, 0x4483, {0xA5, 0x02, 0x6B, 0xCD, 0xA4, 0x28, 0xCD, 0x96} };
78 #define ROUND_UP_COUNT(Count,Pow2) \
79 ( ((Count)+(Pow2)-1) & (~(((int)(Pow2))-1)) )
80 #define ETW_HEADER_SIZE 0x60
82 static int etw_counter
;
85 dissect_etw(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree _U_
, void* data _U_
)
87 proto_tree
* etw_header
, * etw_descriptor
, * etw_buffer_context
;
89 uint32_t message_offset
, message_length
, provider_name_offset
, provider_name_length
, user_data_offset
, user_data_length
;
92 static int * const etw_header_flags
[] = {
93 &hf_etw_header_flag_extended_info
,
94 &hf_etw_header_flag_private_session
,
95 &hf_etw_header_flag_string_only
,
96 &hf_etw_header_flag_trace_message
,
97 &hf_etw_header_flag_no_cputime
,
98 &hf_etw_header_flag_32_bit_header
,
99 &hf_etw_header_flag_64_bit_header
,
100 &hf_etw_header_flag_decode_guid
,
101 &hf_etw_header_flag_classic_header
,
102 &hf_etw_header_flag_processor_index
,
106 static int * const etw_event_property_opt
[] = {
107 &hf_etw_event_property_xml
,
108 &hf_etw_event_property_forwarded_xml
,
109 &hf_etw_event_property_legacy_eventlog
,
110 &hf_etw_event_property_legacy_reloggable
,
114 etw_header
= proto_tree_add_subtree(tree
, tvb
, 0, ETW_HEADER_SIZE
, ett_etw_header
, NULL
, "ETW Header");
115 proto_tree_add_item(etw_header
, hf_etw_size
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
117 proto_tree_add_item(etw_header
, hf_etw_header_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
119 proto_tree_add_bitmask(etw_header
, tvb
, offset
, hf_etw_flags
,
120 ett_etw_header_flags
, etw_header_flags
, ENC_LITTLE_ENDIAN
);
122 proto_tree_add_bitmask(etw_header
, tvb
, offset
, hf_etw_event_property
,
123 ett_etw_event_property_types
, etw_event_property_opt
, ENC_LITTLE_ENDIAN
);
125 proto_tree_add_item(etw_header
, hf_etw_thread_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
127 proto_tree_add_item(etw_header
, hf_etw_process_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
129 proto_tree_add_item(etw_header
, hf_etw_time_stamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
131 tvb_get_letohguid(tvb
, offset
, &provider_id
);
132 proto_tree_add_item(etw_header
, hf_etw_provider_id
, tvb
, offset
, 16, ENC_LITTLE_ENDIAN
);
135 etw_descriptor
= proto_tree_add_subtree(etw_header
, tvb
, 40, 16, ett_etw_descriptor
, NULL
, "Descriptor");
136 proto_tree_add_item(etw_descriptor
, hf_etw_descriptor_id
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
138 proto_tree_add_item(etw_descriptor
, hf_etw_descriptor_version
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
140 proto_tree_add_item(etw_descriptor
, hf_etw_descriptor_channel
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
142 proto_tree_add_item(etw_descriptor
, hf_etw_descriptor_level
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
144 proto_tree_add_item(etw_descriptor
, hf_etw_descriptor_opcode
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
146 proto_tree_add_item(etw_descriptor
, hf_etw_descriptor_task
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
148 proto_tree_add_item(etw_descriptor
, hf_etw_descriptor_keywords
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
151 proto_tree_add_item(etw_header
, hf_etw_processor_time
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
153 proto_tree_add_item(etw_header
, hf_etw_activity_id
, tvb
, offset
, 16, ENC_LITTLE_ENDIAN
);
156 etw_buffer_context
= proto_tree_add_subtree(etw_header
, tvb
, 80, 4, ett_etw_descriptor
, NULL
, "Buffer Context");
157 proto_tree_add_item(etw_buffer_context
, hf_etw_buffer_context_processor_number
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
159 proto_tree_add_item(etw_buffer_context
, hf_etw_buffer_context_alignment
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
161 proto_tree_add_item(etw_buffer_context
, hf_etw_buffer_context_logger_id
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
163 proto_tree_add_item_ret_uint(etw_header
, hf_etw_user_data_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &user_data_length
);
165 proto_tree_add_item_ret_uint(etw_header
, hf_etw_message_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &message_length
);
167 proto_tree_add_item_ret_uint(etw_header
, hf_etw_provider_name_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &provider_name_length
);
169 user_data_offset
= offset
;
170 message_offset
= user_data_offset
+ ROUND_UP_COUNT(user_data_length
, sizeof(int32_t));
171 if (message_length
) {
172 proto_tree_add_item(etw_header
, hf_etw_message
, tvb
, message_offset
, message_length
, ENC_LITTLE_ENDIAN
| ENC_UTF_16
);
174 provider_name_offset
= message_offset
+ ROUND_UP_COUNT(message_length
, sizeof(int32_t));
175 if (provider_name_length
) {
176 proto_tree_add_item(etw_header
, hf_etw_provider_name
, tvb
, provider_name_offset
, provider_name_length
, ENC_LITTLE_ENDIAN
| ENC_UTF_16
);
179 col_set_str(pinfo
->cinfo
, COL_DEF_SRC
, "windows");
180 col_set_str(pinfo
->cinfo
, COL_DEF_DST
, "windows");
181 if (memcmp(&mbim_net_providerid
, &provider_id
, sizeof(e_guid_t
)) == 0) {
184 if (WTAP_OPTTYPE_SUCCESS
== wtap_block_get_uint32_option_value(pinfo
->rec
->block
, OPT_PKT_FLAGS
, &pack_flags
)) {
185 switch(PACK_FLAGS_DIRECTION(pack_flags
)) {
186 case PACK_FLAGS_DIRECTION_INBOUND
:
187 col_set_str(pinfo
->cinfo
, COL_DEF_SRC
, "device");
188 col_set_str(pinfo
->cinfo
, COL_DEF_DST
, "host");
190 case PACK_FLAGS_DIRECTION_OUTBOUND
:
191 col_set_str(pinfo
->cinfo
, COL_DEF_SRC
, "host");
192 col_set_str(pinfo
->cinfo
, COL_DEF_DST
, "device");
196 mbim_tvb
= tvb_new_subset_remaining(tvb
, user_data_offset
);
197 call_dissector_only(mbim_dissector
, mbim_tvb
, pinfo
, tree
, data
);
199 else if (message_length
){
200 char* message
= (char*)tvb_get_string_enc(pinfo
->pool
, tvb
, message_offset
, message_length
, ENC_LITTLE_ENDIAN
| ENC_UTF_16
);
201 col_set_str(pinfo
->cinfo
, COL_INFO
, message
);
202 if (provider_name_offset
) {
203 char* provider_name
= (char*)tvb_get_string_enc(pinfo
->pool
, tvb
, provider_name_offset
, provider_name_length
, ENC_LITTLE_ENDIAN
| ENC_UTF_16
);
204 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, provider_name
);
207 col_set_str(pinfo
->cinfo
, COL_INFO
, guids_resolve_guid_to_str(&provider_id
, pinfo
->pool
));
211 return tvb_captured_length(tvb
);
215 proto_register_etw(void)
217 static hf_register_info hf
[] = {
219 { "Size", "etw.size",
220 FT_UINT16
, BASE_DEC
, NULL
, 0,
223 { &hf_etw_header_type
,
224 { "Header Type", "etw.header_type",
225 FT_UINT16
, BASE_DEC
, NULL
, 0,
229 { "Flags", "etw.flags",
230 FT_UINT16
, BASE_DEC
, NULL
, 0,
233 { &hf_etw_header_flag_extended_info
,
234 { "Extended Info", "etw.header.flag.extended_info",
235 FT_UINT32
, BASE_DEC
, NULL
, 0x0001,
238 { &hf_etw_header_flag_private_session
,
239 { "Private Session", "etw.header.flag.private_session",
240 FT_UINT32
, BASE_DEC
, NULL
, 0x0002,
243 { &hf_etw_header_flag_string_only
,
244 { "String Only", "etw.header.flag.string_only",
245 FT_UINT32
, BASE_DEC
, NULL
, 0x0004,
248 { &hf_etw_header_flag_trace_message
,
249 { "Trace Message", "etw.header.flag.trace_message",
250 FT_UINT32
, BASE_DEC
, NULL
, 0x0008,
253 { &hf_etw_header_flag_no_cputime
,
254 { "No CPU time", "etw.header.flag.no_cputime",
255 FT_UINT32
, BASE_DEC
, NULL
, 0x0010,
258 { &hf_etw_header_flag_32_bit_header
,
259 { "32-bit Header", "etw.header.flag.32_bit_header",
260 FT_UINT32
, BASE_DEC
, NULL
, 0x0020,
263 { &hf_etw_header_flag_64_bit_header
,
264 { "64-bit Header", "etw.header.flag.64_bit_header",
265 FT_UINT32
, BASE_DEC
, NULL
, 0x0040,
268 { &hf_etw_header_flag_decode_guid
,
269 { "Decode GUID", "etw.header.flag.decode_guid",
270 FT_UINT32
, BASE_DEC
, NULL
, 0x0080,
273 { &hf_etw_header_flag_classic_header
,
274 { "Classic Header", "etw.header.flag.classic_header",
275 FT_UINT32
, BASE_DEC
, NULL
, 0x0100,
278 { &hf_etw_header_flag_processor_index
,
279 { "Processor Index", "etw.header.flag.processor_index",
280 FT_UINT32
, BASE_DEC
, NULL
, 0x0200,
283 { &hf_etw_event_property
,
284 { "Event Property", "etw.event_property",
285 FT_UINT16
, BASE_DEC
, NULL
, 0,
288 { &hf_etw_event_property_xml
,
289 { "XML", "etw.property.xml",
290 FT_UINT32
, BASE_DEC
, NULL
, 0x0001,
293 { &hf_etw_event_property_forwarded_xml
,
294 { "Forwarded XML", "etw.property.forwarded_xml",
295 FT_UINT32
, BASE_DEC
, NULL
, 0x0002,
298 { &hf_etw_event_property_legacy_eventlog
,
299 { "Legacy Event Log", "etw.property.legacy_event",
300 FT_UINT32
, BASE_DEC
, NULL
, 0x0004,
303 { &hf_etw_event_property_legacy_reloggable
,
304 { "Legacy Reloggable", "etw.property.legacy_reloggable",
305 FT_UINT32
, BASE_DEC
, NULL
, 0x0008,
309 { "Thread ID", "etw.thread_id",
310 FT_UINT32
, BASE_DEC
, NULL
, 0,
313 { &hf_etw_process_id
,
314 { "Process ID", "etw.process_id",
315 FT_UINT32
, BASE_DEC
, NULL
, 0,
318 { &hf_etw_time_stamp
,
319 { "Time Stamp", "etw.time_stamp",
320 FT_UINT64
, BASE_DEC
, NULL
, 0,
323 { &hf_etw_provider_id
,
324 { "Provider ID", "etw.provider_id",
325 FT_GUID
, BASE_NONE
, NULL
, 0,
328 { &hf_etw_buffer_context_processor_number
,
329 { "Processor Number", "etw.buffer_context.processor_number",
330 FT_UINT8
, BASE_DEC
, NULL
, 0,
333 { &hf_etw_buffer_context_alignment
,
334 { "Alignment", "etw.buffer_context.alignment",
335 FT_UINT8
, BASE_DEC
, NULL
, 0,
338 { &hf_etw_buffer_context_logger_id
,
339 { "ID", "etw.buffer_context.logger_id",
340 FT_UINT16
, BASE_DEC
, NULL
, 0,
343 { &hf_etw_message_length
,
344 { "Message Length", "etw.message_length",
345 FT_UINT32
, BASE_DEC
, NULL
, 0,
348 { &hf_etw_provider_name_length
,
349 { "Provider Name Length", "etw.provider_name_length",
350 FT_UINT32
, BASE_DEC
, NULL
, 0,
353 { &hf_etw_provider_name
,
354 { "Provider Name", "etw.provider_name",
355 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
359 { "Event Message", "etw.message",
360 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
363 { &hf_etw_user_data_length
,
364 { "User Data Length", "etw.user_data_length",
365 FT_UINT32
, BASE_DEC
, NULL
, 0,
368 { &hf_etw_descriptor_id
,
369 { "ID", "etw.descriptor.id",
370 FT_UINT16
, BASE_DEC
, NULL
, 0,
373 { &hf_etw_descriptor_version
,
374 { "Version", "etw.descriptor.version",
375 FT_UINT8
, BASE_DEC
, NULL
, 0,
378 { &hf_etw_descriptor_channel
,
379 { "Channel", "etw.descriptor.channel",
380 FT_UINT8
, BASE_DEC
, NULL
, 0,
383 { &hf_etw_descriptor_level
,
384 { "Level", "etw.descriptor.level",
385 FT_UINT8
, BASE_DEC
, NULL
, 0,
388 { &hf_etw_descriptor_opcode
,
389 { "Opcode", "etw.descriptor.opcode",
390 FT_UINT8
, BASE_DEC
, NULL
, 0,
393 { &hf_etw_descriptor_task
,
394 { "Task", "etw.descriptor.task",
395 FT_UINT16
, BASE_DEC
, NULL
, 0,
398 { &hf_etw_descriptor_keywords
,
399 { "Keywords", "etw.descriptor.keywords",
400 FT_UINT64
, BASE_DEC
, NULL
, 0,
403 { &hf_etw_processor_time
,
404 { "Processor Time", "etw.processor_time",
405 FT_UINT64
, BASE_DEC
, NULL
, 0,
408 { &hf_etw_activity_id
,
409 { "Activity ID", "etw.activity_id",
410 FT_GUID
, BASE_NONE
, NULL
, 0,
415 static int *ett
[] = {
418 &ett_etw_buffer_context
,
419 &ett_etw_header_flags
,
420 &ett_etw_event_property_types
423 proto_etw
= proto_register_protocol("Event Tracing for Windows", "ETW", "etw");
424 proto_register_field_array(proto_etw
, hf
, array_length(hf
));
425 proto_register_subtree_array(ett
, array_length(ett
));
427 etw_handle
= register_dissector("etw", dissect_etw
, proto_etw
);
431 proto_reg_handoff_etw(void)
433 dissector_add_uint("wtap_encap", WTAP_ENCAP_ETW
, etw_handle
);
435 mbim_dissector
= find_dissector("mbim.control");
439 * Editor modelines - https://www.wireshark.org/tools/modelines.html
444 * indent-tabs-mode: nil
447 * vi: set shiftwidth=4 tabstop=8 expandtab:
448 * :indentSize=4:tabSize=8:noTabs=true: