<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Netomize Official Blog]]></title><description><![CDATA[Netomize is a defensive cybersecurity consultancy provider.]]></description><link>https://blog.netomize.ca</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1770828794671/5f79da1b-6a05-4077-af3c-b5c3a6a5dd1e.png</url><title>Netomize Official Blog</title><link>https://blog.netomize.ca</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 24 Apr 2026 22:10:48 GMT</lastBuildDate><atom:link href="https://blog.netomize.ca/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Detect Shulfar Malware Encrypted TCP C&C Traffic Using PacketSmith Yara-X Detection Module]]></title><description><![CDATA[Introduction
Splunk published a blog post about a variant of the Gh0stRat malware family used in a new campaign delivered alongside the CloverPlus adware. The blog post is titled "Not Just Annoying Ad]]></description><link>https://blog.netomize.ca/detect-shulfar-malware-encrypted-tcp-c-c-traffic-using-packetsmith-yara-x-detection-module</link><guid isPermaLink="true">https://blog.netomize.ca/detect-shulfar-malware-encrypted-tcp-c-c-traffic-using-packetsmith-yara-x-detection-module</guid><category><![CDATA[packetsmith]]></category><category><![CDATA[yara-x]]></category><category><![CDATA[Malware]]></category><category><![CDATA[PCAP]]></category><category><![CDATA[detection engineering ]]></category><category><![CDATA[network traffic]]></category><category><![CDATA[Virustotal]]></category><category><![CDATA[shulfar]]></category><category><![CDATA[encrypted_traffic]]></category><category><![CDATA[TCP]]></category><dc:creator><![CDATA[Netomize Official Blog]]></dc:creator><pubDate>Fri, 24 Apr 2026 19:27:15 GMT</pubDate><content:encoded><![CDATA[<h1>Introduction</h1>
<p>Splunk published a blog post about a variant of the Gh0stRat malware family used in a new campaign delivered alongside the CloverPlus adware. The blog post is titled "<a href="https://www.splunk.com/en_us/blog/security/detecting-ghost-rat-cloverplus-adware-loader-analysis.html">Not Just Annoying Ads: Adware Bundles Delivering Gh0st RAT</a>", dated April 17, 2026. Although Splunk detects the RAT as a variant of the Gh0stRat family, Netomize refutes linking this variant to the Gh0stRat family due to major differences in code structure, C&amp;C communication protocols, and functionality. Instead, we refer to it as "Shulfar," the reverse of the DLL Export name "RAFlush".</p>
<p>The malware utilizes two communication channels: one via the HTTP protocol and the other through a custom TCP packet payload. Notably, the custom TCP protocol employs a straightforward encryption algorithm, using XOR and addition with a one-byte key, to encrypt the TCP packet's payload.</p>
<p>The malware is a 32-bit DLL written in C. I've chosen it to showcase the "yara" detection module in PacketSmith, highlighting its ability to detect encrypted traffic without relying on a specific key.</p>
<p>The variant with the following information (in the table shown below) matches the "Gh0stRat" variant referenced by the Splunk Threat Research Team. The sample is available on <a href="https://www.virustotal.com/gui/file/ec6ef50587a847d4a655e9bfc5c1aee4078005c0774a3e6fa23949cc4d8fbad3/detection"><strong>VT</strong></a>.</p>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Value</th>
</tr>
</thead>
<tbody><tr>
<td>MD5</td>
<td>20e7a8b973ac2b43c95ddb77308266c9</td>
</tr>
<tr>
<td>SHA-1</td>
<td>e46e6ea272ae628d15bfb7b71ff40e3950fd2e85</td>
</tr>
<tr>
<td>SHA-256</td>
<td>ec6ef50587a847d4a655e9bfc5c1aee4078005c0774a3e6fa23949cc4d8fbad3</td>
</tr>
<tr>
<td>File Size</td>
<td>158856 bytes</td>
</tr>
<tr>
<td>File Type</td>
<td>Win32 DLL</td>
</tr>
</tbody></table>
<p><strong>Table 1</strong> - Malware Basic Properties</p>
<p>Please refer to our previous blog post, "<a href="https://blog.netomize.ca/detect-snappyclient-c-c-traffic-using-packetsmith-yara-x-detection-module">Detect SnappyClient C&amp;C Traffic Using PacketSmith + Yara-X Detection Module</a>", for more information about how to use the PacketSmith "yara" detection module.</p>
<p>The malware is packed. This blog post primarily focuses on the custom TCP packet payload.</p>
<p>Shulfar communicates with the C&amp;C server 107.163.56.251 over TCP/6658. It sends a packet similar to the following:</p>
<img src="https://cdn.hashnode.com/uploads/covers/698bbaaf2b3404faadd9aff8/1d9f1914-f6af-4b83-8905-3d5812e49347.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Figure 1</strong> - Shulfar Encrypted Checkin Packet (TCP payload)</p>
<p>I've made the pcap available for download via Netomize's official repo (RFiles), <a href="https://github.com/Netomize/RFiles/blob/main/packetsmith/shulfar_traffic.pcap">Shulfar packet capture</a> (4,678 bytes).</p>
<p>The packet includes system-specific information and some hardcoded values. Before being sent to the C&amp;C server, it is encrypted with a fixed one-byte key, specifically 0x64. The decrypted packet corresponds to:</p>
<img src="https://cdn.hashnode.com/uploads/covers/698bbaaf2b3404faadd9aff8/4879efaf-b7fc-40e7-a8a3-aaa822de51dc.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Figure 2</strong> - Shulfar Decrypted Checkin Packet (TCP payload)</p>
<p>The structure of the packet in <strong>Figures</strong> <strong>1</strong> and <strong>2</strong> is as follows:</p>
<table>
<thead>
<tr>
<th>Offset</th>
<th>Length</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td>0x00</td>
<td>0x40</td>
<td>Processor name, and if unsuccessful, set it to "Find CPU Error".</td>
</tr>
<tr>
<td>0x40</td>
<td>0x20</td>
<td>Total physical memory in MB (format, "%u MB").</td>
</tr>
<tr>
<td>0x60</td>
<td>0x20</td>
<td>OS version (format, "Win %s SP%d").</td>
</tr>
<tr>
<td>0x80</td>
<td>0x20</td>
<td>Unique constant identifier ("10151338").</td>
</tr>
<tr>
<td>0xA0</td>
<td>0x80</td>
<td>If the file "C:\qylxnhy\lang.ini" exists and includes the substring "http://" but not "search", retrieve the file's buffer (with a length of 253 bytes). Otherwise, return the hardcoded C&amp;C server address "<a href="http://107.163.56.250:18963/main.php">http://107.163.56.250:18963/main.php</a>".</td>
</tr>
<tr>
<td>0x120</td>
<td>0x04</td>
<td>System default UI language ID (for example, 0x0409 en-US).</td>
</tr>
<tr>
<td>0x124</td>
<td>0x04</td>
<td>Fixed value 0xffffffff (-1).</td>
</tr>
</tbody></table>
<p><strong>Table 1</strong> - TCP Packet Structure</p>
<p>Note - 1: The packet has a fixed length of 296 bytes. If the data at offset 0xA0 is read from the "lang.ini" file and exceeds 128 bytes, the file's content will overflow into the rest of the packet's buffer.</p>
<p>The following high-level pseudocode snippet illustrates how the packet is constructed:</p>
<pre><code class="language-cpp">// function rva 0x10005753 (for the dumped DLL with fixed IAT)
int __cdecl collect_sys_info_checkin_pkt(packet_cinfo *pkt_data)
{
  int ram_size;
  LANGID SystemDefaultUILanguage;
  BYTE Data[260];
  CHAR server_addr_from_file[253];
  CHAR SubKey[48];
  _MEMORYSTATUSEX Buffer;
  DWORD Type;
  DWORD cbData;
  HKEY phkResult;

  qmemcpy(SubKey, aHardwareDescri, sizeof(SubKey));
  
  if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, SubKey, 0, KEY_ALL_ACCESS, &amp;phkResult) )
  {
    j_strcpy(pkt_data, aFindCpuError);
  }
  else
  {
    Type = 4;
    cbData = 200;
    reg_query_value(phkResult, aProcessornames, 0, &amp;Type, Data, &amp;cbData);
    reg_close_key(phkResult);
    j_strcpy(pkt_data, Data);
  }
  
  // copy processor name
  copy_buffer_skip_leading_wspaces(pkt_data);
  get_os_version_info(pkt_data-&gt;os_ver_info);
  
  Buffer.dwLength = 64;
  GlobalMemoryStatusEx(&amp;Buffer);
  ram_size = convert_to_mb(Buffer.ullTotalPhys, 20u);
  wvsprintfA_0(pkt_data-&gt;physical_mem, aUMb, (ram_size + 1));
  
  j_strcpy(pkt_data-&gt;identifier, a10151338);    // "10151338"
  
  SystemDefaultUILanguage = GetSystemDefaultUILanguage();
  server_addr_from_file[0] = 0;
  pkt_data-&gt;lang_id = SystemDefaultUILanguage;
  
  memset(&amp;server_addr_from_file[1], 0, 252u);
  
  pkt_data-&gt;const_delimiter = 0xFFFFFFFF;

  if ( check_lang_ini_file(server_addr_from_file, 256u) )
  {
	  return j_strcpy(pkt_data-&gt;server_addr, server_addr_from_file);
  }
  else
  {	  
	// "http://107.163.56.250:18963/main.php"
    return wvsprintfA_0(pkt_data-&gt;server_addr, aS, aHttp1071635625);
  }
}
</code></pre>
<p>And the encryption algorithm pseudocode is:</p>
<pre><code class="language-cpp">int __cdecl encrypt_traffic(int data, int dsize, uint8_t key)
{
  int result;
  int i;
  char edata;

  result = key / 254;
  for ( i = 0; i &lt; dsize; *result = edata )
  {
    result = i + data;
    edata = key % 254 + 1 + (*(i + data) ^ (key % 254 + 1));
    ++i;
  }
  return result;
}
</code></pre>
<p>The initial key provided to the encrypt_traffic function is 0x63, and the final derived key is 0x64. This means the key has to be between 1 and 254. Therefore, to decrypt the traffic, you subtract 0x64 from every byte and XOR it with the same key (0x64).</p>
<p>The server response is neither encrypted nor compressed; the malware anticipates receiving a fixed-size packet of 188 bytes (0xbc) for control commands from the server.</p>
<h1><strong>Detection Logic</strong></h1>
<p>With the packet structure documented and the encryption algorithm understood, we can use <a href="https://virustotal.github.io/yara-x/docs/writing_rules/rule-conditions/#operators">Yara-X operators</a> to simulate the decryption process on the packet's payload, searching for fixed bytes at specific offsets and ranges. We look for " <code>MB\x00</code>" and "<code>Win</code> " among these fixed bytes. Additionally, we verify that the packet's payload size is set to <code>296</code>. While we could include more atomic indicators in the detection logic, it's unnecessary. The two fixed content matches we check for at specific offsets and within a specific range are sufficient to prevent any potential false positives in their encrypted format.</p>
<p>We could derive a rule similar to the following:</p>
<pre><code class="language-cpp">rule shulfar_malware_encrypted_tcp_packet
{
    meta:

	  description = "Detecting Shulfar malware encrypted checkin TCP packet"
      filter      = "Frames (frames:)"
	  sha1        = "e46e6ea272ae628d15bfb7b71ff40e3950fd2e85"
	  reference   = "https://www.splunk.com/en_us/blog/security/detecting-ghost-rat-cloverplus-adware-loader-analysis.html"
	  author      = "Netomize"
	  date        = "04/24/2026"
        
    condition:

		tcp.is_set
		and
		math.in_range(port.src, 1024, 65535) // ephemeral ports
		and
		tcp.data.size == 296
		and
        for any key in (0..255) : 
		(
            for any pos in (tcp.data.offset + 64..tcp.data.offset + 96) : 
			(
                (
					// check for ' ' (0x20)
                    (((uint8(pos) - ((key % 254) + 1)) &amp; 0xff) ^ ((key % 254) + 1))     == 0x20 
					and
                    // check for 'M' (0x4D)
                    (((uint8(pos + 1) - ((key % 254) + 1)) &amp; 0xff) ^ ((key % 254) + 1)) == 0x4d 
					and                    
                    // check for 'B' (0x42) 
                    (((uint8(pos + 2) - ((key % 254) + 1)) &amp; 0xff) ^ ((key % 254) + 1)) == 0x42
					and                    
                    // check for null byte (0x00)
                    (((uint8(pos + 3) - ((key % 254) + 1)) &amp; 0xff) ^ ((key % 254) + 1)) == 0x00
                )
            )
			
			and
			
            for any pos in (tcp.data.offset + 96..tcp.data.offset + 128) : 
			(
                (
					// check for 'W' (0x57)
                    (((uint8(pos) - ((key % 254) + 1)) &amp; 0xff) ^ ((key % 254) + 1))     == 0x57 
					and
                    // check for 'i' (0x69)
                    (((uint8(pos + 1) - ((key % 254) + 1)) &amp; 0xff) ^ ((key % 254) + 1)) == 0x69 
					and                    
                    // check for 'n' (0x6e) 
                    (((uint8(pos + 2) - ((key % 254) + 1)) &amp; 0xff) ^ ((key % 254) + 1)) == 0x6e 
					and                    
                    // check for ' ' byte (0x20)
                    (((uint8(pos + 3) - ((key % 254) + 1)) &amp; 0xff) ^ ((key % 254) + 1)) == 0x20
                )
            )
        )
}
</code></pre>
<p>The detection rule ensures the ephemeral source port range and packet data size are enforced. To verify the fixed content matches " MB\x00" and "Win ", regardless of any specific encryption key, we iterate over all possible keys and establish two loops to check each content match at their respective offsets in the packet.</p>
<h1>Conclusion</h1>
<p>This article demonstrates the capabilities of the PacketSmith "yara" detection module in identifying encrypted traffic without relying on a specific key by simulating the decryption algorithm for all possible keys. Additionally, we have detailed the construction of Shulfar's custom C&amp;C traffic over the TCP channel.</p>
<hr />
<p>Author: Mohamad Mokbel</p>
<p>First release: April 24, 2026</p>
]]></content:encoded></item><item><title><![CDATA[Detect SnappyClient C&C Traffic Using PacketSmith + Yara-X Detection Module]]></title><description><![CDATA[Introduction
Zscaler published a blog post about a new malware called SnappyClient, written in the C++ programming language. The malware communicates with its C&C server using a custom binary protocol]]></description><link>https://blog.netomize.ca/detect-snappyclient-c-c-traffic-using-packetsmith-yara-x-detection-module</link><guid isPermaLink="true">https://blog.netomize.ca/detect-snappyclient-c-c-traffic-using-packetsmith-yara-x-detection-module</guid><category><![CDATA[packetsmith]]></category><category><![CDATA[yara-x]]></category><category><![CDATA[snappyclient]]></category><category><![CDATA[Malware]]></category><category><![CDATA[PCAP]]></category><category><![CDATA[detection engineering ]]></category><category><![CDATA[network traffic]]></category><category><![CDATA[Virustotal]]></category><dc:creator><![CDATA[Netomize Official Blog]]></dc:creator><pubDate>Mon, 23 Mar 2026 19:18:18 GMT</pubDate><content:encoded><![CDATA[<h1>Introduction</h1>
<p>Zscaler published a blog post about a new malware called <a href="https://www.zscaler.com/blogs/security-research/technical-analysis-snappyclient">SnappyClient</a>, written in the C++ programming language. The malware communicates with its C&amp;C server using a custom binary protocol. The traffic is encrypted with ChaCha20-Poly1305 using a key and nonce received from the server, which are exchanged and validated before any control commands are sent or received. I've selected this sample because the C&amp;C traffic structure is almost unfilterable, even with a traditional IDS/IPS, without incurring a high rate of false positives or significant performance impact.</p>
<p>The variant with the following information (in the table shown below) matches the C&amp;C traffic dissected by Zscaler threat research blog. The sample is available on <a href="https://www.virustotal.com/gui/file/eb523f6b0f306ce9fb68adeadac41d2c25b720075f03c75bd3611584dee28cf9/details">VT</a>.</p>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Value</th>
</tr>
</thead>
<tbody><tr>
<td>MD5</td>
<td>ec8258adfbf4ba5b9e8a06d75c5634cc</td>
</tr>
<tr>
<td>SHA-1</td>
<td>feb928a54be40ad4bbf245aaae6968f83b4937f5</td>
</tr>
<tr>
<td>SHA-256</td>
<td>eb523f6b0f306ce9fb68adeadac41d2c25b720075f03c75bd3611584dee28cf9</td>
</tr>
<tr>
<td>File size</td>
<td>3053296 bytes</td>
</tr>
<tr>
<td>File Type</td>
<td>Win32 EXE</td>
</tr>
</tbody></table>
<p>VT's sandbox has a full capture of the C&amp;C traffic, and I've made it available for download via Netomize's official repo (RFiles), <a href="https://github.com/Netomize/RFiles/blob/main/packetsmith/snappyclient_traffic_vt_sandbox_md5_ec8258adfbf4ba5b9e8a06d75c5634cc.pcap">SnappyClient Traffic VT</a> (48.9 KB).</p>
<p>This blog post is about writing detection logic for the C&amp;C traffic based on PacketSmith + Yara-X detection module, using custom pattern identifiers. For an in-depth analysis of how the malware works, please refer to the <a href="https://www.zscaler.com/blogs/security-research/technical-analysis-snappyclient">Zscaler blog post</a>.</p>
<p>Once the malware successfully connects to the server, it receives a ChaCha20 key, a nonce, and a control session ID. Subsequently, SnappyClient sends an encrypted packet with the message header, followed by another packet containing the encrypted and compressed message. Our focus is on the structure of the second packet sent by the malware to the server, used for reporting back to the C&amp;C server. This packet is transmitted via the TCP protocol over ports 3333/3334 to the C&amp;C server at 151[.]242[.]122[.]227.</p>
<img src="https://cdn.hashnode.com/uploads/covers/698bbaaf2b3404faadd9aff8/2bc7a9c7-c1c4-4574-821c-97a20e89bbb1.jpg" alt="SnappyClient C&amp;C Traffic" style="display:block;margin:0 auto" />

