Body-based Signature Content Format

ClamAV stores all body-based (content-based) signatures in a hexadecimal format, with exception to ClamAV's YARA rule support. In this section by a hex-signature we mean a fragment of malware’s body converted into a hexadecimal string which can be additionally extended using various wildcards.

Hexadecimal format

You can use sigtool --hex-dump to convert any data into a hex-string:

zolw@localhost:/tmp/test$ sigtool --hex-dump
How do I look in hex?


ClamAV supports the following wildcards for hex-signatures:

  • ??

    Match any byte.

  • a?

    Match a high nibble (the four high bits).

  • ?a

    Match a low nibble (the four low bits).

  • *

    Match any number of bytes.

  • {n}

    Match n bytes.

  • {-n}

    Match n or less bytes.

  • {n-}

    Match n or more bytes.

  • {n-m}

    Match between n and m bytes (where m > n).

  • HEXSIG[x-y]aa or aa[x-y]HEXSIG

    The [x-y] notation enables matching on a range of any bytes where one side is just a single-byte (two nibbles), represented by "aa". The other side, represented by "HEXSIG" must be at least 2 bytes (4 nibbles).

    The similar notation {n-m} requires that both sides have at least 2 bytes. The difference here is that [x-y] enables matching of just one byte.

    A second, unfortunate, difference is that y cannot be greater than 32.

    Example logical signature:


    In the example signature "testsig", there are two examples of this wildcard variant:

    1. 64[4-4]61616161: This will search for the byte "64" followed by the hex sequence "61616161" with exactly 4 arbitrary bytes in between.

    2. 6262[3-6]65: This will search for the hex sequence "6262" followed by the byte "65" with 3 to 6 arbitrary bytes in between.

    (Note that the "{2}" in between is the other wildcard variant meaning to match 2 arbitrary bytes.)

    Thus the signature matches many variations such as these. Braces and brackets are added in this hex to illustrate the boundaries of the wildcard matches:

    • 64[61616161]616161616{4646}6262[0102]65
    • 64[67676767]616161616{0102}6262[262626]65
    • 64[00000000]616161616{9696}6262[26262636]65

The range signatures * and {} virtually separate a hex-signature into two parts, eg. aabbcc*bbaacc is treated as two sub-signatures aabbcc and bbaacc with any number of bytes between them. It’s a requirement that each sub-signature includes a block of two static characters somewhere in its body. Note that there is one exception to this restriction; that is when the range wildcard is of the form {n} with n<128. In this case, ClamAV uses an optimization and translates {n} to the string consisting of n number of ?? character wildcards. Character wildcards do not divide hex signatures into two parts and so the two static character requirement does not apply.

Character classes

ClamAV supports the following character classes for hex-signatures:

  • (B)

    Match word boundary (including file boundaries).

  • (L)

    Match CR, CRLF or file boundaries.

  • (W)

    Match a non-alphanumeric character.

Alternate strings

  • Single-byte alternates (clamav-0.96) (aa|bb|cc|...) or !(aa|bb|cc|...) Match a member from a set of bytes (eg: aa, bb, cc, ...).

    • Negation operation can be applied to match any non-member, assumed to be one-byte in length.
    • Signature modifiers and wildcards cannot be applied.
  • Multi-byte fixed length alternates (aaaa|bbbb|cccc|...) or !(aaaa|bbbb|cccc|...) Match a member from a set of multi-byte alternates (eg: aaaa, bbbb, cccc, ...) of n-length.

    • All set members must be the same length.
    • Negation operation can be applied to match any non-member, assumed to be n-bytes in length (clamav-0.98.2).
    • Signature modifiers and wildcards cannot be applied.
  • Generic alternates (clamav-0.99) (alt1|alt2|alt3|...) Match a member from a set of alternates (eg: alt1, alt2, alt3, ...) that can be of variable lengths.

    • Negation operation cannot be applied.
    • Signature modifiers and nibble wildcards (eg: ??, a?, ?a) can be applied.
    • Ranged wildcards (eg: {n-m}) are limited to a fixed range of less than 128 bytes (eg: {1} -> {127}).

Note: Using signature modifiers and wildcards classifies the alternate type to be a generic alternate. Thus single-byte alternates and multi-byte fixed length alternates can use signature modifiers and wildcards but will be classified as generic alternate. This means that negation cannot be applied in this situation and there is a slight performance impact.