继微信dat之后的PC端微信解密后数据库数据抽取

您所在的位置:网站首页 micromsgdb文件怎么打开 继微信dat之后的PC端微信解密后数据库数据抽取

继微信dat之后的PC端微信解密后数据库数据抽取

2024-07-13 02:07| 来源: 网络整理| 查看: 265

前段时间弄了下微信的dat图片的解码,后续有同学问数据库的解码怎么弄.. 当然,后边陆陆续续的看了下,加上住院乱七八糟的事情,一直没处理,最近几天处理了下,发现微信数据库的数据格式是真的麻烦...

查看如何查看微信dat图片的请走这里

简单梳理下最近的操作:

通过od拿到PC端微信数据库的密钥通过c++ 将PC端微信数据库db文件进行解密成普通db通过nodejs来读取sqlite数据库,拿到好友和聊天记录

前面两部就不讲了,我也是直接拿着大神的教程直接做的,没啥变化,也讲不出什么东西来。 本文主要是做个简单的记录整理,确实没啥很特别的东西..

先来几张图

根据拿到的64位密钥,对数据库进行解密。

得到解密后的数据库

得到解密后的数据库

通过sqlite 打开看到如下表

MSG数据库

MSG数据库

以MSG.db 为例子,该数据库主要存储的是聊天记录,表MSG中为所有的好友+群组的聊天记录,如下图:

MSG表聊天记录

MSG表聊天记录

数据库

微信MSG下有很多数据库文件,如果我们需要的是好友+聊天记录,那么其实只需要三个数据库文件即可,为: MSG.db MediaMsg.db MicroMsg.db ,当然存储数据达到一定体积后,会有 MSG0 MSG1 等。

MSG.db 存储的为聊天记录数据MicroMsg.db 存储的为好友+群组等等联系人的信息,表为contactMediaMsg.db 主要存储的是语音数据,格式为silk .Misc.db 存储的是头像数据 抽取

所以,我们只需要拿到联系人,然后根据联系人拿到对应的聊天记录,然后对聊天记录进行展示,当然,思路是比较简单的,麻烦的是微信的聊天数据格式比较多,大约十几种,分别包括:消息/图片/表情/语音/视频/地图/名片/撤回/红包/群组消息/拍一拍等等。

我们还需要根据不同的数据格式,解析成不同的内容,由于兴趣有限,只做了比较简单的消息/图片/视频这三个。除了消息外,图片和视频都是存储的路径,文件分表在 filestorage/image 和 filestorage/video 下,我们通过正则匹配到后拿到文件进行展示。

其中蓝色代表存在聊天记录的好友

其中蓝色代表存在聊天记录的好友

样式很low ,随便写的

样式很low ,随便写的

