Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support new callback for slow rules #145

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/buildtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:

- name: Build YARA from source
run: |
YARA_VERSION=4.3.0
YARA_VERSION=4.5.0
wget --no-verbose -O- https://github.com/VirusTotal/yara/archive/v${YARA_VERSION}.tar.gz | tar -C .. -xzf -
( cd ../yara-${YARA_VERSION} && ./bootstrap.sh )
mkdir -p ../yara-build
Expand Down
4 changes: 2 additions & 2 deletions cgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ package yara
// #cgo yara_no_pkg_config LDFLAGS: -lyara -lm
/*
#include <yara.h>
#if YR_VERSION_HEX < 0x040300
#error YARA version 4.3 required
#if YR_VERSION_HEX < 0x040400
#error YARA version 4.4 required
#endif
*/
import "C"
13 changes: 13 additions & 0 deletions rules_callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ type ScanCallbackTooManyMatches interface {
TooManyMatches(*ScanContext, *Rule, string) (bool, error)
}

type ScanCallbackTooSlowScanning interface {
TooSlowScanning(*ScanContext, *Rule, string) (bool, error)
}

// scanCallbackContainer is used by to pass a ScanCallback (and
// associated data) between ScanXxx methods and scanCallbackFunc(). It
// stores the public callback interface and a list of malloc()'d C
Expand Down Expand Up @@ -167,6 +171,15 @@ func scanCallbackFunc(ctx *C.YR_SCAN_CONTEXT, message C.int, messageData, userDa
}
abort, err = c.TooManyMatches(s, rule, yrString.Identifier())
}
case C.CALLBACK_MSG_TOO_SLOW_SCANNING:
if c, ok := cbc.ScanCallback.(ScanCallbackTooSlowScanning); ok {
yrString := String{(*C.YR_STRING)(messageData), cbc.rules}
rule := &Rule{
cptr: C.find_rule(cbc.rules.cptr, yrString.cptr.rule_idx),
owner: cbc.rules,
}
abort, err = c.TooSlowScanning(s, rule, yrString.Identifier())
}
}

if err != nil {
Expand Down
36 changes: 28 additions & 8 deletions rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,14 @@ func TestRule(t *testing.T) {
}

type testCallback struct {
t *testing.T
finished bool
modules map[string]struct{}
matched map[string]struct{}
notMatched map[string]struct{}
logged []string
tooManyMatches []string
t *testing.T
finished bool
modules map[string]struct{}
matched map[string]struct{}
notMatched map[string]struct{}
logged []string
tooManyMatches []string
tooSlowScanning []string
}

func newTestCallback(t *testing.T) *testCallback {
Expand All @@ -260,6 +261,7 @@ func newTestCallback(t *testing.T) *testCallback {
make(map[string]struct{}),
nil,
nil,
nil,
}
}

Expand Down Expand Up @@ -294,7 +296,11 @@ func (c *testCallback) ConsoleLog(_ *ScanContext, s string) {
c.logged = append(c.logged, s)
}
func (c *testCallback) TooManyMatches(_ *ScanContext, r *Rule, s string) (bool, error) {
c.tooManyMatches = append(c.logged, fmt.Sprintf("%s:%s", r.Identifier(), s))
c.tooManyMatches = append(c.tooManyMatches, fmt.Sprintf("%s:%s", r.Identifier(), s))
return false, nil
}
func (c *testCallback) TooSlowScanning(_ *ScanContext, r *Rule, s string) (bool, error) {
c.tooSlowScanning = append(c.tooSlowScanning, fmt.Sprintf("%s:%s", r.Identifier(), s))
return false, nil
}

Expand Down Expand Up @@ -378,3 +384,17 @@ func TestXorKey(t *testing.T) {
t.Fatalf("expected xor key 0x10, got 0x%x", m[0].Strings[0].XorKey)
}
}

func TestTooSlowScanning(t *testing.T) {
cb := newTestCallback(t)
r := makeRules(t, `
rule t { strings: $s1 = /[^\x00]/ condition: any of them }
`)

if err := r.ScanMem(make([]byte, 8000000), 0, 0, cb); err != nil {
t.Error(err)
}
if len(cb.tooSlowScanning) != 1 || cb.tooSlowScanning[0] != "t:$s1" {
t.Errorf("too slow scanning does not contain bad regex: %v", cb.tooManyMatches)
}
}
Loading