森林雪人 发表于 2019-7-21 12:43

微信聊天记录解密查询

本帖最后由 森林雪人 于 2020-1-12 19:03 编辑

拜读大佬的微信数据解密帖子:https://www.52pojie.cn/thread-796230-1-1.html
在其代码基础上添加聊天记录搜索功能,根据微信号搜索单个好友聊天信息。
关键代码如下:
button.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
      String password = DecryptUtiles.initDbPassword(MainActivity.this);
      String uid = DecryptUtiles.initCurrWxUin();
      editText2.setText("");
      try {
          String path = WX_DB_DIR_PATH +"/"+ Md5Utils.md5Encode("mm" + uid) + "/" + WX_DB_FILE_NAME;
          Log.e("path",copyFilePath);
          Log.e("path",path);
          Log.e("path",password);
          net.sqlcipher.database.SQLiteDatabase.loadLibs(MainActivity.this);
          hook=new SQLiteDatabaseHook() {
            @Override
            public void preKey(net.sqlcipher.database.SQLiteDatabase sqLiteDatabase) {
            }
            @Override
            public void postKey(net.sqlcipher.database.SQLiteDatabase sqLiteDatabase) {
            sqLiteDatabase.rawExecSQL("PRAGMA cipher_migrate;");
            }
          };
          net.sqlcipher.database.SQLiteDatabase db = net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(new File(copyFilePath), password, null, hook);
          Cursor c3=null;
          String res3;
          SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          if (editText3.getText().toString().equals("")){
            c3=db.rawQuery("select * from message where type=1 and talker=\'"+editText.getText().toString()+"\'", null);
            Log.e("使用原始微信号查询",editText.getText().toString());
          }else {
            c3=db.rawQuery("select * from message where type=1 and talker=(select username from rcontact where alias=\'"+editText3.getText().toString()+"\')", null);
            Log.e("使用自己定义微信号查询",editText3.getText().toString());
          }
          while (c3.moveToNext()){
            String talker = c3.getString(c3.getColumnIndex("talker"));
            String content = c3.getString(c3.getColumnIndex("content"));
            String createTime = c3.getString(c3.getColumnIndex("createTime"));
            long lt=new Long(createTime);
            Date date=new Date(lt);
            res3=simpleDateFormat.format(date);
            editText2.append(res3+content+" \n");

          }
          if(editText2.getText().toString().equals("")){
            Toast.makeText(getApplicationContext(), "没有聊天记录", Toast.LENGTH_SHORT).show();
          }
          c3.close();
      } catch (Exception e) {
          Log.e("path",e.getMessage());
          e.printStackTrace();
      }
      }
    });
编译后生成应用界面如下图:


在红框1输入好友微信号查询,如果查不到聊天记录,则在红框2处输入微信号查询。

1、如何获取微信号?
打开微信好友资料,在微信号上长按,会弹出复制,选择复制粘贴到红框1或红框2即可。


2、为什么要做两个查询框?
有的微信好友自定义了微信号,他的资料上看到的是修改后的微信号(rcontact.alias),看不到原始微信号(rcontact.username)。
若没有自定义微信号那么alias字段就是空的,好友资料上看到的是原始微信号(rcontact.username)。


最终我们还得使用message表上的talker字段查询聊天内容(message.content),而message.talker的值就是rcontact.username


红框1查询原始微信号,红框2是自定义微信号。

当红框2为空时,查询红框1原始微信号的值:
select * from message where type=1 andtalker=’’

红框2不为空时,查询红框2自定义微信号的值:
select * from message where type=1 andtalker=(select username from rcontact where alias=’’)

3、获取IMEI的三种方式
第一种方式可以在代码中实现获取手机IMEI。
第二种方式可以直接查看DENGTA_META.xml文件中的IMEI_DENGTA的值。
/data/data/com.tencent.mm/shared_prefs/DENGTA_META.xml

第三种方式在手机拨号键中输入*#06#,如果有多个IMEI,通常取第一个。

