Database Data Extraction after Decryption of PC-side Wechat Following Wechat dat

Some time ago, I got the decoding of dat pictures in WeChat, and later some students asked how to decode the database.. Of course, after looking at it one after another, plus the messy things in hospital, it has not been handled. After handling it in the last few days, we found that the data format of the WeChat database is really troublesome...

How to view WeChat dat pictures click the link below

http://sdxlp.cn/article/%E5%BE%AE%E4%BF%A15.html

Recent operations under a simple comb:

  • Get the key of PC-side WeChat database by od
  • Decrypt PC-side WeChat database db file to normal DB through c++.
  • Read sqlite database through nodejs to get friends and chat records

I won't talk about the first two. I also did it directly with the tutorial of the Great God. Nothing changed, and nothing could be said. This article mainly does a simple record compilation, really nothing special..

First few pictures

Decrypt the database based on the 64-bit key you get.

Decrypted database

Open with sqlite to see the following table

MSG database

With MSG. For example, db, this database mainly stores chat records, and MSG table stores chat records for all friends + groups, as shown below:

MSG Table Chat Record

data base

WeChat MSG has a lot of database files. If we need friends + chat records, we only need three database files: MSG.db MediaMsg.db MicroMsg.db, of course, after a certain volume of data is stored, there will be MSG0 MSG1, etc.

  • MSG.db stored as chat log data
  • MicroMsg.db stores contact information as a friend + group, etc.
  • MediaMsg.db mainly stores voice data in silk format.
  • Misc.db stores avatar data

extract

So, we only need to get the contact, then get the corresponding chat record according to the contact, and then show the chat record. Of course, the idea is simpler. The trouble is that there are more chat data formats in WeChat, about a dozen, including: message/picture/emoticon/voice/video/map/business card/recall/red packet/group message/take a photo, and so on.

We also need to parse into different content according to different data formats. Due to limited interest, we only made three simple messages/pictures/videos. Except for messages, pictures and videos are stored paths. File tables are displayed under filestorage/image and filestorage/video s, and we get the files to show through regular matching.

Blue stands for friends who have chat records

Style is low, write freely

Main business code

/****
 * 
 * WeChat uses all business queries
 */


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 {

        /***
         * Get all WeChat contacts - friends
         */
        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)', []);
            //Do a simple sort, 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;
        },
        /***
         * Get all the group data from WeChat
         */
        getGroups: async function () {
            let list = await lib.all(MicroIns, 'select UserName,Remark,NickName,PYInitial,RemarkPYInitial from Contact where type=2');
            //Do a simple sort, 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;
        },
        /***
         * Get public number information in WeChat
         */
        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)');
            //Do a simple sort, 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;
        },

        /***
         * Get information about strangers in WeChat
         */
        getStrangers: async function () {
            let list = await lib.all(MicroIns, 'select UserName,Remark,NickName,PYInitial,RemarkPYInitial from Contact where type=4');
            //Do a simple sort, 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;
        },
        /***
         * Get a row of Contact records from UserName
         */
        getContactByUserName: async function (UserName) {
            let list = await lib.get(MicroIns, 'select UserName,Remark,NickName,PYInitial,RemarkPYInitial from Contact where UserName=?', UserName);
            return list;
        },
        /***
         * Get ContactHeadImgUrl avatar information from UserName
         */
        getHeadImageByUserName: async function (UserName) {
            let list = await lib.get(MicroIns, 'select usrName,smallHeadImgUrl,bigHeadImgUrl,headImgMd5 from ContactHeadImgUrl where usrName=?', UserName);
            return list;
        },
        //Get the number of chat entries
        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 };
        },
        /**
         * Query MSG chat record data in MSG0-N based on UserName
         * @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, picture message
                //type=43, video message
                //type=47, emoticon message
                //type=34, voice message
                //type=1, normal message
                //type=42, business card message
                //type=48, map location message
                //type=49,50, indeterminate
                //type=10000, recall message, message from BytesExtra
                //type=10002, group invitation message
                var info = item.BytesExtra.toString('utf8');
                if (info != null) {
                    info = info.trim();
                    var rr = info.match(/\b(.*)?\u001a/);
                    if (rr) {
                        item.from = rr[1];//From whom to speak
                    }
                }
                var type = item.Type;
                if (type == 3) {//Picture messages, need thumbnails and large map data
                    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) {//video
                    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') {//Emotional message
                    item.StrContent = null;
                    item.BytesExtra = null;
                } else if (type == 34) {//Voice message, need to convert voice data to mp3 or play directly
                    // console.log(item)
                    // console.log(item.BytesExtra.toString('utf8'));
                } else if (type == 1) {//Common message
                    // console.log(item);
                    // console.log(item.StrContent)
                    //Who spoke

                } else if (type == 42) {//Business card message

                } else if (type == 48) {//Map positioning
                    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) {//Retract/Red Bag/Take a Photo
                } else if (type == 10002) {//Invite to Group
                    item.StrContent = 'Invite Group Information';
                    item.BytesExtra = null;
                } else {
                    // console.log(item);
                    if (item.SubType == 6) {//Enclosure

                        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;
        }

    };
}

Other

Of course, it doesn't really make sense to feel like this, after all... The key must be logged in by WeChat before it can be obtained. At the same time, due to the mechanism of WeChat, what can the database see, what can WeChat see.. So it doesn't make much sense unless you're ready to save the record. If you really have spare egg pain in the future, you might beautify the chat record by adding different formats, restoring as much as possible, and then adding a pdf?

Keywords: Database Big Data

Added by Markx on Wed, 09 Feb 2022 04:17:29 +0200