XOR加解密后写入文本文件的EXE可执行文件无法运行问题求助
问题根因
你遇到的问题核心是加密后的二进制数据转文本存储时出现了编码损失:
- 异或运算会生成大量windows-1252编码不支持的控制字符、扩展字符,你现在的代码用文本模式、指定windows-1252编码写加密文件时,这些无法映射的字符会被自动替换为默认替代字符(一般是0x3F问号),写入
fileenc.txt的内容已经和原始加密结果不一致。 - 读取
fileenc.txt时你用的是二进制模式,读到的是被编码修改过的内容,解密后自然和原始EXE的二进制数据不一致,导致EXE无法运行。
你之前不加解密直接读写EXE正常、即时加解密正常,都是因为没有经过编码转换这个会损失数据的环节。
修复方案
加密后的内容直接用二进制流写入文件,完全跳过文本编码转换的步骤,读取时也直接读取二进制数据再转字符串处理,修改后的完整代码如下:
Main(); function Main() { var arrKey = "encryptionkey"; // 加密EXE写入文本文件 Crypt( "C:\\...\\file.exe", "C:\\...\\fileenc.txt", arrKey ); // 解密文本文件写入EXE Crypt( "C:\\...\\fileenc.txt", "C:\\...\\filedec.exe", arrKey ); } function Crypt(fileIn, fileOut, key) { var adTypeBinary = 1, adTypeText = 2, adSaveCreateOverWrite = 2; // 二进制模式读取输入文件 var BinaryStreamRead = new ActiveXObject("ADODB.Stream"); BinaryStreamRead.Type = adTypeBinary; BinaryStreamRead.Open(); BinaryStreamRead.LoadFromFile(fileIn); var fileContent = BinaryStreamRead.Read(); BinaryStreamRead.Close(); // 二进制数据转字符串,不做编码转换 var objRS = new ActiveXObject("ADODB.Recordset"); var adVarChar = 201, adFldLong = 0x80; objRS.Fields.Append("filedata", adVarChar, fileContent.size + 1, adFldLong); objRS.Open(); objRS.AddNew(); objRS.Fields("filedata").AppendChunk(fileContent); var binString = objRS("filedata").value; objRS.Close(); // 补齐密钥长度 while (key.length < binString.length) { key += key; } key = key.substr(0, binString.length); // 异或加解密(加解密逻辑完全一致) var cryptresult = ""; for (var i = 0; i < binString.length; i++) { var charCode = binString.charCodeAt(i) ^ key.charCodeAt(i); cryptresult += String.fromCharCode(charCode); } // 字符串转二进制,全程用1字节对应1字符的iso-8859-1编码避免映射损失 var outStream = new ActiveXObject("ADODB.Stream"); outStream.Type = adTypeText; outStream.Charset = "iso-8859-1"; outStream.Open(); outStream.WriteText(cryptresult); outStream.Position = 0; // 切换到二进制模式,跳过默认生成的BOM头 outStream.Type = adTypeBinary; outStream.Position = 2; var binaryResult = outStream.Read(); outStream.Close(); // 二进制模式直接写入文件 var writeStream = new ActiveXObject("ADODB.Stream"); writeStream.Type = adTypeBinary; writeStream.Open(); writeStream.Write(binaryResult); writeStream.SaveToFile(fileOut, adSaveCreateOverWrite); writeStream.Close(); }
可选优化
如果需要fileenc.txt是可直接查看的文本格式,可在加密后将二进制数据转Base64编码再存储,读取时先解码Base64再解密,也能完全避免编码损失问题。另外异或加密属于弱加密算法,仅适用于非敏感场景的简单内容混淆。
内容的提问来源于stack exchange,提问作者splendorkafta
相关产品推荐
相关产品推荐

