如何加密文件使其不可编辑但可被已有.exe正常读取?
实现方案与操作流程
核心逻辑
你要达成的目标本质是:让目标文件仅能被你的exe解密读取,其他人修改加密后的文件会破坏数据结构,导致解密失败,从而无法被exe正常识别。核心用对称加密即可实现,分两种场景处理:
场景1:你拥有原.exe的源代码(最可靠的方案)
步骤1:选择对称加密算法
优先选轻量高效的,比如AES-128-CBC或者XTEA——加密速度快,资源占用低,适合文件加密。
步骤2:编写简单的加密工具
用你熟悉的语言写个小工具,逻辑很直接:
- 读取要保护的文件内容
- 生成随机密钥(比如AES-128需要16字节密钥)和初始化向量IV
- 用选定算法加密文件内容
- 把IV和加密后的内容存成新文件(可以直接覆盖原文件,或者加
.enc后缀)
注意:密钥要妥善保存,后续要嵌入到你的exe里,别明文存在磁盘上。可以给密钥做简单混淆,比如拆成几个片段存在代码里,运行时再拼接。
给个Python的示例代码(用AES-128-CBC):
from Crypto.Cipher import AES from Crypto.Random import get_random_bytes import os def encrypt_file(input_path, output_path, key): iv = get_random_bytes(16) cipher = AES.new(key, AES.MODE_CBC, iv) with open(input_path, 'rb') as f_in: data = f_in.read() # 填充数据到AES块大小的倍数 padding = AES.block_size - len(data) % AES.block_size data += bytes([padding]) * padding encrypted_data = cipher.encrypt(data) # 把IV和加密数据一起写入(解密时需要IV) with open(output_path, 'wb') as f_out: f_out.write(iv + encrypted_data) # 生成16字节的AES密钥 key = get_random_bytes(16) # 把密钥存到安全位置(之后要嵌入到exe代码里) with open('key.bin', 'wb') as f: f.write(key) # 加密目标文件 encrypt_file('vulnerable_config.txt', 'vulnerable_config.txt', key)
步骤3:修改原exe的读取逻辑
找到exe里读取目标文件的代码段,加上解密逻辑:
- 读取加密后的文件,先提取前16字节的IV,剩下的是加密数据
- 用嵌入的密钥初始化解密器
- 解密数据并去除填充,之后的逻辑和之前读明文文件完全一致
给个C#的解密示例:
using System; using System.IO; using System.Security.Cryptography; public static string GetDecryptedConfig(string filePath) { // 嵌入的密钥(从key.bin里复制的字节数组) byte[] key = new byte[] { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; byte[] encryptedData = File.ReadAllBytes(filePath); // 提取IV(前16字节) byte[] iv = new byte[16]; Array.Copy(encryptedData, 0, iv, 0, 16); byte[] cipherText = new byte[encryptedData.Length - 16]; Array.Copy(encryptedData, 16, cipherText, 0, cipherText.Length); using (Aes aes = Aes.Create()) { aes.Key = key; aes.IV = iv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); using (MemoryStream msDecrypt = new MemoryStream(cipherText)) using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { return srDecrypt.ReadToEnd(); } } }
步骤4:测试验证
- 用加密工具把目标文件加密(直接覆盖原文件的话,exe不用改路径)
- 运行修改后的exe,确认能正常读取内容
- 手动编辑加密后的文件,随便改点内容保存,再运行exe——会因为解密失败无法读取,达到防编辑的目的
场景2:没有原.exe的源代码(只能做代理加载)
这种情况需要做个“中间层”,把加密文件解密到内存,让原exe读内存里的明文,而不是磁盘上的加密文件。
步骤1:加密目标文件
和场景1的步骤1、2完全一样,用对称加密算法加密文件,保存好密钥。
步骤2:编写代理加载器
用C++或者C#写加载器,核心思路是Hook原exe的文件读取API:
- Hook
CreateFile/ReadFile这类API,当exe尝试读取目标文件时,不读磁盘上的加密文件,而是返回内存中解密后的明文数据 - 或者用进程注入,把解密后的内存数据传递给原exe
举个Hook的思路(C++用Detours库):
- 拦截
CreateFileW,当检测到目标文件名时,返回一个自定义的虚拟文件句柄 - 拦截
ReadFile,当读取这个虚拟句柄时,返回内存中的解密数据
步骤3:分发测试
- 把加载器、原exe、加密后的文件放在同一目录
- 运行加载器,它会自动处理解密并让原exe正常读取数据
- 他人修改加密后的文件后,加载器解密时会发现数据损坏,原exe无法正常解析
额外注意事项
- 密钥保护:密钥绝对不能明文存在磁盘,嵌入到exe/加载器后要做代码混淆,防止被反编译提取
- 完整性校验:加密文件时可以加个SHA-256哈希值,exe读取时先验证哈希,防止文件被篡改后解密出垃圾内容
- 大文件优化:如果是大文件,别一次性加密/解密全部内容,分块处理减少内存占用
内容的提问来源于stack exchange,提问作者Developer
相关产品推荐
相关产品推荐