<p>Figure 1 - SnappyClient Egress Cmd Packet</p>
<p>The structure of the packet in Figure 1 is as follows:</p>
<table>
<thead>
<tr>
<th>Offset</th>
<th>Length</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td>0x00</td>
<td>0x02</td>
<td>Packet length in little-endian, starting from offset 0x03</td>
</tr>
<tr>
<td>0x02</td>
<td>0x01</td>
<td>A flag indicating whether the packet contains output tag data or not (the data in the green box). 0x00 or 0x01</td>
</tr>
<tr>
<td>0x03</td>
<td>uint16(0x00)</td>
<td>Encrypted message (including output tag, depending on whether the flag at offset 0x02 is set or not)</td>
</tr>
</tbody></table>
<h1>Detection Logic</h1>
<p>With the packet structure documented, we can develop detection logic to avoid false positives. The packet lacks unique content for anchoring, except for the byte at offset 0x02, which can be 0x00 or 0x01. This is insufficient for quick pattern matching in real-time traffic. Additionally, the encrypted message begins at offset 0x03 and continues to the packet's end, minus the 16-byte output tag size if the flag at offset 0x02 is set.</p>
<p>Understanding these limitations and indicators, we can develop a Yara-X + PacketSmith detection rule utilizing custom PaIDs (Pattern Identifiers) such as <code>tcp</code>, <code>ip</code>, and <code>flow</code>, along with the advanced math tools and operations built into Yara-X.</p>
<p>We could derive a rule similar to the following:</p>
<pre><code class="language-cpp">import "math"

