+++

Introduction

Hello everyone and welcome back to the next post in our Detection Engineering series. In the last post, we started getting our feet wet with detection engineering by reading through a Cisco Talos report on Chaos ransomware’s msaRAT and creating a couple Sigma rules from the activity described in the report. We made one rule for the suspicious curl.exe command used to download the malware and another for Chrome or Edge launching in headless mode with the Chrome DevTools Protocol enabled. At the end of that post I promised we would come back and try writing a ClamAV detection for the same malware, so here we are. I will be completely honest here: ClamAV signatures looked considerably more intimidating to me than Sigma at first. Sigma is YAML, so even if you do not understand every field, you can at least look at the rule and kinda figure out what it is trying to say. A ClamAV logical signature, on the other hand, initially looks like a malware name followed by a wall of semicolons, numbers and hexadecimal. Luckily, once we break that wall apart, the basic idea really is not that terrible. We are going to install ClamAV on Windows, talk about the different signature formats it supports, pull some potentially useful strings out of the Talos report and then combine those strings into a logical signature for the DLL containing msaRAT. There is one important disclaimer before we get going. I do not currently have a verified copy of the actual msaRAT sample analyzed by Talos. We can safely test whether ClamAV accepts our signature and whether its Boolean logic behaves the way we expect, but that is not the same as proving the signature detects the real malware. For now, this is an experimental detection signature built from public threat intelligence. I will make that distinction throughout the post because pretending otherwise would kinda defeat the purpose of learning detection engineering in the first place. So, let’s get ClamAV running and see if we can start to wrap our minds around ClamAV signatures.

What is ClamAV?

ClamAV is an open-source antivirus engine maintained by Cisco Talos. It can inspect files for known malicious content using a collection of signatures and it includes utilities for scanning files, updating the official signature databases and creating or inspecting signatures of our own. The three tools we care about for this post are:

  • clamscan, which scans files and directories.
  • freshclam, which downloads and updates the official ClamAV signature databases.
  • sigtool, which helps analysts create, inspect and troubleshoot signatures. This is also where ClamAV differs from the Sigma rules we wrote previously. Sigma describes suspicious behavior recorded in logs. Our Sigma rules were looking for things like a process named curl.exe executing with certain command-line arguments. ClamAV is instead looking at the contents and structure of a file. It does not know whether Runtime.addBinding was actually executed, it only knows whether the bytes representing that string exist in the file being scanned.

Installing ClamAV on Windows

ClamAV provides both installers and portable ZIP packages for Windows on its official download page. At the time of writing, ClamAV 1.5.4 is the current release. I used the x64 MSI installer because I am on a normal 64-bit Windows system and wanted the simplest setup possible. Pasted image 20260810123527.png So click on whichever operating system you want to install it on and choose the right file for the architecture you’re running. Once the MSI installer is done downloading, go ahead and crack it open. Pasted image 20260810123554.png Alright, lookin good, let’s click Next. Pasted image 20260810123613.png And agree to the EULA. Pasted image 20260810123632.png This is the default installation path on Windows and is totally fine with me, so Next. Pasted image 20260810123649.png And Install. Once ClamAV finishes installing we’re going to want to open up a terminal (PowerShell) and navigate to the ClamAV path. Pasted image 20260810123909.png Awesome. Okay, ClamAV includes a sample configuration for freshclam, but we need to copy it into the main installation directory before we can use it. Pasted image 20260810124052.png Alright, now we’re going to want to actually open up our freshclam.conf in Notepad cause we need to make some edits. Pasted image 20260810124217.png When the frashclam opens, delete the line containing Example, save the file and close Notepad. According to the ClamAV Windows configuration documentation, leaving that line enabled intentionally prevents the sample configuration from being used as-is and we want to use it. So yeah. After that we can go ahead and download the official signatures. Pasted image 20260810130441.png Finally, let’s verify the scanner and sigtool are working. Pasted image 20260810130556.png Awesome, we’re looking good so far. We’re not gonna set up the clamd service or real-time scanning in this post. All we need for writing and testing a custom signature is the command-line scanner so that’s all we’re setting up for now.

How ClamAV Signatures Work

One thing that confused me initially is that there is not one universal “ClamAV rule” format. ClamAV calls these detections signatures, and the extension of the file tells the engine how each line inside it should be interpreted. ClamAV supports quite a few database formats, but these are the three that make the most sense to introduce here:

File type Detection method Basic idea
.hdb or .hsb Whole-file hash Detect this exact file based on its hash and size.
.ndb Extended content signature Detect one hexadecimal byte pattern in a certain target type or location.
.ldb Logical signature Combine several content patterns using Boolean logic.

A hash signature is probably the easiest to make, but it is also extremely fragile. If a single byte in the malware changes, its whole-file hash changes and our detection no longer works. An extended signature lets us search for content rather than an exact file, but we only get one main pattern and therefore have less context. For msaRAT, a logical .ldb signature makes the most sense. The Talos report provides several strings that are individually interesting but much more useful when we require a specific combination of them. The official ClamAV documentation gives the logical-signature format as:

