Problems writing a rule with byte_math

I need help writing a rule for the Request Path section. The section changes from packet to packet (the number of segments in it changes, and therefore the number of bytes per section also changes). In this section, you need to find a sequence of bytes. Since the length in bytes changes, I take the value from the Request Path Size and multiply it by 2, saving it to a variable. Next, I use this variable for depth. The specified section is immediately followed by a data section, which may contain the desired sequence, but this is a false positive.

Here’s what I’ve come up with so far.

alert tcp any any -> any 44818 (msg:"Alert PLC Allen Bradley"; byte_math:bytes 1, offset:46,oper *,rvalue 2, result var, string dec; content:"|20 6b|"; offset:47; depth:var; sid:10001; rev:1;) 

On paper, everything works, but the meerkat gives errors (parser error, ret -1…), swears at byte_math and specifically at the “*” operator. What should I do?

Here is a photo of two dumps on which the rule was written. 1 - should be detected, 2 - should not be detected (sequence “20 6b” in the data section)


Hi Ian,

Thanks for posting. What version of Suricata are you using?

I suspect 6.0.x; if you’re able to, could you try your rule with Suricata built from the master branch?

I am a complete newbie to Suricata. Explain what you mean please. Thanks for the extra time.

First start with what version of Suricata you’re using and also how you did run it, how you setup the suricata.yaml.

I am using Suricata version 6.0.10. The configuration file didn’t configure anything after installation. I use on WSL2 (Kali).

I have two dump files. I run Suricata on them. Here is the command line to run that I am using.

sudo suricata -r dmp.pcap -k none -v.

I also additionally attach a screenshot with the output in which the error.

The multiplication operator is not yet supported (see issue link below). There’s a second issue with your rule – change offset:46,oper to offset 46,oper (remove the :)

I’ve created Bug #6070: byte_match: Multiplication operator not supported - Suricata - Open Information Security Foundation to track this issue.

This is wonderful. Then I want to do through byte_extract, byte_math.

alert tcp any any -> any 44818 (msg:"Alert PLC Allen Bradley"; byte_extract:1,46,len,string,dec; byte_math:bytes 1,offset 47,oper +,rvalue len,result var,string dec; content:"|20 6b|"; offset:47; depth:var; sid:10001; rev:1;)

In the first option, I get the value of the Request Path Size byte and write it to “len”. With the second option, I take the same byte and add “len” to it, writing the result to “var”. Next I use depth:var. This does not cause errors, but it does not detect the package I need (1 dump). Why?

Could you post more details with a concrete example showing the values (and variables) step-by-step?

The main goal of the rule is to detect packets with the “20 6b” sequence, which is located in the Request Path section.

photo_2023-05-18_21-00-48

Since the length of the Request Path block always changes, I want to use the Request Path Size static field value, which specifies the size of the Request Path section.

photo_2023-05-18_21-00-54

With the byte_extract option, we take the value of the Request Path Size field into the variable “len” (decimal).

In the byte_math option, we again take the value of the Request Path Size field and add it to “len”. We write all this into the variable “var” (decimal number). This is done instead of multiplication, which is not supported in my version of Suricata.

Next, we use “var” in the “depth” option to specify the depth to search for the “content” and “offset” options.

Have any idea? Maybe there are other ways to solve my problem?

Hi Ian,

I’ll be following up on this as soon as I can.

The byte keywords are a little tricky. Can you post the steps with expected values at each step as well as the expected result?

byte_extract:1,46,len,string,dec;

This means taking the Request Path Size byte (06 in this case) and storing it in the len variable in decimal form. That is len=6.

byte_math:bytes 1,offset 47,oper +,rvalue len,result var,string dec;

This means taking the Request Path Size byte (06 in our case), adding it to len=6 and storing it in decimal form in “var”. That is “var”=12.

content:“|20 6b|”; offset:47; depth:var;

In this step, we take the value of “var” and substitute it in depth. That is depth:12. This is what I need.

Thanks …

Are any of these steps not working?

Since I can’t look at intermediate variable values anywhere, I don’t know what exactly is misbehaving. The final “depth” does not work out correctly because the packets are not found.

Hi Ian,
Is the offset value of 46 correct? Many times byte_extract is used with contentcontent is used to set the position for byte_extract — use relative if you have content precede byte_extract

Your rule uses 46 (decimal) for the offset but the bytes 20 6b are at offset 0x6c

Looks like we want a better ENIP/CIP parser with a cip.path rule keyword…