微信图片转换

PC端微信图片转换

引言

最近孩子去上早教班,老师在早教群里发了很多孩子的图片,我就想着把这些图片存起来,但是老师发一张我存一张这种模式对程序员来说是一种侮辱,所以我就想是不是存在了微信文件夹下面,一看果不其然,只是格式不是jpg,png,gif等,是dat格式,经过一番百度(ps:微信是国内的东西,所以还是百多搜索比较靠谱)终于找到了解码方法.特此记录.

正文

微信文件目录

微信的图片文件地址这个不难找,具体目录为${wechatFilesDir}/{your_wechat_id}/FileStroage/image,占位符代表微信文件存储目录(微信设置->文件管理)和自己微信的微信号.

所需图片知识

  • jpg/jpeg
    标识头: 0xff 0xd8

  • png
    标识头: 0x89 0x50

  • gif
    标识头: 0x47 0x49

当然还有其他的图片格式可以自行谷歌.

微信.bat文件加密方式

定义一个key值,将图片转换为二进制流,然后每一位与这个key值进行异或(xor),得到新的byte值,然后写入.
所以我们反解就很明显了,假设图片为jpg,我们已知jpg图片前两位为0xff,0xd8,用16进制方式打开.bat文件,得到前两位为x,x1.只需x^0xff==x^0xd8 成立(因为x=key^0xff,x1=key^0xd8),那么这个图片就是jpg.

代码示例

仅仅是一个示例,实际开发应当更严谨处理异常以及分支.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
public void test() throws IOException {
int base = 0xff;
int next = 0xd8;
int pngBase = 0x89;
int pngNext = 0x50;
byte[] bs = Files.readAllBytes(Paths.get("D:\\WebChat\\WeChat Files\\wxid_sxelod34kou321\\FileStorage\\Image\\2020-06\\0ce7898a35eb2a7ac9045480419e5902.dat"));
int firstByte = bs[0] & 0xff;
int secondByte = bs[1] & 0xff;
int key = base ^ firstByte;
String suffix = ".jpg";
if((pngBase ^ firstByte) == (pngNext ^ secondByte)){
key = pngBase ^ firstByte;
suffix = ".png";
}
try(OutputStream os = Files.newOutputStream(Paths.get("D:\\123"+suffix),StandardOpenOption.CREATE)){
for(byte b : bs){
os.write(b ^ key);
}
}
}

后记

通过对比发现一个问题,key值在我公司电脑和家里电脑完全相同.也就是说这个算key的过程应该是拿微信里面的一个固定信息算出来的.这个等在后面在研究一下具体是怎么算的.