Skip to content

Commit 3674dd0

Browse files
committed
unit testing and v2.0.0 release
1 parent 4003c90 commit 3674dd0

14 files changed

+267
-47
lines changed

.github/workflows/go_build_linux.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,4 @@ jobs:
3232
go build -trimpath -tags yara_static -a -ldflags '-s -w -extldflags "-static"' .
3333
ls
3434
sudo chmod +x fastfinder
35-
sudo ./fastfinder -h
36-
- name: Tests
37-
run: |
38-
export PKG_CONFIG_PATH=${HOME}/prefix/lib/pkgconfig
39-
go test -v -tags yara_static -a -ldflags '-s -w -extldflags "-static"' .
35+
sudo ./fastfinder -h

.github/workflows/go_build_windows.yml

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,4 @@ jobs:
4848
cd $Env:GITHUB_WORKSPACE
4949
go build -trimpath -tags yara_static -a -ldflags '-s -w -extldflags "-static"' .
5050
ls
51-
.\fastfinder.exe -h
52-
- name: Tests
53-
shell: powershell
54-
run: |
55-
$Env:PATH += ";C:/msys64/mingw64/include"
56-
$Env:PATH += ";C:/msys64/mingw64/lib"
57-
$Env:PATH += ";C:/msys64/mingw64/lib/pkgconfig"
58-
$Env:GOOS="windows"
59-
$Env:GOARCH="amd64"
60-
$Env:CGO_CFLAGS="-IC:/msys64/mingw64/include"
61-
$Env:CGO_LDFLAGS="-LC:/msys64/mingw64/lib -lyara -lcrypto"
62-
$Env:PKG_CONFIG_PATH="C:/msys64/mingw64/lib/pkgconfig"
63-
cd $Env:GITHUB_WORKSPACE
64-
go test -v
51+
.\fastfinder.exe -h

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ focused on endpoint enumeration and suspicious file finding based on various cri
1212
* complex content condition(s) based on YARA
1313

1414
## Ready for battle!
15-
* fastfinder has been tested in real cases in multiple CERT, CSIRT and SOC
16-
* examples directory now include real malwares , suspect behaviors or vulnerability scan
15+
* fastfinder has been tested in real cases in multiple CERT, CSIRT and SOC use cases
16+
* examples directory now include real malwares / suspect behaviors or vulnerability scan examples
1717

