Compare field from one packet with other packets

  • Suricata 7.0.3
  • Ubuntu Server 24.04.2
  • Installed via APT package

Hi there!

I would like to compare a couple of fields on a proprietary protocol that is sent over UDP.
I’m trying to copy and compare the value by using byte_extract and then handing the result from that to a flowint, so that I can then compare it on the next packet. Something like this:

This is not a rule I’ve tried:
alert ip any any -> any any (msg: "DUP FIELD"; flowint:field,+,0; byte_extract:2,6,newfield; flowint:field,==,newfield;sid:1100011;rev:1;)

After seeing that what I wanted was quite complicated, I thought I should take some steps to fully understand what I’m doing.

When I compare the range of bytes I am extracting to a test consant with content, suricata generates an alert. When I try to use flowint: capturedValue, ==, [the same test constant] it does not.

I’ve tried the following rules to see what works:
alert ip any any -> any any (msg: "A == SEQ = 0x10 A"; dsize:>20; content:"|10 00|"; offset:6; depth:2; sid:1100004; rev:1;)
alert ip any any -> any any (msg: "B == SEQ = 0x10 B"; dsize:>20; byte_extract:2,6,exint,big; flowint:flint,=,exint; flowint:flint,==,16; sid:1100005; rev:1;)
#Same as 1100005 but checking for 1 instead of 16, just in case the endianness was wrong
alert ip any any -> any any (msg: "Bb = SEQ = 0x10 B"; dsize:>20; byte_extract:2,6,exint,big; flowint:flint,=,exint; flowint:flint,==,1; sid:1100006; rev:1;)
alert ip any any -> any any (msg: "C == SEQ = 0x10 C"; dsize:>2; byte_extract:2,6,exint,big; byte_test:exint,=,0x10,0; sid:1100007; rev:1;)
Out of all of these, only 1100004 (A) is triggering.

Is what I’m trying to do even possible? Can rules combine/compare/convert bytes and ints at all?
Should I instead do it by using LUA?

I’m at a loss, any guidance or hint is greatly appreciated!

Thank you for reading this, and thanks in advance for the help : )

Edit: Typo! If there are any more typos on the rules they’re from copying them by hand - Suricata throws no errors or warnings regarding any rules.

For anyone who needs this in the future:

I did it with LUA, it was very simple thanks to these two facts:
You can extract bytes from a string and pack them into number variables.
You can then put those numbers into a flowint.

About my implementation:
I have a rule that just feeds the packet to the script (Like in the LUA examples, replacing the HTTP field descriptor with “payload”).
The script remembers the previous SEQ and counts how many subsequent packets have it too, that counter is another flowint.

Then I have another rule that looks for high values on that counter flowint.

You can probably keep track of even more SEQs with flowvars, but this is plenty for my use case.