diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9ea395f --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b1670c2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "libpcap"] + path = libpcap + url = https://github.com/airbus-cert/libpcap + branch = etw diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..72d360f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,56 @@ +# Minimum CMake required +cmake_minimum_required(VERSION 3.11) + +# Project +project(Winshark LANGUAGES C CXX CSharp VERSION 1.0.0) + +# Config +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + + +SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) +SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) + +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT /WX") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd /WX") + +# Include libpcap +set(LIBRARY_NAME wpcap CACHE STRING "Library name") +set(PCAP_TYPE "etw" CACHE STRING "Packet capture type" FORCE) +add_subdirectory(libpcap) +set_property(TARGET can_set_rfmon_test PROPERTY FOLDER "libpcap") +set_property(TARGET capturetest PROPERTY FOLDER "libpcap") +set_property(TARGET filtertest PROPERTY FOLDER "libpcap") +set_property(TARGET findalldevstest PROPERTY FOLDER "libpcap") +set_property(TARGET fuzz_both PROPERTY FOLDER "libpcap") +set_property(TARGET fuzz_filter PROPERTY FOLDER "libpcap") +set_property(TARGET fuzz_pcap PROPERTY FOLDER "libpcap") +set_property(TARGET opentest PROPERTY FOLDER "libpcap") +set_property(TARGET wpcap PROPERTY FOLDER "libpcap") +set_property(TARGET wpcap_static PROPERTY FOLDER "libpcap") +set_property(TARGET reactivatetest PROPERTY FOLDER "libpcap") +set_property(TARGET rpcapd PROPERTY FOLDER "libpcap") +set_property(TARGET SerializeTarget PROPERTY FOLDER "libpcap") +set_property(TARGET testprogs PROPERTY FOLDER "libpcap") +set_property(TARGET threadsignaltest PROPERTY FOLDER "libpcap") +set_property(TARGET uninstall PROPERTY FOLDER "libpcap") + +install(TARGETS wpcap DESTINATION .) + +# Install dissector write by hand +add_subdirectory(dissector) + +# Add tool to create new dissector from manifest based ETW +add_subdirectory(transluator) + +# Summary +message(STATUS "Configuration summary") +message(STATUS "Project name : ${PROJECT_NAME}") +message(STATUS "Project version : ${PROJECT_VERSION}") + +# CPack part +set(CPACK_GENERATOR "WIX") +set(CPACK_WIX_UPGRADE_GUID "c64ed0aa-c54a-4590-93fb-72e152edefb7") +set(CPACK_WIX_UNINSTALL "1") +set(CPACK_WIX_PATCH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/install/patch.xml") +include(CPack) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d9a10c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/README.md b/README.md index 358fc64..458c1ed 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,169 @@ # Winshark -Winshark +`Wireshark` plugins to work with Event Tracing for Windows + +`Microsoft Message Analyzer` is being retired and its download packages removed from microsoft.com sites on November 25 2019. +Wireshark have built a huge history of network protocol dissector. +The best tool for Windows would be one that can gather and mix all type of log... + +Welcome `Winshark`!!! + +`Winshark` is based on a `libpcap` backend to capture ETW (Event tracing for Windows), and a generator that will produce all dissector for known ETW provider on your machine. +We've added Tracelogging support to conver almost all log technics on Windows Operating System. + +With Winshark, and the powerfull of Windows, we can now capture network and event log in the same tools. Windows expose a lot of ETW provider, in particular one for network capture ;-) +No more needs of an external NDIS driver. + +This is a huge improvement in term of use : +* Enable to mix all kind of event (system and network) +* Enable to use wireshark filtering on event log +* Enable to track network and system log by Process ID !!! +* Enable to capture Windows log and network trace into an unique pcap file !!! + +If you want to : +* [Capture Network Traffic Using Winshark](#Capture-Network-traffic) +* [Filtering on process id](#Filtering-on-process-id) + +## Install + +Please install [Wireshark](https://www.wireshark.org/download.html) before. +Then just install [Winshark](https://github.com/airbus-cert/Winshark/releases). + +Actually, you have to ask `Wireshark` to interpret the DLT_USER 147 as ETW. This is because you have not yet a true value from `libpcap` for our new Data Link. +A pending request has been made to have a didicated DLT value +To do that you have to open `Preferences` tab under the `Edit` panel. Select `DLT_USER` under `Protocols` and `Edit` the encapsulations table : + +![DLT_USER configuration](doc/images/winshark-config-1.PNG) + +And set `etw` for `DLT = 147` : + +![DLT 147 set to ETW protocol](doc/images/winshark-config-2.PNG) + +Enjoy ! + +## Build + +Winshark is powered by `cmake` : + +``` +git clone https://github.com/airbus-cert/winshark --recurcive +mkdir build_winshark +cd build_winshark +cmake ..\Winshark +cmake --build . --target package --config release +``` + +## How does it work + +To better understand how Winshark works, we need to understand how ETW work first. + +ETW is splitted into three parts : +* Provider will emit log and identified by unique id +* Session will mix one or more provider +* Consumer that will read log emitted by a session + +### Provider + +It exist a lot of kind of provider. The most common, and exploitable, are registred provider. A registred provider, or a manifest based provider, are recorded under the registry key `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Publishers`. +This make the link between a provider id and a dll. The manifest is encompass into the associated dll into a ressources names `WEVT_TEMPLATE`. + +You can list all providers registred on your machine using `logman` : + +``` +logman query providers +``` + +You can also list all providers binded by a particular process : + +``` +logman query providers -pid 1234 +``` + +Some of them could appears without name, these kind of provider can produce [WPP](https://posts.specterops.io/data-source-analysis-and-dynamic-windows-re-using-wpp-and-tracelogging-e465f8b653f7) or [TraceLogging](https://posts.specterops.io/data-source-analysis-and-dynamic-windows-re-using-wpp-and-tracelogging-e465f8b653f7) log. + +### Session + +Session are created to collect logs from more than one provider. +You can create your own session using `logman` : + +``` +logman start Mysession -p "Microsoft-Windows-RemoteDesktopServices-RdpCoreTS" -ets -rt +logman update MySession -p "Microsoft-Windows-NDIS-PacketCapture" -ets -rt +``` + +You can list all active session from an admin command line : + +``` +>logman query -ets + +Data Collector Set Type Status +------------------------------------------------------------------------------- +... +EventLog-Application Trace Running +EventLog-Microsoft-Windows-Sysmon-Operational Trace Running +EventLog-System Trace Running +... +The command completed successfully. +``` + +You can see here some interesting session use by event logger to capture log from Application and System session and from Sysmon. + +### Consumer + +A consumer is a simple program that will read logs from a session. Famous consumer are : +* Event Logger +* logman +* netsh +* tracert + +And now `Winshark` !!! `Winshark` is a simple ETW consummer. Underlying, the real consumer is `libpcap`, (`wpcap.dll` in case Windows) which is used by `dumpcap.exe` which is the process in charge of packet capture. + +## Wireshark + +`Wireshark` is splitted in three part (too) : +* `Wireshark.exe` which is in charge of parse and dissect protocol +* `dumpcap.exe` which is in charge of of packet capture +* `libpcap` (`wpcap.dll`) is in charge of interface between dumpcap.exe and the Operating System + +`Winshark` take place in first and last part. It implement a backend for `libpcap` to capture ETW event. +`Winshark` works on ETW session, this is why you can select ETW session in place of Network interface at the start of capture. +Then `Winshark` generate `lua` dissector for each manifest based provider registred on your computer, during installation step. +`Winshark` is also available to parse tracelogging based provider. + +## Capture Network traffic + +To capture network traffic using `Wineshark`, you have to simply activate network tracing through `netsh` : + +``` +netsh.exe trace start capture=yes report=no correlation=no +``` + +And then create an ETW session associate with the `Microsoft-Windows-NDIS-PacketCapture` provider : + +``` +logman start Winshark-PacketCapture -p "Microsoft-Windows-NDIS-PacketCapture" -rt -ets +``` + +Then launch `Wireshark` with administrator privileges and select `Winshark-PacketCapture` interface : + +![ETW interface selection](doc/images/winshark-capture-1.PNG) + +That will start the packet capture : + +![ETW packet capture](doc/images/winshark-capture-2.PNG) + +## Filtering on process id + +ETW mark each packet with an header that set some meta information about the sender. +One of these is the `Process ID` of the emitter. In case of packet capture, this is a huge improvement from a classic packet capture from an NDIS driver. +Simply fill the filter field of wireshark with the following expression : + +``` +etw.header.ProcessId == 1234 +``` + +![ETW packet capture](doc/images/winshark-process-id.PNG) + +## SSTIC (Symposium sur la sécurité des technologies de l'information et des communications) + +This project is part of presentation made for [SSTIC](https://www.sstic.org/2020/presentation/quand_les_bleus_se_prennent_pour_des_chercheurs_de_vulnrabilites/) + diff --git a/dissector/CMakeLists.txt b/dissector/CMakeLists.txt new file mode 100644 index 0000000..bdec18f --- /dev/null +++ b/dissector/CMakeLists.txt @@ -0,0 +1,3 @@ +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/etw.lua" DESTINATION plugins) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/Tracelogging.lua" DESTINATION plugins/winshark) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/Microsoft_Windows_NDIS_PacketCapture.lua" DESTINATION plugins/winshark) diff --git a/dissector/Microsoft_Windows_NDIS_PacketCapture.lua b/dissector/Microsoft_Windows_NDIS_PacketCapture.lua new file mode 100644 index 0000000..14cd55a --- /dev/null +++ b/dissector/Microsoft_Windows_NDIS_PacketCapture.lua @@ -0,0 +1,644 @@ + +local proto = Proto("Microsoft-Windows-NDIS-PacketCapture", "Microsoft-Windows-NDIS-PacketCapture") +local event_id = Field.new("etw.header.EventDescriptor.Id") +local event_version = Field.new("etw.header.EventDescriptor.Version") +local dissector_table = DissectorTable.new("Microsoft-Windows-NDIS-PacketCapture", "Microsoft-Windows-NDIS-PacketCapture 2ed6006e-4729-4609-b423-3ee7bcd678ef", ftypes.STRING) +function proto.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + local id = event_id() + local version = event_version() + dissector_table:try(tostring(id) .. "." .. tostring(version) , buffer, pinfo, tree) +end +local etw_dissector_table = DissectorTable.get("etw") +etw_dissector_table:add("2ed6006e-4729-4609-b423-3ee7bcd678ef", proto) + +event_proto_1001_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.1001.0", "Microsoft-Windows-NDIS-PacketCapture EventId(1001) Version(0)") + +event_proto_1001_0.fields = { ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1001.MiniportIfIndex", "MiniportIfIndex", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1001.LowerIfIndex", "LowerIfIndex", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1001.FragmentSize", "FragmentSize", base.DEC), ProtoField.bytes("Microsoft-Windows-NDIS-PacketCapture.1001.Fragment", "Fragment", base.NONE), ProtoField.uint64("Microsoft-Windows-NDIS-PacketCapture.1001.GftFlowEntryId", "GftFlowEntryId", base.DEC), ProtoField.uint64("Microsoft-Windows-NDIS-PacketCapture.1001.GftOffloadInformation", "GftOffloadInformation", base.DEC) } + + +function event_proto_1001_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_1001_0.name + + local fields = tree:add(event_proto_1001_0, buffer()) + local index = 0 + + local MiniportIfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1001_0.fields[1], buffer(index, 4)) + index = index + 4 + + + local LowerIfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1001_0.fields[2], buffer(index, 4)) + index = index + 4 + + + local FragmentSize_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1001_0.fields[3], buffer(index, 4)) + index = index + 4 + + + fields:add_le(event_proto_1001_0.fields[4], buffer(index, FragmentSize_value)) + index = index + FragmentSize_value + + + local GftFlowEntryId_value = buffer(index, 8):le_uint64() + fields:add_le(event_proto_1001_0.fields[5], buffer(index, 8)) + index = index + 8 + + + local GftOffloadInformation_value = buffer(index, 8):le_uint64() + fields:add_le(event_proto_1001_0.fields[6], buffer(index, 8)) + index = index + 8 + + local ethernet = Dissector.get("eth_withoutfcs") + ethernet:call(buffer(12, FragmentSize_value):tvb() , pinfo , tree ) + +end + +dissector_table:add("1001.0", event_proto_1001_0) + +event_proto_1002_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.1002.0", "Microsoft-Windows-NDIS-PacketCapture EventId(1002) Version(0)") + +event_proto_1002_0.fields = { ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1002.MiniportIfIndex", "MiniportIfIndex", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1002.LowerIfIndex", "LowerIfIndex", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1002.MetadataSize", "MetadataSize", base.DEC), ProtoField.bytes("Microsoft-Windows-NDIS-PacketCapture.1002.Metadata", "Metadata", base.NONE) } + + +function event_proto_1002_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_1002_0.name + + local fields = tree:add(event_proto_1002_0, buffer()) + local index = 0 + + local MiniportIfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1002_0.fields[1], buffer(index, 4)) + index = index + 4 + + + local LowerIfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1002_0.fields[2], buffer(index, 4)) + index = index + 4 + + + local MetadataSize_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1002_0.fields[3], buffer(index, 4)) + index = index + 4 + + + fields:add_le(event_proto_1002_0.fields[4], buffer(index, MetadataSize_value)) + index = index + MetadataSize_value + + +end + +dissector_table:add("1002.0", event_proto_1002_0) + +event_proto_1003_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.1003.0", "Microsoft-Windows-NDIS-PacketCapture EventId(1003) Version(0)") + +event_proto_1003_0.fields = { ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1003.MiniportIfIndex", "MiniportIfIndex", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1003.LowerIfIndex", "LowerIfIndex", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1003.SourcePortId", "SourcePortId", base.DEC), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1003.SourcePortName", "SourcePortName", base.UNICODE), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1003.SourceNicName", "SourceNicName", base.UNICODE), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1003.SourceNicType", "SourceNicType", base.UNICODE), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1003.DestinationCount", "DestinationCount", base.DEC), ProtoField.double("Microsoft-Windows-NDIS-PacketCapture.1003.Destination", "Destination", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1003.FragmentSize", "FragmentSize", base.DEC), ProtoField.bytes("Microsoft-Windows-NDIS-PacketCapture.1003.Fragment", "Fragment", base.NONE), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1003.OOBDataSize", "OOBDataSize", base.DEC), ProtoField.bytes("Microsoft-Windows-NDIS-PacketCapture.1003.OOBData", "OOBData", base.NONE) } + + +function event_proto_1003_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_1003_0.name + + local fields = tree:add(event_proto_1003_0, buffer()) + local index = 0 + + local MiniportIfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1003_0.fields[1], buffer(index, 4)) + index = index + 4 + + + local LowerIfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1003_0.fields[2], buffer(index, 4)) + index = index + 4 + + + local SourcePortId_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1003_0.fields[3], buffer(index, 4)) + index = index + 4 + + + fields:add_le(event_proto_1003_0.fields[4], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + fields:add_le(event_proto_1003_0.fields[5], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + fields:add_le(event_proto_1003_0.fields[6], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + local DestinationCount_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1003_0.fields[7], buffer(index, 4)) + index = index + 4 + + + fields:add_le(event_proto_1003_0.fields[8], buffer(index, 8)) + index = index + 8 + + + local FragmentSize_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1003_0.fields[9], buffer(index, 4)) + index = index + 4 + + + fields:add_le(event_proto_1003_0.fields[10], buffer(index, FragmentSize_value)) + index = index + FragmentSize_value + + + local OOBDataSize_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1003_0.fields[11], buffer(index, 4)) + index = index + 4 + + + fields:add_le(event_proto_1003_0.fields[12], buffer(index, OOBDataSize_value)) + index = index + OOBDataSize_value + + +end + +dissector_table:add("1003.0", event_proto_1003_0) + +event_proto_1011_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.1011.0", "Microsoft-Windows-NDIS-PacketCapture EventId(1011) Version(0)") + +event_proto_1011_0.fields = { ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1011.RulesCount", "RulesCount", base.DEC) } + + +function event_proto_1011_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_1011_0.name + + local fields = tree:add(event_proto_1011_0, buffer()) + local index = 0 + + local RulesCount_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1011_0.fields[1], buffer(index, 4)) + index = index + 4 + + +end + +dissector_table:add("1011.0", event_proto_1011_0) + +event_proto_1012_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.1012.0", "Microsoft-Windows-NDIS-PacketCapture EventId(1012) Version(0)") + +event_proto_1012_0.fields = { ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1012.FriendlyName", "FriendlyName", base.UNICODE), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1012.UniqueName", "UniqueName", base.UNICODE), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1012.ServiceName", "ServiceName", base.UNICODE), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1012.Version", "Version", base.UNICODE) } + + +function event_proto_1012_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_1012_0.name + + local fields = tree:add(event_proto_1012_0, buffer()) + local index = 0 + + fields:add_le(event_proto_1012_0.fields[1], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + fields:add_le(event_proto_1012_0.fields[2], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + fields:add_le(event_proto_1012_0.fields[3], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + fields:add_le(event_proto_1012_0.fields[4], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + +end + +dissector_table:add("1012.0", event_proto_1012_0) + +event_proto_1013_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.1013.0", "Microsoft-Windows-NDIS-PacketCapture EventId(1013) Version(0)") + +event_proto_1013_0.fields = { ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1013.FriendlyName", "FriendlyName", base.UNICODE), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1013.UniqueName", "UniqueName", base.UNICODE), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1013.ServiceName", "ServiceName", base.UNICODE), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.1013.Version", "Version", base.UNICODE) } + + +function event_proto_1013_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_1013_0.name + + local fields = tree:add(event_proto_1013_0, buffer()) + local index = 0 + + fields:add_le(event_proto_1013_0.fields[1], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + fields:add_le(event_proto_1013_0.fields[2], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + fields:add_le(event_proto_1013_0.fields[3], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + fields:add_le(event_proto_1013_0.fields[4], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + +end + +dissector_table:add("1013.0", event_proto_1013_0) + +event_proto_1014_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.1014.0", "Microsoft-Windows-NDIS-PacketCapture EventId(1014) Version(0)") + +event_proto_1014_0.fields = { ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1014.MiniportIfIndex", "MiniportIfIndex", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1014.LowerIfIndex", "LowerIfIndex", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1014.MediaType", "MediaType", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1014.ReferenceContext", "ReferenceContext", base.DEC) } + + +function event_proto_1014_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_1014_0.name + + local fields = tree:add(event_proto_1014_0, buffer()) + local index = 0 + + local MiniportIfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1014_0.fields[1], buffer(index, 4)) + index = index + 4 + + + local LowerIfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1014_0.fields[2], buffer(index, 4)) + index = index + 4 + + + local MediaType_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1014_0.fields[3], buffer(index, 4)) + index = index + 4 + + + local ReferenceContext_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1014_0.fields[4], buffer(index, 4)) + index = index + 4 + + +end + +dissector_table:add("1014.0", event_proto_1014_0) + +event_proto_1015_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.1015.0", "Microsoft-Windows-NDIS-PacketCapture EventId(1015) Version(0)") + +event_proto_1015_0.fields = { ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1015.MiniportIfIndex", "MiniportIfIndex", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1015.LowerIfIndex", "LowerIfIndex", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1015.MediaType", "MediaType", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.1015.ReferenceContext", "ReferenceContext", base.DEC) } + + +function event_proto_1015_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_1015_0.name + + local fields = tree:add(event_proto_1015_0, buffer()) + local index = 0 + + local MiniportIfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1015_0.fields[1], buffer(index, 4)) + index = index + 4 + + + local LowerIfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1015_0.fields[2], buffer(index, 4)) + index = index + 4 + + + local MediaType_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1015_0.fields[3], buffer(index, 4)) + index = index + 4 + + + local ReferenceContext_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_1015_0.fields[4], buffer(index, 4)) + index = index + 4 + + +end + +dissector_table:add("1015.0", event_proto_1015_0) + +event_proto_1016_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.1016.0", "Microsoft-Windows-NDIS-PacketCapture EventId(1016) Version(0)") + +event_proto_1016_0.fields = { ProtoField.uint8("Microsoft-Windows-NDIS-PacketCapture.1016.RuleId", "RuleId", base.DEC), ProtoField.uint8("Microsoft-Windows-NDIS-PacketCapture.1016.Directive", "Directive", base.DEC), ProtoField.uint16("Microsoft-Windows-NDIS-PacketCapture.1016.Length", "Length", base.DEC), ProtoField.bytes("Microsoft-Windows-NDIS-PacketCapture.1016.Value", "Value", base.NONE) } + + +function event_proto_1016_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_1016_0.name + + local fields = tree:add(event_proto_1016_0, buffer()) + local index = 0 + + local RuleId_value = buffer(index, 1):le_uint() + fields:add_le(event_proto_1016_0.fields[1], buffer(index, 1)) + index = index + 1 + + + local Directive_value = buffer(index, 1):le_uint() + fields:add_le(event_proto_1016_0.fields[2], buffer(index, 1)) + index = index + 1 + + + local Length_value = buffer(index, 2):le_uint() + fields:add_le(event_proto_1016_0.fields[3], buffer(index, 2)) + index = index + 2 + + + fields:add_le(event_proto_1016_0.fields[4], buffer(index, Length_value)) + index = index + Length_value + + +end + +dissector_table:add("1016.0", event_proto_1016_0) + +event_proto_2001_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.2001.0", "Microsoft-Windows-NDIS-PacketCapture EventId(2001) Version(0)") + +event_proto_2001_0.fields = { ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.2001.ErrorCode", "ErrorCode", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.2001.Location", "Location", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.2001.Context", "Context", base.DEC) } + + +function event_proto_2001_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_2001_0.name + + local fields = tree:add(event_proto_2001_0, buffer()) + local index = 0 + + local ErrorCode_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_2001_0.fields[1], buffer(index, 4)) + index = index + 4 + + + local Location_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_2001_0.fields[2], buffer(index, 4)) + index = index + 4 + + + local Context_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_2001_0.fields[3], buffer(index, 4)) + index = index + 4 + + +end + +dissector_table:add("2001.0", event_proto_2001_0) + +event_proto_2002_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.2002.0", "Microsoft-Windows-NDIS-PacketCapture EventId(2002) Version(0)") + +event_proto_2002_0.fields = { ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.2002.ErrorCode", "ErrorCode", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.2002.Location", "Location", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.2002.Context", "Context", base.DEC) } + + +function event_proto_2002_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_2002_0.name + + local fields = tree:add(event_proto_2002_0, buffer()) + local index = 0 + + local ErrorCode_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_2002_0.fields[1], buffer(index, 4)) + index = index + 4 + + + local Location_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_2002_0.fields[2], buffer(index, 4)) + index = index + 4 + + + local Context_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_2002_0.fields[3], buffer(index, 4)) + index = index + 4 + + +end + +dissector_table:add("2002.0", event_proto_2002_0) + +event_proto_2003_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.2003.0", "Microsoft-Windows-NDIS-PacketCapture EventId(2003) Version(0)") + +event_proto_2003_0.fields = { ProtoField.uint8("Microsoft-Windows-NDIS-PacketCapture.2003.RuleId", "RuleId", base.DEC), ProtoField.uint8("Microsoft-Windows-NDIS-PacketCapture.2003.Directive", "Directive", base.DEC), ProtoField.uint16("Microsoft-Windows-NDIS-PacketCapture.2003.Length", "Length", base.DEC), ProtoField.bytes("Microsoft-Windows-NDIS-PacketCapture.2003.Value", "Value", base.NONE) } + + +function event_proto_2003_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_2003_0.name + + local fields = tree:add(event_proto_2003_0, buffer()) + local index = 0 + + local RuleId_value = buffer(index, 1):le_uint() + fields:add_le(event_proto_2003_0.fields[1], buffer(index, 1)) + index = index + 1 + + + local Directive_value = buffer(index, 1):le_uint() + fields:add_le(event_proto_2003_0.fields[2], buffer(index, 1)) + index = index + 1 + + + local Length_value = buffer(index, 2):le_uint() + fields:add_le(event_proto_2003_0.fields[3], buffer(index, 2)) + index = index + 2 + + + fields:add_le(event_proto_2003_0.fields[4], buffer(index, Length_value)) + index = index + Length_value + + +end + +dissector_table:add("2003.0", event_proto_2003_0) + +event_proto_3001_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.3001.0", "Microsoft-Windows-NDIS-PacketCapture EventId(3001) Version(0)") + +event_proto_3001_0.fields = { ProtoField.uint8("Microsoft-Windows-NDIS-PacketCapture.3001.PreviousState", "PreviousState", base.DEC), ProtoField.uint8("Microsoft-Windows-NDIS-PacketCapture.3001.NextState", "NextState", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.3001.Location", "Location", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.3001.Context", "Context", base.DEC) } + + +function event_proto_3001_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_3001_0.name + + local fields = tree:add(event_proto_3001_0, buffer()) + local index = 0 + + local PreviousState_value = buffer(index, 1):le_uint() + fields:add_le(event_proto_3001_0.fields[1], buffer(index, 1)) + index = index + 1 + + + local NextState_value = buffer(index, 1):le_uint() + fields:add_le(event_proto_3001_0.fields[2], buffer(index, 1)) + index = index + 1 + + + local Location_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_3001_0.fields[3], buffer(index, 4)) + index = index + 4 + + + local Context_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_3001_0.fields[4], buffer(index, 4)) + index = index + 4 + + +end + +dissector_table:add("3001.0", event_proto_3001_0) + +event_proto_3002_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.3002.0", "Microsoft-Windows-NDIS-PacketCapture EventId(3002) Version(0)") + +event_proto_3002_0.fields = { ProtoField.uint8("Microsoft-Windows-NDIS-PacketCapture.3002.PreviousState", "PreviousState", base.DEC), ProtoField.uint8("Microsoft-Windows-NDIS-PacketCapture.3002.NextState", "NextState", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.3002.Location", "Location", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.3002.Context", "Context", base.DEC) } + + +function event_proto_3002_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_3002_0.name + + local fields = tree:add(event_proto_3002_0, buffer()) + local index = 0 + + local PreviousState_value = buffer(index, 1):le_uint() + fields:add_le(event_proto_3002_0.fields[1], buffer(index, 1)) + index = index + 1 + + + local NextState_value = buffer(index, 1):le_uint() + fields:add_le(event_proto_3002_0.fields[2], buffer(index, 1)) + index = index + 1 + + + local Location_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_3002_0.fields[3], buffer(index, 4)) + index = index + 4 + + + local Context_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_3002_0.fields[4], buffer(index, 4)) + index = index + 4 + + +end + +dissector_table:add("3002.0", event_proto_3002_0) + +event_proto_5100_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.5100.0", "Microsoft-Windows-NDIS-PacketCapture EventId(5100) Version(0)") + +event_proto_5100_0.fields = { ProtoField.uint8("Microsoft-Windows-NDIS-PacketCapture.5100.SourceId", "SourceId", base.DEC), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.5100.RundownId", "RundownId", base.DEC), ProtoField.uint64("Microsoft-Windows-NDIS-PacketCapture.5100.Param1", "Param1", base.DEC), ProtoField.uint64("Microsoft-Windows-NDIS-PacketCapture.5100.Param2", "Param2", base.DEC), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.5100.ParamStr", "ParamStr", base.UNICODE), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.5100.Description", "Description", base.UNICODE) } + + +function event_proto_5100_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_5100_0.name + + local fields = tree:add(event_proto_5100_0, buffer()) + local index = 0 + + local SourceId_value = buffer(index, 1):le_uint() + fields:add_le(event_proto_5100_0.fields[1], buffer(index, 1)) + index = index + 1 + + + local RundownId_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_5100_0.fields[2], buffer(index, 4)) + index = index + 4 + + + local Param1_value = buffer(index, 8):le_uint64() + fields:add_le(event_proto_5100_0.fields[3], buffer(index, 8)) + index = index + 8 + + + local Param2_value = buffer(index, 8):le_uint64() + fields:add_le(event_proto_5100_0.fields[4], buffer(index, 8)) + index = index + 8 + + + fields:add_le(event_proto_5100_0.fields[5], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + fields:add_le(event_proto_5100_0.fields[6], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + +end + +dissector_table:add("5100.0", event_proto_5100_0) + +event_proto_5101_0 = Proto("Microsoft-Windows-NDIS-PacketCapture.5101.0", "Microsoft-Windows-NDIS-PacketCapture EventId(5101) Version(0)") + +event_proto_5101_0.fields = { ProtoField.uint8("Microsoft-Windows-NDIS-PacketCapture.5101.SourceId", "SourceId", base.DEC), ProtoField.string("Microsoft-Windows-NDIS-PacketCapture.5101.SourceName", "SourceName", base.UNICODE), ProtoField.uint32("Microsoft-Windows-NDIS-PacketCapture.5101.IfIndex", "IfIndex", base.DEC), ProtoField.uint16("Microsoft-Windows-NDIS-PacketCapture.5101.LayerCount", "LayerCount", base.DEC), ProtoField.int16("Microsoft-Windows-NDIS-PacketCapture.5101.LayerInfo", "LayerInfo", base.DEC) } + + +function event_proto_5101_0.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = event_proto_5101_0.name + + local fields = tree:add(event_proto_5101_0, buffer()) + local index = 0 + + local SourceId_value = buffer(index, 1):le_uint() + fields:add_le(event_proto_5101_0.fields[1], buffer(index, 1)) + index = index + 1 + + + fields:add_le(event_proto_5101_0.fields[2], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 + + + local IfIndex_value = buffer(index, 4):le_uint() + fields:add_le(event_proto_5101_0.fields[3], buffer(index, 4)) + index = index + 4 + + + local LayerCount_value = buffer(index, 2):le_uint() + fields:add_le(event_proto_5101_0.fields[4], buffer(index, 2)) + index = index + 2 + + + local LayerInfo_value = buffer(index, 2):le_int() + fields:add_le(event_proto_5101_0.fields[5], buffer(index, 2)) + index = index + 2 + + +end + +dissector_table:add("5101.0", event_proto_5101_0) + diff --git a/dissector/Tracelogging.lua b/dissector/Tracelogging.lua new file mode 100644 index 0000000..939e72d --- /dev/null +++ b/dissector/Tracelogging.lua @@ -0,0 +1,142 @@ +-- This is the main tracelogging disector +-- As tracelogging encompass its scheme directly into +-- Extended data, we need to create dynamic Proto bases on scheme +-- Read from extendedata field from etw dissector + +local tracelogging = Proto("Tracelogging", "Tracelogging") + +-- field use by Tracelogging to extract scheme +local extended_data_field = Field.new("etw.ExtendedData") + +local tl_dissector_table = DissectorTable.new("Tracelogging", "Tracelogging", ftypes.STRING) + +-- This function convert scheme type into lua type +-- tree: current tree node use to display type +-- buffer: buffer contain type +-- tag_type: type extracted from scheme +-- tag_name: name extracted from scheme +function parse_field(tree, buffer, tag_type, tag_name) + tag_name_formated = string.format("%s:", tag_name); + if tag_type == 1 then local value = buffer(0):le_ustringz(); tree:add(tag_name_formated, value) ; return (value:len() + 1) * 2; + elseif tag_type == 2 then local value = buffer(0):stringz(); tree:add(tag_name_formated, value) ; return value:len() + 1; + elseif tag_type == 3 then tree:add(tag_name_formated, buffer(0, 1):le_int()); return 1; + elseif tag_type == 4 then tree:add(tag_name_formated, buffer(0, 1):le_uint()); return 1; + elseif tag_type == 5 then tree:add(tag_name_formated, buffer(0, 2):le_int()); return 2; + elseif tag_type == 6 then tree:add(tag_name_formated, buffer(0, 2):le_uint()); return 2; + elseif tag_type == 7 then tree:add(tag_name_formated, buffer(0, 4):le_int()); return 4; + elseif tag_type == 8 then tree:add(tag_name_formated, buffer(0, 4):le_uint()); return 4; + elseif tag_type == 9 then tree:add(tag_name_formated, buffer(0, 8):le_uint64()); return 8; + elseif tag_type == 10 then tree:add(tag_name_formated, buffer(0, 8):le_int64()); return 8; + elseif tag_type == 11 then tree:add(tag_name_formated, buffer(0, 4):le_float()); return 4; + elseif tag_type == 12 then tree:add(tag_name_formated, buffer(0, 8):le_float()); return 8; + elseif tag_type == 13 then tree:add(tag_name_formated, buffer(0, 4):le_uint()); return 4; + elseif tag_type == 14 then return parse_array_field(tree, buffer, tag_type, tag_name); + elseif tag_type == 15 then tree:add(tag_name_formated, buffer(0, 16)); return 16; + elseif tag_type == 17 then tree:add(tag_name_formated, buffer(0, 8)); return 8; + elseif tag_type == 18 then tree:add(tag_name_formated, buffer(0, 16)); return 16; + elseif tag_type == 20 then tree:add(tag_name_formated, buffer(0, 4):le_uint()); return 4; + elseif tag_type == 21 then tree:add(tag_name_formated, buffer(0, 8):le_uint()); return 8; + end +end + +-- Parse an array of type as defined by tracelogging macro +-- tree: current tree node use to display type +-- buffer: buffer contain type +-- tag_type: type extracted from scheme +-- tag_name: name extracted from scheme +function parse_array_field(tree, buffer, tag_type, tag_name) + local i = 0; + local nb = buffer(0, 2):le_uint(); + local index = 2; + + local array = tree:add(tag_name); + while i < nb do + index = index + parse_field(array, buffer(index):tvb(), tag_type, string.format("[%d]", i)); + i = i + 1; + end + return index +end + +-- Tracelogging dissector definition +-- Mainly extract scheme from extendedata parse from etw dissector +-- and create a sub Proto for this scheme if not parsed before +-- WARNING: TL accept that different scheme for same TL name, this not handle by this dissector +function tracelogging.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + local name = nil + local scheme = {} + + local extended_data = extended_data_field()():tvb() + local offset = 0 + + while offset < extended_data:len() do + local ext_type = extended_data(offset, 2):le_uint() + local size = extended_data(offset + 2, 2):le_uint() + local data = extended_data(offset + 4, size):tvb() + + -- detect scheme + if ext_type == 11 then + local size = data(0, 2):le_uint() + local tag = data(2, 1):le_uint() + -- name of the protocol + name = data(3):stringz():gsub(" ", "_") + local scheme_data = data(3 + name:len() + 1):tvb() + local offset_scheme = 0 + local index_tag = 1 + + while offset_scheme < scheme_data:len() do + + local field_name = scheme_data(offset_scheme):stringz():gsub(" ", "_") + local tag_in = scheme_data(offset_scheme + field_name:len() + 1, 1):le_uint() + + offset_scheme = offset_scheme + field_name:len() + 1 + 1 + -- tag out field ignore + if bit32.band(tag_in, 0x80) == 0x80 then + print("tag_out") + local tag_out = scheme_data(offset_scheme, 1):le_uint() + if bit32.band(tag_out, 0x80) == 0x80 then + offset_scheme = offset_scheme + 5 + else + offset_scheme = offset_scheme + 1 + end + end + + scheme[index_tag] = {tag = tag_in, name = field_name} + + index_tag = index_tag + 1 + end + end + offset = offset + size + 4 + end + + tl_proto = tl_dissector_table:get_dissector(name) + + if tl_proto == nil then + local tl_proto = Proto(name, name) + tl_proto.dissector = function(buffer, pinfo, tree) + pinfo.cols.protocol = tl_proto.name + + local proto_tree = tree:add(tl_proto, buffer()) + local index = 0 + -- loop over all scheme entry and parse them + for i, element in ipairs(scheme) do + local tag_type = bit32.band(element.tag, 0x1F) + local is_array = bit32.band(element.tag, 0x20) == 0x20 or bit32.band(element.tag, 0x40) == 0x40 + if is_array then + index = index + parse_array_field(proto_tree, buffer(index):tvb(), tag_type, element.name) + else + index = index + parse_field(proto_tree, buffer(index):tvb(), tag_type, element.name) + end + end + end + + tl_dissector_table:add(name, tl_proto) + end + + tl_dissector_table:try(name, buffer, pinfo, tree) +end + +local etw_dissector_table = DissectorTable.get("etw") +etw_dissector_table:add("Tracelogging", tracelogging) \ No newline at end of file diff --git a/dissector/etw.lua b/dissector/etw.lua new file mode 100644 index 0000000..35e699c --- /dev/null +++ b/dissector/etw.lua @@ -0,0 +1,130 @@ +-- This is the main dissector for all winshark based dissector +-- This dissector will parse all meta infos for ETW packet captured +-- throw the ETW backend for lib pcap + +etw_proto = Proto("ETW","Event Trace for Windows"); + +local header_size = ProtoField.uint16("etw.header.Size", "Size", base.DEC); +local header_type = ProtoField.uint16("etw.header.HeaderType", "HeaderType", base.DEC); +local header_flags = ProtoField.uint16("etw.header.Flags", "Flags", base.DEC); +local header_eventproperty = ProtoField.uint16("etw.header.EventProperty", "EventProperty", base.DEC); +local header_threadid = ProtoField.uint32("etw.header.ThreadId", "ThreadId", base.DEC); +local header_processid = ProtoField.uint32("etw.header.ProcessId", "ProcessId", base.DEC); +local header_timestamp = ProtoField.uint64("etw.header.TimeStamp", "TimeStamp", base.DEC); +local header_providerid = ProtoField.guid("etw.header.ProviderId", "ProviderId", base.DEC); +local header_processtime = ProtoField.uint64("etw.header.ProcessorTime", "ProcessorTime", base.DEC); +local header_activityid = ProtoField.guid("etw.header.ActivityId", "ActivityId", base.DEC); + +local header_eventdescriptor_id = ProtoField.uint16("etw.header.EventDescriptor.Id", "Id", base.DEC); +local header_eventdescriptor_version = ProtoField.uint8("etw.header.EventDescriptor.Version", "Version", base.DEC); +local header_eventdescriptor_channel = ProtoField.uint8("etw.header.EventDescriptor.Channel", "Channel", base.DEC); +local header_eventdescriptor_level = ProtoField.uint8("etw.header.EventDescriptor.Level", "Level", base.DEC); +local header_eventdescriptor_opcode = ProtoField.uint8("etw.header.EventDescriptor.Opcode", "Opcode", base.DEC); +local header_eventdescriptor_task = ProtoField.uint16("etw.header.EventDescriptor.Task", "Task", base.DEC); +local header_eventdescriptor_keyword = ProtoField.uint64("etw.header.EventDescriptor.Keyword", "Keyword", base.HEX); + +local header_extendeddatalength = ProtoField.uint16("etw.header.ExtendedDataLength", "ExtendedDataLength", base.DEC); +local header_extendeddata = ProtoField.bytes("etw.ExtendedData", "ExtendedData", base.NONE); +local header_extendeddatatype = ProtoField.uint16("etw.ExtendedData.Type", "ExtType", base.DEC); +local header_extendeddatasize = ProtoField.uint16("etw.ExtendedData.Size", "DataSize", base.DEC); + + +etw_proto.fields = { + header_size, + header_type, + header_flags, + header_eventproperty, + header_threadid, + header_processid, + header_timestamp, + header_providerid, + header_processtime, + header_activityid, + header_eventdescriptor_id, + header_eventdescriptor_version, + header_eventdescriptor_channel, + header_eventdescriptor_level, + header_eventdescriptor_opcode, + header_eventdescriptor_task, + header_eventdescriptor_keyword, + header_extendeddatalength, + header_extendeddatasize, + header_extendeddatatype, + header_extendeddata +} + +-- declate the personnal etw dissector table +etw_dissector_table = DissectorTable.new("etw", "Event Tracing for Windows", ftypes.STRING) + +function etw_proto.dissector(buffer, pinfo, tree) + length = buffer:len(); + if length == 0 then return end + + pinfo.cols.protocol = etw_proto.name; + + local etw = tree:add(etw_proto, buffer()); + local event_header = etw:add(buffer(0, 80), "EventHeader") + + event_header:add_le(header_size, buffer(0, 2)); + event_header:add_le(header_type, buffer(2, 2)); + event_header:add_le(header_flags, buffer(4, 2)); + event_header:add_le(header_eventproperty, buffer(6, 2)); + event_header:add_le(header_threadid, buffer(8, 4)); + event_header:add_le(header_processid, buffer(12, 4)); + event_header:add_le(header_timestamp, buffer(16, 8)); + event_header:add_le(header_providerid, buffer(24, 16)); + + local event_descriptor = event_header:add(buffer(40, 16), "EventDescriptor"); + event_descriptor:add_le(header_eventdescriptor_id, buffer(40, 2)); + event_descriptor:add_le(header_eventdescriptor_version, buffer(42, 1)); + event_descriptor:add_le(header_eventdescriptor_channel, buffer(43, 1)); + event_descriptor:add_le(header_eventdescriptor_level, buffer(44, 1)); + event_descriptor:add_le(header_eventdescriptor_opcode, buffer(45, 1)); + event_descriptor:add_le(header_eventdescriptor_task, buffer(46, 2)); + event_descriptor:add_le(header_eventdescriptor_keyword, buffer(48, 8)); + + event_header:add_le(header_processtime, buffer(56, 8)); + event_header:add_le(header_activityid, buffer(64, 16)); + event_header:add_le(header_extendeddatalength, buffer(80, 2)); + + -- convert to string guid + -- Provider id is the switch use by sub dissector + -- Tracelogging use trcelogging string as identifier + local providerid = string.format("%08x-%04x-%04x-%04x-%04x%04x%04x", + buffer(24, 4):le_uint(), + buffer(28, 2):le_uint(), + buffer(30, 2):le_uint(), + buffer(32, 2):uint(), buffer(34, 2):uint(), buffer(36, 2):uint(), buffer(38, 2):uint() + ); + + extended_data_length = buffer(80, 2):le_uint(); + local extended_data = etw:add_le(header_extendeddata, buffer(82, extended_data_length)); + + local offset = 0; + local index = 0; + while offset < extended_data_length do + local ext_type = buffer(82 + offset, 2):le_uint() + local size = buffer(82 + offset + 2, 2):le_uint() + local data = extended_data:add(buffer(82 + offset, size + 4), string.format("[%d]", index)) + + index = index + 1 + + data:add_le(header_extendeddatatype, buffer(82 + offset, 2)) + data:add_le(header_extendeddatasize, buffer(82 + offset + 2, 2)) + data:add(buffer(82 + offset + 4, size), "Data") + + -- detecting trace logging protocol + -- tracelogging encompass its scheme directly into extended data + if ext_type == 11 then + providerid = "Tracelogging" + end + + offset = offset + size + 4; + end + + -- select corect dissector and pass UserData + etw:add(buffer(82 + extended_data_length, length - 82 - extended_data_length), "UserData") + etw_dissector_table:try(providerid, buffer(82 + extended_data_length, length - 82 - extended_data_length):tvb(), pinfo, tree); + +end + diff --git a/doc/images/winshark-capture-1.PNG b/doc/images/winshark-capture-1.PNG new file mode 100644 index 0000000..c7b9992 Binary files /dev/null and b/doc/images/winshark-capture-1.PNG differ diff --git a/doc/images/winshark-capture-2.PNG b/doc/images/winshark-capture-2.PNG new file mode 100644 index 0000000..ac59b1b Binary files /dev/null and b/doc/images/winshark-capture-2.PNG differ diff --git a/doc/images/winshark-config-1.PNG b/doc/images/winshark-config-1.PNG new file mode 100644 index 0000000..5ada7e5 Binary files /dev/null and b/doc/images/winshark-config-1.PNG differ diff --git a/doc/images/winshark-config-2.PNG b/doc/images/winshark-config-2.PNG new file mode 100644 index 0000000..e340d82 Binary files /dev/null and b/doc/images/winshark-config-2.PNG differ diff --git a/doc/images/winshark-process-id.PNG b/doc/images/winshark-process-id.PNG new file mode 100644 index 0000000..4598030 Binary files /dev/null and b/doc/images/winshark-process-id.PNG differ diff --git a/install/patch.xml b/install/patch.xml new file mode 100644 index 0000000..1c5dbb1 --- /dev/null +++ b/install/patch.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + NOT Installed + + + + \ No newline at end of file diff --git a/libpcap b/libpcap new file mode 160000 index 0000000..7acae62 --- /dev/null +++ b/libpcap @@ -0,0 +1 @@ +Subproject commit 7acae62a1e905ffb0fbb091361c36fb3e8029c25 diff --git a/transluator/CMakeLists.txt b/transluator/CMakeLists.txt new file mode 100644 index 0000000..99397eb --- /dev/null +++ b/transluator/CMakeLists.txt @@ -0,0 +1,23 @@ +set(TRANSLUATOR_SRC + src/DissectorLua.cs + src/DissectorPython.cs + src/Manifest.cs + src/Transluator.cs +) + +add_executable(Transluator ${TRANSLUATOR_SRC}) +set_property(TARGET Transluator PROPERTY VS_DOTNET_TARGET_FRAMEWORK_VERSION "v4.5") +set_property(TARGET Transluator PROPERTY VS_DOTNET_REFERENCES + "System" + "System.Xml" + "System.Runtime" + "${CMAKE_CURRENT_SOURCE_DIR}/third_party/Microsoft.Diagnostics.Tracing.TraceEvent.2.0.36/lib/net45/Microsoft.Diagnostics.Tracing.TraceEvent.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/third_party/Microsoft.Diagnostics.Tracing.TraceEvent.2.0.36/lib/net45/Microsoft.Diagnostics.FastSerialization.dll" +) + +install(TARGETS Transluator DESTINATION .) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/third_party/Microsoft.Diagnostics.Tracing.TraceEvent.2.0.36/lib/net45/Microsoft.Diagnostics.Tracing.TraceEvent.dll" DESTINATION .) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/third_party/Microsoft.Diagnostics.Tracing.TraceEvent.2.0.36/lib/net45/Microsoft.Diagnostics.FastSerialization.dll" DESTINATION .) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/third_party/Microsoft.Diagnostics.Tracing.TraceEvent.2.0.36/lib/net45/Dia2Lib.dll" DESTINATION .) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/third_party/Microsoft.Diagnostics.Tracing.TraceEvent.2.0.36/lib/net45/OSExtensions.dll" DESTINATION .) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/third_party/Microsoft.Diagnostics.Tracing.TraceEvent.2.0.36/lib/net45/TraceReloggerLib.dll" DESTINATION .) \ No newline at end of file diff --git a/transluator/src/DissectorLua.cs b/transluator/src/DissectorLua.cs new file mode 100644 index 0000000..205bb25 --- /dev/null +++ b/transluator/src/DissectorLua.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Xml.Serialization; +using Microsoft.Diagnostics.Tracing.Parsers; +using System.Linq; + +namespace Transluator +{ + static class DissectorLUATemplate + { + public const string PROVIDER = @" +local proto = Proto(""{0}"", ""{0}"") +local event_id = Field.new(""etw.header.EventDescriptor.Id"") +local event_version = Field.new(""etw.header.EventDescriptor.Version"") +local dissector_table = DissectorTable.new(""{0}"", ""{0} {1}"", ftypes.STRING) +local protocols = {{}} +local current_protocol = nil +function proto.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + local id = event_id() + local version = event_version() + dissector_table:try(tostring(id) .. ""."" .. tostring(version) , buffer, pinfo, tree) +end +local etw_dissector_table = DissectorTable.get(""etw"") +etw_dissector_table:add(""{1}"", proto) +"; + public const string EVENT_HEADER = @"current_protocol = Proto(""{0}.{1}.{2}"", ""{0} EventId({1}) Version({2})"")"; + public const string EVENT_FIELD_NAME = @"{0}_{1}"; + public const string EVENT_FIELD = @"{1}(""{2}.{3}.{4}.{0}"", ""{0}"", {5})"; + public const string EVENT_PROTO_FIELD = @"current_protocol.fields = {{ {0} }}"; + + public const string EVENT_DECLARATION = @" +function current_protocol.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + local event_proto_{0}_{1} = protocols[""{0}.{1}""] + pinfo.cols.protocol = event_proto_{0}_{1}.name + pinfo.cols.info = event_proto_{0}_{1}.description + + local fields = tree:add(event_proto_{0}_{1}, buffer()) + local index = 0 + {2} +end +protocols[""{0}.{1}""] = current_protocol +dissector_table:add(""{0}.{1}"", current_protocol) +"; + public const string EVENT_FIELD_DECLARATION_WITH_VALUE = @" + local {{3}}_value = buffer(index, {0}):{1}() + fields:add_le(event_proto_{{0}}_{{1}}.fields[{{2}}], buffer(index, {0})) + index = index + {0} +"; + public const string EVENT_FIELD_DECLARATION_SIMPLE = @" + fields:add_le(event_proto_{{0}}_{{1}}.fields[{{2}}], buffer(index, {0})) + index = index + {0} +"; + + public const string EVENT_FIELD_DECLARATION_UZSTRING = @" + fields:add_le(event_proto_{0}_{1}.fields[{2}], buffer(index, (buffer(index):le_ustringz():len() + 1) * 2), tostring(buffer(index):le_ustringz())) + index = index + (buffer(index):le_ustringz():len() + 1) * 2 +"; + + public const string EVENT_FIELD_DECLARATION_ANSISTRING = @" + fields:add_le(event_proto_{0}_{1}.fields[{2}], buffer(index, (buffer(index):stringz():len() + 1)), tostring(buffer(index):stringz())) + index = index + (buffer(index):stringz():len() + 1) +"; + + public const string EVENT_FIELD_DECLARATION_WITH_LENGTH = @" + fields:add_le(event_proto_{0}_{1}.fields[{2}], buffer(index, {3}_value)) + index = index + {3}_value +"; + + public const string EVENT_FIELD_DECLARATION_SID = @" + fields:add_le(event_proto_{0}_{1}.fields[{2}], buffer(index, 8 + buffer(index + 1, 1):le_int() * 4)) + index = index + 8 + buffer(index + 1, 1):le_int() * 4 +"; + + public static readonly Dictionary> EVENT_DATA_TYPE_CONVERT = new Dictionary>() + { + { Data.InType.Binary, new Tuple("ProtoField.bytes", "base.NONE", EVENT_FIELD_DECLARATION_WITH_LENGTH) }, + { Data.InType.Int8, new Tuple("ProtoField.int8", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 1, "le_int")) }, + { Data.InType.Int16, new Tuple("ProtoField.int16", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 2, "le_int")) }, + { Data.InType.Int32, new Tuple("ProtoField.int32", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 4, "le_int")) }, + { Data.InType.Int64, new Tuple("ProtoField.int64", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 8, "le_int64")) }, + { Data.InType.UInt16, new Tuple("ProtoField.uint16", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 2, "le_uint")) }, + { Data.InType.UInt32, new Tuple("ProtoField.uint32", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 4, "le_uint")) }, + { Data.InType.UInt64, new Tuple("ProtoField.uint64", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 8, "le_uint64")) }, + { Data.InType.UInt8, new Tuple("ProtoField.uint8", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 1, "le_uint")) }, + { Data.InType.GUID, new Tuple("ProtoField.guid", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_SIMPLE, 16)) }, + { Data.InType.UnicodeString, new Tuple("ProtoField.string", "base.UNICODE", EVENT_FIELD_DECLARATION_UZSTRING) }, + { Data.InType.AnsiString, new Tuple("ProtoField.string", "base.ASCII", EVENT_FIELD_DECLARATION_ANSISTRING) }, + { Data.InType.Boolean, new Tuple("ProtoField.int8", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 1,"le_uint")) }, + { Data.InType.Double, new Tuple("ProtoField.double", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 8, "le_float")) }, + { Data.InType.HexInt32, new Tuple("ProtoField.int32", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 4, "le_int")) }, + { Data.InType.HexInt64, new Tuple("ProtoField.int64", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 8, "le_int64")) }, + { Data.InType.FILETIME, new Tuple("ProtoField.int64", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 8, "le_int64")) }, + { Data.InType.Pointer, new Tuple("ProtoField.int64", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 8, "le_int64")) }, + { Data.InType.SYSTEMTIME, new Tuple("ProtoField.bytes", "base.NONE", string.Format(EVENT_FIELD_DECLARATION_SIMPLE, 16)) }, + { Data.InType.SID, new Tuple("ProtoField.bytes", "base.NONE", EVENT_FIELD_DECLARATION_SID) }, + { Data.InType.Float, new Tuple("ProtoField.float", "base.DEC", string.Format(EVENT_FIELD_DECLARATION_WITH_VALUE, 4, "le_float")) }, + }; + + } + + public static class ProviderExtensions + { + public static string FormatProviderName(this Provider provider) + { + return provider.name.Replace(" ", "_"); + } + } + + class DissectorLUA + { + + public Manifest Manifest { get; private set; } + + private static void GenerateProvider(Provider provider, StreamWriter writer) + { + writer.WriteLine(string.Format(DissectorLUATemplate.PROVIDER, provider.FormatProviderName(), provider.guid)); + } + + private static void GenerateEvent(Event etwEvent, Provider provider, StreamWriter writer) + { + writer.WriteLine(string.Format(DissectorLUATemplate.EVENT_HEADER, provider.FormatProviderName(), etwEvent.value, etwEvent.version)); + var template = provider.templates.Where(x => x.tid == etwEvent.template).Single(); + var fields_declaration = template.datas.Select( + x => string.Format( + DissectorLUATemplate.EVENT_FIELD, + x.name, + DissectorLUATemplate.EVENT_DATA_TYPE_CONVERT[x.inType].Item1, + provider.FormatProviderName(), + etwEvent.value, + etwEvent.version, + DissectorLUATemplate.EVENT_DATA_TYPE_CONVERT[x.inType].Item2 + ) + ); + + writer.WriteLine("\n" + + string.Format( + DissectorLUATemplate.EVENT_PROTO_FIELD, + string.Join(", ", fields_declaration) + ) + "\n" + ); + + // build the core parser + var result = ""; + var index = 1; + + foreach (var data in template.datas) + { + if(data.inType == Data.InType.Binary) + { + if(data.length != null) + { + result += string.Format(DissectorLUATemplate.EVENT_DATA_TYPE_CONVERT[data.inType].Item3, etwEvent.value, etwEvent.version, index, data.length.Replace(" ", "")) + "\n"; + } + else if(data.name == "hash") + { + result += string.Format(string.Format(DissectorLUATemplate.EVENT_FIELD_DECLARATION_SIMPLE, 16), etwEvent.value, etwEvent.version, index) + "\n"; + } + else if(data.name == "SHA1Hash") + { + result += string.Format(string.Format(DissectorLUATemplate.EVENT_FIELD_DECLARATION_SIMPLE, 20), etwEvent.value, etwEvent.version, index) + "\n"; + } + else if(data.name == "CredKeyIdentifier") + { + result += string.Format(string.Format(DissectorLUATemplate.EVENT_FIELD_DECLARATION_SIMPLE, 32), etwEvent.value, etwEvent.version, index) + "\n"; + } + } + else if(data.length != null) + { + result += string.Format(DissectorLUATemplate.EVENT_FIELD_DECLARATION_WITH_LENGTH, etwEvent.value, etwEvent.version, index, data.length.Replace(" ", "")) + "\n"; + } + else + { + result += string.Format(DissectorLUATemplate.EVENT_DATA_TYPE_CONVERT[data.inType].Item3, etwEvent.value, etwEvent.version, index, data.name) + "\n"; + } + index++; + } + + writer.WriteLine(string.Format(DissectorLUATemplate.EVENT_DECLARATION, etwEvent.value, etwEvent.version, result)); + } + + public DissectorLUA(Manifest source) + { + this.Manifest = source; + } + + public void create(Stream output) + { + using (var s = new StreamWriter(output)) + { + GenerateProvider(this.Manifest.instrumentation.events.provider, s); + + // delete all event with same value and version (exist in scheme) + var eventSet = new HashSet(this.Manifest.instrumentation.events.provider.events, new EventComparer()); + + foreach (var etwEvent in eventSet) + { + if(etwEvent.template == null) + { + continue; + } + GenerateEvent(etwEvent, this.Manifest.instrumentation.events.provider, s); + } + } + } + } +} diff --git a/transluator/src/DissectorPython.cs b/transluator/src/DissectorPython.cs new file mode 100644 index 0000000..07ab2aa --- /dev/null +++ b/transluator/src/DissectorPython.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Xml.Serialization; +using Microsoft.Diagnostics.Tracing.Parsers; +using System.Linq; + +namespace Transluator +{ + static class DissectorPythonTemplate + { + public const string PROVIDER = @"# -*- coding: utf-8 -*- +"""""" +{0} +GUID : {1} +"""""" +from construct import Int8sl, Int8ul, Int16ul, Int16sl, Int32sl, Int32ul, Int64sl, Int64ul, Bytes, Double, Float32l, Struct +from etl.utils import WString, CString, SystemTime, Guid +from etl.dtyp import Sid +from etl.parsers.etw.core import Etw, declare, guid +"; + + public const string EVENT_TEMPLATE = @" +@declare(guid=guid(""{0}""), event_id={1}, version={2}) +class {3}_{1}_{2}(Etw): + pattern = Struct( +{4} + ) +"; + public const string EVENT_FIELD = @" ""{0}"" / {1}"; + public const string EVENT_FIELD_WITH_LENTH = @" ""{0}"" / Bytes(lambda this: this.{1})"; + public const string EVENT_FIELD_STATIC_LENGTH = @" ""{0}"" / Bytes({1})"; + + public static readonly Dictionary EVENT_DATA_TYPE_CONVERT = new Dictionary() + { + { Data.InType.Binary, "Bytes" }, + { Data.InType.Int8, "Int8sl" }, + { Data.InType.Int16, "Int16sl" }, + { Data.InType.Int32, "Int32sl" }, + { Data.InType.Int64, "Int64sl" }, + { Data.InType.UInt16, "Int16ul" }, + { Data.InType.UInt32, "Int32ul" }, + { Data.InType.UInt64, "Int64ul" }, + { Data.InType.UInt8, "Int8ul" }, + { Data.InType.GUID, "Guid" }, + { Data.InType.UnicodeString, "WString" }, + { Data.InType.AnsiString, "CString" }, + { Data.InType.Boolean, "Int8ul" }, + { Data.InType.Double, "Double" }, + { Data.InType.HexInt32, "Int32ul" }, + { Data.InType.HexInt64, "Int64ul" }, + { Data.InType.FILETIME, "Int64ul" }, + { Data.InType.Pointer, "Int64ul" }, + { Data.InType.SYSTEMTIME, "SystemTime" }, + { Data.InType.SID, "Sid" }, + { Data.InType.Float, "Float32l" }, + }; + + } + + + class DissectorPython + { + + public Manifest Manifest { get; private set; } + + private static void GenerateProvider(Provider provider, StreamWriter writer) + { + writer.WriteLine(string.Format(DissectorPythonTemplate.PROVIDER, provider.name, provider.guid)); + } + + private static void GenerateEvent(Event etwEvent, Provider provider, StreamWriter writer) + { + Console.WriteLine("{0}_{1}_{2}", provider.name.Replace("-", "_").Replace(" ", "_"), etwEvent.value, etwEvent.version); + var template = provider.templates.Where(x => x.tid == etwEvent.template).Single(); + var fields_declaration = new List(); + + + foreach (var data in template.datas) + { + if (data.inType == Data.InType.Binary) + { + if (data.length != null) + { + fields_declaration.Add(string.Format(DissectorPythonTemplate.EVENT_FIELD_WITH_LENTH, data.name, data.length.Replace(" ", ""))); + } + else if (data.name == "hash") + { + fields_declaration.Add(string.Format(DissectorPythonTemplate.EVENT_FIELD_STATIC_LENGTH, data.name, 16)); + } + else if (data.name == "SHA1Hash") + { + fields_declaration.Add(string.Format(DissectorPythonTemplate.EVENT_FIELD_STATIC_LENGTH, data.name, 20)); + } + else if (data.name == "CredKeyIdentifier") + { + fields_declaration.Add(string.Format(DissectorPythonTemplate.EVENT_FIELD_STATIC_LENGTH, data.name, 32)); + } + } + else if (data.length != null) + { + fields_declaration.Add(string.Format(DissectorPythonTemplate.EVENT_FIELD_WITH_LENTH, data.name, data.length.Replace(" ", ""))); + } + else + { + fields_declaration.Add(string.Format(DissectorPythonTemplate.EVENT_FIELD, data.name, DissectorPythonTemplate.EVENT_DATA_TYPE_CONVERT[data.inType])); + } + } + + writer.WriteLine( + string.Format( + DissectorPythonTemplate.EVENT_TEMPLATE, provider.guid, etwEvent.value, etwEvent.version, provider.name.Replace("-", "_").Replace(" ", "_"), + string.Join(",\n", fields_declaration) + ) + ); + } + + public DissectorPython(Manifest source) + { + this.Manifest = source; + } + + public void create(Stream output) + { + using (var s = new StreamWriter(output)) + { + GenerateProvider(this.Manifest.instrumentation.events.provider, s); + + // delete all event with same value and version (exist in scheme) + var eventSet = new HashSet(this.Manifest.instrumentation.events.provider.events, new EventComparer()); + + foreach (var etwEvent in eventSet) + { + if(etwEvent.template == null) + { + continue; + } + GenerateEvent(etwEvent, this.Manifest.instrumentation.events.provider, s); + } + } + } + } +} diff --git a/transluator/src/Manifest.cs b/transluator/src/Manifest.cs new file mode 100644 index 0000000..3c4319a --- /dev/null +++ b/transluator/src/Manifest.cs @@ -0,0 +1,279 @@ +using System; +using System.Xml; +using System.Xml.Serialization; +using System.IO; +using System.Collections.Generic; + +namespace Transluator +{ + [XmlType("map")] + public class Map + { + [XmlAttribute] + public string message; + + [XmlAttribute] + public string value; + } + + [XmlType("valueMap")] + public class ValueMap + { + [XmlAttribute] + public string name; + + [XmlElement("map")] + public List maps; + } + + public class Maps + { + [XmlElement("valueMap")] + public List valueMaps; + } + + [XmlType("opcode")] + public class Opcode + { + [XmlAttribute] + public string name; + + [XmlAttribute] + public string message; + + [XmlAttribute] + public string value; + } + + [XmlType("task")] + public class Task + { + [XmlAttribute] + public string name; + + [XmlAttribute] + public string message; + + [XmlAttribute] + public string value; + + public List opcodes; + } + + [XmlType("event")] + public class Event + { + public enum Level + { + [XmlEnum(Name = "win:Informational")] + Informational, + [XmlEnum(Name = "win:Verbose")] + Verbose, + [XmlEnum(Name = "win:Warning")] + Warning, + [XmlEnum(Name = "win:Error")] + Error, + [XmlEnum(Name = "win:Critical")] + Critical, + [XmlEnum(Name = "win:Always")] + Always + } + + [XmlAttribute] + public string value; + + [XmlAttribute] + public string symbol; + + [XmlAttribute] + public int version; + + [XmlAttribute] + public string task; + + [XmlAttribute] + public Level level; + + [XmlAttribute] + public string template; + + [XmlAttribute] + public string keywords; + + [XmlAttribute] + public string opcode; + } + + public class EventComparer : IEqualityComparer + { + public bool Equals(Event x, Event y) + { + return x.value == y.value && x.version == y.version; + } + + public int GetHashCode(Event obj) + { + return obj.value.GetHashCode() ^ obj.version.GetHashCode(); + } + } + + + [XmlType("data")] + public class Data + { + [XmlAttribute] + public string name; + + public enum InType + { + [XmlEnum(Name = "win:UnicodeString")] + UnicodeString, + [XmlEnum(Name = "win:AnsiString")] + AnsiString, + [XmlEnum(Name = "win:GUID")] + GUID, + [XmlEnum(Name = "win:UInt32")] + UInt32, + [XmlEnum(Name = "win:HexInt32")] + HexInt32, + [XmlEnum(Name = "win:HexInt64")] + HexInt64, + [XmlEnum(Name = "win:Boolean")] + Boolean, + [XmlEnum(Name = "win:UInt16")] + UInt16, + [XmlEnum(Name = "win:Binary")] + Binary, + [XmlEnum(Name = "win:UInt64")] + UInt64, + [XmlEnum(Name = "win:Double")] + Double, + [XmlEnum(Name = "win:UInt8")] + UInt8, + [XmlEnum(Name = "win:Int8")] + Int8, + [XmlEnum(Name = "win:Int16")] + Int16, + [XmlEnum(Name = "win:Int32")] + Int32, + [XmlEnum(Name = "win:Int64")] + Int64, + [XmlEnum(Name = "win:FILETIME")] + FILETIME, + [XmlEnum(Name = "win:Pointer")] + Pointer, + [XmlEnum(Name = "win:SYSTEMTIME")] + SYSTEMTIME, + [XmlEnum(Name = "win:SID")] + SID, + [XmlEnum(Name = "win:Float")] + Float + } + + [XmlAttribute] + public InType inType; + + [XmlAttribute] + public string length; + + [XmlAttribute] + public string count; + + [XmlAttribute] + public string map; + } + + [XmlType("template")] + public class Template + { + [XmlAttribute] + public string tid; + + [XmlElement("data")] + public List datas; + } + + [XmlType("keyword")] + public class Keyword + { + [XmlAttribute] + public string name; + + [XmlAttribute] + public string message; + + [XmlAttribute] + public string mask; + } + + public class Provider + { + [XmlAttribute] + public string name; + + [XmlAttribute] + public Guid guid; + + [XmlAttribute] + public string resourceFileName; + + [XmlAttribute] + public string messageFileName; + + [XmlAttribute] + public string symbol; + + [XmlAttribute] + public string source; + + public List keywords; + + public List tasks; + + public List events; + + public List