Skip to content

Commit da1b32c

Browse files
authored
Add files via upload
1 parent de923e1 commit da1b32c

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed

go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module decrypter
2+
3+
go 1.22.4

main.go

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package main
2+
3+
/*
4+
This project was experimenting with how gecko browsers encrypt and decrypt passwords along with storing them.
5+
6+
I got lot of inspiration from this project https://github.com/unode/firefox_decrypt as well as the information on how to use nss3.dll.
7+
8+
I also used this article to dumb down everything a lot https://medium.com/geekculture/how-to-hack-firefox-passwords-with-python-a394abf18016.
9+
10+
I really like it and it works very well but it's also over 1k lines of code and wanted to make a more simple version for
11+
anyone who wants a simple and easy way to understand.
12+
13+
It should work with any gecko based browser but I have only tested librewolf and firefox so far.
14+
*/
15+
16+
import (
17+
"encoding/base64"
18+
"encoding/json"
19+
"fmt"
20+
"os"
21+
"syscall"
22+
"unsafe"
23+
)
24+
25+
// we got an array of that shit fr
26+
type json_data struct {
27+
Logins []login_data `json:"logins"`
28+
}
29+
30+
// login data struct cause golang 👍
31+
type login_data struct {
32+
Hostname string `json:"hostname"`
33+
FormSubmitURL string `json:"formSubmitURL"`
34+
EncryptedUsername string `json:"encryptedUsername"`
35+
EncryptedPassword string `json:"encryptedPassword"`
36+
TimeCreated int `json:"timeCreated"`
37+
TimeLastUsed int `json:"timeLastUsed"`
38+
TimePasswordChanged int `json:"timePasswordChanged"`
39+
TimesUsed int `json:"timesUsed"`
40+
}
41+
42+
// Get NSS and all it's modules that we need
43+
var (
44+
nss3 = syscall.NewLazyDLL("C:\\Program Files\\Mozilla Firefox\\nss3.dll")
45+
nssInit = nss3.NewProc("NSS_Init")
46+
pk11SDRDecrypt = nss3.NewProc("PK11SDR_Decrypt")
47+
)
48+
49+
// the secItem stuff struct for nss
50+
type secItem struct {
51+
Type int
52+
Data *byte
53+
Len int
54+
}
55+
56+
// We gotta initalize nss fr
57+
func initNSS(profile string) error {
58+
byte_ptr, err := syscall.BytePtrFromString(profile)
59+
if err != nil {
60+
return fmt.Errorf("failed to convert profile path to byte pointer: %v", err)
61+
}
62+
ret, _, err := nssInit.Call(uintptr(unsafe.Pointer(byte_ptr)))
63+
if ret != 0 {
64+
return fmt.Errorf("NSS_Init failed with error: %v", err)
65+
}
66+
return nil
67+
}
68+
69+
// gotta decode the base64 strings fr
70+
func decodeBase64(s string) ([]byte, error) {
71+
//if s[0] == '~' && s[len(s)-1] == '~' {
72+
// s = s[1 : len(s)-1]
73+
//}
74+
decoded, err := base64.StdEncoding.DecodeString(s)
75+
if err != nil {
76+
return nil, fmt.Errorf("failed to decode base64: %v", err)
77+
}
78+
return decoded, nil
79+
}
80+
81+
func decrypt(encrypted string) (string, error) {
82+
encBytes, err := decodeBase64(encrypted)
83+
if err != nil {
84+
return "", err
85+
}
86+
87+
// Initalize our secItem with the pointer to the encrypted bytes and the length
88+
encItem := secItem{Data: &encBytes[0], Len: len(encBytes)}
89+
90+
var decItem secItem
91+
// decrypt the bytes!!!!!!!
92+
ret, _, err := pk11SDRDecrypt.Call(uintptr(unsafe.Pointer(&encItem)), uintptr(unsafe.Pointer(&decItem)), 0)
93+
if ret != 0 {
94+
return "", fmt.Errorf("PK11SDR_Decrypt failed with error: %v", err)
95+
}
96+
97+
// now we gotta convert that hoe back to a string
98+
decBytes := (*[1 << 30]byte)(unsafe.Pointer(decItem.Data))[:decItem.Len:decItem.Len]
99+
return string(decBytes), nil
100+
}
101+
102+
func main() {
103+
// PATH TO THE GECKO BROWSER PROFILE
104+
105+
profile := "C:\\Users\\this1\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\8u9732sm.default-release"
106+
107+
firefoxDir := "C:\\Program Files\\Mozilla Firefox"
108+
os.Setenv("PATH", os.Getenv("PATH")+";"+firefoxDir)
109+
110+
loginsJsonLocation := profile + "\\logins.json"
111+
112+
// Initialize NSS
113+
err := initNSS(profile)
114+
if err != nil {
115+
fmt.Println("Error initializing NSS:", err)
116+
return
117+
}
118+
119+
// Read and parse logins.json f r
120+
loginsJsonData := json_data{}
121+
loginsJsonFile, err := os.Open(loginsJsonLocation)
122+
if err != nil {
123+
fmt.Println("Error opening logins.json:", err)
124+
return
125+
}
126+
defer loginsJsonFile.Close()
127+
128+
// Gotta decode json in golang 😭
129+
jsonParser := json.NewDecoder(loginsJsonFile)
130+
err = jsonParser.Decode(&loginsJsonData)
131+
if err != nil {
132+
fmt.Println("Error decoding logins.json:", err)
133+
return
134+
}
135+
136+
for _, login := range loginsJsonData.Logins {
137+
fmt.Printf("Decrypting login for %s\n", login.Hostname)
138+
decryptedUsername, err := decrypt(login.EncryptedUsername)
139+
if err != nil {
140+
fmt.Println("Error decrypting username for", login.Hostname, ":", err)
141+
continue
142+
}
143+
decryptedPassword, err := decrypt(login.EncryptedPassword)
144+
if err != nil {
145+
fmt.Println("Error decrypting password for", login.Hostname, ":", err)
146+
continue
147+
}
148+
149+
fmt.Printf("Hostname: %s\nUsername: %s\nPassword: %s\n\n", login.Hostname, decryptedUsername, decryptedPassword)
150+
}
151+
}

0 commit comments

Comments
 (0)