Yara-X + PacketSmith Detection Module

A Sneak Peek

Introduction

Version 5 of PacketSmith, codenamed Pinus strobus, is the result of extensive R&D to add unique, unparalleled features that matter to network detection engineers, SoC analysts, and malware and vulnerability researchers. In this release, we’re showcasing a very powerful new feature in PacketSmith: the integration of Yara-X, a state-of-the-art scanning engine and pattern-matching library.

PacketSmith brings the full power of YARA to network traffic analysis. Beyond scanning raw payloads, it exposes deep protocol attributes as nested identifiers within the YARA compiler, enabling rules that target specific network metadata. With versatile filtering, you can tailor your analysis to various data categories—including raw frames, individual TCP/UDP packets, reassembled TCP/UDP streams, and ICMP (v4/v6) payloads. Results are delivered in high-detail via the console, JSON, or XML Workbook format, with the possibility of logging the actual content matches.

Netomize is not aware of any other tool on the market that possesses such capabilities.

The engine supports cross-layer correlation, allowing you to reference any dissected protocol layer simultaneously within a single YARA condition—integrating data from both packet and frame levels into one logic block. For example, you can check the link layer, the network layer and the transport layer, all in the same rule condition.

The official documentation offers in-depth technical specifications alongside advanced, real-world use cases. These examples demonstrate how to leverage PacketSmith’s custom pattern identifiers within YARA-X rules to identify malware C&C traffic and network-based exploitation attempts.

Yara-X and PacketSmith, to a pcap, are what an IDS/IPS is to a pcap/live traffic.

Protocols Exposed

An extensive list of protocols at various network layers has been exposed to provide fine-grained detection capabilities using custom Pattern Identifiers (PaIDs), including:

Object

Description

pcap

The pcap object exposes various pcap header metadata as well-defined attributes.

stream

The stream object provides access to different types of streams, including TCP, UDP and ICMP, at various network layers (IPv4 or IPv6) while supporting traffic directionality.

pkt

The pkt (packet) object provides well-defined attributes that represent specific metadata from the packet header.

ip

The ip object is a unified PaID object that exposes the src and dst addresses for both IPv4 and IPv6. Moreover, it provides the capability to check the type of the IP address (private, loopback, cgnat, link_local, relay, multicast,...).

ip4

The ip4 object exposes most of the IPv4 header attributes, including flags and checking if the IPv4 layer is an IPv4 in IPv6 encapsulation layer.

ip6

The ip6 object exposes most of the IPv6 header attributes, including flags and checks if the IPv6 layer is an IPv6 in IPv4 encapsulation layer. Moreover, all the extensions are exposed via designated pattern identifiers for easier introspection.

ll2

The link layer object ll2.

port

The port object is a unified PaID that works with both the TCP and UDP layers' PaIDs, depending on which layer exists in the packet.

flow

The flow is a unified PaID that works with both the TCP and UDP layers' PaIDs, depending on which layer exists in the packet. 

tcp

The tcp object exposes most of the TCP header attributes, including all the TCP flags and the data payload, aan array of options.

udp

The udp object exposes all the UDP header attributes, including the data payload.

icmp4

The icmp4 object exposes most of the ICMPv4 header attributes, including the data payload.

icmp6

The icmp6 object exposes most of the ICMPv6 header attributes, including the data payload.

dns

The DNS object exposes all of the DNS header attributes, including all the queries and responses, using dedicated structure types. It supports both DNS over UDP and DNS over TCP.

Case Study

In this section, we demonstrate how to leverage the power of the dns object to detect DNS C&C tunnelling traffic in the request and response packets. We’ll take the Denis backdoor, documented publicly by Kaspersky, as an example.

Rather than analyzing the malware’s internal mechanics, this guide focuses on the specific telemetry needed to engineer detection logic. We provide the essential data required to identify DNS-based C&C traffic using PacketSmith’s YARA-X custom PaIDs.

The malware’s pcap denis_bkdr_dns (size: 2,292 bytes) is provided herein for reference.

Denis’s DNS Query Packet

The malware sends a check-in DNS request packet to the server, similar to the following:

Figure 1 - Denis Backdoor DNS Query - Check-in Request

The exfiltrated data in the query name is base64 encoded using the custom alphabet [A-Za-z0-9_-]. Moreover, the DNS request is sent to Google’s public DNS resolver 8.8.8.8 over port 53. The initial check-in request consists of 1 “tunnelling” label/segment of 32 bytes, fixed length.

A sample Yara-X + PacketSmith detection rule utilizing ip4 and dns objects PaIDs, would be structured as follows:

denis_dns_qry.yar
import "string"

rule denis_bkdr_dns_qry_pkt 
{
    meta:
    
      description = "Denis backdoor DNS query packet"
      reference   = "https://securelist.com/use-of-dns-tunneling-for-cc-communications/78203/"
      filter      = "Frames (frames:)"
      sha1        = "1a2cd9b94a70440a962d9ad78e5e46d7d22070d0"
      author      = "Netomize"
      date        = "07/01/2026"

    condition:

	// optional check: ip4.is_set and ip.dst.addr == "8.8.8.8"
	dns.is_set and not dns.over_tcp and not dns.flag.response 
	and 
	dns.flag.opcode == 0 
	and 
	// is recursion desired?
	dns.flag.recdesired
	and
	dns.count.queries == 1		
	and
	dns.qry[0].name.labels.total > 2
	and
	dns.qry[0].type == 10 // NULL
	and
	dns.qry[0].class == 1 // IN
	and

	// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAB-Z.z.teriava.com
	with first_seg = dns.qry[0].name.labels.segments[0] :
	(
		string.length(first_seg) == 32
		and
		first_seg matches /^A{16}[A-Za-z0-9_-]{16}$/
	)
}

