最近每天在隔离点蹲着,发现隔离点的护士小姐姐每天两次在群里扒聊天记录统计一两百号人的体温真是太南了,所以想写个程序帮小姐姐自动收集,今天刚好隔离期满,也算是给这段特殊的经历留个纪念。

这篇文章主要内容是:

  • 如何找到微信本地缓存数据库存放地址

    • Mac OS 关闭 SIP 系统完整性保护
    • lldb 断点调试得到缓存数据库地址
  • 如何打开数据库
    • lldb 断点调试得到数据库密码
    • 使用 DB Browser for SQLite 打开数据库并重设密码
  • 微信本地缓存数据库的结构介绍
    • Contact - wccontact_new2.db - 好友信息
    • Group - group_new.db - 群聊和群成员信息
    • Message - {msg_0.db - msg_9.db} - 聊天记录和公众号文章
    • Favorites - favorites.db - 收藏
  • 如何解析数据库并提取目标信息

找到微信本地缓存数据库存放地址并获取数据库密码

捷径

对于Mac OS 系统,一个 short answer 是

/Users/xxx/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/

打开后,可以看到:

这里需要重点关注的是看起来很像 md5 码形式的文件,每个文件都代表一个曾经在你的电脑上登陆过并留下缓存的微信账号,有了下面将会介绍的解码方法,你可以逐个打开解析,确认到底哪个账号是你要找的。

总体来说,Windows 系统同理。

LLDB 调试

在没有任何信息的情况下,我们如何找到一个获取数据库地址的系统性方法?答案在于LLDB断点调试。

什么是 LLDB?

LLDB is a next generation, high-performance debugger. It is built as a set of reusable components which highly leverage existing libraries in the larger LLVM Project, such as the Clang expression parser and LLVM disassembler.
LLDB is the default debugger in Xcode on Mac OS X and supports debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.
All of the code in the LLDB project is available under the standard LLVM License, an open source “BSD-style” license.

简言之,LLDB是一个有着 REPL(交互式解析器) 的特性和 C++ |Python 插件的开源调试器新一代高性能调试器。随着Xcode5的发布,LLDB调试器成为macOS系统调试的基础部分。对于开源和其他非基于GUI的应用程序调试的开发,可以将终端窗口中的LLDB用作传统的命令行调试器。

这里的主要的信息是:

  • LLDB 是一个内建于 OS 终端窗口的命令行调试器
  • LLDB 可以和系统运行的进程进行交互调试

这意味着,使用 LLDB 我们可以通过在命令行打断点来获得正在运行的进程的后台信息。这也是我们可以通过 LLDB 来寻找微信数据库地址以及获取访问密码的主要原因。

准备工作:关闭SIP系统完整性保护

系统完整性保护(SIP)是 OS X El Capitan 及更高版本所采用的一项安全技术,旨在帮助防止潜在恶意软件修改 Mac 上受保护的文件和文件夹,但这也造成了安装某些特殊版本软件的或者做特殊修改的时候权限不足。在这里就体现在使用 LLDB 调试时候,所有的调试语句都会被系统拒绝,因此在正式进行调试之前,一个重要的准备工作就是检查系统完整性保护(SIP)的开启状态,如果开启的话,要把它关闭。

  • 检查 SIP 的开启状态
    在终端里输入 csrutil status 回车,如果看到:

    System Integrity Protection status: enabled.

    这说明的 SIP 已经开启,如果要继续调试的话,需要关闭。如果是 System Integrity Protection status: disabled. 则说明 SIP 已经处于关闭状态,可以直接进行调试。

  • 关闭 SIP

    • 重启,并在开机的时候长按 CommandR

    • 进入系统恢复状态

    • 点击屏幕顶部工具栏上的 实用工具,选择终端

    • 在终端中输入 csrutil disable 回车,会出现

      Successfully disabled System Integrity Protection. Please restart the machine for the changes to take effect.

    • 再次重启生效

  • 记得在调试后按照同样的步骤输入 csrutil enable 重新开启 SIP 惹