4、wx_data.db文件说明
本程序是把微信聊天数据库文件EnMicroMsg.db,复制到手机外部存储根目录/wx_data.db。查询聊天记录是连接手机外部存储根目录/wx_data.db
本程序运行后自动进行EnMicroMsg.db复制操作,根据你的EnMicroMsg.db的大小,我的文件差不多500MB,复制了近6秒。
下次运行时,程序会判断是否存在wx_data.db文件,如果存在,不再进行复制操作。
这样做是避免每次启动时都会重复复制微信数据库,其实也没有必要每次启动都复制。

public static void copyFile(String oldPath, String newPath) {
    try {
      int byteRead = 0;
      File oldFile = new File(oldPath);
      File sdfile = new File(newPath);
      if (oldFile.exists()&&!sdfile.exists()) { //目标文件存在时不复制

      InputStream inStream = new FileInputStream(oldPath); //读入原文件
      FileOutputStream fs = new FileOutputStream(newPath);
      byte[] buffer = new byte;
      while ((byteRead = inStream.read(buffer)) != -1) {
          fs.write(buffer, 0, byteRead);
      }
      inStream.close();
      }
    } catch (Exception e) {
      Log.e("copyFile", "复制单个文件操作出错");
      e.printStackTrace();
    }
}
所以如果你想看到最新的聊天记录请把手机根目录下wx_data.db文件删除。重新运行程序会自动复制最新EnMicroMsg.db数据库到手机外部存储根目录/wx_data.db。

5、如何在电脑上查看微信聊天数据库
wx_data.db可以复制到电脑上使用SQLCipher打开,打开时会要求你输入密码。

这个7位密码就是你的IMEI拼接微信账号的uin后进行32位MD5运算后取前7位的值,密码在程序启动时会在logcat中打印出来。


可以使用adb连接到手机,
adb shell
logcat "decrypt.wx.com.wxdatabasedecryptkey"|grep path


提示:
1、在电脑上使用SQLCipher打开wx_data.db,需要在点击查询前把wx_data.db复制到电脑上,因为你一旦点击查询了,wx_data.db进行初始化, 初始化后的wx_data.db使用SQLCipher将无法打开。
初始化是在第一次查询时进行,如果wx_data.db数据量比较大,程序会卡上几秒钟。后面的查询不会卡了。
2、本测试demo运行后会将/data/data/com.tencent.mm/目录及其下所有文件权限置为777,用于复制微信聊天数据库及计算数据库加密的密码。当手机重启后,会自动重置这个目录为微信私有。

附上测试demo
链接:https://pan.baidu.com/s/1aFekxMITWkbQnx7Vo4zUmg
提取码:yapn

森林雪人 发表于 2019-7-21 14:33

tail88 发表于 2019-7-21 14:14
大神,uin码前面那个“-”要参与运算吗?拼接时是IMEI+uin还是uin+IMEI?

imei + uin,就是两个字符串连接起来再进行MD5 ,“-”当然要带上。

云朵上de流年 发表于 2022-5-29 15:03

电脑版有吗?跪求大佬出电脑版

breezehan 发表于 2021-11-14 19:30

不错,有时 IMEI 使用默认是 1234567890ABCDEF,我没有导出需求,所有算出密码后,一般使用 sqlcipher 命令行 解密后,再使用guisqlitebrowser打开。

大男人 发表于 2019-7-21 14:40

学习一下,谢谢

wake 发表于 2019-7-21 12:44

这个好!

阿峰 发表于 2019-7-21 13:13

可以用于取证

tail88 发表于 2019-7-21 14:14

大神,uin码前面那个“-”要参与运算吗?拼接时是IMEI+uin还是uin+IMEI?

丿终结者 发表于 2019-7-21 14:32

不错 学习了{:301_999:}

展小哥 发表于 2019-7-21 14:34

这个不错,学习了,加油楼主~

zeikojo 发表于 2019-7-21 14:47

是不是本地删除了之后就不会再有了?

GL62662 发表于 2019-7-21 14:48

不错666666666666666
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 微信聊天记录解密查询