VirusTotal / yara

The pattern matching swiss knife
https://virustotal.github.io/yara/
BSD 3-Clause "New" or "Revised" License
8.26k stars 1.44k forks source link

Multiple @ offset conditions #1885

Closed djlukic closed 1 year ago

djlukic commented 1 year ago

Hi

I tried to do this kind of condition but can't get a rule to hit

strings:

    $header = { 50 4B 03 04 }

    $a = "google"
    $b = "microsoft"

condition:

    $a at (@header[1] + 50)
    and
    $b at (@header[2] + 50)

If I remove $b at (@header[2] + 50) it detects just fine. Thank you!

wxsBSD commented 1 year ago

We would need to know the file you're scanning to debug this. The rule works fine on some test data I tossed together:

wxs@mbp yara % xxd ~/x
00000000: 504b 0304 0000 0000 0000 0000 0000 0000  PK..............
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000030: 0000 676f 6f67 6c65 504b 0304 0000 0000  ..googlePK......
00000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000060: 0000 0000 0000 0000 0000 6d69 6372 6f73  ..........micros
00000070: 6f66 74                                  oft
wxs@mbp yara % cat rules/a.yara
rule a {
  strings:
    $header = { 50 4B 03 04 }
    $a = "google"
    $b = "microsoft"
  condition:
    $a at (@header[1] + 50) and $b at (@header[2] + 50)
}
wxs@mbp yara % ./yara rules/a.yara ~/x
a /Users/wxs/x
wxs@mbp yara %

In your case, without knowing the file your scanning, it seems like the microsoft string is not at that specific offset relative to @header[2].

r0ny123 commented 1 year ago

In your case, without knowing the file your scanning, it seems like the microsoft string is not at that specific offset relative to @header[2].

Or it could be there is no 2nd occurrence of @header.

djlukic commented 1 year ago

I don't know what is going on. If I do this it works. So 2nd header exist, I've already tried this with #header == 2

$a at (@header[1] + 50) and
$b at (@header[2] + 50)

But if I try this it doesn't work.

$a at (uint16(@header[1]) + 50) and
$b at (uint16(@header[2]) + 50)

If I only do this it works $a at (uint16(@header[1]) + 50)

Why it doesn't like (uint16(@header[2]) ?

wxsBSD commented 1 year ago

uint16(@header[2] + 50) is taking the 16 bits at @header[2] + 50 is and treating them as an unsigned little endian integer. If the value at @header[2] + 50 is 0x0100 then you are saying $a at 0x0001 which is probably not what you want.

The @header[2] + 50 expression is evaluated to some integer offset in the file, and the value at that offset is then used to check if $a matches there.

djlukic commented 1 year ago

But why it checks $a when I say $b at?

wxsBSD commented 1 year ago

I was trying to explain to you what it the uint16() stuff was doing.

To explain this further can you please provide a file that you think should match so we can talk about a concrete example?

djlukic commented 1 year ago

I didn't forget about this, need more time and I'll report back.

djlukic commented 1 year ago

I think the problem was with for loop somehow, hence the confusion. I tried to reproduce the problem without for loop and didn't find any problem with @header[1] and @header[2] so we can consider this one as solved. Thank you!