Heyxk / notes

学习笔记

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

小米手机提取微信聊天记录数据库

Heyxk opened this issue · comments

commented

小米6提取微信聊天记录笔记

通过MI6本地备份提取聊天记录

要导出微信安卓客户端的聊天记录,首先得找到聊天记录的数据库。
安卓客户端的聊天记录储存在私有目录 /data/data/com.tencent.mm/MicroMsg 下,这个目录需要root权限才能进去,但是,那样太太太麻烦了,好在我们MI6有本地备份的功能,利用这个功能。我们轻而易举就可以获得数据库。

需要的工具

此处下载

环境

需要安装Java环境,未安装可以搜索Java安装

提取数据库

  1. 首先到手机:设置->更多设置->备份和重置->本地备份 里面点击新建备份,选择软件程序中的微信进行备份

  2. 然后到文件管理 /内部储存设备/MIUI/backup/ALLBackup/ 下将备份的文件夹复制到电脑

  3. 接下来是从备份的文件中提取微信聊天记录,通过WinHex软件查看备份包信息,发现miui备份包是在原生安卓的备份基础上多加了一个文件头。选中多余的文件头,按delete键删除,点击保存。修改后的文件就是标准的原生安卓备份文件。

  4. 接下来,将修改后的com.tencent.mm.bak 处理成原文件,首先将abe.jar复制到和com.tencent.mm.bak同一个文件夹下
    终端执行:

java -jar abe.jar unpack com.tencent.mm.bak mm.tar

会生成一个mm.tar文件,用解压软件将这个包解压,会得到一个apps文件夹,apps文件夹下面有com.tencent.mm文件夹,聊天记录数据库就存在apps/com.tencent.mm/r/MicroMsg/ 下,打开文件夹会发现里面有32位字符(MD5值)的文件夹(登录过多个用户的有多个),打开此文件夹其中EnMicroMsg.db就是要找的数据库文件。

生成数据库密码

找到聊天数据库了,但是目前还不能得到聊天记录,因为这个数据库是sqlcipher加密数据库,需要密码才能打开。

数据库密码有很多种生成方式:

  1. 手机IMEI+uin(微信用户id userinformation) 将拼接的字符串MD5加密取前7位

    IMEI123456uinabc,则拼接后的字符串为123456abc 将此字符串用MD5加密(32位)后

    df10ef8509dc176d733d59549e7dbfaf 那么前7位df10ef8 就是数据库的密码,由于有的手机是双卡,有多个IMEI,或者当手机获取不到IMEI时会用默认字符串1234567890ABCDEF来代替,由于种种原因,并不是所有人都能得出正确的密码,此时我们可以换一种方法。

  2. 反序列化CompatibleInfo.cfgsystemInfo.cfg

    不管是否有多个IMEI ,或者是微信客户端没有获取到IMEI,而使用默认字符串代替,微信客户端都会将使用的信息保存在MicroMsg文件夹下面的CompatibleInfo.cfgsystemInfo.cfg文件中,可以通过这两个文件来得到正确的密码,但是这两个文件需要处理才能看到信息。

  3. 使用hook方式得到数据库的密码,这个方法最有效参考

  4. 暴力破解

...

使用反序列化的方式获得密码

