继微信dat之后的PC端微信解密后数据库数据抽取
前段時間弄了下微信的dat圖片的解碼,后續有同學問數據庫的解碼怎么弄.. 當然,后邊陸陸續續的看了下,加上住院亂七八糟的事情,一直沒處理,最近幾天處理了下,發現微信數據庫的數據格式是真的麻煩...
查看如何查看微信dat圖片的請走這里
簡單梳理下最近的操作:
- 通過od拿到PC端微信數據庫的密鑰
- 通過c++ 將PC端微信數據庫db文件進行解密成普通db
- 通過nodejs來讀取sqlite數據庫,拿到好友和聊天記錄
前面兩部就不講了,我也是直接拿著大神的教程直接做的,沒啥變化,也講不出什么東西來。 本文主要是做個簡單的記錄整理,確實沒啥很特別的東西..
先來幾張圖
根據拿到的64位密鑰,對數據庫進行解密。
得到解密后的數據庫
通過sqlite 打開看到如下表
MSG數據庫
以MSG.db 為例子,該數據庫主要存儲的是聊天記錄,表MSG中為所有的好友+群組的聊天記錄,如下圖:
MSG表聊天記錄
數據庫
微信MSG下有很多數據庫文件,如果我們需要的是好友+聊天記錄,那么其實只需要三個數據庫文件即可,為: MSG.db MediaMsg.db MicroMsg.db ,當然存儲數據達到一定體積后,會有 MSG0 MSG1 等。
- MSG.db 存儲的為聊天記錄數據
- MicroMsg.db 存儲的為好友+群組等等聯系人的信息,表為contact
- MediaMsg.db 主要存儲的是語音數據,格式為silk .
- Misc.db 存儲的是頭像數據
抽取
所以,我們只需要拿到聯系人,然后根據聯系人拿到對應的聊天記錄,然后對聊天記錄進行展示,當然,思路是比較簡單的,麻煩的是微信的聊天數據格式比較多,大約十幾種,分別包括:消息/圖片/表情/語音/視頻/地圖/名片/撤回/紅包/群組消息/拍一拍等等。
我們還需要根據不同的數據格式,解析成不同的內容,由于興趣有限,只做了比較簡單的消息/圖片/視頻這三個。除了消息外,圖片和視頻都是存儲的路徑,文件分表在 filestorage/image 和 filestorage/video 下,我們通過正則匹配到后拿到文件進行展示。
其中藍色代表存在聊天記錄的好友
樣式很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) {//gifvar 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 ?
總結
以上是生活随笔為你收集整理的继微信dat之后的PC端微信解密后数据库数据抽取的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串函数 tirm 的作用
- 下一篇: VB6连接各种类型的数据库