|
diff --git a/Makefile b/Makefile index d5b9661..bd1ed51 100644 --- a/ Makefile+++ b/ Makefile |
| @@ -38,7 +38,7 @@ docker: ## Build docker image |
| 38 | docker tag $(IMAGE_NAME):latest $(IMAGE_NAME):$(IMAGE_VERSION) |
38 | docker tag $(IMAGE_NAME):latest $(IMAGE_NAME):$(IMAGE_VERSION) |
| 39 | |
39 | |
| 40 | docker-tests: ## Run docker image against the samples folder |
40 | docker-tests: ## Run docker image against the samples folder |
| 41 | @docker run --rm -v $(shell pwd)/data/samples:/data $(IMAGE_NAME):latest |
41 | @(docker run --rm -v $(shell pwd)/data/samples:/data $(IMAGE_NAME):latest && exit 1) || (test $$? -eq 255 || exit 1) |
| 42 | |
42 | |
| 43 | docker-publish: ## Push docker image to the container registry |
43 | docker-publish: ## Push docker image to the container registry |
| 44 | @docker push $(IMAGE_NAME):latest |
44 | @docker push $(IMAGE_NAME):latest |
|
|
diff --git a/main.go b/main.go index de64b90..d4976eb 100644 --- a/ main.go+++ b/ main.go |
| @@ -30,6 +30,9 @@ const ( |
| 30 | FileBufferSize = 32 * 1024 // 32KB |
30 | FileBufferSize = 32 * 1024 // 32KB |
| 31 | YaraMaxThreads = 32 |
31 | YaraMaxThreads = 32 |
| 32 | TempDirPrefix = "pmf-" |
32 | TempDirPrefix = "pmf-" |
| |
33 | ExitCodeOk = 0 |
| |
34 | ExitCodeWithMatches = 255 |
| |
35 | ExitCodeWithError = 1 |
| 33 | ) |
36 | ) |
| 34 | |
37 | |
| 35 | var ( |
38 | var ( |
| @@ -93,7 +96,7 @@ func handleError(err error, desc string, isFatal bool) { |
| 93 | } |
96 | } |
| 94 | log.Println("[ERROR]"+desc, err) |
97 | log.Println("[ERROR]"+desc, err) |
| 95 | if isFatal { |
98 | if isFatal { |
| 96 | os.Exit(1) |
99 | os.Exit(ExitCodeWithError) |
| 97 | } |
100 | } |
| 98 | } |
101 | } |
| 99 | } |
102 | } |
| @@ -111,8 +114,9 @@ func writeRulesFiles(content fs.FS) string { |
| 111 | for _, rulesFile := range rulesFiles { |
114 | for _, rulesFile := range rulesFiles { |
| 112 | // read embedded content |
115 | // read embedded content |
| 113 | f, err := content.Open(path.Join("data", rulesFile)) |
116 | f, err := content.Open(path.Join("data", rulesFile)) |
| 114 | handleError(err, "unable to read embedded rule", true) |
117 | handleError(err, "unable to open embedded rule", true) |
| 115 | ruleData, err := io.ReadAll(f) |
118 | ruleData, err := io.ReadAll(f) |
| |
119 | handleError(err, "unable to read rule content", true) |
| 116 | |
120 | |
| 117 | // write to temporary file |
121 | // write to temporary file |
| 118 | err = os.WriteFile(path.Join(rulesPath, rulesFile), ruleData, 0640) |
122 | err = os.WriteFile(path.Join(rulesPath, rulesFile), ruleData, 0640) |
| @@ -297,13 +301,14 @@ func loadRulesFile(fileName string) (*yara.Rules, error) { |
| 297 | |
301 | |
| 298 | func main() { |
302 | func main() { |
| 299 | startTime := time.Now() |
303 | startTime := time.Now() |
| |
304 | matchesFound := false |
| 300 | _, err := flags.Parse(&args) |
305 | _, err := flags.Parse(&args) |
| 301 | if err != nil { |
306 | if err != nil { |
| 302 | os.Exit(1) |
307 | os.Exit(ExitCodeWithError) |
| 303 | } |
308 | } |
| 304 | if args.ShowVersion { |
309 | if args.ShowVersion { |
| 305 | println(version) |
310 | println(version) |
| 306 | os.Exit(0) |
311 | os.Exit(ExitCodeOk) |
| 307 | } |
312 | } |
| 308 | |
313 | |
| 309 | // check rules path |
314 | // check rules path |
| @@ -317,7 +322,7 @@ func main() { |
| 317 | // update rules if required |
322 | // update rules if required |
| 318 | if args.Update { |
323 | if args.Update { |
| 319 | updateRules() |
324 | updateRules() |
| 320 | os.Exit(0) |
325 | os.Exit(ExitCodeOk) |
| 321 | } |
326 | } |
| 322 | |
327 | |
| 323 | // add custom excluded file extensions |
328 | // add custom excluded file extensions |
| @@ -428,6 +433,7 @@ func main() { |
| 428 | for target, count := range matchCount { |
433 | for target, count := range matchCount { |
| 429 | if count >= DangerousMinScore { |
434 | if count >= DangerousMinScore { |
| 430 | log.Println("[WARNING] dangerous file found:", target) |
435 | log.Println("[WARNING] dangerous file found:", target) |
| |
436 | matchesFound = true |
| 431 | } |
437 | } |
| 432 | } |
438 | } |
| 433 | } else { // single file mode |
439 | } else { // single file mode |
| @@ -437,6 +443,7 @@ func main() { |
| 437 | err := scanner.SetCallback(&matches).ScanFile(args.Positional.Target) |
443 | err := scanner.SetCallback(&matches).ScanFile(args.Positional.Target) |
| 438 | handleError(err, "unable to scan target", true) |
444 | handleError(err, "unable to scan target", true) |
| 439 | for _, match := range matches { |
445 | for _, match := range matches { |
| |
446 | matchesFound = true |
| 440 | log.Println("[WARNING] match found:", args.Positional.Target, match.Rule) |
447 | log.Println("[WARNING] match found:", args.Positional.Target, match.Rule) |
| 441 | if args.Verbose { |
448 | if args.Verbose { |
| 442 | for _, matchString := range match.Strings { |
449 | for _, matchString := range match.Strings { |
| @@ -460,6 +467,11 @@ func main() { |
| 460 | log.Println("[DEBUG] deleting temporary folder:", args.RulesDir) |
467 | log.Println("[DEBUG] deleting temporary folder:", args.RulesDir) |
| 461 | } |
468 | } |
| 462 | err := os.RemoveAll(args.RulesDir) |
469 | err := os.RemoveAll(args.RulesDir) |
| 463 | handleError(err, "unable to delete temporary folder", true) |
470 | handleError(err, fmt.Sprintf("unable to delete temporary folder '%s'", args.RulesDir), false) |
| 464 | } |
471 | } |
| |
472 | |
| |
473 | if matchesFound { |
| |
474 | os.Exit(ExitCodeWithMatches) |
| |
475 | } |
| |
476 | os.Exit(ExitCodeOk) |
| 465 | } |
477 | } |
|