LLDB 获取微信数据库地址
  • 打开微信,但是不要登录

  • 在命令行里输入 lldb -p $(pgrep WeChat)

    (lldb) process attach --pid 77855
    Process 77855 stopped
    * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOPframe #0: 0x00007fff6e878dfa libsystem_kernel.dylib`mach_msg_trap + 10
    libsystem_kernel.dylib`mach_msg_trap:
    ->  0x7fff6e878dfa <+10>: retq   0x7fff6e878dfb <+11>: nop    libsystem_kernel.dylib`mach_msg_overwrite_trap:0x7fff6e878dfc <+0>:  movq   %rcx, %r100x7fff6e878dff <+3>:  movl   $0x1000020, %eax          ; imm = 0x1000020
    Target 0: (WeChat) stopped.Executable module set to "/Applications/WeChat.app/Contents/MacOS/WeChat".
    Architecture set to: x86_64h-apple-macosx-.
    
  • 这时候微信的进程被我们暂停了,需要在命令行中输入 c 回车,可以看到:

    Process 77855 resuming

  • 扫码登陆微信

  • 输入 br set -n '[WCTDatabase initWithPath:]

    Breakpoint 1: where = WCDB`-[WCTDatabase(Database) initWithPath:], address = 0x000000010e54120a
    
  • 进入 聊天备份与恢复 页面点击恢复聊天记录到手机 触发断点

    Process 78136 stopped
    * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1frame #0: 0x000000010e54120a WCDB`-[WCTDatabase(Database) initWithPath:]
    WCDB`-[WCTDatabase(Database) initWithPath:]:
    ->  0x10e54120a <+0>: pushq  %rbp0x10e54120b <+1>: movq   %rsp, %rbp0x10e54120e <+4>: pushq  %r150x10e541210 <+6>: pushq  %r14
    Target 0: (WeChat) stopped.
    
  • 在命令行输入 po $arg3

    /Users/xxxx/Library/Containers/com.tencent.xinWeChat/Data/Library/ApplicationSupport/com.tencent.xinWeChat/2.0b4.0.9/Backup/d9381f8bfa1ab8fa0f5e54b2858dffc3/EA2CC6CD-FCD2-4570-9CAC-9C95FF7E348B/Backup.db

  • 以上可以得到微信数据库的本地存储地址,确切地来说是微信备份文件的存储地址,往上一层文件夹就可以找到微信好友和聊天记录数据库

LLDB 获取微信数据库密码
  • 接着上面的操作在命令行里输入 br set -n sqlite3_key

    Breakpoint 2: 2 locations.
    
  • 输入 memory read --size 1 --format x --count 32 $rsi

    0x7fff78a12bc9: 0x69 0x6e 0x59 0x74 0x57 0x69 0x74 0x68
    0x7fff78a12bd1: 0x50 0x61 0x34 0x68 0x3a 0x00 0x73 0x65
    0x7fff78a12bd9: 0x74 0x53 0x70 0x65 0x65 0x64 0x4d 0x75
    0x7fff78a12be1: 0x6c 0x74 0x69 0x70 0x6c 0x69 0x65 0x72
    
  • 按照以下的步骤处理上面的输出即可得到 64 位密码:

    • 只保留 : 右边的数据

      0x69 0x6e 0x59 0x74 0x57 0x69 0x74 0x68
      0x50 0x61 0x34 0x68 0x3a 0x00 0x73 0x65
      0x74 0x53 0x70 0x65 0x65 0x64 0x4d 0x75
      0x6c 0x74 0x69 0x70 0x6c 0x69 0x65 0x72
      
    • 删掉所有的 0x

      69 6e 59 74 57 69 74 68
      50 61 34 68 3a 00 73 65
      74 53 70 65 65 64 4d 75
      6c 74 69 70 6c 69 65 72
      
    • 删掉所有的空格和换行

      696e597457697468506134683a0073657453706565644d756c7469706c696572
      
    • 以上就是打开数据库的 64 位密码啦,该密码适用于聊天记录,好友信息,群聊成员等各个数据库

打开数据库并重设密码

微信存储数据用的是轻量级的数据库工具 SQLite ,有很多软件可以打开,这里以 DB Browser for SQLite 为例。比如我双击聊天记录数据库 msg_0.db,会出现以下界面:

注意:

  • Encryption settings 选择 SQLClipher 3 defaults
  • 右边的密码形式选择 Raw key
  • 密码填写 0x 加上之前获取的 64 位密码,所以一共是 66 位

如果正确操作的话,这里应该可以打开数据库了。这里我们来看下数据库的结构,这里可以看出这个数据库里一共有 144 张表,每张表对应一个微信好友/群聊/公众号的聊天记录。

一个典型的表的属性如下:

最重要的几个属性为:

  • msgCreateTime 聊天时间戳
  • msgContent 聊天内容
  • messageType 聊天类型 文字为1

点击浏览数据可以进行预览:

为了避免每次打开都输入密码,我们可以移除数据库的密码。在 DB Browser for SQLite 中的具体操作是 工具 - 设置加密 - OK,即直接重设为空密码,这样也方便我们进一步提取数据。

本地存储的微信数据库里都有什么?

我翻了翻几个文件夹,认为以下四项最有分析意义,当然还有其他的小伙伴们可以自行发掘。

  • Contact - wccontact_new2.db - 好友信息
  • Group - group_new.db - 群聊和群成员信息
  • Message - {msg_0.db - msg_9.db} - 聊天记录和公众号文章
  • Favorites - favorites.db - 收藏
微信好友/公众号

首先来看联系人数据库 wccontact_new2.db,这里主要就是一张表 WCContact,这里面存储了我们加的微信好友和关注的公众号的信息,主要是昵称和微信号 m_nsUsrName。一般公众号以 gh_ 开头。这里的 m_nsUsrName 非常重要,因为聊天数据库里的表名都是 md5 编码后的 m_nsUsrName。比如公众号 广发证券研究 的 m_nsUsrName 为 gh_24e4252623cf,md5 编译后即为 41cbc56f1e10ab139339a40a4df2132d,因此聊天记录数据库里的 Chat_41cbc56f1e10ab139339a40a4df2132d 即为这个公众号的全部历史信息。

群聊/群成员

group_new.db 数据库里有两张表,分别是 GroupContactGroupMember。其中 GroupContact 和微信好友数据库很像,只不过里面存储的是群聊名称和群聊 m_nsUsrName。用法和联系人数据库一样,都是通过对 m_nsUsrName 进行 md5 编译索引到聊天记录数据库里的表。

GroupMember 表里包含了你加群里所有群成员的微信号和昵称,不管有没有加过好友。所以一般如果联系人数据库里有几百个的话,这个表里往往有几千上万条记录。

收藏

favorites.db 里面有 8 张表,其中最重要的是两个,FavoriteItemTableFavoriteSearchTable


FavoriteSearchTable 给了收藏的标题和 localID。


FavoriteItemTable 给了收藏时间戳,收藏内容链接,以及收藏内容来源用户等,并且可以和 FavoriteSearchTable 通过 localID 互相索引。

聊天记录

见上文

如何解析数据库并提取目标信息?

使用解密脚本打开数据库:

from pysqlcipher import dbapi2 as sqlite
output = 'output_db_whole.db'
key = 'a3c77a9'
conn = sqlite.connect(db)
c = conn.cursor()
c.execute("PRAGMA key = '" + key + "';")
c.execute("PRAGMA cipher_use_hmac = OFF;")
c.execute("PRAGMA cipher_page_size = 1024;")
c.execute("PRAGMA kdf_iter = 4000;")
c.execute("SELECT name FROM sqlite_master WHERE type='table'")
c.execute("ATTACH DATABASE '" + output + "' AS db KEY '';")
c.execute("SELECT sqlcipher_export('db');")
c.execute("DETACH DATABASE db;")
conn.close()

从群聊数据库里提取群聊列表,使用 transmd5 函数获得群聊索引序号 md5 编码,并写入文本文件中:

import sqlite3
import time, datetime
import hashlibconn = sqlite3.connect('group_new.db')
print("Opened database successfully")def transmd5(string):m = hashlib.md5(string.encode(encoding='UTF-8')).hexdigest()return(m)def transfertime(timeStamp):timeArray = time.localtime(timeStamp)otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)return(otherStyleTime)cursor = conn.execute("SELECT m_nsUsrName, nickname, m_nsFullPY, m_nsChatRoomMemList from GroupContact")
f = open('groupcontact.txt','w')
for row in cursor:for i in range(3):f.write(row[i]+';')f.write(transmd5(row[0]))f.write('\n')print("Operation done successfully")
conn.close()

从以上结果里面,我们可以得到我们想要的群聊在数据库中的 md5 编码 Chat_aa309112204d5fd125c5a8bad609ff25。同时提取群聊成员列表,准备与聊天记录进行合并:

conn = sqlite3.connect('group_new.db')cursor = conn.execute("SELECT m_nsUsrName, nickname from GroupMember")
f = open('groupmember.txt','w')
for row in cursor:for i in range(2):f.write(row[i]+';')f.write('\n')conn.close()

由于聊天记录被自动拆分到了 10 个数据库文件 msg_0.db - msg_9.db 里,需要遍历所有的数据库文件获取每个数据库里所有的表名才能确定我们要的聊天记录到底存储在哪个文件里。

def sheetname(i):conn = sqlite3.connect('msg_%s.db'%i)return(conn)def getdata(conn):cursor = conn.execute("select name from sqlite_master where type='table'")tab_name=cursor.fetchall()tab_name=[line[0] for line in tab_name]return(tab_name)f = open('sheetname.txt','a')
for j in range(10):conn = sheetname(j)tab_name = getdata(conn)for i in tab_name:f.write(i+','+'sheet_%s'%j+'\n')conn.close()

经过这一步,我们可以精确定位想要的群聊到底在哪个数据库文件里的哪张表里。于是可以从聊天数据库里提取指定群聊信息的聊天记录,转换时间戳,使用正则表达式筛选符合指定信息的聊天记录,并写入文本文件中:

conn = sqlite3.connect('msg_0.db')def transfertime(timeStamp):timeArray=time.localtime(timeStamp)otherStyleTime=time.strftime("%Y-%m-%d %H:%M:%S",timeArray)return(otherStyleTime)cursor=conn.execute("SELECT msgCreateTime,messageType,msgContent from Chat_aa309112204d5fd125c5a8bad609ff25 where messageType=1")f = open('chatrecord.txt','w')for row in cursor:a = re.findall('[\d]+.*[\d]+\.[\d]',row[2].split(':')[-1])if a != []:f.write("%s;%s;%s;\n"%(transfertime(row[0]),row[2].split(':')[0],a))conn.close()


如果不通过正则表达式筛选的话,得到的就是文本格式的聊天记录:

这里存在一个问题是,聊天记录里只有每个人的微信号,没有昵称,因此我们需要把这张表和群聊成员表合并,并导出最终的结果:

import pandas as pd
import csvdf1 = pd.read_table('/Users/mengjiexu/PycharmProjects/wx/chatrecord.txt',sep = ';')
df1.columns = ['timestamp','wxindex','record','']
df2 = pd.read_table('/Users/mengjiexu/PycharmProjects/wx/groupmember.txt',sep = ';',error_bad_lines=False,quoting=csv.QUOTE_NONE)
df2.columns = ['wxindex','nickname','']
df = pd.merge(df1,df2,on = 'wxindex',how='left')
df.to_csv('resultspd.csv',mode ='w',encoding='gb18030')

如果对自己的好友分布感兴趣,还可以导出自己的好友和公众号列表,并进行进一步的分析:

conn = sqlite3.connect('wccontact_new2.db')cursor = conn.execute("SELECT m_nsUsrName, nickname, m_nsFullPY, m_nsAliasName  from WCContact")
#df = pd.DataFrame(cursor, columns=['username','nickname','fullpy','aliasname'])
#df.to_csv('contact.csv', sep=',', mode='a', encoding='utf8')
f = open('contact.txt','a')
for row in cursor:for i in range(3):f.write(row[i]+',')f.write('\n')conn.close()

参考链接

  1. https://www.jianshu.com/p/0f41c120160d
  2. https://jingyan.baidu.com/article/f0e83a255eea0622e591013d.html
  3. https://www.jianshu.com/p/90224ab9cdf2
  4. http://xferris.cn/dao-chu-wei-xin-bei-fen-de-mac/
  5. https://www.jianshu.com/p/93bbcda3133a

如何优雅地管理微信数据库?相关推荐

  1. php 管理 mysql 数据库 代码_安装并使用phpMyAdmin管理MySQL数据库_php

    学会使用基于web数据库的管理工具phpMyAdmin. 如果使用合适的工具,mysql数据库的管理就会为得相当简单.应用MySQL命令行方式需要对MySQL知识非常熟悉,对SQL语言也是同样的道理. ...

  2. 在Asp.NET Core中如何优雅的管理用户机密数据

    在Asp.NET Core中如何优雅的管理用户机密数据 背景 回顾 在软件开发过程中,使用配置文件来管理某些对应用程序运行中需要使用的参数是常见的作法. 在早期VB/VB.NET时代,经常使用.ini ...

  3. sqlitestudio和mysql_SQLiteStudio优雅调试Android手机数据库Sqlite(推荐)

    前言 调试Android中的数据库有多种方式,目前比较流行的是:借助电脑端浏览器来调试,可以使用如下两个玩意: 博主在调试sqlite的时候,发现了个更加简单和强大的工具来调试sqlite数据库. S ...

  4. 用python wxpy管理微信公众号,并利用微信获取自己的开源数据。

    之前了解到itchat 乃至于 wxpy时 是利用tuling聊天机器人的接口.调用接口并保存双方的问答结果可以作为自己的 问答词库 的一个 数据库累计. 这些数据可以用于自己训练. 而最近希望获取一 ...

  5. 微信是胖客户端瘦服务器,一款管理微信客户软件的系统体系结构设计?

    泛普管理微信客户软件的客户应用程序精简到一个通用的浏览器软件.第二层Web服务器将启动相应的进程来响应客户的请求,并动态生成一串HTML代码,其中嵌入处理的主机终端模式由于硬件选择有限,硬件投资得不到 ...

  6. 设计一个采购、销售和客户管理应用数据库

    设计一个采购.销售和客户管理应用数据库 这是西安邮电大学软件工程数据库原理及应用的一次疫情期末大作业.如果觉得本文编辑不是很符合你的预期,可以加我QQ或者微信可提供当时写的word文档(私聊备注来意) ...

  7. 如何优雅的管理游戏资源

    在游戏的开发过程中,前期的规划 往往比 后期的"优化"更为重要!比如多分辨率适配,如果前期没有规划好,可能导致的情况是,画面只在当前测试开发机或者一部分机型正常显示.做了多套资源适 ...

  8. 使用phpMyAdmin管理WordPress数据库入门指南

    WordPress 是使用 PHP 作为其脚本语言和 MySQL 作为其数据库管理系统编写的.为了使用 WordPress,您实际上不需要学习其中任何一个. 但是,对这两者有一个非常基本的了解可以帮助 ...

  9. 深入Quartz,优雅地管理你的定时任务

    深入Quartz,优雅地管理你的定时任务 1 初识Quartz 2 Quartz基础使用 2.1 基于时间间隔的定时任务 2.2 基于Cron表达式的定时任务 3 Quartz解读 3.1 Job 3 ...

最新文章

  1. MySQL面试题 | 附答案解析(二)
  2. 【万里征程——Windows App开发】DatePickerFlyout、TimePickerFlyout的使用
  3. 华为路由器上有没有mac表_MAC地址表、ARP缓存表、路由表及交换机、路由器基本原理...
  4. 如何在Linux命令行中替换多个文件中的字符串
  5. Huber Loss function
  6. java模拟器下载文件_KEmulator(java模拟器)最新下载
  7. android上的单片机编程软件下载,AVR单片机编程软件(AVR_fighter)
  8. 动态规划之马拉车算法(Python解法)
  9. 全球气象数据网站(大气、海洋数据应有尽有)
  10. c语言程序设计问号是什么意思,在C语言中,该语句在z=xy?x:y中是什么意思,问号表示什么意思...
  11. swift tabbar 自定义+号 底部34导航栏适配
  12. 计算机论文研究思路怎么写,论文研究思路要写什么
  13. Access-培训管理系统-03-建个数据库
  14. 在线PS把图片背景变成透明(灰白格子)
  15. python最佳编程语言_前十大编程语言你会几种?
  16. 半世浮尘洗铅华,余半生为君温酒煮茶
  17. 面向对象:面向对象程序设计
  18. 西数DES数据库取证分析大师系统
  19. 1、会计的概念、职能和目标
  20. Nacos 基础知识

热门文章

  1. 太原理工和山西大学计算机,双一流建设后,山西大学和太原理工你更想去哪一个?...
  2. C语言打印多颜色字体,多功能打印,协助开发调试
  3. 自己怎么开发一个软件app、如何开发一个app系统软件?
  4. 【Java基础】2020如何查看Java官方文档
  5. 工程伦理(2021春)第四章课后习题答案
  6. Pymoo:优化算法收敛性的实例分析
  7. 模拟二进制交叉算子详解
  8. UITextField类对象左视图leftView无效--iOS开发
  9. Win10各版本区别
  10. Contelec KL750-5K0/M-SE醉后不知天在水