主要的业务代码 /**** * * 微信的所有业务查询使用 */ const fs = require('fs'); const sqlite3 = require('sqlite3').verbose(); const lib = require('./lib'); module.exports = function (options) { let wxid = options.wxid; const MicroIns = new sqlite3.Database(options.MicroMsg); const MSGIns = options.MSG.split(',').map(str => { return new sqlite3.Database(str); }); const MEDIAIns = new sqlite3.Database(options.MEDIA); return { /*** * 获取微信所有联系人-朋友 */ getFriends: async function () { let list = await lib.all(MicroIns, 'select UserName,Remark,NickName,PYInitial,RemarkPYInitial from Contact where verifyFlag = 0 and (type=3 or type > 50)', []); //做简单排序,A list.forEach(item => { item.zimu = (item.RemarkPYInitial || item.PYInitial); item.f = item.zimu.length > 0 ? item.zimu.substr(0, 1) : '-'; }); list.sort((a, b) => { return a.f.charCodeAt(0) - b.f.charCodeAt(0); }) return list; }, /*** * 获取微信所有的群数据 */ getGroups: async function () { let list = await lib.all(MicroIns, 'select UserName,Remark,NickName,PYInitial,RemarkPYInitial from Contact where type=2'); //做简单排序,A list.forEach(item => { item.zimu = (item.RemarkPYInitial || item.PYInitial); item.f = item.zimu.length > 0 ? item.zimu.substr(0, 1) : '-'; }); list.sort((a, b) => { return a.f.charCodeAt(0) - b.f.charCodeAt(0); }) return list; }, /*** * 获取微信内的公众号信息 */ getOfficial: async function () { let list = await lib.all(MicroIns, 'select UserName,Remark,NickName,PYInitial,RemarkPYInitial,VerifyFlag from Contact where type=3 and (VerifyFlag=24 or VerifyFlag=8)'); //做简单排序,A list.forEach(item => { item.zimu = (item.RemarkPYInitial || item.PYInitial); item.f = item.zimu.length > 0 ? item.zimu.substr(0, 1) : '-'; }); list.sort((a, b) => { return a.f.charCodeAt(0) - b.f.charCodeAt(0); }) return list; }, /*** * 获取微信内群里的陌生人信息 */ getStrangers: async function () { let list = await lib.all(MicroIns, 'select UserName,Remark,NickName,PYInitial,RemarkPYInitial from Contact where type=4'); //做简单排序,A list.forEach(item => { item.zimu = (item.RemarkPYInitial || item.PYInitial); item.f = item.zimu.length > 0 ? item.zimu.substr(0, 1) : '-'; }); list.sort((a, b) => { return a.f.charCodeAt(0) - b.f.charCodeAt(0); }) return list; }, /*** * 根据UserName 获得Contact的一行记录 */ getContactByUserName: async function (UserName) { let list = await lib.get(MicroIns, 'select UserName,Remark,NickName,PYInitial,RemarkPYInitial from Contact where UserName=?', UserName); return list; }, /*** * 根据UserName 获得 ContactHeadImgUrl 头像信息 */ getHeadImageByUserName: async function (UserName) { let list = await lib.get(MicroIns, 'select usrName,smallHeadImgUrl,bigHeadImgUrl,headImgMd5 from ContactHeadImgUrl where usrName=?', UserName); return list; }, //获得聊天记录条数 getRecordCount: async function (UserName) { let count = 0; for (let i in MSGIns) { let temp = await lib.get(MSGIns[i], 'select count(1) as num from MSG where StrTalker=?', UserName); count += temp.num; } return { num: count }; }, /** * 根据UserName 查询 MSG0-N 中MSG 的聊天记录数据 * @param {String} UserName */ getRecordList: async function (UserName) { let list = []; for (let i in MSGIns) { let temp = await lib.all(MSGIns[i], 'select localId,TalkerId,Type,SubType,IsSender,CreateTime,Sequence,StrContent,StrTalker,BytesExtra from MSG where StrTalker=?', UserName); list = list.concat(temp); } list.forEach(item => { //type=3 ,图片消息 //type=43 ,视频消息 //type=47 ,表情消息 //type=34,语音消息 //type=1 ,普通消息 //type=42,名片消息 //type=48,地图定位消息 //type=49,50 ,不确定 //type=10000,撤回消息,消息从BytesExtra中 //type=10002,邀请入群消息 var info = item.BytesExtra.toString('utf8'); if (info != null) { info = info.trim(); var rr = info.match(/\b(.*)?\u001a/); if (rr) { item.from = rr[1];//来自谁发言 } } var type = item.Type; if (type == 3) {//图片消息,需要获得缩略图和大图数据 var info = item.BytesExtra.toString('utf8'); var reg = new RegExp(wxid + '.*?(\.dat)', 'g'); var ja = info.match(reg); if (ja) { item.bigImage = ja[0]; item.smallImage = ja[1]; item.BytesExtra = null; item.StrContent = null; } else { item.StrContent = info; } } else if (type == 43) {//视频 var info = item.BytesExtra.toString('utf8'); var reg = new RegExp(wxid + '.*?(\.jpg)', 'g'); var reg2 = new RegExp('' + wxid + '.*?(\.mp4)', 'g'); var ja = info.match(reg); if (ja != null) { item.videoPost = ja[0]; info = info.replace(ja[0], ''); } var ja2 = info.match(reg2); if (ja2 != null) { item.Video = ja2[0]; } item.StrContent = null; item.BytesExtra = null; } else if (type == '47') {//表情消息 item.StrContent = null; item.BytesExtra = null; } else if (type == 34) {//语音消息,需要将语音数据转为mp3 或直接播放 // console.log(item) // console.log(item.BytesExtra.toString('utf8')); } else if (type == 1) {//普通消息 // console.log(item); // console.log(item.StrContent) //获得是谁发言 } else if (type == 42) {//名片消息 } else if (type == 48) {//地图定位 var label = item.StrContent.match(/label="(.*?)"/); if (label != null) { label = label[1]; } var poiname = item.StrContent.match(/poiname="(.*?)"/); if (poiname != null) { poiname = poiname[1] } item.StrContent = label + poiname; item.BytesExtra = null; } else if (type == 10000) {//撤回/红包/拍一拍 } else if (type == 10002) {//邀请入群 item.StrContent = '邀请入群信息'; item.BytesExtra = null; } else { // console.log(item); if (item.SubType == 6) {//附件 var regExp = new RegExp('((' + wxid + ').*)'); if (regExp) { item.filePath = regExp[0]; } } else if (item.SubType == 5 || item.SubType == 33) { var reg = new RegExp(wxid + '.*?(\.jpg)', 'g'); var ja = info.match(reg); if (ja) { item.bigImage = ja[0]; } } else if (item.SubType == 8) {//gif var reg = new RegExp(wxid + '.*?(\.gif)', 'g'); var ja = info.match(reg); if (ja) { item.bigImage = ja[0]; } } else { // console.log(info); item.StrContent = item.BytesExtra.toString('utf8'); item.BytesExtra = null; } // console.log(item.BytesExtra.toString('utf8')) } }) return list; }, getMedia: async function () { let list = await lib.all(MEDIAIns, 'select * from media'); return list; } }; } 其他

当然,感觉这个其实是没太有意义的,毕竟...密钥必须要微信登录才可以拿到.同时呢,由于微信的机制,导致数据库能看到啥,微信就能看到啥.. 所以没太大意义,除非准备把记录保存起来,后续如果真的闲的蛋疼的话,可能会吧聊天记录美化下,把不同格式都加上,尽可能的还原,然后加个pdf ?



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3