勒索软件相关:想请教优秀的Golang加密开发高手几个问题
勒索软件相关:想请教优秀的Golang加密开发高手几个问题 我的Qnap Nas最近感染了一种用Go语言编写的勒索软件,我别无选择只能支付赎金……我算是“幸运”的,因为黑客发给我一个用于解密文件的二进制程序。
我不想使用他们的二进制程序,因为谁知道它会在我的Nas或电脑上再次做什么。
因此,我对其进行了逆向工程,并编写了自己的简单解密代码。当我在JPEG图像上测试时,我以为它运行良好:
package main
import (
"crypto/aes"
"crypto/cipher"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
)
func decryptFile(key string, srcpath string) {
fmt.Printf("UnLock: %s\n", srcpath)
ext := filepath.Ext(srcpath)
if ext != ".encrypt" {
log.Fatal("not a ech0raix encrypted file - must end with .encrypt")
}
dstpath := strings.TrimSuffix(srcpath, ext)
content, err := ioutil.ReadFile(srcpath)
if err != nil {
panic(err.Error())
}
block, err := aes.NewCipher([]byte(key))
if err != nil {
panic(err)
}
iv := content[:aes.BlockSize]
cyphertext := content[aes.BlockSize:]
plaintext := make([]byte, len(content)-aes.BlockSize)
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(plaintext, cyphertext)
f, err := os.Create(dstpath)
if err != nil {
panic(err.Error())
}
_, err = io.Copy(f, bytes.NewReader(plaintext))
if err != nil {
panic(err.Error())
}
}
当然,我还有一些非常大的文件(例如虚拟机文件),最小也有40 GB,即使在我的电脑上,解密程序也会因为巨大的内存分配而失败。
所以我编写了以下代码来分块解密:
package main
import (
"crypto/aes"
"crypto/cipher"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
)
//const key = "4STDs9cmUlkiujXuLkdTouoqOIfER4TE"
const default_buffer_size = 65536
func UNUSED(x ...interface{}) {}
func check(e error) {
if e != nil {
panic(e)
}
}
func decryptFile(key string, srcpath string) {
fmt.Printf("UnLock: %s\n", srcpath)
ext := filepath.Ext(srcpath)
if ext != ".encrypt" {
log.Fatal("not a ech0raix encrypted file - must end with .encrypt")
}
dstpath := strings.TrimSuffix(srcpath, ext)
// Create the cipher object and decrypt the data
block, err := aes.NewCipher([]byte(key))
check(err)
// Open the input and output files
input_file, err := os.Open(srcpath)
check(err)
output_file, err := os.Create(dstpath)
check(err)
// get the size of the ciphered data
//fi, _ := input_file.Stat()
//check(err)
//data_len := int(fi.Size()) - aes.BlockSize
// read the iv from input file
iv := make([]byte, aes.BlockSize)
n1, err := input_file.Read(iv)
UNUSED(n1)
check(err)
// Set buffer size
buffer_size := default_buffer_size
// read b
stream := cipher.NewCFBDecrypter(block, iv)
input_buffer := make([]byte, buffer_size)
decrypted_bytes := make([]byte, buffer_size)
read_len, total_len := 0, 0
for ok := true; ok; ok = (read_len > 0) {
read_len, _ = input_file.Read(input_buffer)
total_len += read_len
if read_len == buffer_size {
stream.XORKeyStream(decrypted_bytes, input_buffer)
_, _ = output_file.Write(decrypted_bytes)
} else if read_len > 0 {
stream.XORKeyStream(decrypted_bytes, input_buffer)
tmp_buffer := decrypted_bytes[:read_len]
_, _ = output_file.Write(tmp_buffer)
//fmt.Println("What should I do ?????")
}
}
input_file.Close()
output_file.Close()
}
但是,当我第一次在JSON文件上测试时,我发现解密后的文件开头部分是正确的,但末尾有一些垃圾数据。
这是两种方法的结果: https://github.com/vricosti/ech0raix_decryptor/tree/dev/decrypt_by_chunk/tests
那么,您认为我应该如何修改第二个算法以获得正确的解密数据呢? 分块方法的代码也可以在这个git仓库中找到: https://github.com/vricosti/ech0raix_decryptor/tree/dev/decrypt_by_chunk
谢谢
更多关于勒索软件相关:想请教优秀的Golang加密开发高手几个问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
好的,首先我不是来讨论哲学的,我支付了赎金并得到了一个解密工具,我已经对其进行了逆向工程,看起来没有病毒。我和黑客谈过,甚至辱骂了他们,结果我被封禁了。我的问题是技术性的,不是哲学性的。 我只想要一个这个解密工具的开源版本。
更多关于勒索软件相关:想请教优秀的Golang加密开发高手几个问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
永远不要付钱,卸载然后重新安装你的操作系统。永远不要与“骗子”/“黑客”交谈,也永远不要把你的私密照片给任何人。
关于你的“算法”,它看起来非常简单,我不会尝试。你在无谓地消耗精力去“对抗”一些骗子。接受你的损失,快速向前看,不要再浪费更多的时间和精力了。
你的分块解密代码存在一个关键问题:CFB模式是流式加密模式,解密时需要保持状态连续性。在每次循环中,你都在重新创建decrypted_bytes缓冲区,但没有正确处理部分读取的情况。
以下是修复后的代码:
package main
import (
"crypto/aes"
"crypto/cipher"
"io"
"log"
"os"
"path/filepath"
"strings"
)
const bufferSize = 64 * 1024 // 64KB缓冲区
func decryptFile(key string, srcpath string) error {
log.Printf("解密: %s", srcpath)
ext := filepath.Ext(srcpath)
if ext != ".encrypt" {
log.Fatal("不是ech0raix加密文件 - 必须以.encrypt结尾")
}
dstpath := strings.TrimSuffix(srcpath, ext)
// 创建密码对象
block, err := aes.NewCipher([]byte(key))
if err != nil {
return err
}
// 打开输入输出文件
inputFile, err := os.Open(srcpath)
if err != nil {
return err
}
defer inputFile.Close()
outputFile, err := os.Create(dstpath)
if err != nil {
return err
}
defer outputFile.Close()
// 读取IV
iv := make([]byte, aes.BlockSize)
if _, err := io.ReadFull(inputFile, iv); err != nil {
return err
}
// 创建CFB解密流
stream := cipher.NewCFBDecrypter(block, iv)
// 使用缓冲区进行流式解密
buffer := make([]byte, bufferSize)
decrypted := make([]byte, bufferSize)
for {
n, err := inputFile.Read(buffer)
if n > 0 {
stream.XORKeyStream(decrypted[:n], buffer[:n])
if _, err := outputFile.Write(decrypted[:n]); err != nil {
return err
}
}
if err == io.EOF {
break
}
if err != nil {
return err
}
}
return nil
}
func main() {
key := "4STDs9cmUlkiujXuLkdTouoqOIfER4TE"
srcFile := "test.json.encrypt"
if err := decryptFile(key, srcFile); err != nil {
log.Fatal("解密失败:", err)
}
log.Println("解密完成")
}
关键改进:
- 使用
io.ReadFull确保完整读取IV - 解密流对象
stream在整个文件处理过程中保持状态 - 正确处理部分读取:
stream.XORKeyStream(decrypted[:n], buffer[:n]) - 只写入实际读取的字节数:
outputFile.Write(decrypted[:n]) - 使用
io.EOF正确检测文件结束 - 添加了错误处理和资源清理
对于大文件,这个版本应该能正确工作,因为:
- CFB模式是自同步的流密码
- 解密流状态在每次
XORKeyStream调用后自动更新 - 缓冲区大小固定为64KB,内存使用可控
测试时,确保你的密钥是正确的32字节AES-256密钥。如果问题仍然存在,检查原始加密文件是否使用了标准的AES-CFB模式。