rule snappyclient_malware_encrypted_pkt 
{ 
  meta:

    description = "TCP encrypted and compressed packet (client-&gt;server)"
    reference   = "https://www.zscaler.com/blogs/security-research/technical-analysis-snappyclient"
    filter      = "Frames (frames:)"
    sha1        = "feb928a54be40ad4bbf245aaae6968f83b4937f5"
    author      = "Netomize"
    date        = "22/03/2026"	

condition:

   tcp.is_set and ip4.is_set and not ip4.in_ip6 
   and 
   tcp.data.size &gt; 3
   and
   ip.dst.type == 1 // public
   and 
   flow.to_server   // direction
   and 
   math.in_range(port.src, 1024, 65535) // ephemeral ports
   and		
   with buf_size = uint16(tcp.data.offset), buf_offset = tcp.data.offset:
  	(
  		buf_size == (tcp.data.size - 3)
  		and
		( uint8(buf_offset + 2) == 0x00 or uint8(buf_offset + 2) == 0x01 )
		and
		math.entropy(buf_offset + 2, buf_size) &gt;= 4
		and
		math.count(0x00, buf_offset + 2, buf_size) &lt; 8
  	)
}
</code></pre>
<p>The rule checks for the following atomic indicators</p>
<ul>
<li><p>First, we check that we're dealing with a TCP packet over IPv4 using the <code>tcp.is_set</code> and <code>ip4.is_set</code> PaIDs, respectively, while ensuring that this is not an encapsulated IPv4 in IPv6 packet (<code>not ip4.in_ip6</code>)</p>
</li>
<li><p>The minimum size of the TCP payload is 3 bytes (<code>tcp.data.size &gt; 3</code>)</p>
</li>
<li><p>PacketSmith <code>ip</code> PaID can infer the type of the IP address using enum values (PUBLIC = 1, UNSPECIFIED = 2, PRIVATE = 3, CGNAT = 4, LOOPBACK = 5, LINK_LOCAL = 6, IETF_ASSIGNMENTS = 7, DOCUMENTATION = 8 and RELAY = 9, among others)</p>
<ul>
<li>The destination IP address is public (<code>ip.dst.type == 1</code>)</li>
</ul>
</li>
<li><p>The directionality of the packet is to the server (<code>flow.to_server</code>)</p>
</li>
<li><p>Using the "math" module <code>in_range</code> function, we check the range of the ephemeral source port such that it is between 1024 and 65535 (<code>math.in_range(port.src, 1024, 65535)</code>)</p>
</li>
<li><p>We use the <code>with</code> statement to alias the TCP packet payload offset and size</p>
<ul>
<li><code>with buf_size = uint16(tcp.data.offset), buf_offset = tcp.data.offset:</code></li>
</ul>
</li>
<li><p>The uint16 value at offset 0x00 in the TCP payload is equal to the payload's size, minus the first 3 bytes (the header)</p>
<ul>
<li><code>buf_size == (tcp.data.size - 3)</code></li>
</ul>
</li>
<li><p>The byte at offset 0x02 could be either 0x00 or 0x01</p>
<ul>
<li><code>( uint8(buf_offset + 2) == 0x00 or uint8(buf_offset + 2) == 0x01 )</code></li>
</ul>
</li>
<li><p>Since the data is encrypted and compressed, the entropy of the data has to be &gt;= 4</p>
<ul>
<li><p><code>math.entropy(buf_offset + 2, buf_size) &gt;= 4</code></p>
</li>
<li><p>You can safely increase the value if you want to check for large encrypted messages</p>
</li>
</ul>
</li>
<li><p>Finally, using the "math" module and the function <code>count()</code>, we check the encrypted data in the packet for all occurrences of the byte 0x00 such that it is &lt; 8</p>
<ul>
<li><code>math.count(0x00, buf_offset + 2, buf_size) &lt; 8</code></li>
</ul>
</li>
</ul>
<p>Running the above Yara-X rule through the linked pcap via PacketSmith and saving the result as XML, we get the file <a href="https://github.com/Netomize/RFiles/blob/main/packetsmith/yara_dte_2026_03_23_17_11_08.xml">yara_dte_2026_03_23_17_11_08.xml</a> (use MS Excel to view it) with all the detections:</p>
<p><code>PacketSmith.exe -i &lt;infile_pcap&gt; -D yara:xml -F frames: -O .</code></p>
<p>To check for potential false positives, we applied the detection rule to two large pcaps from our collection (511MB and 136MB) and found zero hits.</p>
<h1>Conclusion</h1>
<p>The PacketSmith + Yara‑X approach demonstrates that even highly obfuscated, ChaCha20‑Poly1305‑encrypted C&amp;C channels like SnappyClient can be detected reliably without deep payload inspection. By focusing on protocol-level fingerprints — the packet header, fixed-length framing, and the byte distribution—the detection module achieves a useful signal with potentially zero false positives and modest performance cost.</p>
<hr />
<p>Author: Mohamad Mokbel</p>
<p>First release: March 23, 2026</p>
]]></content:encoded></item><item><title><![CDATA[Detect Malicious .ip6.arpa TLD Reverse DNS Zone Response Packets using PacketSmith Yara-X Detection Module]]></title><description><![CDATA[Introduction
The other day, I was reading this interesting article Abusing .arpa: The TLD That Isn’t Supposed to Host Anything by Infoblox threat intel team, published on February 26, 2026. What got m]]></description><link>https://blog.netomize.ca/detect-malicious-ip6-arpa-tld-reverse-dns-zone-response-packets-using-packetsmith-yara-x-detection-module</link><guid isPermaLink="true">https://blog.netomize.ca/detect-malicious-ip6-arpa-tld-reverse-dns-zone-response-packets-using-packetsmith-yara-x-detection-module</guid><dc:creator><![CDATA[Netomize Official Blog]]></dc:creator><pubDate>Tue, 17 Mar 2026 16:03:31 GMT</pubDate><content:encoded><![CDATA[<h1>Introduction</h1>
<p>The other day, I was reading this interesting article <a href="https://www.infoblox.com/blog/threat-intelligence/abusing-arpa-the-tld-that-isnt-supposed-to-host-anything/">Abusing .arpa: The TLD That Isn’t Supposed to Host Anything</a> by Infoblox threat intel team, published on February 26, 2026. What got my attention is the clever abuse of the <code>.arpa</code> TLD (Address and Routing Parameter Area) for phishing purposes, and in particular, the querying of the IPv6 reverse DNS zone <code>ip6.arpa</code> for an A record instead of being legitimately used for reverse DNS lookup using the <code>PTR</code> record, which translates IP addresses back to domain names. According to <a href="https://www.iana.org/domains/arpa">IANA</a>, the domain <code>ip6.arpa</code> is used for "<em>mapping IPv6 addresses to Internet domain names</em>", that's mapping nibble-reversed IPv6 addresses back to hostnames.</p>
<p>I'm not aware of any prior documentation of such clever usage of the <code>.arpa</code> TLD to evade detection. The article is worth taking the time to read in full.</p>
<p>For example, sending an <strong>A</strong> DNS type query to the domain <code>c.5.2.1.6.3.0.0.0.7.4.0.1.0.0.2.ip6.arpa</code>, the server returns a routable C2 A record, <code>157[.]245[.]92[.]156</code> as shown in the figure below.</p>
<img src="https://cdn.hashnode.com/uploads/covers/698bbaaf2b3404faadd9aff8/7c1d1a32-eb52-4e72-ae66-de8fc0e122e4.png" alt="" style="display:block;margin:0 auto" />

