网上看到有dat文件破解的,不过都是java和python的,没看到有JS的
自己有了些兴致,所以打算用JS实现。平台是Node
本文按照流程来讲,方便大家理解。如果直接想要实现的代码,请拉到最后。
微信的dat图片文件在xxxx/FileStorage/Image
目录下
先要查看加密的dat文件。直接打开肯定是不行的,因为里面是二进制数据,所以需要一个十六进制器打开。
如果用的是VS Code ,那就很方便了,直接ctrl + shift + x
打开插件商店搜索 hexdump for VSCode,用这个插件可以在VSCode上面很方便地查看文件的十六进制码:
然后用VScode打开文件,在文件上右键选择 Show Hexdump
就可以查看十六进制:
微信的dat文件是如何加密的?原理很简单:是把文件内容通过某个数值进行异或操作来进行加密的,所以我们必须要计算出它的异或值。
JPG图片文件的开头都是 FF D8 FF E0 00 10 4A 46 49 46
所以我们可以先用FF D8 FF
先测试计算。(大部分的文件都是jpg的,当然也有少部分存在png文件,可以多试几个dat文件)
当然不用自己计算,我们打开WIN10自带的计算器,切换到程序员模式进行十六进制的异或运算
刚才十六进制打开的文件开头是5B 7C 5B
,所以让5B 7C 5B
和FF D8 FF
进行异或运算就好了:
得出结果是A4 A4 A4
显而易见,异或值是A4(hex)
也就是说可以通过异或值和dat文件解密得到原文件了
每个人的异或值可能不一样
console.time('完成,耗时');
var fs = require('fs');
var xor = 'a4a4a4a4a4'; //异或值(十六进制)
xor = hexToBin(xor);
var dataPath = './0c9a14c9d42da570d3ea13466be20608.dat'; //要解密的文件路径
var resPath = './res.'; //存放路径
var xorLen = 2;
//读取文件,获取到十六进制数据
fs.readFile(dataPath, { encoding: 'hex' }, function (err, data /** 加密后的十六进制数据*/) {
if (err) {
console.log(err);
} else {
var res = handleEncrypted(data, xor); //解密后的十六进制数据
var extension = getNameExtension(res.substring(0,4));
var hex = Buffer.from(res, 'hex'); //转为十六进制
fs.writeFile(resPath + extension, hex, function (err) {
if (err) {
console.log('出错:', err);
}
console.timeEnd('完成,耗时');
})
}
})
//解密加密数据
function handleEncrypted(strEncrypted) {
//先获取异或值(仅限于jpg文件)
// getXor(strEncrypted.substring(0, 4));
let strLength = strEncrypted.length;
var source = '';
var list = [];
for (var i = 0; i < strLength; i = i + xorLen) {
var str = strEncrypted.substring(0, xorLen);
strEncrypted = strEncrypted.substring(xorLen);
var res = getResult(str);
list.push(res);
}
source = list.join('');
return source;
}
//获取异或值
function getXor(str) {
xor = 'ffd8';
xor = getResult(str);
return;
}
//获取文件名后缀
function getNameExtension(hex) {
var str = hex.substring(0, 4);
var res = dataHead.find(function (item) {
return item.hex === hex;
}).name
return res;
}
//十六进制转二进制
function hexToBin(str) {
let hex_array = [{ hex: '0', bin: "0000" }, { hex: '1', bin: "0001" }, { hex: '2', bin: "0010" }, { hex: '3', bin: "0011" }, { hex: '4', bin: "0100" }, { hex: '5', bin: "0101" }, { hex: '6', bin: "0110" }, { hex: '7', bin: "0111" },
{ hex: '8', bin: "1000" }, { hex: '9', bin: "1001" }, { hex: 'a', bin: "1010" }, { hex: 'b', bin: "1011" }, { hex: 'c', bin: "1100" }, { hex: 'd', bin: "1101" }, { hex: 'e', bin: "1110" }, { hex: 'f', bin: "1111" }];
let value = "";
for (let i = 0; i < str.length; i++) {
value += hex_array.find(function (item) {
return item.hex == str[i];
}).bin;
}
return value;
}
//二进制转十六进制
function binToHex(str) {
let hex_array = [{ hex: '0', bin: "0000" }, { hex: '1', bin: "0001" }, { hex: '2', bin: "0010" }, { hex: '3', bin: "0011" }, { hex: '4', bin: "0100" }, { hex: '5', bin: "0101" }, { hex: '6', bin: "0110" }, { hex: '7', bin: "0111" },
{ hex: '8', bin: "1000" }, { hex: '9', bin: "1001" }, { hex: 'a', bin: "1010" }, { hex: 'b', bin: "1011" }, { hex: 'c', bin: "1100" }, { hex: 'd', bin: "1101" }, { hex: 'e', bin: "1110" }, { hex: 'f', bin: "1111" }];
let value = '';
let list = [];
while (str.length > 4) {
list.push(str.substring(0, 4));
str = str.substring(4);
}
list.push(str);
for (let i = 0; i < list.length; i++) {
value += hex_array.find(function (item) {
return item.bin == list[i];
}).hex;
}
return value;
}
//获取计算结果
function getResult(a) {
let A = hexToBin(a);
let B = xor;
let d = "";
for (let i = 0; i < A.length; i++) {
if (A[i] === B[i]) {
d = d.concat('0');
} else {
d = d.concat('1');
}
}
return binToHex(d);
}
//扩展名-十六进制表
var dataHead = [
{
name: 'jpg',
hex: 'ffd8'
},
{
name: 'png',
hex: '8950'
},
{
name: 'gif',
hex: '4749'
}
]
代码其实写的并不是很好,很多地方并没有做优化,还有批量处理这个还没实现,等有空了会更新博客,如果可能的话还会打包成exe文件。