Javascript 解析微信dat文件 微信图片破解

网上看到有dat文件破解的,不过都是java和python的,没看到有JS的
自己有了些兴致,所以打算用JS实现。平台是Node
本文按照流程来讲,方便大家理解。如果直接想要实现的代码,请拉到最后。

1. 查看加密文件

微信的dat图片文件在xxxx/FileStorage/Image目录下
先要查看加密的dat文件。直接打开肯定是不行的,因为里面是二进制数据,所以需要一个十六进制器打开。

如果用的是VS Code ,那就很方便了,直接ctrl + shift + x 打开插件商店搜索 hexdump for VSCode,用这个插件可以在VSCode上面很方便地查看文件的十六进制码:
Javascript 解析微信dat文件 微信图片破解_第1张图片

然后用VScode打开文件,在文件上右键选择 Show Hexdump 就可以查看十六进制:Javascript 解析微信dat文件 微信图片破解_第2张图片
Javascript 解析微信dat文件 微信图片破解_第3张图片

2. 获取异或值

微信的dat文件是如何加密的?原理很简单:是把文件内容通过某个数值进行异或操作来进行加密的,所以我们必须要计算出它的异或值。
Javascript 解析微信dat文件 微信图片破解_第4张图片
JPG图片文件的开头都是 FF D8 FF E0 00 10 4A 46 49 46 所以我们可以先用FF D8 FF 先测试计算。(大部分的文件都是jpg的,当然也有少部分存在png文件,可以多试几个dat文件)
当然不用自己计算,我们打开WIN10自带的计算器,切换到程序员模式进行十六进制的异或运算
刚才十六进制打开的文件开头是5B 7C 5B ,所以让5B 7C 5BFF D8 FF进行异或运算就好了:
Javascript 解析微信dat文件 微信图片破解_第5张图片
得出结果是A4 A4 A4 显而易见,异或值是A4(hex) 也就是说可以通过异或值和dat文件解密得到原文件了

每个人的异或值可能不一样

3. 文件解析代码

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文件。

你可能感兴趣的:(Javascript 解析微信dat文件 微信图片破解)