<p>For the server to return a routable A record, the requested reverse DNS has to be under the threat actor's control, which is registered as a domain name, since this is not a legitimate/valid use of the <code>ip6.arpa</code> domain.</p>
<p>After reading the article, I asked myself how to write a domain-independent generalized detection logic against this abuse of the <code>ip6.arpa</code> domain.</p>
<h1>Detection Logic Using PacketSmith + Yara-X Detection Module</h1>
<p>In this section, we'll write a custom and generic Yara-X rule that uses PacketSmith's custom pattern identifier <code>dns</code> to detect this abuse of the <code>ip6.arpa</code> domain, with zero probability of any false positives.</p>
<div>
<div>ℹ</div>
<div>Please refer to the sneak peek article <a target="_blank" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://packetsmith.ca/yara-x-packetsmith-detection-module/" style="pointer-events:none">Yara-X + PacketSmith Detection Module</a>, for more information about the <code>dns</code> custom pattern identifier and the Yara-X detection module.</div>
</div>

<p>For reference, a pcap <a href="https://github.com/Netomize/RFiles/blob/main/packetsmith/arpa_ip6_reverse_dns_a_record.pcap">arpa_ip6_reverse_dns_a_record.pcap</a> with this behaviour is available for download from Netomize's GitHub repository.</p>
<p>The detection logic is simple and requires checking for a few indicators in the DNS response packet, ensuring that the requested reverse DNS returns an A record. The main detection logic consists of the following atomic indicators:</p>
<ul>
<li><p>The requested reverse DNS ends with <code>ip6.arpa</code></p>
</li>
<li><p>Query/Answer type is <code>A</code> (1), and class is <code>IN</code> (1)</p>
</li>
<li><p>Answer RR TTL is low for fast-flux DNS (optional)</p>
<ul>
<li>In the case of <code>c.5.2.1.6.3.0.0.0.7.4.0.1.0.0.2.ip6.arpa</code>, the server returns an TTL of 5, which is very low for legitimate traffic</li>
</ul>
</li>
<li><p>Answer RR data length is 4 to make sure that the server returned a value, that's an A record</p>
</li>
<li><p>Other indicators are documented in the rule</p>
</li>
</ul>
<p>The rule could be written as follows:</p>
<pre><code class="language-cpp">rule ip6_arpa_tld_dns_rsp_pkt_malicious 
{ 
  meta:

   description = "Detect malicious .ip6.arpa TLD DNS response pkts"
   reference   = "https://www.infoblox.com/blog/threat-intelligence/abusing-arpa-the-tld-that-isnt-supposed-to-host-anything/"
   filter      = "Frames (frames:)"
   author      = "Netomize"
   date        = "17/03/2026"	  

condition:
	
  dns.is_set and not dns.over_tcp and dns.flag.response 
  and 
  dns.flag.opcode   == 0 
  and
  dns.count.queries == 1
  and
  dns.count.ansr_rr == 1
  and
  dns.qry[0].type   == 1  // A
  and
  dns.qry[0].class  == 1 // IN
  and
  dns.qry[0].name.labels.total &gt; 2
  and	  
  // example: c.5.2.1.6.3.0.0.0.7.4.0.1.0.0.2.ip6.arpa
  dns.qry[0].name.qname endswith ".ip6.arpa"
  
  and
  
  dns.ansr_rr[0].type  == 1  // A
  and
  dns.ansr_rr[0].class == 1  // IN
  and
  dns.ansr_rr[0].rdata.size == 4	  
}
</code></pre>
<p>Similar detection logic could be applied to the <a href="https://www.iana.org/domains/arpa">in-addr.arpa</a> reverse DNS zone.</p>
<p>Running the above Yara-X rule through the linked pcap via PacketSmith and saving the result as JSON, we get the file <a href="https://github.com/Netomize/RFiles/blob/main/packetsmith/yara_dte_2026_03_17_11_46_06.json">yara_dte_2026_03_17_11_46_06.json</a> with all the detections:</p>
<p><code>PacketSmith.exe -i arpa_ip6_reverse_dns_a_record.pcap -D yara:console_json -F frames: -O .</code></p>
<h1>Conclusion</h1>
<p>This article documents the misuse of the <code>.arpa</code> TLD, specifically the <code>ip6.arpa</code> reverse DNS zone, as <a href="https://www.infoblox.com/blog/threat-intelligence/abusing-arpa-the-tld-that-isnt-supposed-to-host-anything/">seen in the wild</a>, for phishing purposes, and demonstrates how to write a generic Yara-X rule using PacketSmith's custom pattern identifier <code>dns</code> to detect malicious use of the <code>ip6.arpa</code> reverse DNS zone.</p>
<hr />
<p>Author: Mohamad Mokbel</p>
<p>First release: March 17, 2026</p>
]]></content:encoded></item><item><title><![CDATA[How to Apply VXLAN-GBP Encapsulation to PCAP Files Using PacketSmith]]></title><description><![CDATA[Introduction
In version 5.1.0 (codenamed Taxus), released on March 16, 2026, the injection engine has undergone a significant evolution, transitioning from basic command-line parameters to a robust, t]]></description><link>https://blog.netomize.ca/how-to-apply-vxlan-gbp-encapsulation-to-pcap-files-using-packetsmith</link><guid isPermaLink="true">https://blog.netomize.ca/how-to-apply-vxlan-gbp-encapsulation-to-pcap-files-using-packetsmith</guid><category><![CDATA[vxlan]]></category><category><![CDATA[PCAP]]></category><category><![CDATA[packetsmith]]></category><category><![CDATA[packet]]></category><category><![CDATA[frame]]></category><category><![CDATA[encapsulation]]></category><category><![CDATA[vxlan-gbp]]></category><dc:creator><![CDATA[Netomize Official Blog]]></dc:creator><pubDate>Mon, 16 Mar 2026 12:31:37 GMT</pubDate><content:encoded><![CDATA[<h1>Introduction</h1>
<p>In version 5.1.0 (codenamed Taxus), released on March 16, 2026, the injection engine has undergone a significant evolution, transitioning from basic command-line parameters to a robust, template-driven architecture. Injections are now orchestrated via external JSON objects, enabling highly customizable repeatable traffic generation.</p>
<p>Before version 5.1.0, PacketSmith already supported injecting DNS query and response packets, VLAN encapsulation layer, and TCP handshake packets, and in the latest release, v5.1.0, we've added support for injecting VXLAN-GBP (Virtual Extensible LAN) encapsulation layer, encapsulating the entire (original) frame over UDP. The VXLAN <strong>outer layers</strong> consist of an Ethernet layer, IPv4 or IPv6 layer, and a UDP layer that carries the VXLAN header and the encapsulated frame. All of the outer layers’ attributes are customizable via the JSON object “<strong>vxlan</strong>”, including every flag in the GBP extension and the rest of the fields. Furthermore, PacketSmith can dynamically calculate the outer UDP source port based on the inner 5-tuple. Users can choose from several industry-standard hashing algorithms, including <code>Jenkins</code>, <code>Toeplitz</code>, <code>CRC16</code>, <code>CRC32</code>, and <code>XOR</code>.</p>
<h1>VXLAN-GBP Encapsulation Using PacketSmith</h1>
<p>To encapsulate all the original frames in a pcap with a VXLAN-GBP (Virtual Extensible LAN) encapsulation layer, refer to the file "<code>inject_templates\inj_tpl.json</code>" that resides in the same directory as the PacketSmith executable. The relevant configuration is defined within the <code>vxlan</code> object, located under the <code>inject</code> → <code>layers</code> path in the JSON schema (the '<code>t</code>' notation indicates the required data type for each corresponding key) :</p>
<pre><code class="language-json">{
    // encapsulate the original frame inside a VXLAN layer
    "name": "vxlan",

	"outer_layers":
	{
		"ethernet":
		{
			// t:str
			"src_mac": "00:0c:29:e3:c6:4d",
			// t:str
			"dst_mac" : "00:0c:29:da:d1:de",
			// t:str
			"eth_type": "ipv4" // "ipv4" or "ipv6" 
		},
		
		"ipv4":
		{
			// t:str
			"src_ip": "192.168.0.1",
			// t:str
			"dst_ip": "192.168.0.2",
			// t:int
			"ttl": 64
		},
		
		"ipv6":
		{
			// t:str
			"src_ip": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
			// t:str
			"dst_ip": "2001:db8::ff00:42:8329",
			// t:int
			"hop_limit": 64
		},
		
		"udp":
		{
			// t:int
			"src_port": 1234,
			// t:str - hash functions: "jenkins", "toeplitz", "crc16", "crc32", "xor", "none"
			// if "none", then the source port is set to the static port in "src_port"
			"src_port_hash": "toeplitz",
			// t:int
			"dst_port": 4789 
		}
	},
	
	"flags":
	{
		// t:bool
		"gbp_extension": false,
		// t:bool
		"vni": true,
		// t:bool
		"dont_learn": false,
		// t:bool
		"policy_applied": false,
		// t:int
		"reserved": 0
	},
	
	// t:int
	"group_policy_id": 48,
	// t:int
	"vni": 6969,
	// t:int
	"reserved": 0
}
</code></pre>
<p>All the JSON key values are mutable, providing granular control over all outer-layer parameters. This includes exhaustive support for the GBP extension flags, ensuring every field can be customized to meet specific network requirements.</p>
<p>Let's take the following TCP packet as an example:</p>
<img src="https://cdn.hashnode.com/uploads/covers/698bbaaf2b3404faadd9aff8/9d4546dc-4055-47ae-bd16-7d59294c2916.png" alt="" style="display:block;margin:0 auto" />

