diff options
Diffstat (limited to 'extcap/etwdump.c')
-rw-r--r-- | extcap/etwdump.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/extcap/etwdump.c b/extcap/etwdump.c new file mode 100644 index 00000000..ea803a70 --- /dev/null +++ b/extcap/etwdump.c @@ -0,0 +1,312 @@ +/* etwdump.c + * etwdump is an extcap tool used to dump etw to pcapng + * + * Copyright 2020, Odysseus Yang + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" +#define WS_LOG_DOMAIN "etwdump" + +#include "extcap-base.h" + +#include <wsutil/strtoi.h> +#include <wsutil/filesystem.h> +#include <wsutil/privileges.h> +#include <wsutil/please_report_bug.h> +#include <wsutil/wslog.h> + +#include <cli_main.h> +#include <wsutil/cmdarg_err.h> +#include "etl.h" + +#include <signal.h> + +/* extcap-interface has to be unique, or it may use wrong option output by a different extcapbin */ +#define ETW_EXTCAP_INTERFACE "etwdump" +#define ETWDUMP_VERSION_MAJOR "1" +#define ETWDUMP_VERSION_MINOR "0" +#define ETWDUMP_VERSION_RELEASE "0" + +enum { + EXTCAP_BASE_OPTIONS_ENUM, + OPT_HELP, + OPT_VERSION, + OPT_INCLUDE_UNDECIDABLE_EVENT, + OPT_ETLFILE, + OPT_PARAMS +}; + +static struct ws_option longopts[] = { + EXTCAP_BASE_OPTIONS, + { "help", ws_no_argument, NULL, OPT_HELP}, + { "version", ws_no_argument, NULL, OPT_VERSION}, + { "iue", ws_optional_argument, NULL, OPT_INCLUDE_UNDECIDABLE_EVENT}, + { "etlfile", ws_required_argument, NULL, OPT_ETLFILE}, + { "params", ws_required_argument, NULL, OPT_PARAMS}, + { 0, 0, 0, 0 } +}; + +int g_include_undecidable_event = false; + +void SignalHandler(_U_ int signal) +{ + SUPER_EVENT_TRACE_PROPERTIES super_trace_properties = { 0 }; + super_trace_properties.prop.Wnode.BufferSize = sizeof(SUPER_EVENT_TRACE_PROPERTIES); + super_trace_properties.prop.Wnode.ClientContext = 2; + super_trace_properties.prop.Wnode.Flags = WNODE_FLAG_TRACED_GUID; + super_trace_properties.prop.LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES); + super_trace_properties.prop.LogFileMode = EVENT_TRACE_REAL_TIME_MODE; + /* Close trace when press CONTROL+C when running this console alone */ + ControlTrace((TRACEHANDLE)NULL, LOGGER_NAME, &super_trace_properties.prop, EVENT_TRACE_CONTROL_STOP); +} + +static void help(extcap_parameters* extcap_conf) +{ + extcap_help_print(extcap_conf); +} + +static int list_config(char* interface) +{ + unsigned inc = 0; + + if (!interface) { + ws_warning("No interface specified."); + return EXIT_FAILURE; + } + + if (g_strcmp0(interface, ETW_EXTCAP_INTERFACE)) { + ws_warning("Interface must be %s", ETW_EXTCAP_INTERFACE); + return EXIT_FAILURE; + } + /* + * required=true agu will be displayed before required=false on UI + * + * Empty etlfile and unempty params, read etw events from a live session with the params as the filter + * Unempty etlfile and empty params, read etw events from the etl file without filter + * Unempty etlfile and unemtpy params, read etw events from the etl file with the params as the filter + * Empty eltfile and empty params, invalid + */ + printf("arg {number=%u}{call=--etlfile}{display=etl file}" + "{type=fileselect}{tooltip=Select etl file to display in Wireshark}{required=false}{group=Capture}\n", + inc++); + printf("arg {number=%u}{call=--params}{display=filter parameters}" + "{type=string}{tooltip=Input providers, keyword and level filters for the etl file and live session}{group=Capture}\n", + inc++); + /* + * The undecidable events are those that either don't have sub-dissector or don't have anthing meaningful to display except for the EVENT_HEADER. + */ + printf("arg {number=%u}{call=--iue}{display=Should undecidable events be included}" + "{type=boolflag}{default=false}{tooltip=Choose if the undecidable event is included}{group=Capture}\n", + inc++); + + extcap_config_debug(&inc); + return EXIT_SUCCESS; +} + +int main(int argc, char* argv[]) +{ + char* err_msg; + int option_idx = 0; + int result; + int ret = EXIT_FAILURE; + + char* etlfile = NULL; + char* params = NULL; + + extcap_parameters* extcap_conf = g_new0(extcap_parameters, 1); + char* help_url; + char* help_header = NULL; + + /* Initialize log handler early so we can have proper logging during startup. */ + extcap_log_init("etwdump"); + + /* + * Get credential information for later use. + */ + init_process_policies(); + + /* + * Attempt to get the pathname of the directory containing the + * executable file. + */ + err_msg = configuration_init(argv[0], NULL); + if (err_msg != NULL) { + ws_warning("Can't get pathname of directory containing the extcap program: %s.", + err_msg); + g_free(err_msg); + } + + help_url = data_file_url("etwdump.html"); + extcap_base_set_util_info(extcap_conf, argv[0], ETWDUMP_VERSION_MAJOR, ETWDUMP_VERSION_MINOR, + ETWDUMP_VERSION_RELEASE, help_url); + g_free(help_url); + extcap_base_register_interface(extcap_conf, ETW_EXTCAP_INTERFACE, "Event Tracing for Windows (ETW) reader", 290, "DLT_ETW"); + + help_header = ws_strdup_printf( + " %s --extcap-interfaces\n" + " %s --extcap-interface=%s --extcap-dlts\n" + " %s --extcap-interface=%s --extcap-config\n" + " %s --extcap-interface=%s --etlfile c:\\wwansvc.etl \n" + "--fifo=FILENAME --capture\n", argv[0], argv[0], ETW_EXTCAP_INTERFACE, argv[0], ETW_EXTCAP_INTERFACE, + argv[0], ETW_EXTCAP_INTERFACE); + extcap_help_add_header(extcap_conf, help_header); + g_free(help_header); + + extcap_help_add_option(extcap_conf, "--help", "print this help"); + extcap_help_add_option(extcap_conf, "--version", "print the version"); + extcap_help_add_option(extcap_conf, "--etlfile <filename>", "A etl filename"); + extcap_help_add_option(extcap_conf, "--iue", "Choose if undecidable event is included"); + + if (argc == 1) { + help(extcap_conf); + goto end; + } + + while ((result = ws_getopt_long(argc, argv, ":", longopts, &option_idx)) != -1) { + switch (result) { + case OPT_VERSION: + extcap_version_print(extcap_conf); + ret = EXIT_SUCCESS; + goto end; + + case OPT_HELP: + help(extcap_conf); + ret = EXIT_SUCCESS; + goto end; + + case OPT_ETLFILE: + etlfile = g_strdup(ws_optarg); + break; + + case OPT_PARAMS: + /* Add params as the prefix since getopt_long will ignore the first argument always */ + params = ws_strdup_printf("params %s", ws_optarg); + break; + + case OPT_INCLUDE_UNDECIDABLE_EVENT: + g_include_undecidable_event = true; + break; + + case ':': + /* missing option argument */ + ws_warning("Option '%s' requires an argument", argv[ws_optind - 1]); + break; + + default: + /* Handle extcap specific options */ + if (!extcap_base_parse_options(extcap_conf, result - EXTCAP_OPT_LIST_INTERFACES, ws_optarg)) + { + ws_warning("Invalid option: %s", argv[ws_optind - 1]); + goto end; + } + } + } + + extcap_cmdline_debug(argv, argc); + + if (extcap_base_handle_interface(extcap_conf)) { + ret = EXIT_SUCCESS; + goto end; + } + + if (extcap_conf->show_config) { + ret = list_config(extcap_conf->interface); + goto end; + } + + if (extcap_conf->capture) { + + if (g_strcmp0(extcap_conf->interface, ETW_EXTCAP_INTERFACE)) { + ws_warning("ERROR: invalid interface"); + goto end; + } + + if (etlfile == NULL && params == NULL) + { + ws_warning("ERROR: Both --etlfile and --params arguments are empty"); + goto end; + } + + wtap_init(false); + + signal(SIGINT, SignalHandler); + + switch(etw_dump(etlfile, extcap_conf->fifo, params, &ret, &err_msg)) + { + case WTAP_OPEN_ERROR: + if (err_msg != NULL) { + ws_warning("etw_dump failed: %s.", + err_msg); + g_free(err_msg); + } + else + { + ws_warning("etw_dump failed"); + } + break; + case WTAP_OPEN_NOT_MINE: + if (etlfile == NULL) + { + if (err_msg != NULL) { + ws_warning("The live session didn't capture any event. Error message: %s.", + err_msg); + g_free(err_msg); + } + else + { + ws_warning("The live session didn't capture any event"); + } + } + else + { + if (err_msg != NULL) { + ws_warning("The file %s is not etl format. Error message: %s.", + etlfile, err_msg); + g_free(err_msg); + } + else + { + ws_warning("The file %s is not etl format", etlfile); + } + } + break; + case WTAP_OPEN_MINE: + ret = EXIT_SUCCESS; + break; + } + } + +end: + /* clean up stuff */ + extcap_base_cleanup(&extcap_conf); + + if (etlfile != NULL) + { + g_free(etlfile); + } + if (params != NULL) + { + g_free(params); + } + + return ret; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |