-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
116 lines (96 loc) · 2.55 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
package main
import (
"bufio"
"flag"
"fmt"
"log"
"io"
"os"
"strconv"
"strings"
)
// 17291806236368054941 = solarwinds.businesslayerhost
/*
Process name, service name, and driver path listings are obtained,
and each value is hashed via the FNV-1a + XOR algorithm as described previously
and checked against hardcoded blocklists.
Some of these hashes have been brute force reversed as part of this analysis,
showing that these routines are scanning for analysis tools and antivirus engine components.
*/
func main(){
var onlymatches bool
flag.BoolVar(&onlymatches, "m", false, "only show matches from known hardcoded hashes")
flag.Parse()
// accept input piped to program, or from an arg
var processes io.Reader
processes = os.Stdin
process := flag.Arg(0)
if process != "" {
processes = strings.NewReader(process)
}
sc := bufio.NewScanner(processes)
lines, err := readLines("hardcoded_hashes.txt")
if err != nil {
log.Fatalf("readLines: %s", err)
}
for sc.Scan() {
// convert to lower
lower_process := strings.ToLower(sc.Text())
// get hash and print
currentHash := GetHash(lower_process)
currentHashStr := strconv.FormatUint(currentHash, 10)
if contains(lines, currentHashStr) {
fmt.Printf("%s : %s\n", currentHashStr, lower_process)
} else {
if !onlymatches {
fmt.Printf("%s : %s\n", currentHashStr, lower_process)
}
}
}
}
// replicate the .net hash function
func GetHash(t string) uint64 {
b := []byte(t)
num := uint64(14695981039346656037)
val := uint64(6605813339339102567)
for _,i := range b {
num = num ^ uint64(i)
num = num * 1099511628211
}
return num ^ val
}
func contains(slice []string, item string) bool {
set := make(map[string]struct{}, len(slice))
for _, s := range slice {
set[s] = struct{}{}
}
_, ok := set[item]
return ok
}
// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines, scanner.Err()
}
// original .NET code:
// Private Shared Function GetHash(s As String) As ULong
// Dim num As ULong = 14695981039346656037UL
// Try
// For Each b As Byte In Encoding.UTF8.GetBytes(s)
// num = num Xor CULng(b)
// num *= 1099511628211UL
// Next
// Catch
// End Try
// Return num Xor 6605813339339102567UL
// End Function