<p>To VXLAN-GBP encapsulate it, we use the following command line options:</p>
<p><code>PacketSmith.exe --infile &lt;input_pcap&gt; --outfile &lt;output_pcap&gt; --inject layer:vxlan --checksum</code></p>
<p>Using the above JSON object, we get the following output:</p>
<img src="https://cdn.hashnode.com/uploads/covers/698bbaaf2b3404faadd9aff8/a50ca0fc-e1b4-4977-bcaf-6832e4cb662e.png" alt="" style="display:block;margin:0 auto" />

<h1>Conclusion</h1>
<p>In summary, we have shown how to wrap original PCAP frames with a VXLAN-GBP layer. The shift to a JSON-driven injection engine enables users to define complex tunnelling parameters in a structured format, thereby facilitating consistent, scalable network simulations.</p>
<hr />
<p>Author: Mohamad Mokbel</p>
<p>First release: March 16, 2026</p>
]]></content:encoded></item><item><title><![CDATA[How to Detect EternalBlue Exploitation]]></title><description><![CDATA[Introduction
On February 05, 2026, we released version 5 of PacketSmith, featuring a new detection module that seamlessly integrates Yara-X with most of the protocols supported by PacketSmith. To demo]]></description><link>https://blog.netomize.ca/how-to-detect-eternalblue-exploitation</link><guid isPermaLink="true">https://blog.netomize.ca/how-to-detect-eternalblue-exploitation</guid><category><![CDATA[packetsmith]]></category><category><![CDATA[yara-x]]></category><category><![CDATA[shadowbrokers]]></category><category><![CDATA[smbv1]]></category><category><![CDATA[cve-2017-0144]]></category><category><![CDATA[eternalblue]]></category><dc:creator><![CDATA[Netomize Official Blog]]></dc:creator><pubDate>Thu, 12 Feb 2026 13:45:07 GMT</pubDate><content:encoded><![CDATA[<h1>Introduction</h1>
<p>On February 05, 2026, we released <a href="https://packetsmith.ca/release-notes/">version 5 of PacketSmith</a>, featuring a new detection module that seamlessly integrates Yara-X with most of the protocols supported by PacketSmith. To demonstrate the capabilities of these new features, we published a <a href="https://packetsmith.ca/yara-x-packetsmith-detection-module/">sneak-peek article</a> focusing on the detection of DNS tunnelling in Denis’s Backdoor. In the accompanying documentation, we provide more sophisticated and non-trivial examples that showcase the powerful interplay between PacketSmith and Yara-X's native pattern matching capabilities. For instance, we explain how to detect attempted exploitation of <a href="https://nvd.nist.gov/vuln/detail/cve-2024-38063">CVE-2024-38063</a>, which involves checking the IPv6 extensions.</p>
<p>In this article, we provide another example, showcasing how to detect the famous EternalBlue exploitation vector (<a href="https://nvd.nist.gov/vuln/detail/cve-2017-0144">CVE-2017-0144</a>).</p>
<h1>Detection Logic</h1>
<p>A custom Yara-X rule that uses the pattern identifiers (objects) <code>tcp</code>, <code>flow</code> and <code>port</code>, could be derived similar to the following to detect the anomalous part where the <code>Data Displacement</code> word value is greater than the word value of the field <code>Total Data Count</code>.</p>
<pre><code class="language-cpp">rule smb_memory_corruption_vuln_cve_2017_0144_v3
{
    meta:
	
	  description = "CVE-2017-0144"
	  tags        = "shadowbroker, eternalblue"
      filter      = "Frames (frames:)"
	  reference   = "https://nvd.nist.gov/vuln/detail/cve-2017-0144"
	  author      = "Netomize"
	  date        = "12/02/2026"
	
    strings:
	
	  // SMB Command: Trans2 Secondary (0x33)
      $smb_trans2 = { ff 53 4d 42 33 00 00 00 00 }

    condition:
	
	  tcp.is_set and flow.to_server and (port.dst == 445 or port.dst == 139)
	  and
	  with smb_pkt = tcp.data.offset + 4:
	  (
		// early exit
		$smb_trans2 at smb_pkt
		and
		with total_data_count  = uint16(smb_pkt + 9 + 26),
		     data_displacement = uint16(smb_pkt + 9 + 38):		   
		(
			data_displacement &gt; total_data_count
		)
	  )
}
</code></pre>
<p>The first line in the detection logic should be self-explanatory: <code>tcp.is_set and flow.to_server and (port.dst == 445 or port.dst == 139)</code>. Since we are using the <code>frames</code> filter, which checks every packet, it is advised to use the Boolean expression <code>tcp.is_set</code> to ensure that we are dealing with a TCP packet.</p>
<p>The aliased <code>smb_pkt</code> offset in (<code>smb_pkt = tcp.data.offset + 4</code>) skips the first 4 bytes, which is the NetBIOS Session service. With this expression: <code>$smb_trans2 at smb_pkt</code>, the rule checks for the SMBv1 server component “SMB” with the command Trans2 Secondary (0×33), followed by the NT Status equal to Statuc_Success (0×00000000). This is an atomic early-exit signal, so we filter out all other SMB packets as early as possible.</p>
<p>What follows is the actual detection logic related to the vulnerability, where the <code>data_displacement &gt; total_data_count</code>.</p>
<p>Take the <a href="https://github.com/0xtf/testmynids.org/blob/master/pcaps/shadowbrokers/eternalblue-success-unpatched-win7.pcap">pcap</a> (<em>eternalblue-success-unpatched-win7.pcap</em>) as an example.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770845107993/50bffcee-1ffa-4e78-9bef-84b30a0bf059.png" alt="CVE-2017-0144 - SMBv1 Offending Packet" style="display:block;margin:0 auto" />

<p>Running the above Yara-X rule through the linked pcap via PacketSmith and saving the result as an XML Workbook, we get the file <a href="https://github.com/Netomize/RFiles/blob/main/packetsmith/yara_dte_2026_02_12_12_34_06.xml">yara_dte_2026_02_12_12_34_06.xml</a> (use MS Excel to view it) with all the detections:</p>
<p><code>PacketSmith.exe -i eternalblue-success-unpatched-win7.pcap -D yara:xml -F frames: -O .</code></p>
<h1>Conclusion</h1>
<p>In conclusion, detecting EternalBlue exploitation requires a deep understanding of network protocols and the ability to analyze packet data effectively. By leveraging the capabilities of PacketSmith and Yara-X, security professionals can create custom rules to identify anomalies indicative of this exploit. The integration of these tools allows for precise detection by focusing on specific patterns and behaviours within network traffic, such as the SMBv1 protocol's data displacement issue.</p>
<hr />
<p>Author: Mohamad Mokbel</p>
<p>First release: February 12, 2026</p>
]]></content:encoded></item></channel></rss>