怎么找回微信上被对方撤回的图片?微信撤回图片恢复方法
1 消失的“艳”图
自从微信添加撤回消息功能后,我的好奇心翻了好几番啊!
我们身边有一个逗比,暂且称他为胖胖,经常在朋友圈和微信群里说单口相声,内容以自黑为主,配图恰到好处。他乐观、奉献的精神深深的打动了我们。
前不久他在微信群里放出了一张聊天截图,肯定有料,但奈何他迅速撤回了。然后他在发送和撤回之间迭代,大家的好奇心被撩的不要不要的。最终通过其他渠道终于看到了那张图,治好了我的毕业综合症,心情美丽了好几天。
最近还发生了一起“消息撤回事件”,主人公爱生活,有梦想。具体来说是,力争把生活存成JPEG。对,无处不拍照,无景也能high!他丢过来一张“艳”图,当我准备鸡蛋里挑骨头的时候,他撤回了!心情是这样纸滴:rm -rf /*。
2 真相只有一个
微信的消息撤回功能算是治疗输入法不够智能的一剂良药,但是却毁了生活中的一些小乐子啊。作为一名程序员,我忍无可忍了,柯南附体,必须找到那张消失的“艳”图。之前有听说Xposed框架里的防止微信撤回插件,更加坚定了我的信心。
因为当时刚好PC和手机同时登陆了微信,所以先从PC这里入手。
2.1 PC端
经过一番调研,把储存的位置锁定到了[X]:\Users\[USER]\Documents\WeChat Files\[WECHAT_USER]\Data。里面有一堆以.dat为后缀的文件,他们大小不一,其中最新的一个文件100多KB,我猜这应该就是要找的图片。
于是把后缀改为.jpg试试看,结果失败。果断给Notepad++装上HEX-Editor插件,秒变UltraEdit啊!为了找到图片的加密方法,随便找了一张图,发送过来,并到微信储存图片的位置找到最新的.dat文件,Notepad++打开是这样的(加密后的图片):
在微信的客户端里右键另存为,把图片储存到本地,Notepad++打开是这样的(原始图片):
可以很明显的看到,原始图片的63 63 ...变成了32 32 ...。猜测图片中的每一个字节经都经过了变换。为了方便寻找规律,找到原始图片的00,其对应加密后的图片的51,于是大胆猜测变换的方法是:`
def encode(b): return b + 0x51
但是,0x63 + 0x51并不等于0x32。把16进制换成2进制再看一下:
0110 0011 ? 0101 0001 -------------- 0011 0010
当两个1相加的时候并没有进位,所以这不是加法,而是半加,即异或!赶紧写代码试验一下:
def _decode_pc_dat(self, datfile): magic = 0x51 with open(datfile, 'rb') as f: buf = bytearray(f.read()) imgfile = re.sub(r'.dat$', '.jpg', datfile) with open(imgfile, 'wb') as f: newbuf = bytearray(map(lambda b: b ^ magic, list(buf))) f.write(str(newbuf))
成功找到“艳”图。
2.2 手机端(Android)
通过对微信路径里的文件逐一排查,最终找到了可疑的文件:/sdcard/tencent/MicroMsg/diskcache。该路径里的文件名称类似cache.data.10,大小在2MB左右。如果把后缀改为.jpg,是可以打开的。但是,疑点在于,2MB的图片,竟然马赛克浓度这么高,这充其量也就是才10几KB吧。而且,每一个文件都是2MB左右,人工的痕迹很明显啊。
能够打开图片,说明文件的内容是没有做任何修改的,文件头、文件尾都是非常正规的。难道,微信的工程师把多个图片串联了起来?!像这样:
图片1的头部 图片1的尾部 图片2的头部 图片2的尾部 ...
因为JPEG的文件是以ff d8 ff e0开始的,以ff d9结束,搜索一下:
在一个图片的二进制中搜索到了多个文件头,且文件头的前面是一个文件尾标识,与猜测吻合。至此,可以写出解密方法了:
def _decode_android_dat(self, datfile): with open(datfile, 'rb') as f: buf = f.read() last_index = 0 for i, m in enumerate(re.finditer(b'\xff\xd8\xff\xe0\x00\x10\x4a\x46', buf)): if m.start() == 0: continue imgfile = '%s_%d.jpg' % (datfile, i) with open(imgfile, 'wb') as f: f.write(buf[last_index: m.start()]) last_index = m.start()
3 神奇的0x51
对于PC端图片的加密,工程师选择了一个神奇的数字0x51与各个字节进行异或。为什么要选择0x51呢?
>>> chr(0x51) 'Q'
0x51对应的ASCII码为“QQ”的Q!
最后献上微信图片解密、找回撤回的图片工具: https://github.com/zhangxiaoyang/WechatImageDecoder。
参考
http://image.kejixun.com/2015/0504/20150504034225444.jpg
https://www.zhihu.com/question/35056157
https://github.com/zhangxiaoyang/WechatImageDecoder
本文转自知乎专栏Yang的后花园:https://zhuanlan.zhihu.com/p/21388706

本文地址:https://xxzh.net/computer/zhaohui-weixin-chehui-tupian.html
版权说明:如非注明,本站文章均为 修行者博客 原创,转载请注明出处和附带本文链接。