图形图像您现在的位置是:首页 > 博客日志 > 图形图像

解码解密微信电脑版image文件夹下缓存的用户图片 dat文件解码解密查看方法

<a href='mailto:'>微wx笑</a>的头像微wx笑 2021-07-28图形图像1708 6 0关键字: 解码  解密  微信  image  图片  dat  java  

在使用微信Mac版的时候,接收到的图片可以直接右键》打开文件所在位置就能查看图片,但是Windows版本的就不行了,虽然文件已经接收保存到本地了,但是却以“.dat”格式进行保存并且进行了加密处理,用图片浏览器打开也提示无法查看。这里就介绍一下使用Java语言对其进行批量解密的方法。

在使用微信Mac版的时候,接收到的图片可以直接右键》打开文件所在位置就能查看图片,但是Windows版本的就不行了,虽然文件已经接收保存到本地了,但是却以“.dat”格式进行保存并且进行了加密处理,用图片浏览器打开也提示无法查看。这里就介绍一下使用Java语言对其进行批量解密的方法。IHY无知


IHY无知

一、找到图片

Windows版本想到找到微信聊天记录中的图片,需要以下步骤:IHY无知

1、设置

image.pngIHY无知

2、文件管理,打开文件夹

image.pngIHY无知

3、打开 FileStorage》Image 文件夹

image.pngIHY无知

二、解密原理

1. 原理描述


IHY无知

原理很简单,就是按字节对接收到的图片文件进行了异或处理保存为dat文件,查看时再解码,并且使用的加密代码几乎是一样的,只要我们弄到了加密的字节码,使用其对dat文件进行异或操作保存为png文件便可以查看了。IHY无知


IHY无知

2. 获取加密字节码

16进制编辑器 HEdit下载IHY无知

链接: https://pan.baidu.com/s/1lcaXiWyL31oYhxMAMGAOiA 提取码: bqx6 复制这段内容后打开百度网盘手机App,操作更方便哦IHY无知

image.pngIHY无知


IHY无知

将其中一个文件夹的dat文件通过16进制编辑器打开,记录其开头两个16进制的值,随机挑选一部分dat文件打开,查看开头两个16进制的值并对比,一般来说是一样的,这两个值是解密的关键。IHY无知

3、文件头对比

加密的文件头部IHY无知

image.pngIHY无知

解密后的文件头部IHY无知

image.pngIHY无知

我这里开头的两个值几乎都是8C AB,同时我们了解到网络中传输的图片多为jpeg格式,而jpeg格式的图片开头两个16进制的值通常为FF D8,我们打开计算器,将这两个值异或一下,得到两个16进制的值,通常来说应该是一样的,那么这个16进制的值就是解码的关键了。IHY无知

4、使用计算器计算加密字节码

打开计算器,查看菜单选中程序员、基本IHY无知

image.pngIHY无知

鼠标点击输入 8CAB,点击XorIHY无知

image.pngIHY无知

再输入FFD8,点击=号,就可以等到结果了IHY无知

image.pngIHY无知

本机的结果是73,那么我们只需要将dat文件的所有数据都与73异或便可以得到解密数据了,同时把数据保存为png格式便可以使用看图软件直接查看了。IHY无知

注意:每个人得到的值可能不一样。IHY无知

注意:这里只是教大家怎么手动计算,后面代码里面已经可以通过程序自动计算了。IHY无知


IHY无知

三、批量执行解密

处理逻辑

1、 获取指定路径下的所有dat文件,进入for循环处理IHY无知

2、按次序读入dat文件,获取加密字节码及扩展名,然后按byte对其数据与加密字节码进行异或IHY无知

3、将异或后的数据保存下来,后缀改为对应的扩展名,输出到指定文件夹IHY无知

解密代码:decode.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.util.Date;
/**
 * 微信电脑版image文件夹下缓存的用户图片dat文件解码解密类
 * @author lipw
 * @email admin@ivu4e.com
 * @site https://ivu4e.com/
 */
class decode
{
    public static void main(String[] args) {
        System.out.println("hello");
        // 使用时修改这里的路径就可以了
        BatchDecodeFileContent("D:/Documents/WeChat Files/wxid_/FileStorage/Image/2021-07""D:/Documents/WeChat Files/wxid_/FileStorage/Image/decodeimg5");
    }
 
