Skip to content

Latest commit

 

History

History
169 lines (122 loc) · 7.67 KB

neteventebpfext.md

File metadata and controls

169 lines (122 loc) · 7.67 KB

Net Event eBPF Extension (neteventebpfext)

Introduction

Thi extension provides a way to capture network events generated from kernel components using eBPF. The extension is built on top of the eBPF for Windows, as per the eBPF Extensions model, and leverages the library files from this repo.

Getting Started

Prerequisites

  • eBPF for Windows must be installed. Please follow the instructions in the eBPF for Windows - Getting started guide to install the eBPF for Windows components on a test-enabled Windows machine/VM.

Building & Testing the extension

After cloning the repository, make sure to initialize the submodules by running the following command from the root of the repository:

.\scripts\initialize_repo.ps1

Then, build the ntosebpfext.sln solution from the root of the repository, by running the following command:

msbuild ntosebpfext.sln /p:Configuration=Debug /p:Platform=x64

To regards of this extension, the following artifacts will be generated in the x64\Debug (in this case) directory:

  • netevent_ebpf_ext_export_program_info.exe - A user-mode cmdlet that exports the eBPF program information to the eBPF store.
  • neteventebpfext.sys - The driver that loads the eBPF program and attaches it to the network events.
  • nteevent_sim.sys - The driver that simulates network events.
  • netevent_monitor.sys - The native eBPF program that will be invoked by the neteventebpfext extension upon receiving network events, which will store them in a ring-buffer map.
  • neteventebpfext_unit.exe - An end-to-end unit test that includes a user-mode application that reads the network events from the ring buffer. The test will generate network events using the netevent_sim driver, which will flow through the neteventebpfext extension and into the netevent_monitor eBPF program, which will store the events in the ring buffer map.

Testing

To run the end-to-end unit test, you can use the neteventebpfext_unit.exe application as follows:

# Required only if the eBPF program information is not exported yet
netevent_ebpf_ext_export_program_info.exe

# Run the test with debugging enabled
neteventebpfext_unit.exe -d yes

This test will perform the following steps:

  1. Export the eBPF program info to the eBPF Store (located in System's registry, under HKCU\Software\eBPF).
  2. Load & start the nteevent_sim.sys driver.
  3. Load & start the neteventebpfext.sys driver.
  4. Load and attach the netevent_monitor.sys eBPF program.
  5. Register a callback to read the network events from the ring buffer.
  6. Display the network events generated by the nteevent_sim driver.
  7. Stop and unload all the drivers.

Installing the extension

Once generated the artifacts, to deploy the extension you need to:

  • Export the eBPF program to the system's eBPF store using the netevent_ebpf_ext_export_program_info.exe application:

    netevent_ebpf_ext_export_program_info.exe --clear # Mainly, to clear-out any previous eBPF program information related to this program type.
    netevent_ebpf_ext_export_program_info.exe
  • Load and start the neteventebpfext.sys eBPF extension driver which will enable loading eBPF programs of type netevent_monitor and attaching the to the network event source:

    sc create neteventebpfext type=kernel start=demand binPath=neteventebpfext.sys
    sc start neteventebpfext

Development

eBPF for Windows Extensions use the Network Module Registar (NMR) to interact with the eBPF programs (through eBPF Core), and NMR providers. The neteventebpfext extension is an implementation of an Network Provider Interface (NPI) client that attaches to the network events sourced by providers its same NPI.

Writing an eBPF program that attaches to the neteventebpfext extension

The simplest way to write an eBPF program that attaches to the network events is to review the netevent_monitor.c eBPF program that is provided in the \tools\netevent_monitor project. This program will store the network events in a ring buffer map.

The Network Provider Interface (NPI) in include\ebpf_netevent_hooks.hdefines the following structure for the network events:

typedef struct
{
    unsigned char* event_data_start; ///< Pointer to start of the data associated with the event.
    unsigned char* event_data_end;   ///< Pointer to end of the data associated with the event (i.e. first byte *outside*
                                     ///< the memory range).
} netevent_event_info_t;

To write your own eBPF program, you must create your own project (similar to the netevent_monitor project) and define a section of type netevent_monitor in your eBPF program. The netevent_monitor section is used by the neteventebpfext extension to attach the eBPF program to the network events.

#include "ebpf_helpers.h"
#include "ebpf_netevent_hooks.h" // For the netevent_event_md_t and netevent_event_hook_t definitions.

// Define any eBPF maps that you need here
struct
{
    //... my_map members
} my_map SEC(".maps");

// The following line is optional, but is used to verify
// that the MyNetEventHandler prototype is correct or the compiler
// would complain when the function is actually defined below.
netevent_event_hook_t MyNetEventHandler;

// Define the eBPF program that will be attached to the network events.
SEC("netevent_monitor")
int
MyNetEventHandler(netevent_event_md_t* ctx)
{
    // Your eBPF program logic here

    return 0;
}

The extension supports attaching multiple eBPF programs (as NPI clients), to which the network events will be dispatched.

Writing an NMR provider that generates network events

Under tools\netevent_sim, you can find a simple NMR provider that generates demo network events, with detailed comments. The provider is implemented as a native kernel driver and showcases how to register itself to the NMR as an NPI provider and generate network events using the NMR API through a configurable kernel timer.

In ebpf_extensions\neteventebpfext\netevent_ebpf_ext_event.c you can find the definition of NPIID to be used by the NMR provider, along with the dispatch table exported by the eBPF extension as an NMR client:

const NPIID netevent_npiid = {0x2227e81a, 0x8d8b, 0x11d4, {0xab, 0xad, 0x00, 0x90, 0x27, 0x71, 0x9e, 0x09}};

The dispatch table for the network events provider is defined in ebpf_extensions\neteventebpfext\netevent_ebpf_ext_event.c as follows:

typedef struct _ebpf_helper_function_addresses
{
    ebpf_extension_header_t header;  ///< Common eBPF For Windows Extension header.
    UINT32 helper_function_count;    ///< Number of helper functions in the dispatch table.
    UINT64* helper_function_address; ///< Array of helper function addresses.
} ebpf_helper_function_addresses_t;

Currently, the neteventebpfext extension supports the following helper function (which will so be the only element in the helper_function_address array):

void _ebpf_netevent_push_event(_In_ netevent_event_md_t* netevent_event)

This function will dispatch the network event to all the eBPF programs attached to the extension.

For a more in-depth understanding of NMR and how to develop NPI providers & clients, please refer to the Network Module Registar (NMR) documentation.