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.
- 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.
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 theneteventebpfext
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 thenetevent_sim
driver, which will flow through theneteventebpfext
extension and into thenetevent_monitor
eBPF program, which will store the events in the ring buffer map.
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:
- Export the eBPF program info to the eBPF Store (located in System's registry, under
HKCU\Software\eBPF
). - Load & start the
nteevent_sim.sys
driver. - Load & start the
neteventebpfext.sys
driver. - Load and attach the
netevent_monitor.sys
eBPF program. - Register a callback to read the network events from the ring buffer.
- Display the network events generated by the
nteevent_sim
driver. - Stop and unload all the drivers.
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 typenetevent_monitor
and attaching the to the network event source:sc create neteventebpfext type=kernel start=demand binPath=neteventebpfext.sys sc start neteventebpfext
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.
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.h
defines 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.
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.