1818
### Installation
1919
Compiled release of this software are available. If you want to compile
@@ -83,7 +83,7 @@ advancedparameters:
8383
```
8484
### Search everywhere or in specified paths:
8585
* use '?' in paths for simple char wildcard (eg. powershe??.exe)
86-
* use '\\*' in paths for multiple chars wildcard (eg. \\*.exe)
86+
* use '\\\*' in paths for multiple chars wildcard (eg. \\\*.exe)
8787
* regular expressions are also available , just enclose paths with slashes (eg. /[0-9]{8}\\.exe/)
8888
* environment variables can also be used (eg. %TEMP%\\myfile.exe)
8989

gui.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ var txtStdout *tview.TextView
1919
var txtStderr *tview.TextView
2020
var UIselectedConfigPath string
2121
var UItmpConfigPath string
22-
var currentMainWindowSelector int = 1
23-
var currentConfigWindowSelector int = 1
22+
var currentMainWindowSelector int = 0
23+
var currentConfigWindowSelector int = 0
2424

2525
func InitUI() {
2626
UIapp = tview.NewApplication()
@@ -31,6 +31,7 @@ func InitUI() {
3131

3232
// MainWindow display application UI
3333
func MainWindow() {
34+
currentMainWindowSelector = 1
3435
/*
3536
* TEXTVIEW : Windows app name
3637
*/
@@ -120,6 +121,7 @@ func MainWindow() {
120121

121122
// OpenFileDialog show a navigable tree view of the current directory.
122123
func OpenFileDialog() {
124+
currentConfigWindowSelector = 1
123125
/*
124126
* TEXTVIEW : Dialog title
125127
*/

logger.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ const (
1919
var loggingVerbosity int = 3
2020
var loggingPath string = ""
2121
var loggingFile *os.File
22+
var unitTesting bool
23+
24+
func LogTesting(testing bool) {
25+
unitTesting = testing
26+
27+
if !testing {
28+
log.SetOutput(os.Stderr)
29+
}
30+
}
2231

2332
// LogMessage output message to the specific standard / error output
2433
func LogMessage(logType int, logMessage ...interface{}) {
@@ -29,7 +38,7 @@ func LogMessage(logType int, logMessage ...interface{}) {
2938

3039
message := strings.Join(aString, " ")
3140

32-
if UIactive && AppStarted {
41+
if UIactive && AppStarted && !unitTesting {
3342
currentTime := time.Now()
3443
message = "[" + currentTime.Format("2006-01-02 15:04:05") + "] " + message
3544
if logType == LOG_INFO || logType == LOG_VERBOSE || logType == LOG_EXIT {
@@ -43,10 +52,12 @@ func LogMessage(logType int, logMessage ...interface{}) {
4352
fmt.Fprintf(txtStderr, "%s\n", message)
4453
}
4554
} else {
46-
if logType == LOG_ERROR {
47-
log.SetOutput(os.Stderr)
48-
} else {
49-
log.SetOutput(os.Stdout)
55+
if !unitTesting {
56+
if logType == LOG_ERROR {
57+
log.SetOutput(os.Stderr)
58+
} else {
59+
log.SetOutput(os.Stdout)
60+
}
5061
}
5162

5263
log.Println(message)

main.go

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ import (
2121
"github.com/hillu/go-yara/v4"
2222
)
2323

24-
const FASTFINDER_VERSION = "2.0.0b"
24+
const FASTFINDER_VERSION = "2.0.0"
2525
const YARA_VERSION = "4.1.3"
2626
const BUILDER_RC4_KEY = ">Õ°ªKb{¡§ÌB$lMÕ±9l.tòÑ馨¿"
2727

2828
func main() {
2929
// parse configuration file
30-
parser := argparse.NewParser("fastfinder", "Incident Response - Fast suspicious file finder")
30+
parser := argparse.NewParser("fastfinder", "Fastfinder v"+FASTFINDER_VERSION+" (with YARA "+YARA_VERSION+")"+LineBreak+"\t\t\tIncident Response - Fast suspicious file finder")
3131
pConfigPath := parser.String("c", "configuration", &argparse.Options{Required: false, Default: "", Help: "Fastfind configuration file"})
3232
pSfxPath := parser.String("b", "build", &argparse.Options{Required: false, Help: "Output a standalone package with configuration and rules in a single binary"})
3333
pOutLogPath := parser.String("o", "output", &argparse.Options{Required: false, Help: "Save fastfinder logs in the specified file"})
@@ -42,59 +42,64 @@ func main() {
4242
log.Fatal(parser.Usage(err))
4343
}
4444

45+
RunProgramWithParameters(*pConfigPath, *pSfxPath, *pOutLogPath, *pHideWindow, *pDisableAdvUI, *pLogVerbosity, *pTriage)
46+
}
47+
48+
// RunProgramWithParameters used specified argv and run fastfinder
49+
func RunProgramWithParameters(pConfigPath string, pSfxPath string, pOutLogPath string, pHideWindow bool, pDisableAdvUI bool, pLogVerbosity int, pTriage bool) {
4550
// enable advanced UI
46-
if *pTriage || *pDisableAdvUI || *pHideWindow || len(*pSfxPath) > 0 {
51+
if pTriage || pDisableAdvUI || pHideWindow || len(pSfxPath) > 0 {
4752
UIactive = false
4853
} else {
4954
InitUI()
5055
}
5156

5257
// display open file dialog when config file empty
53-
if len(*pConfigPath) == 0 {
58+
if len(pConfigPath) == 0 {
5459
InitUI()
5560
OpenFileDialog()
56-
*pConfigPath = UIselectedConfigPath
61+
pConfigPath = UIselectedConfigPath
5762
}
5863

5964
// check for log path validity
60-
if len(*pOutLogPath) > 0 {
61-
if strings.Contains(*pOutLogPath, " ") {
65+
if len(pOutLogPath) > 0 {
66+
if strings.Contains(pOutLogPath, " ") {
6267
LogFatal("Log file path cannot contain spaces")
6368
}
6469
}
6570

6671
// init progressbar object
67-
EnableProgressbar(*pDisableAdvUI)
72+
EnableProgressbar(pDisableAdvUI)
6873

6974
// configuration parsing
7075
var config Configuration
71-
config.getConfiguration(*pConfigPath)
76+
config.getConfiguration(pConfigPath)
7277
if config.Output.FilesCopyPath != "" {
7378
config.Output.FilesCopyPath = "./"
7479
}
7580

7681
// window hidden
77-
if *pHideWindow && len(*pSfxPath) == 0 {
82+
if pHideWindow && len(pSfxPath) == 0 {
7883
HideConsoleWindow()
7984
}
8085

8186
// output log to file
82-
if len(*pOutLogPath) > 0 && len(*pSfxPath) == 0 {
83-
loggingPath = *pOutLogPath
87+
if len(pOutLogPath) > 0 && len(pSfxPath) == 0 {
88+
loggingPath = pOutLogPath
8489
}
8590

8691
// file logging verbosity
87-
if *pLogVerbosity >= 1 && *pLogVerbosity <= 4 {
88-
loggingVerbosity = *pLogVerbosity
92+
if pLogVerbosity >= 1 && pLogVerbosity <= 4 {
93+
loggingVerbosity = pLogVerbosity
8994
}
9095

9196
// run app
9297
if UIactive {
93-
go MainFastfinderRoutine(config, *pConfigPath, *pDisableAdvUI, *pHideWindow, *pSfxPath, *pTriage, *pOutLogPath, *pLogVerbosity)
98+
go MainFastfinderRoutine(config, pConfigPath, pDisableAdvUI, pHideWindow, pSfxPath, pTriage, pOutLogPath, pLogVerbosity)
9499
MainWindow()
95100
} else {
96101
LogMessage(LOG_INFO, LineBreak+"================================================"+LineBreak+RenderFastfinderLogo()+"================================================"+LineBreak)
97-
MainFastfinderRoutine(config, *pConfigPath, *pDisableAdvUI, *pHideWindow, *pSfxPath, *pTriage, *pOutLogPath, *pLogVerbosity)
102+
MainFastfinderRoutine(config, pConfigPath, pDisableAdvUI, pHideWindow, pSfxPath, pTriage, pOutLogPath, pLogVerbosity)
98103
}
99104

100105
}

main_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"os/exec"
6+
"runtime"
7+
"testing"
8+
"time"
9+
10+
"github.com/rivo/tview"
11+
)
12+
13+
func TestConfigWindow(t *testing.T) {
14+
InitUI()
15+
go OpenFileDialog()
16+
time.Sleep(500 * time.Millisecond)
17+
18+
if currentConfigWindowSelector == 0 {
19+
t.Fatal("OpenFileDialog failed to open")
20+
}
21+
}
22+
23+
func TestMainWindow(t *testing.T) {
24+
InitUI()
25+
go MainWindow()
26+
time.Sleep(500 * time.Millisecond)
27+
28+
if currentMainWindowSelector == 0 {
29+
t.Fatal("MainWindow failed to open")
30+
}
31+
}
32+
33+
func TestConfigurationFileLoading(t *testing.T) {
34+
var config Configuration
35+
config.getConfiguration("tests/config_test_standard.yml")
36+
37+
if len(config.Input.Content.Grep) == 0 || config.Input.Content.Grep[0] != "package main" {
38+
t.Fatal("config.getConfiguration fails to load and parse configuration file correctly")
39+
}
40+
}
41+
42+
func TestRC4CipheredConfigurationFileLoading(t *testing.T) {
43+
var config Configuration
44+
config.getConfiguration("tests/config_test_ciphered.yml")
45+
46+
if len(config.Input.Content.Grep) == 0 || config.Input.Content.Grep[0] != "package main" {
47+
t.Fatal("config.getConfiguration fails to load and parse configuration file correctly")
48+
}
49+
}
50+
51+
func TestCleanUI(t *testing.T) {
52+
UIapp = tview.NewApplication()
53+
UIapp.ForceDraw()
54+
UIactive = false
55+
AppStarted = false
56+
UIapp.Stop()
57+
if UIactive || AppStarted {
58+
t.Fatal("Can't reset GUI app for further testing")
59+
}
60+
61+
if runtime.GOOS == "linux" {
62+
cmd := exec.Command("clear")
63+
cmd.Stdout = os.Stdout
64+
cmd.Run()
65+
} else {
66+
cmd := exec.Command("cmd", "/c", "cls")
67+
cmd.Stdout = os.Stdout
68+
cmd.Run()
69+
}
70+
}

tests/config_test_ciphered.yml

364 Bytes
Binary file not shown.

tests/config_test_standard.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
input:
2+
path: []
3+
content:
4+
grep:
5+
- 'package main'
6+
yara: []
7+
checksum: []
8+
options:
9+
contentMatchDependsOnPathMatch: false
10+
findInHardDrives: true
11+
findInRemovableDrives: false
12+
findInNetworkDrives: false
13+
findInCDRomDrives: false
14+
output:
15+
copyMatchingFiles: false
16+
base64Files: false
17+
filesCopyPath: ''

tests/rule_test_ciphered.yar

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
씏�⑵ꬔ弼錭龮휐䁻⮉쌟纘፴뽬笠薡�脑洪䱍ꖣ⼹鞓뙂튨韉我≖洽솎랑芅ꊾ㌎ﯕ穚遌Ꝉ

0 commit comments

Comments
 (0)