Read Me
= agent99
This program was originally called agent99, but I like 'agent99' better. agent99/agent99 is a
program designd to monitor and record activity on a network. It doesn't DO anything with
the data it finds, but just generates an event stream.
I've had two use cases in mind:
- generating events for a network management system
- collecting security-related information to demonstrate the amount of information that can be collected
from passive sniffing of a network.
As supplied, it logs lines to a text file. There is a simple interface to change the
logging functionality. See the description under DESIGN.
It started out as a straight 'C' program, but I changed to C++ after having problems
with lost pointers. Mainly with the string handling functions. It's amazing that 'C' has
been around for so long without any real string functions. No wonder there are so many
buffer overflows out there.
This was implemented a long time ago. It is the first and last C++ program that I ever
wrote, and future plans are to migrate it to another language.
== DESIGN
The core of the program is a single module (a99.cc). There are also some utility modules
(CList, Fact, Var). These implement the data storage and handling functionality.
Logging is done by a descendent of the Logger module. The supplied FileLogger is a
descendent of Logger, and implements logging to a text file.
Information is extracted from network packets by Inspector's. There is a base Inspector
class, with descendends Inspector_Tcp and Inspector_Udp.
For each TCP session, a list of Inspector_Tcp descendents is created. This list remains
associated with this TCP connection until it closes.
For UDP packets, there are no sessions, so only one list of Inspector_Udp descendents is
created. Every UDP packet is presented to every UDP inspector for processing.
TCP inspectors for some protocols are provided (HTTP, Telnet, SMTP etc). To implement a
TCP inspector, copy one of the provided inspectors.
When a new TCP connection is recognised by libnids, agent99 calls each registered TCP
inspector with the details of the connection to see if they want to have access to it's
data. Any inspector that says 'yes' allocates a new instance of itself, which is linked
to the connection. So every TCP connection is monitored by it's own instance of the
appropriate inspector.
When the inspectors initialise, they add incomplete facts to a
per-inspector fact database. For instance, if it wants to store the username and
password of a telnet connection, it could create a fact that looks like:
"host/222.22.22.22/server/tcp/23/client/111.11.11.11/user/%s/pass/%s". Because it
doesn't know the username and password yet, it uses markers (the "%s"'s) in their place.
It then tells the fact database that the first "%s" represents a variable called
"telnet_user", and the next represents a variable called "telnet_pass". When it later
sees other packets on the connection, and recognises a telnet username, it will fillin
the variable "telnet_user" with the value found. If the username it saw was "johnny",
the fact stored in memory would now look like:
host/222.22.22.22/server/tcp/23/client/111.11.11.11/user/johhny/pass/%s
Later, when the password Ieg. 'fred') is seen, the last "%s" would be filled in.
host/222.22.22.22/server/tcp/23/client/111.11.11.11/user/johhny/pass/fred
The sample fact above shows the format for lines as they are generated by agent99. The
above translates to "host 202.33.44.55 is a server for tcp service 23. A user of this
server has a username of johnny and a password of fred"
Other samples are:
host/222.22.22.22/server/tcp/80/server/MyLittleServer/8.7
The web server at 222.22.22.22 is running the software "MyLittleServer/8.7".
host/111.11.11.11/client/tcp/80/user-agent/Mozilla/4.72 [en] (X11; U; Linux 2.2.14-5.0 i686)
The http client on 111.11.11.11 uses the http user-agent "Mozilla/4.72 [en] (X11; U;
Linux 2.2.14-5.0 i686).
host/222.22.22.22/server/tcp/80/client/111.11.11.11/auth/Basic/data/testuser:freddy
The client 111.11.11.11 connected to the http server 222.22.22.22 using HTTP basic authentication. The
authentication data (user:password) was "testuser:freddy".
== STATUS
agent99 performs it's basic function, but is still more of
an experimental framework than a solid implementation. The code shows the effects of my
tinkering and changing things half way through. Once I am happy with it's functionality
and general design I will re-write it properly.
It was also my first and last C++ program. I am not happy with the obfuscation that C++
generates over the functionality, so am planning to re-implement in another language.
Recomendations welcome!
== LIBS
agent99 uses some external libraries. You'll need to have these installed before you can
run it. The numbers in [brackets] after the library name shows the version(s) that this
version of a99 has been tested with:
libnids [1.16] http://www.packetfactory.net/Projects/libnids/
libnet [1.0.2a] http://www.packetfactory.net/projects/libnet/
libpcap [0.4] ftp://ftp.ee.lbl.gov/libpcap.tar.Z
libstr [0.9.4] http://www.engelschall.com/sw/str/ for string handling functions.
== COMPATIBILITY/PROBLEMS
- With Solaris 2.7 and gcc, had to comment the '#include <math.h>' line out of str_p.h in libstr. libstr
then compiled ok.
- If using shared libraries, make sure your system is configured to find them. (ldconfig or LD_LIBRARY_PATH)
# ./a99 -V
ld.so.1: ./a99: fatal: libstr.so.9: open failed: No such file or directory
Killed
# LD_LIBRARY_PATH=/usr/local/lib
# export LD_LIBRARY_PATH
# ./a99 -V
Agent 99 0.0 build 414 11May2001. Copyright Darryl Luff 2000-2001.
#
TESTING
--------
agent99 has been tested on these systems:
- Redhat Linux [6.2,7.0] (works fine)
- Solaris 2.7 (works)
- Solaris 2.6 (works)
// vim:: textwidth=88