Simplifying Deep Packet Analytics Rules
In a blog post earlier this year, Using Deep Packet Analytics to Extract Specific Bytes, I introduced a mechanism for looking at specific bytes using Deep Packet Analytics (DPA) rules that were packet-focused. In September, we released LogRhythm NetMon 3.5.1, which had several updated DPA methods. These new methods greatly simplify the process of writing DPA rules and also offer new enhanced capabilities. The information in this blog applies to all NetMon releases from 3.5.1 or higher.
Scanning packet payloads continues to be a highly valuable part of both network analytics and network forensics. These investigations can be the difference between mitigating and missing a threat. Sometimes you just need to dive into the packet-level information!
Matching an Application
One of the key goals for any packet-level rule is to run as fast and efficiently as possible. The rule should exit as early as possible if conditions are not met to continue processing. One of the most common checks is to see if the packet is part of a session with a specific application classification.
For example, you don’t want rules that analyze DNS to waste any time looking at ICMP traffic. NetMon builds an application path that contains the sequence of applications leading up to the terminal application (or application last classified).
For terminal applications such as DNS and ICMP, determining the terminal application is easy. Simply use:
if GetLatestApplication(dpMsg) == dns then…
What if you’re looking at something more sophisticated, such as trying to extract additional handshake details in SSL/TLS communication?
SSL is usually an intermediate application in a multi-part path. For example, Pandora is actually /ip/tcp/ssl/https/pandora. If you are looking for a terminal application of “ssl” using GetLatestApplication, the rule wouldn’t match on Pandora traffic because “ssl” is not the latest application. You could work around the problem by doing a string match on the full application path field, but that is slow and inefficient.
In NetMon 3.5.1, you can use a new method to look for an application anywhere in the path. This method also does the comparison, so you receive a convenient Boolean value:
if HasApplication(dpMsg, ssl) then…
Packets, Payloads, VLANs, and Length
In the Using Deep Packet Analytics to Extract Specific Bytes blog, there were many extra steps to determine if VLAN wrappers existed and how long they might be. The packet numbering was also 1-based (first packet byte is indexed as packet #1) instead of 0-based (first packet byte is indexed as packet #0) like most other systems.
Fortunately, our development team thought the old approach was inefficient and confusing. All of our methods that look for a packet in a sequence are now 0-based indexes, similar to what you would see in Wireshark.
In 3.5.1, we’ve also introduced a new concept of packet vs. payload:
Packet: The raw packet from the very first byte to the very last byte
Payload: The body of the packet, starting after the optional VLAN wrapper, MAC fields, and EthType
In essence, the packet is everything visible to the network interface. The payload is the guts, containing the information you are most likely interested in. Unless you need the VLAN header or the packet header, you should use the payload version of these methods.
With either the packet or the payload, you can perform several functions:
Figure 1: Packet/Payload Functions
If you need to know more about the VLAN offset, you can use a command called GetVLANOffset(msg, packet) to determine how many bytes are in the VLAN header. Typically, the retuned value will be 0 or 4. In some cases, you might find a “double VLAN” and see 8 bytes of VLAN header. Once you get the length of the VLAN offset, you can use the methods above to get the values.
But I Want Hex!
In many security contexts, you might be looking for a specific sequence of hex-based characters. Getting back a string isn’t as useful as seeing the Hexadecimal representation of the characters. Fortunately, you can use two utility functions to work with HEX representations.
The StringToHex function converts the string retrieved from GetPacketString or GetPayloadString into a sequence of hexadecimal characters. Using this method, you can then search for strings of hex values instead of strings of characters.
The HexDump function generates a string that looks like something you’d expect from Wireshark. You’ll see the hexadecimal characters on the left, and the raw string on the right. Unprintable characters are replaced with periods.
Figure 2: HexDump Function
Real-World Examples of DPA Rules
Let’s look at a couple of scenarios where these new methods will matter.
ICMP Tunnel Revisited
In our first example, we’re going back to the Identifying PowerShell Tunneling Through ICMP blog from earlier this year. In that blog, I wanted to identify ICMP packets with a specific signature in the packet payload.
The ICMP packet with the start of the tunnel looked like this:
Figure 3: ICMP Packet
In that blog, to find the signature with the old API methods, you had to:
1. Write a method to identify the VLAN offset
2. Write a method to read a stream of bytes (one byte at a time)
3. Look for ICMP packets
4. Look for ICMP ping requests (byte 35 plus the variable VLAN offset)
5. Get a very specific set of bytes to compare to a signature (first few bytes of payload match Windows)
6. Get a very specific set of bytes that represents the user (bytes 78 + VLAN offset)
7. Convert the raw bytes into a string
8. Log the results
This took several helper methods and some code that was more confusing than I would have liked.
With the methods from NetMon 3.5.1, the helper methods and convoluted structure can be replaced with a shorter and easier-to-read piece of code. In this new process, you only need to:
1. Look for ICMP packets
2. Look for ICMP ping requests
3. Get the full payload and then match the full text signature “Windows PowerShell”
4. Use a regular expression to parse out the user
Figure 4: Detecting Reverse PowerShell
Not only is the new approach much shorter, it is also far more resilient to changes in the Nishang client. Now you can look for the signature regardless of exactly where it is in the data—adding spaces or other padding won’t invalidate the rule!
You can find this complete rule in the NetMon Help under: Deep Packet Analytics –> Deep Packet Analytics Rule Examples –> Detect Reverse PowerShell
A Simple Snort-Like Rule
You can also see the value of the new methods by looking at a typical Snort signature rule. Let’s imagine we have a Snort rule that is:
Alert tcp any <> (msg:”Possible executable”; content:”program cannot be run in DOS mode”)
This Snort rule would fire in any number of scenarios when a portable executable file is sent over the network. Although this signature can be benign, it is one indication of executable code moving from place to place and may be worth investigating.
From a security perspective, this is just one example and not a surefire way to catch all executable traffic. Even as a Snort rule, this example will generate many non-useful true positives. That is, the rule will trigger on PE transfers, but without additional analysis, you can’t determine if the PE transfer is normal, suspicious, or malicious.
In NetMon, you can use the HasApplication method and the GetPayloadString to replicate this rule as follows:
Figure 5: Detecting PE Transfer
The new DPA methods in NetMon 3.5.1 make it much easier and faster to write effective and efficient rules that process packet-level information. Using these methods, NetMon opens a whole new set of possibilities to detect new and interesting network-based threats.
If you are interested in DPA rules or learning more about NetMon, please join our community!