@@ -8,8 +8,10 @@ import (
8
8
"crypto/sha1"
9
9
"crypto/sha256"
10
10
"crypto/sha512"
11
+ "encoding/binary"
11
12
"encoding/base64"
12
13
"encoding/hex"
14
+ "unicode/utf16"
13
15
"flag"
14
16
"fmt"
15
17
"log"
@@ -18,9 +20,11 @@ import (
18
20
"io"
19
21
"strconv"
20
22
)
21
- // version
23
+ // version history
24
+ // v2022-12-15.2030; initial release
25
+ // v2022-12-16.1800; fixed ntlm hash function
22
26
func versionFunc () {
23
- wordlistBase64Decode ( "Q3ljbG9uZSBoYXNoIGdlbmVyYXRvciB2MjAyMi0xMi0xNS4yMDMwCg ==" )
27
+ funcBase64Decode ( "Q3ljbG9uZSBoYXNoIGdlbmVyYXRvciB2MjAyMi0xMi0xNi4xODAwCg ==" )
24
28
}
25
29
// help function
26
30
func helpFunc () {
@@ -29,14 +33,14 @@ func helpFunc() {
29
33
"\n Example Usage:" +
30
34
"\n ./hashgen -m md5 -w wordlist.txt" +
31
35
"\n ./hashgen -m md5 -w wordlist.txt > output.txt\n " +
32
- "\n Supported functions:\n base64decode\n base64encode\n bcrypt\n crc32\n md4\n md5\n sha1\n sha256\n sha512\n "
36
+ "\n Supported functions:\n base64decode\n base64encode\n bcrypt\n crc32\n md4\n md5\n ntlm \ n sha1\n sha256\n sha512\n "
33
37
fmt .Println (str )
34
38
os .Exit (0 )
35
39
}
36
40
// main function
37
41
func main () {
38
- m := flag .String ("m" , "algo " , "Mode:" )
39
- w := flag .String ("w" , "wordlist.txt " , "Path to wordlist:" )
42
+ m := flag .String ("m" , "" , "Mode:" )
43
+ w := flag .String ("w" , "" , "Path to wordlist:" )
40
44
version := flag .Bool ("version" , false , "Prints program version:" )
41
45
cyclone := flag .Bool ("cyclone" , false , "" )
42
46
help := flag .Bool ("help" , false , "Prints help:" )
@@ -46,20 +50,20 @@ func main() {
46
50
versionFunc ()
47
51
os .Exit (0 )
48
52
} else if * cyclone == true {
49
- wordlistBase64Decode ("Q29kZWQgYnkgY3ljbG9uZSA7KQo=" )
53
+ funcBase64Decode ("Q29kZWQgYnkgY3ljbG9uZSA7KQo=" )
50
54
os .Exit (0 )
51
55
} else if * help == true {
52
56
helpFunc ()
53
57
}
54
58
// run sanity checks on algo input (m)
55
59
if len (* m ) < 3 {
56
- fmt .Println ("--> -m input not read <--\n " )
60
+ fmt .Println ("--> missing ' -m algo' <--\n " )
57
61
helpFunc ()
58
62
os .Exit (0 )
59
63
}
60
64
// run sanity checks on wordlist input (w)
61
- if len (* w ) < 3 {
62
- fmt .Println ("--> -w input not read <--\n " )
65
+ if len (* w ) < 1 {
66
+ fmt .Println ("--> missing '-m wordlist' <--\n " )
63
67
helpFunc ()
64
68
os .Exit (0 )
65
69
}
@@ -74,30 +78,29 @@ if err != nil {
74
78
}
75
79
defer file .Close ()
76
80
scanner := bufio .NewScanner (file )
77
- // optionally, resize scanner's capacity for lines over 64K, see next example
78
81
for scanner .Scan () {
79
- // do stuff with lines scanned
82
+ // call hash functions for line scanner
80
83
line := scanner .Text ()
81
84
if * m == "md5" {
82
- wordlistMd5 (line )
85
+ funcMd5 (line )
83
86
} else if * m == "md4" {
84
- wordlistMd4 (line )
87
+ funcMd4 (line )
85
88
} else if * m == "ntlm" {
86
- wordlistNtlm (line )
89
+ funcNtlm (line )
87
90
} else if * m == "sha1" {
88
- wordlistSha1 (line )
91
+ funcSha1 (line )
89
92
} else if * m == "sha256" {
90
- wordlistSha256 (line )
93
+ funcSha256 (line )
91
94
} else if * m == "sha512" {
92
- wordlistSha512 (line )
95
+ funcSha512 (line )
93
96
} else if * m == "crc32" {
94
- wordlistCrc32 (line )
97
+ funcCrc32 (line )
95
98
} else if * m == "bcrypt" {
96
- wordlistBcrypt (line )
99
+ funcBcrypt (line )
97
100
} else if * m == "base64encode" {
98
- wordlistBase64Encode (line )
101
+ funcBase64Encode (line )
99
102
} else if * m == "base64decode" {
100
- wordlistBase64Decode (line )
103
+ funcBase64Decode (line )
101
104
}
102
105
}
103
106
if err := scanner .Err (); err != nil {
@@ -107,95 +110,78 @@ defer file.Close()
107
110
// hashing functions
108
111
109
112
// md4 hashing function
110
- func wordlistMd4 (line string ) {
113
+ func funcMd4 (line string ) {
111
114
hash := md4 .New ()
112
115
io .WriteString (hash , line )
113
116
fmt .Printf ("%x\n " , hash .Sum (nil ))
114
117
}
115
118
// ntlm hashing function
116
- // go does not have an ntlm hash function
117
- // we use some hacky logic to convert the
118
- // plaintext to UTF16, then call the md4 function
119
- func wordlistNtlm (line string ) {
120
- u := ""
121
- _ = 0
122
- for i , c := range line {
123
- u = u + string (c ) + "\x00 "
124
- _ = i
125
- }
126
- h := md4 .New ()
127
- h .Write ([]byte (u ))
128
- md4 := h .Sum (nil )
129
- fmt .Printf ("%x\n " , md4 )
119
+ // code modified from https://github.com/tv42/ntlmv2hash/blob/master/nthash.go
120
+ func funcNtlm (line string ) {
121
+ input := utf16 .Encode ([]rune (line ))
122
+ hash := md4 .New ()
123
+ if err := binary .Write (hash , binary .LittleEndian , input ); err != nil {
124
+ panic (fmt .Errorf ("Failed NTLM hashing password: %w" , err ))
125
+ }
126
+ outputHash := hash .Sum (nil )
127
+ // encode to conventional uppercase hex
128
+ fmt .Printf ("%X\n " , outputHash )
130
129
}
131
130
// md5 hashing function
132
- func wordlistMd5 (line string ) {
131
+ func funcMd5 (line string ) {
133
132
hash := md5 .Sum ([]byte (line ))
134
- wordlistHash := hex .EncodeToString (hash [:])
135
- fmt .Println (wordlistHash )
133
+ outputHash := hex .EncodeToString (hash [:])
134
+ fmt .Println (outputHash )
136
135
}
137
136
// sha1 hashing function
138
- func wordlistSha1 (line string ) {
137
+ func funcSha1 (line string ) {
139
138
hash := sha1 .Sum ([]byte (line ))
140
- wordlistHash := hex .EncodeToString (hash [:])
141
- fmt .Println (wordlistHash )
139
+ outputHash := hex .EncodeToString (hash [:])
140
+ fmt .Println (outputHash )
142
141
}
143
142
// sha256 hashing function
144
- func wordlistSha256 (line string ) {
143
+ func funcSha256 (line string ) {
145
144
hash := sha256 .Sum256 ([]byte (line ))
146
- wordlistHash := hex .EncodeToString (hash [:])
147
- fmt .Println (wordlistHash )
145
+ outputHash := hex .EncodeToString (hash [:])
146
+ fmt .Println (outputHash )
148
147
}
149
148
// sha256 hashing function
150
- func wordlistSha512 (line string ) {
149
+ func funcSha512 (line string ) {
151
150
hash := sha512 .Sum512 ([]byte (line ))
152
- wordlistHash := hex .EncodeToString (hash [:])
153
- fmt .Println (wordlistHash )
151
+ outputHash := hex .EncodeToString (hash [:])
152
+ fmt .Println (outputHash )
154
153
}
155
- // bcrypt cost 10 hashing function
156
- func wordlistBcrypt (line string ) {
157
- getBcrypt (line )
154
+ // bcrypt cost 10 (DefaultCost) hashing function
155
+ // https://pkg.go.dev/golang.org/x/crypto/bcrypt
156
+ func funcBcrypt (line string ) {
157
+ pwd := []byte (line )
158
+ hash := hashAndSalt (pwd )
159
+ fmt .Println (hash )
160
+ }
161
+ func hashAndSalt (pwd []byte ) string {
162
+ hash , err := bcrypt .GenerateFromPassword (pwd , bcrypt .DefaultCost )
163
+ if err != nil {
164
+ log .Println (err )
165
+ }
166
+ return string (hash )
158
167
}
159
168
// crc32 hashing function
160
- func wordlistCrc32 (line string ) {
169
+ func funcCrc32 (line string ) {
161
170
hash := crc32 .ChecksumIEEE ([]byte (line ))
162
- wordlistHash := strconv .FormatUint (uint64 (hash ), 16 )
163
- fmt .Println (wordlistHash )
171
+ outputHash := strconv .FormatUint (uint64 (hash ), 16 )
172
+ fmt .Println (outputHash )
164
173
}
165
174
// base64 encode function
166
- func wordlistBase64Encode (line string ) {
175
+ func funcBase64Encode (line string ) {
167
176
str := base64 .StdEncoding .EncodeToString ([]byte (line ))
168
177
fmt .Println (str )
169
178
}
170
179
// base64 decode function
171
- func wordlistBase64Decode (line string ) {
180
+ func funcBase64Decode (line string ) {
172
181
str , err := base64 .StdEncoding .DecodeString (line )
173
182
if err != nil {
174
183
fmt .Println ("Wordlist doesn't appear to be base64 encoded." )
175
184
os .Exit (0 )
176
185
}
177
186
fmt .Printf ("%s\n " , str )
178
187
}
179
-
180
- // bcrypt encode function
181
- // https://pkg.go.dev/golang.org/x/crypto/bcrypt
182
- func getBcrypt (line string ) {
183
- pwd := []byte (line )
184
- hash := hashAndSalt (pwd )
185
- fmt .Println (hash )
186
- }
187
- func getPwd () []byte {
188
- var pwd string
189
- _ , err := fmt .Scan (& pwd )
190
- if err != nil {
191
- log .Println (err )
192
- }
193
- return []byte (pwd )
194
- }
195
- func hashAndSalt (pwd []byte ) string {
196
- hash , err := bcrypt .GenerateFromPassword (pwd , bcrypt .DefaultCost )
197
- if err != nil {
198
- log .Println (err )
199
- }
200
- return string (hash )
201
- }
0 commit comments