SignatureName;TargetDescriptionBlock;LogicalExpression;Subsig0;Subsig1;Subsig2;...

Well, that certainly looks like something. Let’s break it down.

Signature Name

The first field is simply the name ClamAV reports when the signature matches. Signature names cannot contain spaces and should be descriptive enough for us to have some idea of what was actually detected. For our test rule, I am going with:

Win.Trojan.MsaRAT_Test-1

Talos has a standard naming convention for signatures that looks like the following.

{platform}.{category}.{name}-{signature id}-{revision}

So comparing this to our rule name, the platform is Windows, category is Trojans and then for the actual name part we put what we’re trying to detect and a version number. Also just because this is a test signature I include that as well.

Target Description Block

The next field tells ClamAV what kind of content should be inspected. ClamAV uses numeric target types, including:

  • Target:0 for any file type.
  • Target:1 for Windows Portable Executable files, including EXEs and DLLs.
  • Target:2 for OLE2 containers, including MSI installation files. Using Target:0 would technically let ClamAV look for our strings everywhere, but that would be unnecessarily broad and less efficient. Since we are writing this first signature for the malicious lib.dll, our target block will be:
Target:1

Logical Expression

The logical expression describes which content patterns must match before ClamAV reports a detection. Each pattern, or subsignature, is numbered starting with zero. So the first pattern is 0, the second is 1, the third is 2 and so on. The operators work about how you would expect:

0&1

means subsignature 0 and subsignature 1 must match, while:

0|1

means either one may match. Parentheses let us group conditions just like a normal Boolean expression:

0&(1|2)

That expression requires subsignature 0 and either subsignature 1 or 2. So, hey, already considerably less scary than it looked five minutes ago.

Subsignatures

Finally, each remaining semicolon-separated field contains a byte pattern ClamAV should look for. Native ClamAV content signatures represent these bytes in hexadecimal rather than plain text. This allows a signature to describe machine instructions and non-printable data in addition to normal ASCII strings. For example, the ASCII string:

msaOpen

becomes:

6d73614f70656e

ClamAV also supports wildcards, offsets and modifiers for more advanced signatures, but I think we have enough going on for our first one. We are going to stick with exact, case-sensitive ASCII strings for now. The full hexadecimal pattern syntax is available in the ClamAV content-signature documentation.

Understanding What We Are Detecting

Before blindly turning every interesting word in the Talos report into hex, let’s make sure we understand the malware chain. According to the Talos analysis, the attacker first downloads and executes update_ms.msi. When installation finishes, the MSI triggers a custom action named CA_Run_EA2AEBC3. That action loads lib.dll, which is embedded in the MSI’s Binary table as Bin_lib_EA2AEBC3, directly into memory. The DLL exposes an exported function named RUN, which is designed to be called by the installer. The important distinction here is that the MSI is the delivery container and lib.dll is the actual Rust-based msaRAT payload. Talos refers to the installer extracting the payload, but also specifically says the custom action loads it directly into memory. We should not assume that a normally visible file named lib.dll is permanently written to disk. This also means our potential strings belong to two different layers:

String Expected artifact Usefulness
CA_Run_EA2AEBC3 MSI Distinctive custom-action name, but it belongs in an MSI-focused signature.
Bin_lib_EA2AEBC3 MSI Distinctive Binary-table entry, but again specific to the MSI.
RUN DLL export Relevant to the execution chain but far too generic by itself.
msaOpen, msaClose, msaError, msaMessage DLL Unusual binding names and much stronger as a group.
dataAck DLL The fifth binding registered by the malware; weaker alone but useful with the others.
Runtime.addBinding DLL Connects the binding names to the malware’s use of CDP.
is-01-ast.ols-img-12.workers.dev DLL Highly specific infrastructure, although an attacker can change it easily.

For this first signature, I am going to target the DLL and leave CA_Run_EA2AEBC3 and Bin_lib_EA2AEBC3 for a future MSI rule. I am also dropping RUN. Plenty of legitimate DLLs could export a function with that name, and the other strings give us considerably better context.

Converting Our Strings to Hexadecimal

The ClamAV documentation demonstrates sigtool --hex-dump for converting content into hexadecimal. We can do the same by calling sigtool from the ClamAV directory Pasted image 20260810151120.png Important Note: That trailing 0doa at the end there is the newline character so we can discard those characters. That leaves us with msaOpen in hex as:

6d73614f70656e

After converting all our candidate strings, we end up with the following subsignatures:

Index Original string Hexadecimal pattern
0 msaOpen 6d73614f70656e
1 msaClose 6d7361436c6f7365
2 msaError 6d73614572726f72
3 msaMessage 6d73614d657373616765
4 dataAck 6461746141636b
5 Runtime.addBinding 52756e74696d652e61646442696e64696e67
6 is-01-ast.ols-img-12.workers.dev 69732d30312d6173742e6f6c732d696d672d31322e776f726b6572732e646576

Building our Signature

The strictest possible version of this signature would require every single string:

0&1&2&3&4&5&6

