Skip to content

Commit d1a9476

Browse files
fixed ntlm hash function
v2022-12-16.1800; fixed ntlm hash function
1 parent 9b3cbc4 commit d1a9476

File tree

1 file changed

+65
-79
lines changed

1 file changed

+65
-79
lines changed

hashgen.go

Lines changed: 65 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import (
88
"crypto/sha1"
99
"crypto/sha256"
1010
"crypto/sha512"
11+
"encoding/binary"
1112
"encoding/base64"
1213
"encoding/hex"
14+
"unicode/utf16"
1315
"flag"
1416
"fmt"
1517
"log"
@@ -18,9 +20,11 @@ import (
1820
"io"
1921
"strconv"
2022
)
21-
// version
23+
// version history
24+
// v2022-12-15.2030; initial release
25+
// v2022-12-16.1800; fixed ntlm hash function
2226
func versionFunc() {
23-
wordlistBase64Decode("Q3ljbG9uZSBoYXNoIGdlbmVyYXRvciB2MjAyMi0xMi0xNS4yMDMwCg==")
27+
funcBase64Decode("Q3ljbG9uZSBoYXNoIGdlbmVyYXRvciB2MjAyMi0xMi0xNi4xODAwCg==")
2428
}
2529
// help function
2630
func helpFunc() {
@@ -29,14 +33,14 @@ func helpFunc() {
2933
"\nExample Usage:"+
3034
"\n./hashgen -m md5 -w wordlist.txt"+
3135
"\n./hashgen -m md5 -w wordlist.txt > output.txt\n"+
32-
"\nSupported functions:\nbase64decode\nbase64encode\nbcrypt\ncrc32\nmd4\nmd5\nsha1\nsha256\nsha512\n"
36+
"\nSupported functions:\nbase64decode\nbase64encode\nbcrypt\ncrc32\nmd4\nmd5\nntlm\nsha1\nsha256\nsha512\n"
3337
fmt.Println(str)
3438
os.Exit(0)
3539
}
3640
// main function
3741
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:")
4044
version := flag.Bool("version", false, "Prints program version:")
4145
cyclone := flag.Bool("cyclone", false, "")
4246
help := flag.Bool("help", false, "Prints help:")
@@ -46,20 +50,20 @@ func main() {
4650
versionFunc()
4751
os.Exit(0)
4852
} else if *cyclone == true {
49-
wordlistBase64Decode("Q29kZWQgYnkgY3ljbG9uZSA7KQo=")
53+
funcBase64Decode("Q29kZWQgYnkgY3ljbG9uZSA7KQo=")
5054
os.Exit(0)
5155
} else if *help == true {
5256
helpFunc()
5357
}
5458
// run sanity checks on algo input (m)
5559
if len(*m) < 3 {
56-
fmt.Println("--> -m input not read <--\n")
60+
fmt.Println("--> missing '-m algo' <--\n")
5761
helpFunc()
5862
os.Exit(0)
5963
}
6064
// 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")
6367
helpFunc()
6468
os.Exit(0)
6569
}
@@ -74,30 +78,29 @@ if err != nil {
7478
}
7579
defer file.Close()
7680
scanner := bufio.NewScanner(file)
77-
// optionally, resize scanner's capacity for lines over 64K, see next example
7881
for scanner.Scan() {
79-
// do stuff with lines scanned
82+
// call hash functions for line scanner
8083
line := scanner.Text()
8184
if *m == "md5" {
82-
wordlistMd5(line)
85+
funcMd5(line)
8386
} else if *m == "md4" {
84-
wordlistMd4(line)
87+
funcMd4(line)
8588
} else if *m == "ntlm" {
86-
wordlistNtlm(line)
89+
funcNtlm(line)
8790
} else if *m == "sha1" {
88-
wordlistSha1(line)
91+
funcSha1(line)
8992
} else if *m == "sha256" {
90-
wordlistSha256(line)
93+
funcSha256(line)
9194
} else if *m == "sha512" {
92-
wordlistSha512(line)
95+
funcSha512(line)
9396
} else if *m == "crc32" {
94-
wordlistCrc32(line)
97+
funcCrc32(line)
9598
} else if *m == "bcrypt" {
96-
wordlistBcrypt(line)
99+
funcBcrypt(line)
97100
} else if *m == "base64encode" {
98-
wordlistBase64Encode(line)
101+
funcBase64Encode(line)
99102
} else if *m == "base64decode" {
100-
wordlistBase64Decode(line)
103+
funcBase64Decode(line)
101104
}
102105
}
103106
if err := scanner.Err(); err != nil {
@@ -107,95 +110,78 @@ defer file.Close()
107110
// hashing functions
108111

109112
// md4 hashing function
110-
func wordlistMd4(line string) {
113+
func funcMd4(line string) {
111114
hash := md4.New()
112115
io.WriteString(hash, line)
113116
fmt.Printf("%x\n", hash.Sum(nil))
114117
}
115118
// 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)
130129
}
131130
// md5 hashing function
132-
func wordlistMd5(line string) {
131+
func funcMd5(line string) {
133132
hash := md5.Sum([]byte(line))
134-
wordlistHash := hex.EncodeToString(hash[:])
135-
fmt.Println(wordlistHash)
133+
outputHash := hex.EncodeToString(hash[:])
134+
fmt.Println(outputHash)
136135
}
137136
// sha1 hashing function
138-
func wordlistSha1(line string) {
137+
func funcSha1(line string) {
139138
hash := sha1.Sum([]byte(line))
140-
wordlistHash := hex.EncodeToString(hash[:])
141-
fmt.Println(wordlistHash)
139+
outputHash := hex.EncodeToString(hash[:])
140+
fmt.Println(outputHash)
142141
}
143142
// sha256 hashing function
144-
func wordlistSha256(line string) {
143+
func funcSha256(line string) {
145144
hash := sha256.Sum256([]byte(line))
146-
wordlistHash := hex.EncodeToString(hash[:])
147-
fmt.Println(wordlistHash)
145+
outputHash := hex.EncodeToString(hash[:])
146+
fmt.Println(outputHash)
148147
}
149148
// sha256 hashing function
150-
func wordlistSha512(line string) {
149+
func funcSha512(line string) {
151150
hash := sha512.Sum512([]byte(line))
152-
wordlistHash := hex.EncodeToString(hash[:])
153-
fmt.Println(wordlistHash)
151+
outputHash := hex.EncodeToString(hash[:])
152+
fmt.Println(outputHash)
154153
}
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)
158167
}
159168
// crc32 hashing function
160-
func wordlistCrc32(line string) {
169+
func funcCrc32(line string) {
161170
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)
164173
}
165174
// base64 encode function
166-
func wordlistBase64Encode(line string) {
175+
func funcBase64Encode(line string) {
167176
str := base64.StdEncoding.EncodeToString([]byte(line))
168177
fmt.Println(str)
169178
}
170179
// base64 decode function
171-
func wordlistBase64Decode(line string) {
180+
func funcBase64Decode(line string) {
172181
str, err := base64.StdEncoding.DecodeString(line)
173182
if err != nil {
174183
fmt.Println("Wordlist doesn't appear to be base64 encoded.")
175184
os.Exit(0)
176185
}
177186
fmt.Printf("%s\n", str)
178187
}
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

Comments
 (0)