一个面向 Windows 的微信消息导出与浏览工具:从已登录的微信进程读取关键信息,解密数据库,合并聊天库,并在本地界面中浏览会话与消息。
WeChatMsgDump 是基于 C++20 + Qt6 的桌面程序,核心目标是把“微信本地数据库 -> 可读消息”这条链路工程化,包含:
- 读取微信进程信息(版本、路径、wxid、数据目录等)
- 按版本偏移提取解密所需信息
- 批量解密多库并合并输出
- 联系人、会话、历史消息的本地查询与展示
- 自动识别当前机器上已登录微信进程
- 展示微信版本、用户标识、数据目录等信息
- 解密核心聊天数据库(含
MSG*.db/MediaMSG*.db/MicroMsg.db/ OpenIM 相关库) - 合并解密产物,生成统一可查询数据库
- 浏览会话列表、消息历史、头像及多种消息类型(文本、图片、语音、视频、文件、引用、转账、系统消息等)
当前仓库实现以 微信 3.x(V3 体系) 为主,支持版本由 source/msgcore/resource/configs/offsetv3.json 决定。
- 偏移表最早版本:
3.2.1.154 - 偏移表最新版本:
3.9.12.55 - 已实现解密器与进程读取器:
v3
说明:
- 代码中有 v4 预留设计(工厂/抽象层),但当前仓库资源与实现仍以 v3 为主。
- 超出偏移表范围的微信版本可能出现“无法读取密钥/解密失败”。
context/:项目AI知识库(架构、流程、接口、构建、数据库模型)design/:架构设计图(PlantUML)source/:源码主目录source/wechatmsgdump/:程序入口(EXE)source/msgui/:UI 层(解密向导 + 消息浏览)source/msgcore/:核心层(进程读取、解密、合并、查询)source/junuoui/:通用 UI 组件库source/junuobase/:基础工具库source/include/:跨模块接口定义(如global_interface.h)
classDiagram
class IJCoreEntry {
<<interface>>
+GetCoreApplication() IJCoreApplication*
}
class JCoreEntry
JCoreEntry --|> IJCoreEntry
IJCoreEntry --> IJCoreApplication
class IJCoreApplication {
<<interface>>
+GetDecryptManager() IJWeChatDBDecryptManager*
}
class JCoreApplication
JCoreApplication --|> IJCoreApplication
IJCoreApplication --> IJWeChatDBDecryptManager
class JAbstractWeChatProcessReader {
<<interface>>
+GetWeChatProcessId(forceRead=false) long
+GetWeChatExecutablePath(forceRead=false) QString
+GetWeChatVersion(forceRead=false) QString
+GetNickName(forceRead=false) QString
+GetWeChatUserName(forceRead=false) QString
+GetPhoneNumber(forceRead=false) QString
+GetWxid(forceRead=false) QString
+GetDataPath(forceRead=false) QString
}
class JWeChatProcessReaderV3 {
+GetDecryptKey() QString
}
class JWeChatProcessReaderV4
JWeChatProcessReaderV3 --|> JAbstractWeChatProcessReader
JWeChatProcessReaderV4 --|> JAbstractWeChatProcessReader
class JWeChatProcessReaderFactory {
+CreateWeChatProcessReader(...) JAbstractWeChatProcessReader*
}
JWeChatProcessReaderFactory o-- JAbstractWeChatProcessReader
class JAbstractWeChatDBDecryptor {
<<interface>>
+SetParam(inputFile, outputFile, key) void
+Decrypt() bool
}
class JWeChatDBDecryptorV3
class JWeChatDBDecryptorV4
JWeChatDBDecryptorV3 --|> JAbstractWeChatDBDecryptor
JWeChatDBDecryptorV4 --|> JAbstractWeChatDBDecryptor
class JWeChatDBDecryptorFactory {
+CreateWeChatDBDecryptor(...) JAbstractWeChatDBDecryptor*
}
JWeChatDBDecryptorFactory o-- JAbstractWeChatDBDecryptor
class JAbstractWeChatDBCombiner {
<<interface>>
+SetParam(inputFileList, outputFile) void
+Combine() bool
}
class JWeChatDBCombiner
JWeChatDBCombiner --|> JAbstractWeChatDBCombiner
class IJWeChatDBDecryptManager {
<<interface>>
+StartReadWeChatProcess() bool
+StartDecryptDataBase() bool
-m_spWeChatProcessReader JAbstractWeChatProcessReader*
-m_spWeChatDBDecryptor JAbstractWeChatDBDecryptor*
-m_spWeChatDBCombiner JAbstractWeChatDBCombiner*
}
class JWeChatDBDecryptManager
JWeChatDBDecryptManager --|> IJWeChatDBDecryptManager
IJWeChatDBDecryptManager --> JAbstractWeChatProcessReader
IJWeChatDBDecryptManager --> JAbstractWeChatDBDecryptor
IJWeChatDBDecryptManager --> JAbstractWeChatDBCombiner
IJWeChatDBDecryptManager --|> IJCoreSubject
class IJCoreSubject {
<<interface>>
+AttachObserver(observer) void
+DetachObserver(observer) void
+Notify(event) void
}
class IJCoreEvent {
<<interface>>
+Type() int
}
class IJCoreObserver {
<<interface>>
+OnCoreEvent(event) bool
-m_pSubject IJCoreSubject*
}
IJCoreSubject ..> IJCoreEvent
IJCoreSubject ..> IJCoreObserver
IJCoreObserver ..> IJCoreEvent
classDiagram
class IJCoreSubject {
<<interface>>
}
class IJCoreEvent {
<<interface>>
}
class IJCoreObserver {
<<interface>>
}
IJCoreSubject ..> IJCoreObserver
IJCoreSubject ..> IJCoreEvent
class ContactInfo {
+m_wxid QString
+m_userName QString
+m_nickName QString
+m_remarkName QString
+m_headImage QIcon
}
class IJMsgViewManager {
<<interface>>
+GetContactInfo(wxid) std::optional~ContactInfo~
+GetSelfWxid() QString
+StartQueryAllStrTalker() bool
+StartQueryMessageCount(talker) bool
+StartQueryChatHistory(talker, ts, forward, limit) bool
}
IJMsgViewManager --|> IJCoreSubject
class WechatDbReader {
+selectAllStrTalkerFromMSG(...)
+selectContactByUserName(...)
+selectChatCountByUserName(...)
+selectChatHistoryByUserName(...)
+selectHeadImageByUserName(...)
}
class MsgType {
<<enumeration>>
UnKnown
PlantText
Image
Voice
Video
Sticker
SharedCardLink
MergedChatRecord
TextWithQuote
Transfer
File
SystemNotice
Tickle
}
class IJMessage {
<<interface>>
+GetMsgType() MsgType
+GetSenderWxid() QString
+GetStrTalker() QString
+GetCreateTime() qint64
+IsSender() bool
+GetDisplayText() QString
+GetRawField(key) QVariant
}
class JMessageBase {
+GetMsgType() MsgType
+GetSenderWxid() QString
+GetStrTalker() QString
+GetCreateTime() qint64
+IsSender() bool
+GetDisplayText() QString
+GetRawField(key) QVariant
-m_rawRecord QVariantMap
-m_msgType MsgType
}
JMessageBase --|> IJMessage
class JTextMessage
class JImageMessage
class JVoiceMessage
class JVideoMessage
class JStickerMessage
class JFileMessage
class JLinkMessage
class JQuoteTextMessage
class JMergedChatRecordMessage
class JTransferMessage
class JSystemNoticeMessage
class JUnknownMessage
JTextMessage --|> JMessageBase
JImageMessage --|> JMessageBase
JVoiceMessage --|> JMessageBase
JVideoMessage --|> JMessageBase
JStickerMessage --|> JMessageBase
JFileMessage --|> JMessageBase
JLinkMessage --|> JMessageBase
JQuoteTextMessage --|> JMessageBase
JMergedChatRecordMessage --|> JMessageBase
JTransferMessage --|> JMessageBase
JSystemNoticeMessage --|> JMessageBase
JUnknownMessage --|> JMessageBase
class JMessageFactory {
+Create(raw) std::shared_ptr~IJMessage~
-resolveMsgType(type, subType) MsgType
}
class QIconEngine
class JOnlineIconEngine {
+JOnlineIconEngine(url)
+clone() QIconEngine*
+paint(p, rc, m, s) void
+pixmap(sz, m, s) QPixmap
+StartRequest() void
+IsReady() bool
-m_url QString
-m_headPixmap QPixmap
-m_requesting bool
-m_spNetworkManager QNetworkAccessManager*
}
JOnlineIconEngine --|> QIconEngine
class JMsgViewManager {
+GetContactInfo(wxid) std::optional~ContactInfo~
+StartQueryAllStrTalker() bool
+StartQueryMessageCount(talker) bool
+StartQueryChatHistory(talker, ts, forward, limit) bool
-onSelectHeadImageUrlFinished(...)
-onSelectContactInfoFinished(...)
-onSelectChatHistoryFinished(...)
-m_spDbReader WechatDbReader*
-m_contactCache QCache~QString, ContactInfo~
}
JMsgViewManager --|> IJMsgViewManager
JMsgViewManager o-- WechatDbReader
JMsgViewManager ..> JMessageFactory : use static Create
JMsgViewManager ..> JOnlineIconEngine : create QIcon(engine)
JMsgViewManager ..> IJMessage : notify message list
class MsgViewWidget
MsgViewWidget --|> IJCoreObserver
MsgViewWidget ..> IJMsgViewManager : call API
JMsgViewManager ..> IJCoreEvent : Notify(result via event)
wechatmsgdump.exe启动并加载msgui.dllmsgui.dll动态加载msgcore.dll,获取核心入口- UI 进入解密向导:读取进程信息 -> 选择进程 -> 开始解密
msgcore并行解密多个数据库,完成后合并为统一库- UI 切换到消息浏览:查询会话、消息数、历史消息并渲染
- Windows 10/11(项目主要面向 Windows)
- Visual Studio 2022(MSVC)
- CMake >= 3.16
- Python 3(用于构建脚本)
- vcpkg
- 作者是Qt6.5.3
在 x64-windows triplet 下安装:
vcpkg install openssl:x64-windows protobuf:x64-windows说明:
openssl供解密模块链接protobuf用于.proto代码生成与链接
在仓库根目录执行(推荐 out-of-source 构建):
mkdir build
cd build
# Debug
cmake ..\source ^
-DCMAKE_BUILD_TYPE=Debug ^
-DCMAKE_TOOLCHAIN_FILE=path/to/vcpkg/scripts/buildsystems/vcpkg.cmake ^
-DVCPKG_TARGET_TRIPLET=x64-windows
cmake --build . --config Debug -jRelease(如需关闭优化便于调试)示例:
cmake ..\source ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_TOOLCHAIN_FILE=path/to/vcpkg/scripts/buildsystems/vcpkg.cmake ^
-DVCPKG_TARGET_TRIPLET=x64-windows ^
-DCMAKE_C_FLAGS_RELEASE="/Od" ^
-DCMAKE_CXX_FLAGS_RELEASE="/Od"
cmake --build . --config Release -j- 可执行文件:
build/output/bin/wechatmsgdump.exe - 动态库:
build/output/lib/ - 翻译文件:
build/output/translation/
- 合并数据库默认输出:
AppLocalDataLocation/<wxid>/merged_db.db - 解密临时目录:
AppLocalDataLocation/<wxid>/decrypted/ - 建议在“微信已登录、数据库文件完整、无权限拦截”场景下执行解密
优先检查:
- 微信版本是否在
offsetv3.json支持范围内 - 目标目录文件访问权限是否正常
- 是否被安全软件拦截文件读写
可以,通常需要:
- 补齐新版本偏移到
offsetv3.json(或引入 v4 配置与实现) - 必要时扩展解密器/进程读取器工厂注册项
联系人与头像采用“缓存命中即时返回 + 异步回填通知”的策略,首次查询可能出现短暂占位。
- 本项目与腾讯/微信官方无关联。
- 请仅在合法合规、获得授权的前提下使用本项目。
- 严禁将本项目用于任何非法用途;使用者自行承担相关责任。