-
Notifications
You must be signed in to change notification settings - Fork 4
Home
The proxy consists of several components described here to aid with the elfbac integration.
The cmake based build links together several static libraries to create the "proxyd" executable.
- libhammer - This is the core parser library. It is currently built and installed separately using its own build system.
- libdnp3hammer - The dnp3 parser that uses and extends libhammer to implement a full dissector for the protocol.
- libproxy - This library implements the logic of the proxy, mainly network code. It coordinates calls to active parser plugin and the system networking APIs.
- proxyd - The entry point does little other than read the command line options and inject the selected parser plugin.
These two libraries can more or less be considered to have the same permissions. They allocate their own memory during global initialization and they should be the only module capable of touching this memory.
After initialization, user code (in this case the proxy) creates one or more StreamProcessor instances. The instances expose a pointer to a heap buffer that proxy code uses to make system calls to fill with arriving TCP stream data. The proxy itself should not be able to write to or deference this "dirty heap data" that is attacker supplied.
Once the buffer has been filled by the operating system, the proxy invokes the feed function on the stream processor, which triggers a set of callback functions depending on the input data. The proxy module will need permissions to be able to read the data in these callbacks, but should not be able to write to it.
The data passed to the callbacks consists primarily of the final results of the parsing process, i.e. the specific data structures representing DNP3 protocol objects. These are allocated during the parse process by libhammer and filled by libdnp3hammer. Second, some callbacks are passed raw frame data which libdnp3hammer copies from the input buffer into a "context"-specific buffer of its own allocation. See the overview section below for details.
The proxy merely coordinates system calls (read/write) on behalf of the active parser plugin (null or dnp3). It should not be able to read or write to the dirty heap. The proxy needs permission to read from "clean heap" (TBD what this actually means since there is no separate heap ATM) for the purposes of logging. The proxy currently logs C-strings (example) that are allocated inside the dnp3hammer library itself and then relies on user code to free them.
ALL: The heap allocated strings for the pretty-printing API will likely need read permission from inside the proxy w/ the current logging library. We can ditch the logging library if it creates problems
The entry point initializes the logging subsystem and injects the selected parser into the proxy library.
The following things can be changed if they create problems for elfbac integration:
- We can ditch the logging library if required and just use std::err or a simple callback.
- We can integrate all of the libproxy and proxyd stuff together if it makes things simpler.
- Quasistatic objects
-
HParser
s mainly - allocated during initialization by libhammer via combinator calls from libdnp3hammer
-
- Input buffer
- contains raw bytes read from the network
- allocated by libdnp3hammer
- written to by the kernel via syscalls from libproxy
- read by libhammer (parsing link-layer frames)
- read by libdnp3hammer (to copy into context buffer)
- "Context" buffer
- contains link-layer frames associated with a specific link-layer address pair
- allocated by libdnp3hammer
- written to by libdnp3hammer (copied direct from input buffer)
- read by kernel (during output) via syscalls from libproxy
- intermediate parse results
- allocated during parsing by libhammer
- written to by libhammer
- may be written by libdnp3hammer? (semantic actions)
- read by libdnp3hammer and libhammer(?)
- final parse results (protocol structs)
- DNP3-specific types (
DNP_*
) - allocated during parsing (indirectly) by libhammer via actions from libdnp3hammer
- written to by libdnp3hammer (semantic actions)
- may be written to by libhammer? (initialization, ...)
- read by libdnp3hammer for pretty-printing
- may be read by libproxy during callbacks?
- DNP3-specific types (
- pretty-printed representations
- allocated by libdnp3hammer
- written to by libdnp3hammer
- read by kernel or libproxy for diagnostic output