ips_ack.cc
ips_asn1.cc
ips_base64.cc
+ ips_ber_data.cc
+ ips_ber_skip.cc
ips_bufferlen.cc
ips_byte_extract.cc
ips_byte_jump.cc
add_dynamic_module(ips_ack ips_options ips_ack.cc)
add_dynamic_module(ips_asn1 ips_options ips_asn1.cc asn1_detect.cc asn1_detect.h asn1_util.h asn1_util.cc)
add_dynamic_module(ips_base64 ips_options ips_base64.cc)
+ add_dynamic_module(ips_ber_data ips_options ips_ber_data.cc)
+ add_dynamic_module(ips_ber_skip ips_options ips_ber_skip.cc)
add_dynamic_module(ips_bufferlen ips_options ips_bufferlen.cc)
add_dynamic_module(ips_byte_test ips_options ips_byte_test.cc)
add_dynamic_module(ips_byte_jump ips_options ips_byte_jump.cc)
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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_ber_data.cc author Brandon Stultz <brastult@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "framework/cursor.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+#include "hash/hashfcn.h"
+#include "profiler/profiler.h"
+#include "utils/util_ber.h"
+
+using namespace snort;
+
+#define s_name "ber_data"
+
+static THREAD_LOCAL ProfileStats berDataPerfStats;
+
+class BerDataOption : public IpsOption
+{
+public:
+ BerDataOption(uint32_t t) : IpsOption(s_name)
+ { type = t; }
+
+ uint32_t hash() const override;
+ bool operator==(const IpsOption&) const override;
+
+ bool is_relative() override
+ { return true; }
+
+ EvalStatus eval(Cursor&, Packet*) override;
+
+private:
+ uint32_t type;
+};
+
+//-------------------------------------------------------------------------
+// class methods
+//-------------------------------------------------------------------------
+
+uint32_t BerDataOption::hash() const
+{
+ uint32_t a = type, b = 0, c = 0;
+
+ mix_str(a,b,c,s_name);
+ finalize(a,b,c);
+
+ return c;
+}
+
+bool BerDataOption::operator==(const IpsOption& ips) const
+{
+ const BerDataOption& rhs = (const BerDataOption&)ips;
+
+ if ( type != rhs.type )
+ return false;
+
+ return true;
+}
+
+IpsOption::EvalStatus BerDataOption::eval(Cursor& c, Packet*)
+{
+ RuleProfile profile(berDataPerfStats);
+
+ BerReader ber(c);
+ BerElement e;
+
+ if ( !ber.read(c.start(), e) )
+ return NO_MATCH;
+
+ if ( e.type != type )
+ return NO_MATCH;
+
+ if ( !c.add_pos(e.total_length - e.length) )
+ return NO_MATCH;
+
+ return MATCH;
+}
+
+//-------------------------------------------------------------------------
+// module
+//-------------------------------------------------------------------------
+
+static const Parameter s_params[] =
+{
+ { "~type", Parameter::PT_INT, "0:255", nullptr,
+ "move to the data for the specified BER element type" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#define s_help \
+ "rule option to move to the data for a specified BER element"
+
+class BerDataModule : public Module
+{
+public:
+ BerDataModule() : Module(s_name, s_help, s_params) { }
+
+ bool begin(const char*, int, SnortConfig*) override;
+ bool set(const char*, Value&, SnortConfig*) override;
+
+ ProfileStats* get_profile() const override
+ { return &berDataPerfStats; }
+
+ Usage get_usage() const override
+ { return DETECT; }
+
+public:
+ uint32_t type;
+};
+
+bool BerDataModule::begin(const char*, int, SnortConfig*)
+{
+ type = 0;
+ return true;
+}
+
+bool BerDataModule::set(const char*, Value& v, SnortConfig*)
+{
+ if ( v.is("~type") )
+ type = v.get_uint32();
+ else
+ return false;
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// api methods
+//-------------------------------------------------------------------------
+
+static Module* mod_ctor()
+{
+ return new BerDataModule;
+}
+
+static void mod_dtor(Module* m)
+{
+ delete m;
+}
+
+static IpsOption* ber_data_ctor(Module* p, OptTreeNode*)
+{
+ BerDataModule* m = (BerDataModule*)p;
+ return new BerDataOption(m->type);
+}
+
+static void ber_data_dtor(IpsOption* p)
+{
+ delete p;
+}
+
+static const IpsApi ber_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, 0,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ ber_data_ctor,
+ ber_data_dtor,
+ nullptr
+};
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+#else
+const BaseApi* ips_ber_data[] =
+#endif
+{
+ &ber_data_api.base,
+ nullptr
+};
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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_ber_skip.cc author Brandon Stultz <brastult@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "framework/cursor.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+#include "hash/hashfcn.h"
+#include "profiler/profiler.h"
+#include "utils/util_ber.h"
+
+using namespace snort;
+
+#define s_name "ber_skip"
+
+static THREAD_LOCAL ProfileStats berSkipPerfStats;
+
+class BerSkipOption : public IpsOption
+{
+public:
+ BerSkipOption(uint32_t t, bool o) : IpsOption(s_name)
+ { type = t; optional = o; }
+
+ uint32_t hash() const override;
+ bool operator==(const IpsOption&) const override;
+
+ bool is_relative() override
+ { return true; }
+
+ EvalStatus eval(Cursor&, Packet*) override;
+
+private:
+ uint32_t type;
+ bool optional;
+};
+
+//-------------------------------------------------------------------------
+// class methods
+//-------------------------------------------------------------------------
+
+uint32_t BerSkipOption::hash() const
+{
+ uint32_t a = type, b = optional, c = 0;
+
+ mix_str(a,b,c,s_name);
+ finalize(a,b,c);
+
+ return c;
+}
+
+bool BerSkipOption::operator==(const IpsOption& ips) const
+{
+ const BerSkipOption& rhs = (const BerSkipOption&)ips;
+
+ if ( type != rhs.type )
+ return false;
+
+ if ( optional != rhs.optional )
+ return false;
+
+ return true;
+}
+
+IpsOption::EvalStatus BerSkipOption::eval(Cursor& c, Packet*)
+{
+ RuleProfile profile(berSkipPerfStats);
+
+ BerReader ber(c);
+ BerElement e;
+
+ if ( !ber.read(c.start(), e) )
+ return NO_MATCH;
+
+ if ( e.type != type )
+ {
+ if ( optional )
+ return MATCH;
+ else
+ return NO_MATCH;
+ }
+
+ if ( !c.add_pos(e.total_length) )
+ return NO_MATCH;
+
+ return MATCH;
+}
+
+//-------------------------------------------------------------------------
+// module
+//-------------------------------------------------------------------------
+
+static const Parameter s_params[] =
+{
+ { "~type", Parameter::PT_INT, "0:255", nullptr,
+ "BER element type to skip" },
+
+ { "optional", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match even if the specified BER type is not found" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#define s_help "rule option to skip BER element"
+
+class BerSkipModule : public Module
+{
+public:
+ BerSkipModule() : Module(s_name, s_help, s_params) { }
+
+ bool begin(const char*, int, SnortConfig*) override;
+ bool set(const char*, Value&, SnortConfig*) override;
+
+ ProfileStats* get_profile() const override
+ { return &berSkipPerfStats; }
+
+ Usage get_usage() const override
+ { return DETECT; }
+
+public:
+ uint32_t type;
+ bool optional;
+};
+
+bool BerSkipModule::begin(const char*, int, SnortConfig*)
+{
+ type = 0;
+ optional = false;
+ return true;
+}
+
+bool BerSkipModule::set(const char*, Value& v, SnortConfig*)
+{
+ if ( v.is("~type") )
+ type = v.get_uint32();
+
+ else if ( v.is("optional") )
+ optional = true;
+
+ else
+ return false;
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// api methods
+//-------------------------------------------------------------------------
+
+static Module* mod_ctor()
+{
+ return new BerSkipModule;
+}
+
+static void mod_dtor(Module* m)
+{
+ delete m;
+}
+
+static IpsOption* ber_skip_ctor(Module* p, OptTreeNode*)
+{
+ BerSkipModule* m = (BerSkipModule*)p;
+ return new BerSkipOption(m->type, m->optional);
+}
+
+static void ber_skip_dtor(IpsOption* p)
+{
+ delete p;
+}
+
+static const IpsApi ber_skip_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, 0,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ ber_skip_ctor,
+ ber_skip_dtor,
+ nullptr
+};
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+#else
+const BaseApi* ips_ber_skip[] =
+#endif
+{
+ &ber_skip_api.base,
+ nullptr
+};
+
extern const BaseApi* ips_ack[];
extern const BaseApi* ips_asn1[];
extern const BaseApi* ips_base64[];
+extern const BaseApi* ips_ber_data[];
+extern const BaseApi* ips_ber_skip[];
extern const BaseApi* ips_byte_extract[];
extern const BaseApi* ips_byte_jump[];
extern const BaseApi* ips_byte_math[];
PluginManager::load_plugins(ips_ack);
PluginManager::load_plugins(ips_asn1);
PluginManager::load_plugins(ips_base64);
+ PluginManager::load_plugins(ips_ber_data);
+ PluginManager::load_plugins(ips_ber_skip);
PluginManager::load_plugins(ips_byte_extract);
PluginManager::load_plugins(ips_byte_jump);
PluginManager::load_plugins(ips_byte_math);
sfmemcap.h
stats.h
util.h
+ util_ber.h
util_cstring.h
util_jsnorm.h
util_unfold.h
snort_bounds.h
stats.cc
util.cc
+ util_ber.cc
util_cstring.cc
util_jsnorm.cc
util_net.cc
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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.
+//--------------------------------------------------------------------------
+// util_ber.cc author Brandon Stultz <brastult@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "util_ber.h"
+
+namespace snort
+{
+
+bool BerReader::read_int(uint32_t size, uint32_t& intval)
+{
+ unsigned bytes = 0;
+
+ intval = 0;
+
+ // check if we can read int data
+ if ( cursor + size > end )
+ return false;
+
+ for ( unsigned i = 0; i < size; i++ )
+ {
+ uint8_t b = *cursor++;
+
+ // handle null padding
+ if ( bytes == 0 && b == 0 )
+ continue;
+
+ intval <<= 8;
+ intval |= b;
+ bytes++;
+
+ // check if int fits into uint32_t
+ if ( bytes > 4 )
+ return false;
+ }
+
+ return true;
+}
+
+bool BerReader::read_type(uint32_t& type)
+{
+ unsigned bytes = 0;
+ uint8_t b;
+
+ type = 0;
+
+ if ( cursor + 1 > end )
+ return false;
+
+ b = *cursor++;
+
+ if ( (b & 0x1F) != 0x1F )
+ {
+ // short-form type
+ type = b;
+ return true;
+ }
+
+ // long-form type
+ while ( true )
+ {
+ if ( cursor + 1 > end )
+ return false;
+
+ b = *cursor++;
+
+ // handle null padding
+ if ( bytes == 0 && b == 0x80 )
+ continue;
+
+ type <<= 7;
+ type |= b & 0x7F;
+ bytes++;
+
+ // check if type fits into uint32_t
+ if ( bytes > 4 )
+ return false;
+
+ // check continuation bit
+ if ( (b & 0x80) == 0 )
+ break;
+ }
+
+ return true;
+}
+
+bool BerReader::read_length(uint32_t& length)
+{
+ unsigned size;
+ uint8_t b;
+
+ length = 0;
+
+ if ( cursor + 1 > end )
+ return false;
+
+ b = *cursor++;
+
+ if ( (b & 0x80) == 0 )
+ {
+ // short-form length
+ length = b;
+ return true;
+ }
+
+ // long-form length
+ size = b & 0x7F;
+
+ if ( size == 0 )
+ return false;
+
+ if ( !read_int(size, length) )
+ return false;
+
+ return true;
+}
+
+bool BerReader::read(const uint8_t* c, BerElement& e)
+{
+ const uint8_t* start = c;
+
+ if ( c < beg || c > end )
+ return false;
+
+ cursor = c;
+
+ if ( !read_type(e.type) )
+ return false;
+
+ if ( !read_length(e.length) )
+ return false;
+
+ // set BER data pointer
+ e.data = cursor;
+
+ // jump BER data
+ cursor += e.length;
+
+ // cursor must be > start
+ if ( cursor <= start )
+ return false;
+
+ // calculate total BER length
+ e.total_length = cursor - start;
+
+ return true;
+}
+
+bool BerReader::convert(BerElement& e, uint32_t& intval)
+{
+ if ( e.type != BerType::INTEGER )
+ return false;
+
+ if ( e.data < beg || e.data > end )
+ return false;
+
+ // set cursor to int data
+ cursor = e.data;
+
+ if ( !read_int(e.length, intval) )
+ return false;
+
+ return true;
+}
+
+bool BerReader::extract(const uint8_t*& c, uint32_t& intval)
+{
+ BerElement e;
+
+ if ( !read(c, e) )
+ return false;
+
+ // save end of element position
+ c = cursor;
+
+ if ( !convert(e, intval) )
+ return false;
+
+ return true;
+}
+
+bool BerReader::skip(const uint8_t*& c, uint32_t type)
+{
+ BerElement e;
+
+ if ( !read(c, e) )
+ return false;
+
+ if ( e.type != type )
+ return false;
+
+ c = cursor;
+
+ return true;
+}
+
+bool BerReader::data(const uint8_t*& c, uint32_t type)
+{
+ BerElement e;
+
+ if ( !read(c, e) )
+ return false;
+
+ if ( e.type != type )
+ return false;
+
+ c = e.data;
+
+ return true;
+}
+
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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.
+//--------------------------------------------------------------------------
+// util_ber.h author Brandon Stultz <brastult@cisco.com>
+
+#ifndef UTIL_BER_H
+#define UTIL_BER_H
+
+#include "main/snort_types.h"
+#include "framework/cursor.h"
+
+namespace snort
+{
+
+enum BerType
+{
+ BOOLEAN = 1,
+ INTEGER,
+ BIT_STRING,
+ STRING,
+};
+
+struct BerElement
+{
+ uint32_t type;
+ uint32_t length;
+ uint32_t total_length;
+ const uint8_t* data;
+};
+
+class SO_PUBLIC BerReader
+{
+public:
+ BerReader(Cursor& c)
+ {
+ beg = c.buffer();
+ end = c.endo();
+ }
+
+ bool read(const uint8_t* c, BerElement& e);
+
+ bool convert(BerElement& e, uint32_t& intval);
+ bool extract(const uint8_t*& c, uint32_t& intval);
+
+ bool skip(const uint8_t*& c, uint32_t type);
+ bool data(const uint8_t*& c, uint32_t type);
+
+private:
+ bool read_int(uint32_t size, uint32_t& intval);
+
+ bool read_type(uint32_t& type);
+ bool read_length(uint32_t& length);
+
+ const uint8_t* beg;
+ const uint8_t* cursor;
+ const uint8_t* end;
+};
+
+}
+#endif
+