Skip to content

Commit 059616d

Browse files
committed
Prefix global rules; fix include statements for tests
Signed-off-by: egibs <20933572+egibs@users.noreply.github.com>
1 parent c98e5e3 commit 059616d

41 files changed

Lines changed: 206 additions & 151 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/style.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ jobs:
3131

3232
- name: Install yara-x
3333
run: |
34-
wget https://github.com/VirusTotal/yara-x/releases/download/v0.10.0/yara-x-v0.10.0-x86_64-unknown-linux-gnu.gzip -O yara-x.gzip
35-
tar -xzvf yara-x.gzip && mv yr /usr/local/bin/ && rm yara-x.gzip
34+
wget https://github.com/VirusTotal/yara-x/releases/download/v0.15.0/yara-x-v0.15.0-x86_64-unknown-linux-gnu.gz -O yara-x.gz
35+
tar -xzvf yara-x.gz && mv yr /usr/local/bin/ && rm yara-x.gz
3636
- name: Verify yr installation
3737
run: |
3838
yr --version

pkg/compile/compile.go

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
package compile
55

66
import (
7+
"bytes"
78
"context"
89
"fmt"
910
"io/fs"
11+
"os"
1012
"path/filepath"
1113
"regexp"
1214
"strings"
@@ -17,6 +19,11 @@ import (
1719
yarax "github.com/VirusTotal/yara-x/go"
1820
)
1921

22+
const (
23+
globalInclude = `include "rules/global/global.yara"`
24+
globalPath = "rules/global/global.yara"
25+
)
26+
2027
var FS = rules.FS
2128

2229
// badRules are noisy 3rd party rules to silently disable.
@@ -159,16 +166,57 @@ func removeRules(data []byte, rulesToRemove []string) []byte {
159166
return newlinePattern.ReplaceAll(modified, []byte("\n\n"))
160167
}
161168

169+
// findRoot locates the repository root on the fly.
170+
func findRoot(start string) string {
171+
current := start
172+
for {
173+
next := filepath.Join(current, "rules")
174+
if _, err := os.Stat(next); err == nil {
175+
return current
176+
}
177+
178+
parent := filepath.Dir(current)
179+
if parent == current {
180+
return ""
181+
}
182+
183+
current = parent
184+
}
185+
}
186+
187+
// replaceGlobal updates the include string to reference the absolute path of rules/global/global.yara
188+
// by default, the relative path is valid for local compilations and builds done from the root of the repository,
189+
// but this is not valid for test files located in various directories.
190+
func replaceGlobal(data []byte, path string) []byte {
191+
modified := data
192+
if bytes.Contains(data, []byte(globalInclude)) {
193+
modified = bytes.Replace(data, []byte(globalInclude), []byte(fmt.Sprintf(`include "%s"`, path)), 1)
194+
}
195+
return modified
196+
}
197+
162198
func Recursive(ctx context.Context, fss []fs.FS) (*yarax.Rules, error) {
163199
if ctx.Err() != nil {
164200
return nil, ctx.Err()
165201
}
166202

167-
yxc, err := yarax.NewCompiler(yarax.ConditionOptimization(true))
203+
yxc, err := yarax.NewCompiler(yarax.ConditionOptimization(true), yarax.EnableIncludes(true))
168204
if err != nil {
169205
return nil, fmt.Errorf("yarax compiler: %w", err)
170206
}
171207

208+
// use the current working directory to determine the root path
209+
// this only needs to be done once
210+
cwd, err := os.Getwd()
211+
if err != nil {
212+
return nil, err
213+
}
214+
abs, err := filepath.Abs(cwd)
215+
if err != nil {
216+
return nil, err
217+
}
218+
rootPath := findRoot(abs)
219+
172220
rulesToRemove := getRulesToRemove()
173221

174222
for _, root := range fss {
@@ -177,14 +225,21 @@ func Recursive(ctx context.Context, fss []fs.FS) (*yarax.Rules, error) {
177225
return err
178226
}
179227

180-
if !d.IsDir() && (filepath.Ext(path) == ".yara" || filepath.Ext(path) == ".yar") {
228+
if d.IsDir() {
229+
return nil
230+
}
231+
232+
if filepath.Ext(path) == ".yara" || filepath.Ext(path) == ".yar" {
181233
bs, err := fs.ReadFile(root, path)
182234
if err != nil {
183235
return fmt.Errorf("readfile: %w", err)
184236
}
185237

186238
bs = removeRules(bs, rulesToRemove)
187239

240+
globalAbs := filepath.Join(rootPath, globalPath)
241+
bs = replaceGlobal(bs, globalAbs)
242+
188243
yxc.NewNamespace(path)
189244
if err := yxc.AddSource(string(bs), yarax.WithOrigin(path)); err != nil {
190245
return fmt.Errorf("failed to parse %s: %v", path, err)

rules/anti-behavior/random_behavior.yara

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include "rules/global.yara"
1+
include "rules/global/global.yara"
22

33
import "math"
44

@@ -12,7 +12,7 @@ rule setuptools_random: critical {
1212
$not_easy_install = "pid = random.randint(0, sys.maxsize)"
1313
1414
condition:
15-
python_setup and $ref and none of ($not*)
15+
global_python_setup and $ref and none of ($not*)
1616
}
1717

1818
rule java_random: low {

rules/anti-static/elf/entropy.yara

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include "rules/global.yara"
1+
include "rules/global/global.yara"
22

33
import "math"
44

@@ -8,7 +8,7 @@ rule higher_elf_entropy_68: medium {
88
filetypes = "elf"
99

1010
condition:
11-
normal_elf and math.entropy(1, filesize) >= 6.95
11+
global_normal_elf and math.entropy(1, filesize) >= 6.95
1212
}
1313

1414
rule normal_elf_high_entropy_7_4: high {
@@ -21,7 +21,7 @@ rule normal_elf_high_entropy_7_4: high {
2121
$not_bazel = "BazelLogHandler"
2222
2323
condition:
24-
filesize < 30MB and normal_elf and math.entropy(1, filesize) >= 7.4 and none of ($not*)
24+
filesize < 30MB and global_normal_elf and math.entropy(1, filesize) >= 7.4 and none of ($not*)
2525
}
2626

2727
rule normal_elf_high_entropy_footer_7_4: high {
@@ -30,7 +30,7 @@ rule normal_elf_high_entropy_footer_7_4: high {
3030
filetypes = "elf"
3131

3232
condition:
33-
normal_elf and math.entropy(filesize - 8192, filesize) >= 7.4
33+
global_normal_elf and math.entropy(filesize - 8192, filesize) >= 7.4
3434
}
3535

3636
rule normal_elf_high_entropy_footer_7_4_rc4: high {
@@ -43,5 +43,5 @@ rule normal_elf_high_entropy_footer_7_4_rc4: high {
4343
$cmp_r_x_256 = { 48 81 f? 00 01 00 00 } // cmp {rbx, rcx, …}, 256
4444
4545
condition:
46-
filesize < 25MB and normal_elf and math.entropy(filesize - 8192, filesize) >= 7.4 and any of them
46+
filesize < 25MB and global_normal_elf and math.entropy(filesize - 8192, filesize) >= 7.4 and any of them
4747
}

rules/anti-static/macho/entropy.yara

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include "rules/global.yara"
1+
include "rules/global/global.yara"
22

33
import "math"
44

@@ -8,7 +8,7 @@ rule higher_entropy_6_9: medium {
88
filetypes = "macho"
99

1010
condition:
11-
small_macho and math.entropy(1, filesize) >= 6.9
11+
global_small_macho and math.entropy(1, filesize) >= 6.9
1212
}
1313

1414
rule high_entropy_7_2: high {
@@ -21,5 +21,5 @@ rule high_entropy_7_2: high {
2121
$bin_java = "bin/java"
2222
2323
condition:
24-
small_macho and math.entropy(1, filesize) >= 7.2 and not $bin_java
24+
global_small_macho and math.entropy(1, filesize) >= 7.2 and not $bin_java
2525
}

rules/anti-static/macho/footer.yara

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include "rules/global.yara"
1+
include "rules/global/global.yara"
22

33
import "math"
44

@@ -12,5 +12,5 @@ rule high_entropy_trailer: high {
1212
$page_zero = "_PAGEZERO"
1313
1414
condition:
15-
filesize < 10MB and macho and $page_zero and math.entropy(filesize - 1024, filesize - 1) >= 4
15+
filesize < 10MB and global_macho and $page_zero and math.entropy(filesize - 1024, filesize - 1) >= 4
1616
}

rules/anti-static/packer/aes.yara

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include "rules/global.yara"
1+
include "rules/global/global.yara"
22

33
import "math"
44

@@ -13,5 +13,5 @@ rule go_aes: high {
1313
$decrypt = "NewCFBDecrypter"
1414
1515
condition:
16-
small_binary and math.entropy(1, filesize) >= 7 and all of them
16+
global_small_binary and math.entropy(1, filesize) >= 7 and all of them
1717
}

rules/anti-static/unmarshal/marshal.yara

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include "rules/global.yara"
1+
include "rules/global/global.yara"
22

33
import "math"
44

@@ -20,5 +20,5 @@ rule setuptools_py_marshal: suspicious {
2020
filetypes = "py"
2121

2222
condition:
23-
python_setup and unmarshal_py_marshal
23+
global_python_setup and unmarshal_py_marshal
2424
}

rules/c2/addr/ip.yara

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include "rules/global.yara"
1+
include "rules/global/global.yara"
22

33
rule hardcoded_ip: medium {
44
meta:
@@ -45,7 +45,7 @@ rule bin_hardcoded_ip: high {
4545
$not_2345 = "23.45.67.89"
4646
4747
condition:
48-
filesize < 12MB and elf_or_macho and 1 of ($sus_ip*) and none of ($not*)
48+
filesize < 12MB and global_elf_or_macho and 1 of ($sus_ip*) and none of ($not*)
4949
}
5050

5151
rule http_hardcoded_ip: high exfil {

rules/c2/addr/url.yara

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include "rules/global.yara"
1+
include "rules/global/global.yara"
22

33
import "math"
44

@@ -82,7 +82,7 @@ rule binary_with_url: low {
8282
$ref = /https*:\/\/[\w\.\/]{8,160}[\/\w\=\&]{0,32}/
8383
8484
condition:
85-
filesize < 150MB and elf_or_macho and $ref
85+
filesize < 150MB and global_elf_or_macho and $ref
8686
}
8787

8888
rule binary_url_with_question: high {
@@ -99,7 +99,7 @@ rule binary_url_with_question: high {
9999
$not_mesibo = "https://api.mesibo.com/api.php?"
100100
101101
condition:
102-
filesize < 150MB and elf_or_macho and $ref and none of ($not*)
102+
filesize < 150MB and global_elf_or_macho and $ref and none of ($not*)
103103
}
104104

105105
rule script_url_with_question: high {

0 commit comments

Comments
 (0)