由于我的手机有多个IMEI码,试了半天出来的密码都不对,故使用此方法来得到密码。
首先将CompatibleInfo.cfgsystemInfo.cfg以及EnMicroMsg.db复制出来,将下面这段代码保存到IMEI.java文件

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.security.MessageDigest;
import java.util.HashMap;
public class IMEI {
 public static void main(String[] args) {
  try {
   ObjectInputStream in = new ObjectInputStream(new FileInputStream(
     args[0]));
   Object DL = in.readObject();
   HashMap hashWithOutFormat = (HashMap) DL;
   ObjectInputStream in1 = new ObjectInputStream(new FileInputStream(
     args[1]));
   Object DJ = in1.readObject();
   HashMap hashWithOutFormat1 = (HashMap) DJ;
   String s = String.valueOf(hashWithOutFormat1.get(Integer
     .valueOf(258))); // 取手机的IMEI
   System.out.println("The IMEI is : " + s);
   String uin = String.valueOf(hashWithOutFormat.get(Integer.valueOf(1)));
   System.out.println("The uin is : " + uin);
   s = s + uin; //合并到一个字符串
   s = encode(s); // hash
   System.out.println("The Key is : " + s.substring(0, 7));
   in.close();
   in1.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 public static String encode(String content)
  {
   try {
    MessageDigest digest = MessageDigest.getInstance("MD5");
    digest.update(content.getBytes());
    return getEncode32(digest);
    }
   catch (Exception e)
   {
    e.printStackTrace();
   }
   return null;
  }
  private static String getEncode32(MessageDigest digest)
  {
   StringBuilder builder = new StringBuilder();
   for (byte b : digest.digest())
   {
    builder.append(Integer.toHexString((b >> 4) & 0xf));
    builder.append(Integer.toHexString(b & 0xf));
   }
    return builder.toString();

  }
}

将这段代码保存到IMEI.java文件,将三个文件放在相同目录下
终端运行

javac IMEI.java
java IMEI systemInfo.cfg CompatibleInfo.cfg

运行完成后就会得到密码
参考链接

解密数据库

Windows用户可以使用sqlcipher.exe软件来查看数据库
打开数据库,输入密码,就可以查看数据库中的表
文字聊天记录储存在message表中,可以选中表,点击软件的右上角file-export导出表到csv文件,可以通过Excell查看表中的信息
执行这段命令可以查看制定对象的聊天记录

select datetime(subStr(cast(m.createTime as text),1,10),'unixepoch', 'localtime') as theTime,case m.isSend when 0 then r.nickname when 1 then ''end as person,m.content from message m inner join rcontact r on m.talker = r.username where m.type=1 and r.nickname = '对方微信昵称'

Linux用户可以使用sqlcipher来解密

sudo apt-get update

sudo apt-get install sqlcipher

sqlcipher EnMicroMsg.db 'PRAGMA key = "yourkey"; PRAGMA cipher_use_hmac = off; PRAGMA kdf_iter = 4000; ATTACH DATABASE "decrypted_database.db" AS decrypted_database KEY "";SELECT sqlcipher_export("decrypted_database");DETACH DATABASE decrypted_database;' 

执行上面的命令之后会得到一个解密后的数据库decrypted_database.db,可以使用数据库软件查看

得到数据库之后可以分析一下你的聊天记录,顺便制作一个词云来给你的心上人看一下你们都聊了啥:eyes:

看了一下我和女票日消息数走势,最多一天竟然发了809条:joy:

命令行获取的IMEI为null是什么原因呀

我也是有这个null的问题,看了下手机有两个imei,尝试用了第一个imei 加上uid 做一个md5的hash,前七位就是密码

C:\wechat>java IMEI systemInfo.cfg CompatibleInfo.cfg
错误: 找不到或无法加载主类 IMEI

这个是什么问题??急求

先不要急,不过我不太了解这个中文错误码对应的英文是什么,应该不是null

你能确认一下你 IMEI.java 健全?

你能确认一下你 IMEI.java 健全?

我试过几次不行就换其他方法了,使用iemi少一位加uin取MD5 加密32位小写前面七位解出了密码:)

如果他获取的IMEI是null 那他下面算md5就会用null这4个字母

我和你的完全不一样,我miui 10 开发版,备份出来的bak文件完全就是一个压缩包,可以直接winrar查看,并没有app这个目录,直接就是com.tencent.mm/r,r下面也没有MicroMsg.

commented

您好,运行脚本时我也出现了这个问题:
错误: 找不到或无法加载主类 IMEI 原因: java.lang.ClassNotFoundException: IMEI

commented

日消息数走势是怎么分析的呀

commented

日消息数走势是怎么分析的呀

这个就是一个统计图,按时间分类就好

我的CompatibleInfo.cfg是空的

因为CompatibleInfo.cfg 有可能0字节,所以IMEI.java需要修改下

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.security.MessageDigest;
import java.util.HashMap;
import java.io.File;

public class IMEI {
    public static void main(String[] args) {
        try {
            ObjectInputStream in = new ObjectInputStream(new FileInputStream(args[0]));
            Object DL = in.readObject();
            HashMap hashWithOutFormat = (HashMap) DL;

           // CompatibleInfo.cfg 有可能0字节
           String imei = "1234567890ABCDEF"; // 默认字符串
           File fCompatibleInfo = new File(args[1]);
           // 取手机的IMEI
           if(fCompatibleInfo.length() > 0) {
            FileInputStream fisCompatibleInfo = new FileInputStream(fCompatibleInfo);
            ObjectInputStream in1 = new ObjectInputStream(fisCompatibleInfo);
            Object DJ = in1.readObject();            
            HashMap hashWithOutFormat1 = (HashMap) DJ;
            imei = String.valueOf(hashWithOutFormat1.get(Integer.valueOf(258)));
            in1.close();
           }
           System.out.println("The IMEI is : " + imei);

           String uin = String.valueOf(hashWithOutFormat.get(Integer.valueOf(1)));
           System.out.println("The uin is : " + uin);
           imei = imei + uin; //合并到一个字符串
           imei = encode(imei); // hash
           System.out.println("The Key is : " + imei.substring(0, 7));
           in.close();           
        } catch (Exception e) {
            e.printStackTrace();
        }
 }

 public static String encode(String content)
  {
   try {
    MessageDigest digest = MessageDigest.getInstance("MD5");
    digest.update(content.getBytes());
    return getEncode32(digest);
    }
   catch (Exception e)
   {
    e.printStackTrace();
   }
   return null;
  }
  private static String getEncode32(MessageDigest digest)
  {
   StringBuilder builder = new StringBuilder();
   for (byte b : digest.digest())
   {
    builder.append(Integer.toHexString((b >> 4) & 0xf));
    builder.append(Integer.toHexString(b & 0xf));
   }
    return builder.toString(); 
  }
}


保存java文件以后

> javac IMEI.java
> java IMEI systemInfo.cfg CompatibleInfo.cfg

这个java代码中,uin的获取是没问题的。
The uin is :得到的uin和 com.tencent.mm/sp/auth_info_key_prefs.xml 文件里的
<int name="_auth_uin" value="" />
的value值是一样的。

根据uin计算的key,解密数据库实测没有问题。