daisvke/dcrypt
GitHub: daisvke/dcrypt
一个模拟勒索软件行为的跨平台文件加密解密工具,使用 AES-128 CBC 算法加密指定目录下的文件并添加自定义文件头。
Stars: 0 | Forks: 0
# **dcrypt**
## **描述**
dcrypt 是一个跨平台的文件加密/解密工具,它会在加密文件中添加一个自定义文件头,用于存储解密和管理加密内容所需的基本元数据。
### **功能特性**
- dcrypt 仅在 `dcrypt.h` 中指定的目录下工作:
```
# 定义 DC_TARGET_PATHS { "/home/user/folder1", /home/user/folder2" } // 末尾不要加 '/'
```
- 默认处理的扩展名列表可以在 `extensions.c` 中找到:
```
const char *handled_extensions[] = {
"der", "pfx", "key", "crt", "csr", "p12", "pem", "odt", "ott", "sxw", "stw", "uot",
"3ds", "max", "3dm", "ods", "ots", "sxc", "stc", "dif", "slk", "wb2", "odp", "otp",
"sxd", "std", "uop", "odg", "otg", "sxm", "mml", "lay", "lay6", "asc", "sqlite3",
"sqlitedb", "sql", "accdb", "mdb", "db", "dbf", "odb", "frm", "myd", "myi", "ibd",
"mdf", "ldf", "sln", "suo", "cs", "c", "cpp", "pas", "h", "asm", "js", "cmd", "bat",
"ps1", "vbs", "vb", "pl", "dip", "dch", "sch", "brd", "jsp", "php", "asp", "rb",
"java", "jar", "class", "sh", "mp3", "wav", "swf", "fla", "wmv", "mpg", "vob",
"mpeg", "asf", "avi", "mov", "mp4", "3gp", "mkv", "3g2", "flv", "wma", "mid",
"m3u", "m4u", "djvu", "svg", "ai", "psd", "nef", "tiff", "tif", "cgm", "raw",
"gif", "png", "bmp", "jpg", "jpeg", "vcd", "iso", "backup", "zip", "rar", "7z",
"gz", "tgz", "tar", "bak", "tbk", "bz2", "PAQ", "ARC", "aes", "gpg", "vmx",
"vmdk", "vdi", "sldm", "sldx", "sti", "sxi", "602", "hwp", "snt", "onetoc2",
"dwg", "pdf", "wk1", "wks", "123", "rtf", "csv", "txt", "vsdx", "vsd", "edb",
"eml", "msg", "ost", "pst", "potm", "potx", "ppam", "ppsx", "ppsm", "pps",
"pot", "pptm", "pptx", "ppt", "xltm", "xltx", "xlc", "xlm", "xlt", "xlw",
"xlsb", "xlsm", "xlsx", "xls", "dotx", "dotm", "dot", "docm", "docb", "docx",
"doc"
};
```
- 程序将使用加密密钥 + 为每个文件生成的唯一 IV 来加密这些文件夹中的文件内容。
- 文件使用 AES-128 CBC 算法进行加密。
- IV 存储在加密文件的文件头中。
- 程序会重命名上述文件夹中的所有文件,为其添加 ".dcrypt" 扩展名。
- 如果文件已经有此扩展名,则不会被重命名。
- 用于加密文件的密钥长度必须为 32 个字符(由于我们执行的是 AES-128 CBC 加密,它会在内部被转换为 16 字节的密钥)。
- 程序将使用加密密钥执行反向操作,以将文件恢复到原始状态。
## 命令
```
# 编译(使用 -03 标志进行完全优化)
make
# Windows
make TARGET=win
# 或者,用于调试(-g3 标志)
make DEBUG=yes
# Windows
make TARGET=win DEBUG=yes
# 用法:
./dcrypt [-h|-v|-s|-k |-r ]
Options:
-v, --version Show version information
-s, --silent Run in silent mode (non-verbose)
-k, --key Provide an encryption key
-r, --reverse Decrypt using the provided decryption key
-h, --help Show this help message and exit
```
## 测试
```
# 清理,创建包含测试文件的测试文件夹,编译,然后运行程序
make run
# 在测试文件夹中创建测试文件
make quine
# 或者如果你想为每个给定的扩展名生成 30 个文件
make quine n=30 ext="txt vob cpp crt"
```
## 截图
`make quine` 创建具有不同扩展名的测试文件...

