From: Pranav Bhalerao (prbhaler) Date: Tue, 19 Oct 2021 10:54:18 +0000 (+0000) Subject: Merge pull request #3108 in SNORT/snort3 from ~AMARNAYA/snort3:vba_trace_option to... X-Git-Tag: 3.1.15.0~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f10f7608abfb7fe3bc8106599c618dafea6ed4bf;p=thirdparty%2Fsnort3.git Merge pull request #3108 in SNORT/snort3 from ~AMARNAYA/snort3:vba_trace_option to master Squashed commit of the following: commit 677a94f271b0e1673c0dd4d2100ab05abe0af2a6 Author: Amarnath Nayak Date: Tue Oct 12 15:03:06 2021 +0000 http_inspect, ips_option: decoupling the vba_data ips option from http_inspect and adding the trace debug option to vba_data --- diff --git a/src/decompress/file_decomp_zip.cc b/src/decompress/file_decomp_zip.cc index 2f929056d..adbcb5738 100644 --- a/src/decompress/file_decomp_zip.cc +++ b/src/decompress/file_decomp_zip.cc @@ -22,7 +22,6 @@ #endif #include "file_decomp_zip.h" -#include "file_olefile.h" #include "helpers/boyer_moore_search.h" #include "utils/util.h" diff --git a/src/decompress/file_olefile.cc b/src/decompress/file_olefile.cc index d2ad7a106..dce7dc4b2 100644 --- a/src/decompress/file_olefile.cc +++ b/src/decompress/file_olefile.cc @@ -60,6 +60,9 @@ void OleFile :: walk_directory_list() FileProperty* node; char* file_name; + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "Parsing the Directory list.\n"); + current_sector = header->get_first_dir(); sector_size = header->get_sector_size(); @@ -137,6 +140,8 @@ void OleFile :: walk_directory_list() else current_sector = INVALID_SECTOR; } + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "End of Directory list parsing.\n"); } FileProperty* DirectoryList :: get_file_node(char* name) @@ -157,7 +162,11 @@ int32_t OleFile :: get_next_fat_sector(int32_t sec_id) if (fat_list and sec_id > INVALID_SECTOR and sec_id < fat_list_len) return fat_list[sec_id]; else + { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "The next sector ID of fat sector %d is not available in fat list.\n", sec_id); return INVALID_SECTOR; + } } // Every index of mini_fat_list array is the minifat sector ID and the value present @@ -167,7 +176,12 @@ int32_t OleFile :: get_next_mini_fat_sector(int32_t sec_id) if (mini_fat_list and sec_id > INVALID_SECTOR and sec_id < mini_fat_list_len) return mini_fat_list[sec_id]; else + { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "The next sector ID of mini fat sector %d is not available in minifat list.\n", + sec_id); return INVALID_SECTOR; + } } // The offset of a sector is header_size + (sector_number * size_of_each_sector). @@ -276,6 +290,9 @@ void OleFile :: get_file_data(char* file, uint8_t*& file_data, int32_t& data_len { memcpy(temp_data, (file_buf + byte_offset), (buf_len - byte_offset)); data_len += buf_len - byte_offset; + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, + CURRENT_PACKET, "Returning with partial data of %d bytes for the " + "file %s.\n", data_len, file); return; } if ((data_len + sector_size) < stream_size) @@ -305,6 +322,9 @@ void OleFile :: get_file_data(char* file, uint8_t*& file_data, int32_t& data_len { memcpy(temp_data, (file_buf + byte_offset), (buf_len - byte_offset)); data_len += buf_len - byte_offset; + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, + CURRENT_PACKET, "Returning with partial data of %d bytes for " + "the file %s.\n", data_len, file); return; } if ((data_len + mini_sector_size) < stream_size) @@ -333,9 +353,15 @@ void OleFile :: populate_fat_list() int32_t max_secchain_cnt = header->get_sector_size()/4; int32_t count = 0; + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "Reading the FAT list array.\n"); fat_list_len = ( header->get_fat_sector_count() * header->get_sector_size() ) / 4; if (fat_list_len < 1) + { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "FAT list array is empty.\n"); return; + } fat_list = new int32_t[fat_list_len]; @@ -368,6 +394,8 @@ void OleFile :: populate_fat_list() else return; } + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "FAT list array is populated.\n"); } // The function populate_mini_fat_list() reads the contents of mini FAT array sectors to @@ -381,9 +409,15 @@ void OleFile :: populate_mini_fat_list() int32_t max_secchain_cnt = header->get_sector_size()/4; int32_t count = 0; + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "Reading the Mini-FAT list array.\n"); mini_fat_list_len = ( header->get_minifat_count() * header->get_sector_size() ) / 4; if (mini_fat_list_len < 1) + { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "Mini-FAT list array is empty.\n"); return; + } mini_fat_list = new int32_t[mini_fat_list_len]; @@ -418,6 +452,8 @@ void OleFile :: populate_mini_fat_list() else current_sector = INVALID_SECTOR; } + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "Mini-FAT list array is populated..\n"); } // API to parse the OLE File Header. @@ -426,14 +462,24 @@ void OleFile :: populate_mini_fat_list() // sector (with SecID 0) always starts at file offset 512. bool OleFile :: parse_ole_header() { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "Staring the OLE header parsing.\n"); header = new OleHeader; if (!header->set_byte_order(file_buf + HEADER_BYTE_ORDER_OFFSET)) + { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, CURRENT_PACKET, + "Invalid byte order in the OLE header. Returning.\n"); return false; + } // Header Signature (8 bytes) is Identification signature of the OLE file, // and must be of the value 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1. if (!header->match_ole_sig(file_buf)) + { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, CURRENT_PACKET, + "Invalid file signature of OLE file. Returning.\n"); return false; + } // Minor Version field should be set to 0x003E. header->set_minor_version(file_buf + HEADER_MINOR_VER_OFFSET); @@ -463,9 +509,13 @@ bool OleFile :: parse_ole_header() header->set_dir_sector_count(file_buf + HEADER_DIR_SECTR_CNT_OFFSET); - // DIFAT array of 32-bit integer fields contains the first 109 FAT sector locations of the compound file. + // DIFAT array of 32-bit integer fields contains the first 109 FAT sector locations of the + // compound file. header->set_difat_array(file_buf + HEADER_DIFAT_ARRY_OFFSET); + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "Parsing of OLE header is done.\n"); + return true; } @@ -478,7 +528,11 @@ int32_t OleFile :: get_file_offset(const uint8_t* data, int32_t data_len) searcher = snort::LiteralSearch::instantiate(search_handle, (const uint8_t*)"ATTRIBUT", 8, true); if (searcher == nullptr) + { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, CURRENT_PACKET, + "Error in the searcher.\n"); return -1; + } int32_t offset = searcher->search(search_handle, data, data_len); delete searcher; @@ -529,7 +583,11 @@ void OleFile :: decompression(const uint8_t* data, int32_t* data_len, uint8_t*& return; if (*data!= SIG_COMP_CONTAINER) + { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, CURRENT_PACKET, + "Invalid Compressed flag.\n"); return; + } header = LETOHS_UNALIGNED(data + 1); @@ -537,6 +595,8 @@ void OleFile :: decompression(const uint8_t* data, int32_t* data_len, uint8_t*& if (((header >> 12) & 0x07) != 0b011) { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "Invalid Chunk signature.\n"); } data += 3; @@ -637,12 +697,21 @@ void OleFile :: find_and_extract_vba(uint8_t*& vba_buf, uint32_t& vba_buf_len) int32_t offset = get_file_offset(data, data_len); if (offset <= 0) { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, + CURRENT_PACKET, + "Stream %s of size %ld does not have VBA code within first detected" + " %d bytes\n", node->get_name(), node->get_stream_size(), data_len); delete[] data1; continue; } data += offset - 4; data_len = data_len - offset + 4; + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, + CURRENT_PACKET, "Stream %s of size %ld has vba code starting at " + "offset %d bytes. First %d bytes will be processed\n", + node->get_name(), node->get_stream_size(), (offset - 4), data_len); + decompression(data, &data_len, vba_buf, &vba_buffer_offset); delete[] data1; if ( vba_buffer_offset >= MAX_VBA_BUFFER_LEN) @@ -666,10 +735,15 @@ void OleFile :: find_and_extract_vba(uint8_t*& vba_buf, uint32_t& vba_buf_len) // an ole file and creating a mapping between the storage/stream name and the // fileproperty object.Afterwards, based on the directory the data is fetched and // extracted & RLE decompression is done. -void oleprocess(const uint8_t* const ole_file, const uint32_t ole_length, uint8_t*& vba_buf, uint32_t& vba_buf_len) +void oleprocess(const uint8_t* const ole_file, const uint32_t ole_length, uint8_t*& vba_buf, + uint32_t& vba_buf_len) { if (ole_length < OLE_HEADER_LEN) + { + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "OLE file data is too short for the inspection. Returning\n"); return; + } std::unique_ptr olefile (new OleFile(ole_file,ole_length)); diff --git a/src/decompress/file_olefile.h b/src/decompress/file_olefile.h index 05179ee64..e42c76ffc 100644 --- a/src/decompress/file_olefile.h +++ b/src/decompress/file_olefile.h @@ -26,7 +26,10 @@ #include #include +#include "detection/detection_engine.h" #include "helpers/literal_search.h" +#include "ips_options/ips_vba_data.h" +#include "main/snort_debug.h" #include "utils/util.h" #include "utils/util_utf.h" @@ -53,6 +56,11 @@ #define DIR_STREAM_SIZE_OFFSET 120 #define DIR_NEXT_ENTR_OFFSET 128 +#define CURRENT_PACKET snort::DetectionEngine::get_current_packet() + +#define VBA_DEBUG(module_name, module_id, log_level, p, ...) \ + trace_logf(log_level, module_name , module_id, p, __VA_ARGS__) + #define memcpy_id(destn, dsize, src, ssize) \ ((dsize>=ssize) ? memcpy(destn, src, ssize) : memcpy( \ destn, src, dsize)) diff --git a/src/decompress/test/file_olefile_test.cc b/src/decompress/test/file_olefile_test.cc index 090d528cb..0a23ab0a7 100644 --- a/src/decompress/test/file_olefile_test.cc +++ b/src/decompress/test/file_olefile_test.cc @@ -33,6 +33,8 @@ #include #include +THREAD_LOCAL const snort::Trace* vba_data_trace = nullptr; + namespace snort { LiteralSearch::Handle* LiteralSearch::setup() { return nullptr; } @@ -43,6 +45,10 @@ void UtfDecodeSession::set_decode_utf_state_charset(CharsetCode) { } bool UtfDecodeSession::decode_utf(unsigned char const*, unsigned int, unsigned char*, unsigned int, int*) { return true; } UtfDecodeSession::UtfDecodeSession() { } +Packet* DetectionEngine::get_current_packet() { return nullptr; } +void trace_vprintf(char const*, unsigned char, char const*, snort::Packet const*, char const*, va_list) { } +uint8_t TraceApi::get_constraints_generation() { return 0; } +void TraceApi::filter(snort::Packet const&) { } } TEST_GROUP(Olefile_oleprocess_test) diff --git a/src/ips_options/CMakeLists.txt b/src/ips_options/CMakeLists.txt index 1d4e81d1a..7bbfb9a97 100644 --- a/src/ips_options/CMakeLists.txt +++ b/src/ips_options/CMakeLists.txt @@ -45,6 +45,8 @@ SET( PLUGIN_LIST ips_tos.cc ips_ttl.cc ips_window.cc + ips_vba_data.cc + ips_vba_data.h ) @@ -70,6 +72,8 @@ set (IPS_SOURCES ips_js_data.cc ips_service.cc ips_so.cc + ips_vba_data.cc + ips_vba_data.h ) if ( HAVE_HYPERSCAN ) diff --git a/src/ips_options/ips_options.cc b/src/ips_options/ips_options.cc index b46344da8..809a3b987 100644 --- a/src/ips_options/ips_options.cc +++ b/src/ips_options/ips_options.cc @@ -44,6 +44,7 @@ extern const BaseApi* ips_service; extern const BaseApi* ips_sha256; extern const BaseApi* ips_sha512; extern const BaseApi* ips_so; +extern const BaseApi* ips_vba_data; #ifdef STATIC_IPS_OPTIONS extern const BaseApi* ips_ack[]; @@ -111,6 +112,7 @@ static const BaseApi* ips_options[] = ips_sha256, ips_sha512, ips_so, + ips_vba_data, nullptr }; diff --git a/src/ips_options/ips_vba_data.cc b/src/ips_options/ips_vba_data.cc new file mode 100644 index 000000000..94412d27f --- /dev/null +++ b/src/ips_options/ips_vba_data.cc @@ -0,0 +1,121 @@ + +//-------------------------------------------------------------------------- +// Copyright (C) 2021 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- +// ips_vba_data.cc author Amarnath Nayak + +#include "ips_vba_data.h" + +#include "framework/module.h" + +using namespace snort; + +THREAD_LOCAL const Trace* vba_data_trace = nullptr; + +CursorActionType VbaDataOption::get_cursor_type() const +{ return CAT_SET_VBA; } + +IpsOption::EvalStatus VbaDataOption::eval(Cursor& c, Packet* p) +{ + RuleProfile profile(vbaDataPerfStats); + + InspectionBuffer buf; + if (!p->flow->gadget->get_fp_buf(buf.IBT_VBA, p, buf)) + return NO_MATCH; + + c.set(s_name, buf.data, buf.len); + return MATCH; +} + + +ProfileStats* VbaDataModule::get_profile() const +{ return &vbaDataPerfStats; } + +void VbaDataModule::set_trace(const Trace* trace) const +{ vba_data_trace = trace; } + + +const TraceOption* VbaDataModule::VbaDataModule::get_trace_options() const +{ + #ifndef DEBUG_MSGS + return nullptr; + #else + static const TraceOption vba_data_trace_options(nullptr, 0, nullptr); + return &vba_data_trace_options; + #endif +} + +//------------------------------------------------------------------------- +// api methods +//------------------------------------------------------------------------- + + +static Module* mod_ctor() +{ + return new VbaDataModule; +} + +static void mod_dtor(Module* m) +{ + delete m; +} + +static IpsOption* vba_data_ctor(Module*, OptTreeNode*) +{ + return new VbaDataOption; +} + +static void vba_data_dtor(IpsOption* p) +{ + delete p; +} + +static const IpsApi vba_data_api = +{ + { + PT_IPS_OPTION, + sizeof(IpsApi), + IPSAPI_VERSION, + 0, + API_RESERVED, + API_OPTIONS, + s_name, + s_help, + mod_ctor, + mod_dtor + }, + OPT_TYPE_DETECTION, + 0, PROTO_BIT__TCP, + nullptr, + nullptr, + nullptr, + nullptr, + vba_data_ctor, + vba_data_dtor, + nullptr +}; + +#ifdef BUILDING_SO +SO_PUBLIC const BaseApi* snort_plugins[] = +#else +const BaseApi* ips_vba_data[] = +#endif +{ + &vba_data_api.base, + nullptr +}; + diff --git a/src/ips_options/ips_vba_data.h b/src/ips_options/ips_vba_data.h new file mode 100644 index 000000000..534899b7f --- /dev/null +++ b/src/ips_options/ips_vba_data.h @@ -0,0 +1,64 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- +// ips_vba_data.h author Amarnath Nayak + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "detection/detection_engine.h" +#include "framework/cursor.h" +#include "framework/ips_option.h" +#include "framework/module.h" +#include "profiler/profiler.h" +#include "trace/trace.h" + +#define s_name "vba_data" +#define s_help \ + "rule option to set the detection cursor to the MS Office Visual Basic for Applications macros buffer" + +static THREAD_LOCAL snort::ProfileStats vbaDataPerfStats; + +extern THREAD_LOCAL const snort::Trace* vba_data_trace; + +class VbaDataOption : public snort::IpsOption +{ +public: + VbaDataOption() : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) { } + + snort::CursorActionType get_cursor_type() const override; + + snort::IpsOption::EvalStatus eval(Cursor&, snort::Packet*) override; +}; + +class VbaDataModule : public snort::Module +{ +public: + VbaDataModule() : Module(s_name, s_help) { } + + snort::ProfileStats* get_profile() const override; + + snort::Module::Usage get_usage() const override + {return DETECT;} + + void set_trace(const snort::Trace* trace) const override; + + const snort::TraceOption* get_trace_options() const override; +}; + diff --git a/src/service_inspectors/http_inspect/http_api.cc b/src/service_inspectors/http_inspect/http_api.cc index 8e6f5f03e..6f7257b45 100644 --- a/src/service_inspectors/http_inspect/http_api.cc +++ b/src/service_inspectors/http_inspect/http_api.cc @@ -117,7 +117,6 @@ extern const BaseApi* ips_http_trailer; extern const BaseApi* ips_http_true_ip; extern const BaseApi* ips_http_uri; extern const BaseApi* ips_http_version; -extern const BaseApi* ips_vba_data; #ifdef BUILDING_SO SO_PUBLIC const BaseApi* snort_plugins[] = @@ -144,7 +143,6 @@ const BaseApi* sin_http[] = ips_http_true_ip, ips_http_uri, ips_http_version, - ips_vba_data, nullptr }; diff --git a/src/service_inspectors/http_inspect/http_msg_body.cc b/src/service_inspectors/http_inspect/http_msg_body.cc index 2a364ff60..9f61c19f5 100644 --- a/src/service_inspectors/http_inspect/http_msg_body.cc +++ b/src/service_inspectors/http_inspect/http_msg_body.cc @@ -526,6 +526,10 @@ const Field& HttpMsgBody::get_decomp_vba_data() uint8_t* buf = nullptr; uint32_t buf_len = 0; + VBA_DEBUG(vba_data_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, CURRENT_PACKET, + "Found OLE file. Sending %d bytes for the processing.\n", + session_data->fd_state->ole_data_len); + oleprocess(session_data->fd_state->ole_data_ptr, session_data->fd_state->ole_data_len, buf, buf_len); if (buf && buf_len) diff --git a/src/service_inspectors/http_inspect/ips_http.cc b/src/service_inspectors/http_inspect/ips_http.cc index 3a4a9af8d..5940ac00c 100644 --- a/src/service_inspectors/http_inspect/ips_http.cc +++ b/src/service_inspectors/http_inspect/ips_http.cc @@ -70,7 +70,6 @@ bool HttpCursorModule::begin(const char*, int, SnortConfig*) break; case HTTP_BUFFER_CLIENT_BODY: case HTTP_BUFFER_RAW_BODY: - case BUFFER_VBA_DATA: inspect_section = IS_BODY; break; case HTTP_BUFFER_RAW_TRAILER: @@ -1202,46 +1201,6 @@ static const IpsApi version_api = nullptr }; -//------------------------------------------------------------------------- -// vba_data -//------------------------------------------------------------------------- -// - -#undef IPS_OPT -#define IPS_OPT "vba_data" -#undef IPS_HELP -#define IPS_HELP "rule option to set the detection cursor to the MS Office Visual Basic for Applications macros buffer" -static Module* vba_data_mod_ctor() -{ - return new HttpCursorModule(IPS_OPT, IPS_HELP, BUFFER_VBA_DATA, CAT_SET_VBA, - PSI_VBA_DATA); -} - -static const IpsApi vba_data_api = -{ - { - PT_IPS_OPTION, - sizeof(IpsApi), - IPSAPI_VERSION, - 1, - API_RESERVED, - API_OPTIONS, - IPS_OPT, - IPS_HELP, - vba_data_mod_ctor, - HttpCursorModule::mod_dtor - }, - OPT_TYPE_DETECTION, - 0, PROTO_BIT__TCP, - nullptr, - nullptr, - nullptr, - nullptr, - HttpIpsOption::opt_ctor, - HttpIpsOption::opt_dtor, - nullptr -}; - //------------------------------------------------------------------------- // plugins //------------------------------------------------------------------------- @@ -1264,5 +1223,4 @@ const BaseApi* ips_http_trailer = &trailer_api.base; const BaseApi* ips_http_true_ip = &true_ip_api.base; const BaseApi* ips_http_uri = &uri_api.base; const BaseApi* ips_http_version = &version_api.base; -const BaseApi* ips_vba_data = &vba_data_api.base;