    /**
    * 批量对文件进行解密处理
    * @param    inputFileDir 要解密的文件夹
    * @param    outputFileDir 解密后保存在哪个文件夹
    */
    public static void BatchDecodeFileContent(String inputFileDir, String outputFileDir){
        File f = new File(inputFileDir);
        if (!f.exists() || !f.isDirectory()){
            System.out.println("要解密的文件夹不存在!");
        }
         
        if (!outputFileDir.endsWith("/")){
            outputFileDir = outputFileDir.concat("/");
        }
        File o = new File(outputFileDir);
        if (!o.exists()){
            try {
                System.out.println("解密后保存的文件夹不存在,尝试创建...");
                o.mkdirs();
            catch (Exception e) {
                System.out.println("创建解密后保存的文件夹失败,程序终止执行");
                return;
            }
        }
         
        File[] fl = f.listFiles(new FilenameFilter(){
            @Override
            public boolean accept(File dir, String name) {
                if (name.endsWith(".dat")){
                    return true;
                }
                return false;
            }
        });
        System.out.println("共找到 " + fl.length + " 个 dat 文件");
 
        if (fl.length == 0){
            System.out.println("没有需要解码的文件");
        }
        long begin = new Date().getTime();
        System.out.println("====开始解码====time:" + begin);
 
        Bom bom;
        FileInputStream fis;
        File of;
        FileOutputStream fos;
        byte[] bs = new byte[1024 1024];
        int rl;
        for (File file : fl){
            System.out.println(file.getAbsolutePath());
            try {
                fis = new FileInputStream(file);
                rl = fis.read(bs);
                bom = getFileBom(bs);
                if (bom.getXorVal() == 0x00 || bom.getExtn() == null){
                    System.out.println("获取加密的字节码失败");
                    continue;
                }
                of = new File(outputFileDir + file.getName() + bom.getExtn());
                fos = new FileOutputStream(of);
                while(rl > 0){
                    for (int i = 0; i < rl; i++){
                        bs[i] = (byte)(bs[i] ^ bom.getXorVal());
                    }
                    fos.write(bs, 0, rl);
                    rl = fis.read(bs);
                }
 
                fis.close();
                fos.close();
            catch (Exception e) {
                 
            }
        }
         
        long end = new Date().getTime();
        System.out.println("decode2====" + fl.length + " 个dat文件解码完成====用时:" + (end - begin));
    }
 
    /**
     * 获取加密的字节码
     * @param buff 读取的文件的第一块,包含文件头的部分
     * @return
     */
    public static Bom getFileBom(byte[] buff){
        Bom bom = new Bom();
        if (buff.length < 2){
            return bom;
        }
        // jpeg
        if ((byte)(buff[0] ^ 0xFF) == (byte)(buff[1] ^ 0xD8)){
            bom.setXorVal((byte)(buff[0] ^ 0xFF));
            bom.setExtn(".jpeg");
             return bom;
        }
        // png
        if ((byte)(buff[0] ^ 0x89) == (byte)(buff[1] ^ 0x50)){ // Xor计算之后需要加上强制类型转换(byte),否则比较的时候会出现不相等的情况
             bom.setXorVal((byte)(buff[0] ^ 0x89));
             bom.setExtn(".png");
             return bom;
        }
        // bmp
        if ((byte)(buff[0] ^ 0x42) == (byte)(buff[1] ^ 0x4D)){
            bom.setXorVal((byte)(buff[0] ^ 0x42));
            bom.setExtn(".bmp");
             return bom;
        }
        // gif
        if ((byte)(buff[0] ^ 0x47) == (byte)(buff[1] ^ 0x49)){
            bom.setXorVal((byte)(buff[0] ^ 0x47));
            bom.setExtn(".gif");
             return bom;
        }
        // tif
        if ((byte)(buff[0] ^ 0x49) == (byte)(buff[1] ^ 0x49)){
            bom.setXorVal((byte)(buff[0] ^ 0x49));
            bom.setExtn(".tif");
             return bom;
        }
        System.out.printf("%x%x==%x%x", buff[0], buff[1],(buff[0] ^ 0x89),(buff[1] ^ 0x50));
        return bom;
    }
 
    // 文件头
    static class Bom {
        // 对文件加密解密使用的字节码
        byte xorVal = 0x00;
        // 文件扩展名
        String extn = null;
         
        public Bom() {
 
        }
        public byte getXorVal() {
            return xorVal;
        }
        public void setXorVal(byte xorVal) {
            this.xorVal = xorVal;
        }
        public String getExtn() {
            return extn;
        }
        public void setExtn(String extn) {
            this.extn = extn;
        }
         
    }
}

使用时注意:
IHY无知

1、输入输出目录的替换IHY无知

2、0x73是对 dat 文件中的字节与 FF、D8 进行异或运算得到的数字,具体计算方法参考下面的链接。IHY无知

其它语言版本:

参考:https://blog.csdn.net/a386115360/article/details/103215560/ IHY无知


IHY无知

本文由 微wx笑 创作,采用 署名-非商业性使用-相同方式共享 4.0 许可协议,转载请附上原文出处链接及本声明。
原文链接:https://www.ivu4e.cn/blog/image/2021-07-28/707.html

很赞哦! (8) 有话说 (0)

文章评论