加密后,所有文件都会获得 `.dcrypt` 扩展名,并且在文件开头会有自定义文件头。

## 技术细节
### **dcrypt 文件头结构说明:**
当 dcrypt 加密文件时,它会通过添加一个 **自定义文件头** 来修改原始内容。此文件头存储了解密文件和管理加密内容所需的元数据。
| **偏移量** | **值** | **描述** |
|-------------|---------------------------------------|-------------------------------------------|
| **0x0000** | `"2DCRYPT!"` | 用于识别加密文件的 Magic 值/签名。 |
| **0x0008** | **AES 加密期间使用的初始化向量** | AES 加密期间使用的随机 IV,以明文形式存储在此处。 |
| **0x0018** | **原始文件大小** | 原始未加密文件的大小。用于验证解密是否成功。 |
| **0x001C** | **加密文件内容 (AES-128 CBC)** | 原始文件的实际 **AES-128 CBC** 加密内容。
### **数据加密**
dcrypt 执行 AES-128 CBC 加密以对数据进行加密。
#### **链接**
在 CBC 模式下,每个明文块在被加密之前会与前一个密文块进行 XOR 运算。
这意味着每个块的加密依赖于前一个块的密文,从而增强了安全性。 #### **IV(初始化向量)** IV 是一个随机值,用于确保相同的明文块产生不同的密文。
这可以防止加密数据中出现模式。
- 如果没有 IV(即 NULL IV),过程会更快,但安全性较低。 - 相同的明文将产生相同的密文。 - dcrypt 使用下面提到的 keygen 为每个文件创建唯一的 IV。 - 所使用的 IV 随后被保存在自定义文件头中,并在解密期间被检索。 #### **填充** 使用 OpenSSL 的 EVP 函数进行加密时,默认使用的填充方案是 PKCS#7 填充。
如果明文数据不是块大小的整数倍(AES 为 16 字节),PKCS#7 填充会在明文末尾添加字节。 ### **密钥生成器** #### 密钥长度 - Windows 的 CryptoAPI 生成的 AES 密钥可能包含不可打印字符。该密钥本质上是一个二进制数据块,并且不限于可打印的 ASCII 字符。 - 这就是为什么我们使用被转换为十六进制字符串的密钥,因此长度为 32B(16 x 2),因为密钥的每个字节由两个十六进制字符表示。 #### **AES 128 位密钥的 Keygen:/dev/urandom** 我们的 keygen 函数使用给定的字符集生成指定宽度的随机加密密钥。它使用 /dev/urandom 或 /dev/random 为随机数生成器提供种子,并从字符集中随机选择字符来构建密钥。
- 使用 /dev/xrandom 的优点: - 密码学安全性:/dev/xrandom 旨在提供密码学安全的随机数。它使用从设备驱动程序和其他来源收集的环境噪声来生成随机数,使得预测输出变得困难得多。 - 非确定性:与基于初始种子生成确定性序列的伪随机数生成器 (PRNG) rand() 不同,/dev/xrandom 生成非确定性的随机数。这意味着即使在短时间内多次读取它,您也会得到不同的值。 - 更高的熵:从 /dev/xrandom 生成的随机数的随机性质量(熵)显著高于 rand()。这使其适用于需要高质量随机性的应用程序,例如加密密钥、安全 token 和其他安全敏感操作。 - /dev/urandom 或 /dev/random: - 阻塞行为:/dev/random 是随机数的阻塞源。 这意味着如果系统没有足够的熵(随机性)可用, 从 /dev/random 读取将会阻塞(即等待),直到收集到足够的熵。 这可能会导致需要随机数的应用程序出现延迟。 - 虽然它可能无法提供与 /dev/random 相同级别的熵, 但 /dev/urandom 通常被认为对于大多数应用程序(包括密码学用途)足够安全。这就是我们在这里使用它的原因。 #### **IV 128 位密钥的 Keygen:基于当前时间(具有纳秒精度)的 rand()** - 使用两个不同的函数随机生成加密密钥 这两个函数使用不同精度的当前时间作为种子。 - charset:可用于密钥的字符集 - strength:密钥的宽度 - 为 rand() 使用的随机数生成器设置种子 有助于确保 rand() 生成的随机数序列 在程序每次运行时都不同。 - 种子是根据当前时间设置的,这使其具有唯一性,但并非完美无缺: - 使用 srand(time(NULL)) 会以当前时间(秒)为随机数生成器设置种子。 - 这意味着如果在同一秒内多次调用 srand(time(NULL)),您将获得相同的随机数序列,因为种子值没有改变。 - 使用 clock_gettime():此函数可以提供纳秒级精度,具体取决于所使用的时钟。这将提高密钥的随机性。 ## Windows 要在 Windows 上设置开发环境,您需要安装以下工具: ### 安装 #### GCC - **安装**:您需要安装 **MSYS2**。可以从 [MSYS2 官方网站](https://www.msys2.org/) 下载。 - **环境设置**:安装 MSYS2 后,将以下路径添加到系统的环境变量中: C:\msys64\ucrt64\bin - **更新包**:打开 MSYS2 终端并运行以下命令以更新包数据库并安装 GCC: pacman -Syu # 更新包数据库 pacman -Su # 更新已安装的包 pacman -S mingw-w64-x86_64-gcc # 安装 64 位 GCC #### Make - **安装**:您需要安装 **GNUWin32**。可以从 [GnuWin32 的官方网站](http://gnuwin32.sourceforge.net/) 下载。 - **环境设置**:安装 GNUWin32 后,将以下路径添加到系统的环境变量中: C:\Program Files (x86)\GnuWin32\bin ### CryptoAPI 在开发我们的应用程序时,我们评估了 Windows 上可用的多种加密库和框架。经过慎重考虑,我们决定使用 **CryptoAPI**,原因如下: - **与 Windows 的原生集成** CryptoAPI 是 Microsoft 提供的内置加密 API,这意味着它与 Windows 操作系统原生集成。这种集成确保了更好的兼容性和性能,因为它利用了底层的 Windows 安全功能和基础设施。 - **性能优化** 作为原生 API,CryptoAPI 在 Windows 平台上进行了性能优化。它在可用的情况下利用硬件加速,提供高效的加密操作,这对于需要高吞吐量和低延迟的应用程序至关重要。 - **更广泛的 Windows 操作系统兼容性** CryptoAPI 旨在各种版本的 Windows 操作系统(包括 Windows 7、8、10 和 Windows Server 版本)中无缝工作。这种广泛的兼容性使我们的应用程序能够支持各种 Windows 环境,使更多用户无需额外依赖或兼容层即可访问。 ### CRLF - 当您正常打开一个文件时: ``` outfilefd = open(target_path, O_CREAT | O_RDWR | O_TRUNC, 0755); ``` Windows 会自动翻译行尾符(`\r\n` 和 `\n`)并把事情搞砸。 - 除非您明确告诉它“二进制模式”,否则 Windows 会认为您正在读取“文本文件”并试图变得智能(但实际上破坏了二进制数据)。 - 这就是为什么我们必须使用 `O_BINARY` 标志: ``` outfilefd = open(target_path, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0755); ``` - 在 Linux 上,不存在这种转换。 ### 内存映射中的 Windows API 在内存映射文件操作期间会使用 API 函数 `CreateFileMapping` 和 `MapViewOfFile`。 | API 函数 | 用途 | |----------------------|-------------------------------------------------------------------------| | `CreateFileMapping` | 创建文件映射对象(为映射设置内存) | | `MapViewOfFile` | 将该对象的视图映射到调用进程的地址空间中 | #### 使用流程 1. **创建/打开文件** 2. **CreateFileMapping**:为文件保留内存(内核对象) 3. **MapViewOfFile**:在虚拟内存中访问文件的内容 4. **使用映射的数据** 5. **清理**:使用 `UnmapViewOfFile` 和 `CloseHandle`。 ## 实用命令 ``` # Windows: # 以十六进制表示法获取文件,并且仅打印前 3 行 Format-Hex .\sample.txt.dcrypt | Select-Object -First 3 # 在 Unix 上的等效操作 hexdump -C ./sample.txt.dcrypt | head -n 3 ``` ## Linux ### 安装 #### Valgrind & OpenSSL ``` sudo apt update sudo apt install valgrind libssl-dev ``` ## 文档 * [节对象 - Section Objects (Windows)](https://blahcat.github.io/2023-04-04-section-objects-kernel-user-communication-mode/) * [CreateFileMapping() (Windows)](https://learn.microsoft.com/en-us/windows/win32/memory/creating-a-file-mapping-object)
这意味着每个块的加密依赖于前一个块的密文,从而增强了安全性。 #### **IV(初始化向量)** IV 是一个随机值,用于确保相同的明文块产生不同的密文。
这可以防止加密数据中出现模式。
- 如果没有 IV(即 NULL IV),过程会更快,但安全性较低。 - 相同的明文将产生相同的密文。 - dcrypt 使用下面提到的 keygen 为每个文件创建唯一的 IV。 - 所使用的 IV 随后被保存在自定义文件头中,并在解密期间被检索。 #### **填充** 使用 OpenSSL 的 EVP 函数进行加密时,默认使用的填充方案是 PKCS#7 填充。
如果明文数据不是块大小的整数倍(AES 为 16 字节),PKCS#7 填充会在明文末尾添加字节。 ### **密钥生成器** #### 密钥长度 - Windows 的 CryptoAPI 生成的 AES 密钥可能包含不可打印字符。该密钥本质上是一个二进制数据块,并且不限于可打印的 ASCII 字符。 - 这就是为什么我们使用被转换为十六进制字符串的密钥,因此长度为 32B(16 x 2),因为密钥的每个字节由两个十六进制字符表示。 #### **AES 128 位密钥的 Keygen:/dev/urandom** 我们的 keygen 函数使用给定的字符集生成指定宽度的随机加密密钥。它使用 /dev/urandom 或 /dev/random 为随机数生成器提供种子,并从字符集中随机选择字符来构建密钥。
- 使用 /dev/xrandom 的优点: - 密码学安全性:/dev/xrandom 旨在提供密码学安全的随机数。它使用从设备驱动程序和其他来源收集的环境噪声来生成随机数,使得预测输出变得困难得多。 - 非确定性:与基于初始种子生成确定性序列的伪随机数生成器 (PRNG) rand() 不同,/dev/xrandom 生成非确定性的随机数。这意味着即使在短时间内多次读取它,您也会得到不同的值。 - 更高的熵:从 /dev/xrandom 生成的随机数的随机性质量(熵)显著高于 rand()。这使其适用于需要高质量随机性的应用程序,例如加密密钥、安全 token 和其他安全敏感操作。 - /dev/urandom 或 /dev/random: - 阻塞行为:/dev/random 是随机数的阻塞源。 这意味着如果系统没有足够的熵(随机性)可用, 从 /dev/random 读取将会阻塞(即等待),直到收集到足够的熵。 这可能会导致需要随机数的应用程序出现延迟。 - 虽然它可能无法提供与 /dev/random 相同级别的熵, 但 /dev/urandom 通常被认为对于大多数应用程序(包括密码学用途)足够安全。这就是我们在这里使用它的原因。 #### **IV 128 位密钥的 Keygen:基于当前时间(具有纳秒精度)的 rand()** - 使用两个不同的函数随机生成加密密钥 这两个函数使用不同精度的当前时间作为种子。 - charset:可用于密钥的字符集 - strength:密钥的宽度 - 为 rand() 使用的随机数生成器设置种子 有助于确保 rand() 生成的随机数序列 在程序每次运行时都不同。 - 种子是根据当前时间设置的,这使其具有唯一性,但并非完美无缺: - 使用 srand(time(NULL)) 会以当前时间(秒)为随机数生成器设置种子。 - 这意味着如果在同一秒内多次调用 srand(time(NULL)),您将获得相同的随机数序列,因为种子值没有改变。 - 使用 clock_gettime():此函数可以提供纳秒级精度,具体取决于所使用的时钟。这将提高密钥的随机性。 ## Windows 要在 Windows 上设置开发环境,您需要安装以下工具: ### 安装 #### GCC - **安装**:您需要安装 **MSYS2**。可以从 [MSYS2 官方网站](https://www.msys2.org/) 下载。 - **环境设置**:安装 MSYS2 后,将以下路径添加到系统的环境变量中: C:\msys64\ucrt64\bin - **更新包**:打开 MSYS2 终端并运行以下命令以更新包数据库并安装 GCC: pacman -Syu # 更新包数据库 pacman -Su # 更新已安装的包 pacman -S mingw-w64-x86_64-gcc # 安装 64 位 GCC #### Make - **安装**:您需要安装 **GNUWin32**。可以从 [GnuWin32 的官方网站](http://gnuwin32.sourceforge.net/) 下载。 - **环境设置**:安装 GNUWin32 后,将以下路径添加到系统的环境变量中: C:\Program Files (x86)\GnuWin32\bin ### CryptoAPI 在开发我们的应用程序时,我们评估了 Windows 上可用的多种加密库和框架。经过慎重考虑,我们决定使用 **CryptoAPI**,原因如下: - **与 Windows 的原生集成** CryptoAPI 是 Microsoft 提供的内置加密 API,这意味着它与 Windows 操作系统原生集成。这种集成确保了更好的兼容性和性能,因为它利用了底层的 Windows 安全功能和基础设施。 - **性能优化** 作为原生 API,CryptoAPI 在 Windows 平台上进行了性能优化。它在可用的情况下利用硬件加速,提供高效的加密操作,这对于需要高吞吐量和低延迟的应用程序至关重要。 - **更广泛的 Windows 操作系统兼容性** CryptoAPI 旨在各种版本的 Windows 操作系统(包括 Windows 7、8、10 和 Windows Server 版本)中无缝工作。这种广泛的兼容性使我们的应用程序能够支持各种 Windows 环境,使更多用户无需额外依赖或兼容层即可访问。 ### CRLF - 当您正常打开一个文件时: ``` outfilefd = open(target_path, O_CREAT | O_RDWR | O_TRUNC, 0755); ``` Windows 会自动翻译行尾符(`\r\n` 和 `\n`)并把事情搞砸。 - 除非您明确告诉它“二进制模式”,否则 Windows 会认为您正在读取“文本文件”并试图变得智能(但实际上破坏了二进制数据)。 - 这就是为什么我们必须使用 `O_BINARY` 标志: ``` outfilefd = open(target_path, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0755); ``` - 在 Linux 上,不存在这种转换。 ### 内存映射中的 Windows API 在内存映射文件操作期间会使用 API 函数 `CreateFileMapping` 和 `MapViewOfFile`。 | API 函数 | 用途 | |----------------------|-------------------------------------------------------------------------| | `CreateFileMapping` | 创建文件映射对象(为映射设置内存) | | `MapViewOfFile` | 将该对象的视图映射到调用进程的地址空间中 | #### 使用流程 1. **创建/打开文件** 2. **CreateFileMapping**:为文件保留内存(内核对象) 3. **MapViewOfFile**:在虚拟内存中访问文件的内容 4. **使用映射的数据** 5. **清理**:使用 `UnmapViewOfFile` 和 `CloseHandle`。 ## 实用命令 ``` # Windows: # 以十六进制表示法获取文件,并且仅打印前 3 行 Format-Hex .\sample.txt.dcrypt | Select-Object -First 3 # 在 Unix 上的等效操作 hexdump -C ./sample.txt.dcrypt | head -n 3 ``` ## Linux ### 安装 #### Valgrind & OpenSSL ``` sudo apt update sudo apt install valgrind libssl-dev ``` ## 文档 * [节对象 - Section Objects (Windows)](https://blahcat.github.io/2023-04-04-section-objects-kernel-user-communication-mode/) * [CreateFileMapping() (Windows)](https://learn.microsoft.com/en-us/windows/win32/memory/creating-a-file-mapping-object)
标签:信息窃取, 加密密钥, 加密算法, 勒索软件, 安全测试工具, 客户端加密, 恶意软件, 批量测试, 指定扩展名加密, 数据加密, 数据破坏, 文件加密, 文件管理, 目标路径过滤, 自定义文件头, 跨平台工具