# The Complexities of byte\_jump

**URL:** <https://community.emergingthreats.net/t/the-complexities-of-byte-jump/111>\
**Category:** Tutorials, Tips & Tricks\
**Created:** [October 28, 2022, 2:26pm UTC](https://community.emergingthreats.net/t/the-complexities-of-byte-jump/111 "2022-10-28T14:26:42Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![bmurphy](https://avatars.discourse-cdn.com/v4/letter/b/f19dbf/32.png) [@bmurphy](https://community.emergingthreats.net/u/bmurphy)\
**Post date:** [October 28, 2022, 2:26pm UTC](https://community.emergingthreats.net/t/the-complexities-of-byte-jump/111/1 "2022-10-28T14:26:42Z")

</div>

## Background

`byte_jump` is considered one of the more difficult to use Snort/Suricata keywords. It seems that every time `byte_jump` is called for it requires re-learning the specific syntax and nuances of this keyword.

`byte_jump` is used when the length of a packet, or the length of a “segment” of data is encoded into the packet itself. In relation to malware, this behavior can be observed in many malware families, and we can make use of it to reduce false positives by ensuring the packet length is _exactly_ that which is encoded in the packet.

Many protocols also include payload/data lengths, and `byte_jump` can be used to test for buffer overflows.

## Resources

Feel free to use the public [Dalton](https://github.com/secureworks/dalton) instance located at [https://doesmyrule.work](https://doesmyrule.work/dalton/coverage/suricata/) to replicate the examples findings.

### Official Documentation of byte\_jump

[Snort](http://manual-snort-org.s3-website-us-east-1.amazonaws.com/node32.html#SECTION004532000000000000000)  
[Suricata](https://suricata.readthedocs.io/en/latest/rules/payload-keywords.html#byte-jump)

### Helpful blogs/mailing list posts

[Cisco Talos - Using byte\_jump as Detection Mechanism](https://blog.talosintelligence.com/2010/01/using-bytejump-as-detection-mechanism.html)

## Detection Pointer

In order to understand byte\_jump, it’s helpful to think of a “detection pointer” which corresponds to the current location within the packet/payload/buffer/etc the IDS engine has progressed to while matching content. It can be moved forward and backward depending on which keywords and options are used.

This “detection pointer” is known formally as the “Detection Offset End Pointer” or the `doe_ptr`.

This detection pointer exists before, after or between bytes. Some keywords, such as `content`, `offset` and `distance` move the detection pointer.

- [`content`](https://suricata.readthedocs.io/en/latest/rules/payload-keywords.html#content)
  - moves the detection pointer when it finds a positive match

- [`offset`](https://suricata.readthedocs.io/en/latest/rules/payload-keywords.html#offset)
  - statically moves the detection pointer relative to the start of the packet/payload/buffer

- [`distance`](https://suricata.readthedocs.io/en/latest/rules/payload-keywords.html#distance)
  - moves the detection pointer relative to a previous positive `content` match.
  - negative values move the pointer backward

`byte_jump` is another keyword that moves the detection pointer. In order to determine how far to move the detection pointer, `byte_jump` will read bytes from the packet/payload/buffer.

## Important Behaviors

### Location of the start of jump

By default `byte_jump` will jump from just after the last byte used to determine the distance of the jump.  
Consider the payload used in [Example 1](#example-1-12) below:

```auto
\x00\x00\x00\x2bWindows 10 Pro|x64|12 GB|John-PC|John|Admin

```

If byte\_jump is configured to use the first four bytes of this payload (`byte_jump:4,0;`), the jump wil start from just after `\x2b` and before `W`. As the detection pointer exists between bytes, the engine will start the jump between two bytes.

### No alert if there is no data beyond the jump

If the jump causes the detection pointer to move to the end of, or beyond, the packet/payload/buffer, no alert will be produced. See [Example 1](#example-1-12) for more details.

## Syntax

There are many options to `byte_jump` and not all will be discussed here. There are only two required options, which are positional in nature.

1. num of bytes
2. offset

The most common optional arguments used are:

1. `post_offset`
  - steps backwards or forward a number of bytes _after_ making the jump

2. `from_beginning`
  - makes the “jump” from before the first byte of the packet/payload/buffer

3. `relative`
  - adjust the offset “relative” to the last positive content match

# Examples

The following examples will provide a simple introduction to byte\_jump using the mentioned common optional arguments. The examples will focus on using the `byte_jump` keyword to detection a malware checkin. Example rules will focus on the use of the `byte_jump` keyword and less on the best practices of rule writing, as a result some rules will be intentionally sub-optimal to not distract from the specifics of the `byte_jump`.

## Example 1

Example 1 will demonstrate the basic use of `byte_jump` in combination with the post\_offset option and the `isdataat` keyword to ensure that a payload or buffer is an exact length included in the packet itself.

### Payload

Consider [pcap\_1.pcap](https://community.emergingthreats.net/uploads/short-url/knsU7rF526rKi6HFZ50oGyt3JCq.pcap) with the following raw content:

```auto
\x00\x00\x00\x2bWindows 10 Pro|x64|12 GB|John-PC|John|Admin

```

The first 4 bytes are a “length header” (`\x00\x00\x00\x2b`) indicating the length of the remaining payload in hex\*. Note that it does not include the “length header” bytes themselves. For the sake of this example, assume the length is variable but the start of the data (`Windows\x20`) is always the same. As other elements in the payload are variable length, as such, the packet will not have a predetermined length. In effort to reduce FPs, the signature should ensure the packet length matches the length in the “length header”.

\*byte\_jump does allow for an option (dec) to treat the bytes used to determine the distance of the jump as decimal instead of hex.

In this example, the “length header” indicates there are 43 bytes of data.

The signature logic being attempted here is:

1. Ensure `Windows\x20`is in the packet (for simplicities the exact location of those bytes will not be considered)
2. Ensure the data after the “length header” is _exactly_ the length set forth in the “length header”.

#### Signature Attempt #1

```auto
alert tcp-pkt $HOME_NET any -> $EXTERNAL_NET any (flow:established,to_server; content:"Windows|20|"; byte_jump:4,0; sid:1;)

```

The content match provided will move the pointer right between the `\x20` and `1` of `10 Pro`. The byte\_jump options indicate to interpret four bytes, starting at “absolute” (no `relative` option) offset of 0. byte\_jump will then move the pointer to _before_ the first byte (`0x00`), read in four bytes (\x00\x00\x00\x2b) and then make the jump of 43 bytes (hex \x2b) **starting at the end of the four bytes read**. This moves the pointer to the end of the payload.

Step 1: Content Match  
Step 2: back to offset 0  
Step 3: “Consume” the bytes  
Step 4: Make the jump

##### Visual Analysis

![z_byte_jump_1](https://us1.discourse-cdn.com/flex016/uploads/emergingthreats/original/1X/c321e23af8777c09927a07920d7341b6d3005ffa.gif)

##### Outcome

sid:1 does not produce an alert. This lack of alert is due to the behavior of `byte_jump` which only evaluates to true (causing an alert) when there is data beyond the location of the detection pointer, _after_ the jump.

Two rules below will demonstrate this behavior by using the  
[`isdataat`](https://suricata.readthedocs.io/en/suricata-6.0.0/rules/payload-keywords.html#isdataat) keyword in attempt to prove there either is or is not data after the jump. Based on the rules below (sid:2 and sid:3), it’s reasonable to assume at least one of them should produce an alert.

```auto
alert tcp-pkt $HOME_NET any -> $EXTERNAL_NET any (flow:established,to_server; content:"Windows|20|"; byte_jump:4,0; isdataat:1,relative; sid:2;)
alert tcp-pkt $HOME_NET any -> $EXTERNAL_NET any (flow:established,to_server; content:"Windows|20|"; byte_jump:4,0; isdataat:!1,relative; sid:3;)

```

However, neither of them do. This demonstrates an important behavior of `byte_jump`. It will not alert if there is no data beyond the detection pointer after the jump as been completed.

#### Signature Attempt #2

```auto
alert tcp-pkt $HOME_NET any -> $EXTERNAL_NET any (flow:established,to_server; content:"Windows|20|"; byte_jump:4,0, post_offset -1; sid:4;)

```

In order to cause an alert, we can use the `post_offset` option with a value of `-1` to “step back” one byte, which will move the detection pointer back into the buffer between `i` and `n` as demonstrated by the gif below.

##### Visual Analysis

![z_byte_jump_2](https://us1.discourse-cdn.com/flex016/uploads/emergingthreats/original/1X/fff0874609d96940281441e761ea94d7afd9e1ee.gif)

##### Outcome

While sid:4 does produce an alert, there is no logic which ensures that the next byte is end of the  
packet/payload/buffer.

#### Signature Attempt #3

In order to ensure the byte\_jump has actually jumped to the _end_ of the packet/payload/buffer, the `isdataat` keyword, along with a negated match can be used.

In practice, this will ensure that there is _NOT_ data, two byes away from the current detection pointer location.

```auto
alert tcp-pkt $HOME_NET any -> $EXTERNAL_NET any (flow:established,to_server; content:"Windows|20|"; byte_jump:4,0, post_offset -1; isdataat:!2,relative; sid:5;)

```

##### Visual Analysis

![z_byte_jump_3](https://us1.discourse-cdn.com/flex016/uploads/emergingthreats/original/1X/3ea5fd2babdc8b9e006c4a7bdb04afa9e8c618ec.gif)

##### Outcome

sid:5 contains logic which matches on:

1. `Windows\x20`is in the payload
2. The payload, not including the “length header”, is exactly the length indicated in the “length header”.

## Example 2

Example 2 will demonstrate the use of `from_beginning`. This option is useful when the “length header” includes the length of the “length header”.

### Payload

Consider [pcap\_2.pcap](https://community.emergingthreats.net/uploads/short-url/hvsq6amUgj5vFQ2StbHw8eBDEh0.pcap) with the following raw content:

```auto
\x00\x00\x00\x2fWindows 10 Pro|x64|12 GB|John-PC|John|Admin

```

This content includes the length of the header in the “length header” field. Given there is only a single “length header” this is a good candidate to demonstrate the use of the `from_beginning` option.

Using `from_beginning` causes the engine jump from the start of the packet/payload/buffer. As demonstrated in [Example 1](#example-1-12) the `post_offset` option and `isdataat` keyword will be leveraged again.

#### Signature Attempt #1

```auto
alert tcp-pkt $HOME_NET any -> $EXTERNAL_NET any (flow:established,to_server; content:"Windows|20|"; byte_jump:4,0, from_beginning, post_offset -1; isdataat:!2,relative; sid:6;)

```

## Example 3

Example 3 will demonstrate the use of the `relative` option.

The `relative` options effects the offset of the byte\_jump command. That is to stay, it effects which bytes the engines uses to determine the length of the jump, it does **not** make the start of the jump relative to the last content match.

### Payload

Consider [pcap\_3.pcap](https://community.emergingthreats.net/uploads/short-url/9R0ere3apU9VUQQuSYDkzpQMqfh.pcap) with the raw data of:

```auto
\x00\x01\x25\x00\x00\x00\x2bWindows 10 Pro|x64|12 GB|John-PC|John|Admin

```

This content a total of 4 different fields:

- Packet Type Length - `\x00\x01`
- Packet Type - `\x25`
- Data Length - `\x00\x00\x00\x2b`
- Data - `Windows 10 Pro|x64|12 GB|John-PC|John|Admin`

#### Signature Attempt #1

As the “data length header” is at a variable location from the start of the packet, the `relative` option can be leveraged. In this case, the `relative` keyword will be used to “back up” to the start of the “data length” field after finding the start of the Data. As in previous example, assume the length is variable but the start of the data (`Windows\x20`) is always the same.

```auto
alert tcp-pkt $HOME_NET any -> $EXTERNAL_NET any (flow:established,to_server; content:"Windows|20|"; byte_jump:4,-12,relative, post_offset -1; isdataat:!2,relative; sid:6;)

```

#### Visual Analysis

![z_byte_jump_4](https://us1.discourse-cdn.com/flex016/uploads/emergingthreats/original/1X/8c538018713a6e2a4a622140ccfa73d36c58ac82.gif)

#### Outcome

sid:6 produces an alert and contains all the required logic to ensure the “Data” is exactly the length indicated in the “Data Length” header and that there is nothing after it in the payload.f