The rule checks various attributes in the dns PaID about the malware’s request packet. The dns.qry is an array, and since this is a request packet, only one question/query is sent, thus the array access of index 0. Additionally, the number of labels in the query is also provided as part of the dns object’s nested attributes (L. 25). The DNS type (L. 27) and the class (L. 29) are enforced. Finally, the labels of the DNS name are stored in an array of segments (we refer to the actual label in a domain as a segment). We use the Yara-X with statement to alias the first segment identifier (L. 33), to check its length of 32 fixed characters (L. 35) using the string module, and on line 37, we regex-match the pattern of the segment. 

You may access the entirety of the query’s name using the PaID dns.name.qname. Considering the details of the detection logic, this rule is highly unlikely to cause any false positives.

Including the optional ip.dst.addr == “8.8.8.8” condition may lead to false negatives, as it fails to account for malware variants utilizing alternative DNS resolvers.

Denis’s DNS Response Packet

The C&C server communicates with the malware using specially crafted DNS response packets in the Answers resource record of type NULL (10), class IN (1), with the control commands and data in the data payload.

The C&C server sends a DNS response packet, similar to the following:

Figure 2 - Denis Backdoor DNS Response Packet

The Null data payload carries the server’s specially crafted C&C packet. For the purposes of this detection, it is important to note that the command code is located at offset 0x10 within that payload, and the minimum data length is 20 bytes.

A sample Yara-X + PacketSmith detection rule utilizing the dns objects PaIDs would be structured as follows:

denis_dns_qry.yar
import "math"

rule denis_bkdr_dns_rsp_pkt
{
    meta:
    
      description = "Denis backdoor DNS response packet"
      reference   = "https://securelist.com/use-of-dns-tunneling-for-cc-communications/78203/"
      filter      = "Frames (frames:)"
      sha1        = "1a2cd9b94a70440a962d9ad78e5e46d7d22070d0"
      author      = "Netomize"
      date        = "07/01/2026"

    condition:
		
	 dns.is_set and not dns.over_tcp and dns.flag.response 
	 and 
	 dns.flag.recdesired
	 and
	 dns.count.queries == 1
	 and
	 dns.count.ansr_rr == 1
	 and		
	 with ans = dns.ansr_rr[0], ans_rsize = dns.ansr_rr[0].rdata.size, ans_roffset = dns.ansr_rr[0].rdata.offset :
	 (
	        ans.type  == 10 // NULL
	        and
	        ans.class == 1  // IN
	        and
	        ans_rsize >= 20			
	        and 
	        (
	            // control commands
	            with cmd = uint8(ans_roffset + 0x10) :
	            (
	               cmd == 0x63 
	               or 
	               math.in_range(cmd, 0x01, 0x07)
	               or 
	               math.in_range(cmd, 0x0a, 0x0c)
	               or
	               math.in_range(cmd, 0x0f, 0x14)
	           )
	       )
	         and
	         math.mode(ans_roffset, 20) == 0x00
	  )
}

The Answers resource record is an array of Answers, but in the case of Denis, it is guaranteed that only one Answers rr is returned, thus the array index of 0 at line 22. We use the math module to optimize range-checking for the different control commands (L. 36 – L.42). Moreover, based on the nature of the data of the first 20 bytes in the data payload, we check that the most common byte is 0x00 (L. 46), using the mode function.

The Answers resource record PaID attributes are shown in Table 1. The rdata offset attribute is a raw pointer in the frame and requires bound checking.

And the DNS name PaID attributes are shown in Table 2 (used by the query and all the resource records) :

To run the above rules against a pcap that contains the malware traffic, we execute PacketSmith with the following arguments:

PacketSmith.exe -i denis_bkdr_dns.pcap -D yara:console -F frames:

This uses the frames “frames:<list_frame_ids>” filter via the “—F/—Filter” option to scan every frame in the pcap. Since no specific frame id is provided, all frames are scanned. Other filters are available too that provide direct access to the UDP/TCP data payload and TCP/UDP/ICMP streams payload.

The detection results (the rest are omitted):

- total number of loaded and compiled Yara rules: 9
- Yara scan time: 0s

*** [ Raw Frames ] ***

id     proto       ip.src:port        ip.dst:port        size     entropy     total     rules
--     -----       -----------        -----------        ----     -------     -----     -----
1      IP4-UDP     10.0.2.15:1044     8.8.8.8:53         322      1.96338     1         denis_bkdr_dns_qry_pkt(0)
2      IP4-UDP     8.8.8.8:53         10.0.2.15:1044     164      4.17482     1         denis_bkdr_dns_rsp_pkt(0)

The size column holds the size of the frame, and the entropy column is the entropy of the frame’s data payload.

Conclusion

This article provides a sneak peek into Yara-X’s integration with PacketSmith by showcasing how to use the dns object PaID to detect real-world malicious traffic while leveraging some of Yara-X’s native functionality.


Author: Mohamad Mokbel (Netomize)

First release: February 05, 2026