Skip to content

Commit

Permalink
Initial release
Browse files Browse the repository at this point in the history
  • Loading branch information
codeyourweb committed Nov 29, 2021
1 parent dbf492f commit 8331d57
Show file tree
Hide file tree
Showing 14 changed files with 714 additions and 2 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 Jean-Pierre GARNIER

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
[![Project Status](https://img.shields.io/badge/status-BETA-yellow?style=flat-square)]()
# _FastFinder_ - Incident Response - Fast suspicious file finder

## What is this project designed for?
Expand Down Expand Up @@ -29,7 +28,7 @@ Depending on where you are looking for files, _FastFinder_ could be used with ad
a configuration file example is available [here](configuration.yaml.example) in this repository
```
input:
path: [] # match file path AND / OR file name based on simple string ('?' and '*' wildcards are available for simple string) OR regular expression (regex have to be enclosed by "/<regex>/")
path: [] # match file path AND / OR file name based on simple string
content:
grep: [] # match literal string value inside file contente
yara: [] # use yara rule and specify rules path(s) for more complex pattern search (wildcards / regex / conditions)
Expand All @@ -41,6 +40,13 @@ output:
base64Files: true # base64 matched content before copy
filesCopyPath: '' # empty value will copy matched files in the fastfinder.exe folder
```
### Note for input path:
* '?' for simple char and '\*' for multiple chars wildcards are available for simple string
* environment variables are also available
* regular expression are allowed , they should be enclosed by /<regex>/
* input path are always case INSENSITIVE
* input content grep strings are always case SENSITIVE
* backslashes haven't to be escaped on simple string pattern (see example)

## About this project and future versions
I initially created this project to automate the creation of fastfind on a wide computer network.
Expand Down
57 changes: 57 additions & 0 deletions README.windows-compilation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

# Installing _FastFinder_ on Windows

_FastFinder_ is design for Windows platform but it's a little bit tricky because it's strongly dependant of go-yara and CGO. Here's a little step by step guide:

## Before installation

All the installation process will be done with msys2/mingw terminal. In order to avoid any error, you have to ensure that your installation directories don't contains space or special characters. I haven't tested to install as a simple user, I strongly advise you to install everything with admin privileges on top of your c:\ drive.

For the configurations and examples below, my install paths are:

* GO: c:\Go
* GOPATH: C:\Users\myuser\go
* Msys2: c:\msys64
* Git: c:\Git

## Install msys2 and dependencies:

First of all, note that you won't be able to get _FastFinder_ working if the dependencies are compiled with another compiler than GCC. There is currently some problems with CGO when external libraries are compiled with Visual C++, so no need to install Visual Studio or vcpkg.

* Download msys2 [from the official website](https://www.msys2.org/) and install it
* there, you will find two distincts binaries shorcut "MSYS2 MSYS" and "MSYS2 MinGW 64bits". Please launch this second one.
* install dependencies with the following command line: `pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-pkg-config base-devel openssl-devel`
* add environment variables in mingw terminal: `export PATH=$PATH:/c/Go/bin:/c/msys64/mingw64/bin:/c/Git/bin`

## Download and compile libyara

It's strongly advised NOT to clone VirusTotal's YARA repository but to download the source code of the latest release. If you compile libyara from the latest commit, it could generate some side effects when linking this library with _FastFinder_ and GCO.

* download latest VirusTotal release source code [from here](https://github.com/VirusTotal/yara/releases)
* unzip the folder in a directory without space and special char
* in mingw terminal, go to yara directory (backslash have to be replace with slash eg. cd c:/yara)
* compile and install using the following command: `./bootstrap.sh &&./configure && make && make install`

## Configure your OS

With this step, you won't need to use mingw terminal anymore and you will be able to use Go to install _FastFinder_ and compile your projects directly from Windows cmd / powershell.

Make sure you have the following as system environment variables (not user env vars). If not, create them:
```
GOARCH=<your-architecture> (eg. amd64)
GOOS=windows
CGO_CFLAGS=-IC:/msys64/mingw64/include
CGO_LDFLAGS=-LC:/msys64/mingw64/lib -lyara -lcrypto
PKG_CONFIG_PATH=C:/msys64/mingw64/lib/pkgconfig
```
You also need C:\msys64\mingw64\bin in your system PATH env vars.

Make sure you have got the following user environment var (not system var):

GOPATH=%USERPROFILE%\go

Note that paths must be written with slashs and not backslash. As already said, don't use path with spaces or special characters.

## Download, Install and compile FastFinder
Now, from Windows cmd or Powershell, you can install _FastFinder_: `go get github.com/codeyourweb/fastfinder`
Compilation should be done with: `go build -tags yara_static -a -ldflags '-extldflags "-static"' .`
78 changes: 78 additions & 0 deletions configuration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package main

import (
"io/ioutil"
"log"
"regexp"
"strings"

"gopkg.in/yaml.v2"
)

type Configuration struct {
Input Input `yaml:"input"`
Options Options `yaml:"options"`
Output Output `yaml:"output"`
}

type Input struct {
Path []string `yaml:"path"`
Content Content `yaml:"content"`
}

type Content struct {
Grep []string `yaml:"grep"`
Yara []string `yaml:"yara"`
}

type Options struct {
FindInHardDrives bool `yaml:"findInHardDrives"`
FindInRemovableDrives bool `yaml:"findInRemovableDrives"`
FindInNetworkDrives bool `yaml:"findInNetworkDrives"`
}

type Output struct {
Base64Files bool `yaml:"base64Files"`
FilesCopyPath string `yaml:"filesCopyPath"`
}

func (c *Configuration) getConfiguration(configFile string) *Configuration {

yamlFile, err := ioutil.ReadFile(configFile)
if err != nil {
log.Fatalf("Configuration file reading error #%v ", err)
}
err = yaml.Unmarshal(yamlFile, c)
if err != nil {
log.Fatalf("Configuration file parsing error: %v", err)
}

environmentVariables := getEnvironmentVariables()

for i := 0; i < len(c.Input.Path); i++ {
// replace environment variables
for _, env := range environmentVariables {
if strings.Contains(strings.ToLower(c.Input.Path[i]), "%"+strings.ToLower(env.Name)+"%") {
c.Input.Path[i] = strings.Replace(c.Input.Path[i], "%"+env.Name+"%", env.Value, -1)
}
}

// handle regex and simple find strings
if c.Input.Path[i][0] != '/' || c.Input.Path[i][len(c.Input.Path[i])-1] != '/' {
c.Input.Path[i] = regexp.QuoteMeta(strings.ToLower(c.Input.Path[i]))
// use regular expression ".+" for "*" search pattern
if strings.Contains(strings.ToLower(c.Input.Path[i]), "\\\\\\*") {
c.Input.Path[i] = strings.Replace(c.Input.Path[i], "\\\\\\*", ".+", -1)
}

if strings.Contains(strings.ToLower(c.Input.Path[i]), "\\?") {
c.Input.Path[i] = strings.Replace(c.Input.Path[i], "\\?", ".", -1)
}
} else {
c.Input.Path[i] = strings.Trim(c.Input.Path[i], "/")
}

}

return c
}
12 changes: 12 additions & 0 deletions configuration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
input:
path: []
content:
grep: []
yara: []
options:
findInHardDrives: true
findInRemovableDrives: true
findInNetworkDrives: true
output:
base64Files: true
filesCopyPath: ''
19 changes: 19 additions & 0 deletions configuration.yaml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
input:
path:
- '%APPDATA%\\*.exe'
- '%TEMP%\\*.exe'
- 'Windows\SysWOW64\c?d.exe'
- 'Windows\System32\notepad\*'
- '/temp\\{[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}\}\\\w+\.exe$/'
content:
grep:
- 'This program cannot be run in DOS mode'
yara:
- './example.yar'
options:
findInHardDrives: true
findInRemovableDrives: false
findInNetworkDrives: false
output:
base64Files: true
filesCopyPath: ''
6 changes: 6 additions & 0 deletions example.yar
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
rule example{
strings:
$a = "This program cannot be run in DOS mode"
condition:
all of them and uint16(0) == 0x5a4d
}
41 changes: 41 additions & 0 deletions finder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"io/ioutil"
"log"
"regexp"
"strings"
)

func pathsFinder(files []string, patterns []string) (matchingFiles []string) {
for _, expression := range patterns {
for _, f := range files {
if match, _ := regexp.MatchString(`(?i)`+expression, f); match {
matchingFiles = append(matchingFiles, f)
}
}
}

return matchingFiles
}

func findInFiles(files []string, patterns []string) (matchingFiles []string) {
for _, f := range files {

b, err := ioutil.ReadFile(f)
if err != nil {
log.Println("Unable to read", f)
continue
}

for _, expression := range patterns {
if strings.Contains(string(b), expression) {
if !contains(matchingFiles, f) {
matchingFiles = append(matchingFiles, f)
}
}
}
}

return matchingFiles
}
12 changes: 12 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/codeyourweb/fastfinder

go 1.17

require (
github.com/akamensky/argparse v1.3.1
github.com/gen2brain/go-unarr v0.1.2
github.com/h2non/filetype v1.1.3
github.com/hillu/go-yara/v4 v4.1.0
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881
gopkg.in/yaml.v2 v2.4.0
)
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
github.com/akamensky/argparse v1.3.1 h1:kP6+OyvR0fuBH6UhbE6yh/nskrDEIQgEA1SUXDPjx4g=
github.com/akamensky/argparse v1.3.1/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
github.com/gen2brain/go-unarr v0.1.2 h1:17kYZ2WMCVFrnmU4A+7BeFXblIOyE8weqggjay+kVIU=
github.com/gen2brain/go-unarr v0.1.2/go.mod h1:P05CsEe8jVEXhxqXqp9mFKUKFV0BKpFmtgNWf8Mcoos=
github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=
github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
github.com/hillu/go-yara/v4 v4.1.0 h1:ZLT9ar+g5r1IgEp1QVYpdqYCgKMNm7DuZYUJpHZ3yUI=
github.com/hillu/go-yara/v4 v4.1.0/go.mod h1:rkb/gSAoO8qcmj+pv6fDZN4tOa3N7R+qqGlEkzT4iys=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
19 changes: 19 additions & 0 deletions logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import (
"log"
"os"
)

const LOG_INFO = 0
const LOG_ERROR = -1

func logMessage(logType int, logMessage ...interface{}) {
if logType == LOG_INFO {
log.SetOutput(os.Stdout)
} else {
log.SetOutput(os.Stderr)
}

log.Println(logMessage...)
}
Loading

0 comments on commit 8331d57

Please sign in to comment.