That should be highly specific to this sample, but it is also fragile. Infrastructure is easy for attackers to rotate, so requiring the exact Workers domain means a domain change defeats the entire signature. So for our first attempt, I settled on:

0&1&2&3&4&(5|6)

In plain English, ClamAV must find all five binding names and then find either Runtime.addBinding or the known Workers domain. The binding-name family provides the core identity, while the final choice gives us some extra CDP or infrastructure context without requiring both. We’ll be comparing our rule to to official Talos rule they list at the end of their blog post shortly, so we’ll see how far off we were.

Our Completed ClamAV Signature

Combining the signature name, target, logical expression and hexadecimal subsignatures gives us:

Win.Trojan.MsaRAT_Test-1;Target:1;0&1&2&3&4&(5|6);6d73614f70656e;6d7361436c6f7365;6d73614572726f72;6d73614d657373616765;6461746141636b;52756e74696d652e61646442696e64696e67;69732d30312d6173742e6f6c732d696d672d31322e776f726b6572732e646576

Okay, I know that went right back to looking like an indecipherable wall of text, but now we actually know what it’s doing now. So, let’s go ahead and open up Notepad and paste our rule in here. Pasted image 20260810151806.png I know that’s a terrible screenshot, but that’s to highlight an important note. ClamAV signatures go on one line. So This is how it’s supposed to look. We’re gonna go ahead and save this off to a folder we make called signatures. Pasted image 20260810152456.png

Safely Testing the Signature

Here is where we need to be very deliberate about what our test proves. We do not have the authentic lib.dll, so we cannot say we have validated detection of msaRAT itself. What we can test is whether:

  1. ClamAV accepts our logical-signature syntax.
  2. A PE containing the required strings triggers the signature.
  3. A PE missing part of the logical expression does not trigger it. We can do that without any malware by copying a legitimate Windows executable and adding our test strings to the copy. First, let’s create a temporary testing directory. Pasted image 20260810152857.png Let’s go ahead and copy whoami.exe to our test directory. Pasted image 20260810155931.png Alright, now we’re going to append the raw strings msaOpen msaClose msaError msaMessage dataAck Runtime.addBinding to the end of the copied whoami. Pasted image 20260810160611.png So we run that command there that adds our testStrings to the end of the file. We can see this when we open the copied .exe in Notepad and look at the bottom. Pasted image 20260810160745.png This should trigger our ClamAV signature. Alrighty, well let’s go ahead and scan it with our custom signature! Pasted image 20260810160958.png And look at that, we can see the signature properly fired! Quick side note, ClamAV adds UNOFFICIAL because this is a locally supplied signature rather than one in its official database. Now let’s go ahead and scan the normal whoami.exe binary. Pasted image 20260810161308.png Awesome, this file returns OK with 0 infected files, as should be expected. One other detail worth knowing is that using -d to load our custom signature. This means clamscan does not automatically load the official databases downloaded by freshclam. That is of course useful for this isolated test because any detection we receive should come from our rule, but some scanning and unpacking capabilities supplied through other database files may not be available. ClamAV covers this behavior in its signature-testing guidance.

Comparing Our Work to the Talos Signature

Talos states that the official ClamAV signature Win.Downloader.ChaosRaas-10060321-0 detects this threat. So let’s go ahead and see how are rules holds up to what the pros wrote. After updating the official databases with freshclam, sigtool can search them by signature name:

.\sigtool.exe --find="Win.Downloader.ChaosRaas-10060321-0"

Pasted image 20260810161553.png So right off the bat we see a few differences. First, when it comes to naming convention, they label it as a downloader and associate it with the ransomware ChaosRaaS. Which yeah, that makes sense. We then have 5 subsignatures that all need to match for the signature to fire. Alright, we’re going to take their subsignatures into CyberChef and see what strings they were looking for. Pasted image 20260810162102.png So the strings Talos are matching here are:

--remote-debugging-port

window.msaOpen

window.msaClose

{DOMAIN}/token/v1

window.msaError

Hey we weren’t actually too far off so that’s cool. They have msaOpen msaClose msaError as expected, granted with the window. preface. Now where things are different, first the --remote-debugging-port makes a ton of sense. As that it the flag the attackers use to enable CDP for their C2 channel that makes sense, we should have included that. Same deal with the {DOMAIN}/token/v1 endpoint, that is an important element of how a compromised hosts checks in the the C2 server and that is a little more stable than a ephemeral URL that will definitely be changed between attacks so that makes sense. Honestly, for our first go at this not too bad actually so good job everyone!

Conclusion

Today we continued our little detection-engineering adventure by taking the same msaRAT report from our Sigma post and approaching it from the file side. We installed ClamAV on Windows, learned the difference between hash, extended and logical signatures and turned a group of reported strings into our first .ldb rule. We validated that ClamAV accepts the signature and that our signature can detect a safe example binary. However, we cannot yet claim that it catches the authentic malware. Unfortunately, I cannot seem to find a sample of this malware anywhere, but I may have a solution for that so stay tuned for more. Thank you for checking this post out and I’ll see you in the next one!