获取WhatsApp所有消息

47

我想实现一个应用程序,可以在文本视图中显示从Whatsapp接收到的所有消息。 有没有办法做到这一点? 是否可以提取来自Whatsapp的所有消息?


我认为这些消息现在已经加密了,所以我认为你不能轻易地获取它们。http://www.yourdailymac.net/2011/05/whatsapp-storing-messages-and-contact-data-unencrypted-on-ios-and-android-blackberry-symbian/ - SERPRO
请告诉我间谍应用程序如何能够在不进行root的情况下读取WhatsApp发送和接收的消息? - Gvtha
@Gvtha 有任何解决方案吗? - Deepak
7个回答

32

WhatsApp将所有消息存储在加密数据库(pyCrypt)中,但使用Python非常容易解密。

您可以轻松获取Android、iPhone、Blackberry上的此数据库,并将其转储为html文件。以下是完整的说明:阅读、提取Android、iPhone、Blackberry上的WhatsApp备份消息

免责声明:我研究并编写了这个详细的指南。


4
现在它是 db.crypt5。 - amalBit
根据http://forum.xda-developers.com/showthread.php?t=1583021,目前尚不支持Blackberry。 - Clark Superman
1
请告诉我间谍应用程序如何能够在不进行root的情况下读取WhatsApp发送和接收的消息? - Gvtha
通过阅读 Whatsapp 的通知,我认为是 @Gvtha。 - Beyondo
1
通过阅读通知,我们可以读取收到的消息,但无法读取已发送的消息。 - Gvtha
@Gvtha 对于已发送的消息,我已经想到了一种技术(方法),但它太复杂,并且不适用于所有用户,因为它取决于用户的 WhatsApp 设置,所以我不是很确定,可能有比我想到的更简单的方法。如果我发现了,我会在这里更新你。 - Beyondo

19

可用的 Android 代码:(无需 root 权限)

一旦您可以访问 dbcrypt5 文件,这里是解密它的 Android 代码:

private byte[] key = { (byte) 141, 75, 21, 92, (byte) 201, (byte) 255,
        (byte) 129, (byte) 229, (byte) 203, (byte) 246, (byte) 250, 120,
        25, 54, 106, 62, (byte) 198, 33, (byte) 166, 86, 65, 108,
        (byte) 215, (byte) 147 };

private final byte[] iv = { 0x1E, 0x39, (byte) 0xF3, 0x69, (byte) 0xE9, 0xD,
        (byte) 0xB3, 0x3A, (byte) 0xA7, 0x3B, 0x44, 0x2B, (byte) 0xBB,
        (byte) 0xB6, (byte) 0xB0, (byte) 0xB9 };
   long start = System.currentTimeMillis();

    // create paths
    backupPath = Environment.getExternalStorageDirectory()
            .getAbsolutePath() + "/WhatsApp/Databases/msgstore.db.crypt5";
    outputPath = Environment.getExternalStorageDirectory()
            .getAbsolutePath() + "/WhatsApp/Databases/msgstore.db.decrypt";

    File backup = new File(backupPath);

    // check if file exists / is accessible
    if (!backup.isFile()) {
        Log.e(TAG, "Backup file not found! Path: " + backupPath);
        return;
    }

    // acquire account name
    AccountManager manager = AccountManager.get(this);
    Account[] accounts = manager.getAccountsByType("com.google");

    if (accounts.length == 0) {
        Log.e(TAG, "Unable to fetch account!");
        return;
    }

    String account = accounts[0].name;

    try {
        // calculate md5 hash over account name
        MessageDigest message = MessageDigest.getInstance("MD5");
        message.update(account.getBytes());
        byte[] md5 = message.digest();

        // generate key for decryption
        for (int i = 0; i < 24; i++)
            key[i] ^= md5[i & 0xF];

        // read encrypted byte stream
        byte[] data = new byte[(int) backup.length()];
        DataInputStream reader = new DataInputStream(new FileInputStream(
                backup));
        reader.readFully(data);
        reader.close();

        // create output writer
        File output = new File(outputPath);
        DataOutputStream writer = new DataOutputStream(
                new FileOutputStream(output));

        // decrypt file
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec secret = new SecretKeySpec(key, "AES");
        IvParameterSpec vector = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, secret, vector);
        writer.write(cipher.update(data));
        writer.write(cipher.doFinal());
        writer.close();
    } catch (NoSuchAlgorithmException e) {
        Log.e(TAG, "Could not acquire hash algorithm!", e);
        return;
    } catch (IOException e) {
        Log.e(TAG, "Error accessing file!", e);
        return;
    } catch (Exception e) {
        Log.e(TAG, "Something went wrong during the encryption!", e);
        return;
    }

    long end = System.currentTimeMillis();

    Log.i(TAG, "Success! It took " + (end - start) + "ms");

太好了。我能够成功读取消息。但这不是官方API。你怎么知道这些KEY值呢? - Ramachandra Reddy Avula
1
这不是官方的,当Whatsapp的人们更改db.crypt5时,它将停止工作。 - amalBit
当我打开msgstore.db.decrypt时,出现文件不受支持的错误。 - user4584887
我在两年前尝试过这个。自那以后,Whatsapp已经多次更改了他们的加密方法。 - amalBit
@KartikeyKumarSrivastava 他们已经迭代了很多次。我现在一点头绪都没有。你可能需要反向工程应用程序以了解加密格式以进行解密。(仅供教育目的) - amalBit
显示剩余9条评论

12

编辑

由于WhatsApp付出了一些努力来改进他们的加密系统,获取数据不再那么容易。使用新版本的WhatsApp不再可能使用adb备份。应用程序可以拒绝备份,WhatsApp客户端也是如此。如果您碰巧有一个Rooted手机,您可以使用Root Shell来获取未加密的数据库文件。

如果您没有Root权限,仍然可以解密数据,如果您有旧版的WhatsApp APK。找到一个仍允许备份的版本。然后,您可以备份应用程序的数据文件夹,其中将包含一个名为key的加密密钥。

现在您需要加密的数据库。使用您选择的文件浏览器或,如果您更喜欢命令行,请使用adb:

adb pull /sdcard/WhatsApp/Databases/msgstore.db.crypt12

使用这两个文件,您现在可以使用https://gitlab.com/digitalinternals/whatsapp-crypt12获取明文数据库。不能再像以前那样使用Linux板工具(如openssl)了,因为WhatsApp似乎使用了Spongy Castle API的修改版本进行加密,而openssl无法理解。

原始答案(仅适用于旧的crypt7)

由于WhatsApp现在使用crypt7格式,因此不那么容易获取和解密数据库了。有一种使用ADB和USB调试的有效方法。

您可以通过ADB获取加密密钥并解密存储在/sdcard上的消息数据库,或者只需通过ADB备份获取数据库的纯文本版本,这似乎是更容易的选项。

要获取数据库,请执行以下操作:

将Android手机连接到计算机上。现在运行

adb backup -f whatsapp_backup.ab -noapk com.whatsapp

要备份WhatsApp在其私有文件夹中创建的所有文件。
您将获得一个使用tar格式的zlib压缩文件,其中包含一些ADB头。首先我们需要摆脱这些头部,因为它们会混淆解压缩命令:

dd if=whatsapp_backup.ab ibs=1 skip=24 of=whatsapp_backup.ab.nohdr

文件现在可以被解压缩:
cat whatsapp_backup.ab.nohdr | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" 1> whatsapp_backup.tar

这个命令会运行Python并使用zlib解压文件 whatsapp_backup.tar。
现在我们可以对文件进行解压缩:

tar xf whatsapp_backup.tar

归档文件已经解压到您当前的工作目录,您可以在apps/com.whatsapp/db/中找到数据库(msgstore.db和wa.db)。

很遗憾,由于WhatsApp现在使用修改过的Spongy Castle进行加密,因此它无法用于crypt9,您无法再通过adb备份获取数据库的明文版本。请参阅我的编辑,了解如何使用新的crypt12来完成此操作。 - RenWal
@RenWal - 请告诉我,间谍应用程序如何能够在没有root的情况下读取Whatsapp发送和接收的信息? - Gvtha
1
Gitlab仓库链接不再可用。 - OJ7

8

我认为,只有以root用户身份才能访问位于SD卡上的WhatsApp数据库。 如果你打开"\data\data\com.whatsapp",你会发现"databases"链接到"\firstboot\sqlite\com.whatsapp\"


如果root用户访问此数据库文件,那么它是否加密? - Akarsh M
是的,它们都被加密了。您可以按照这个逐步指南进行解密:http://forum.xda-developers.com/showthread.php?p=24603294 - Farzan

4

如果您确实想要一些简单的东西,并且知道如何编写/运行Python,请查看Bas Bosschert的脚本:源代码

#!/usr/bin/env python

import sys
from Crypto.Cipher import AES

try:
    wafile=sys.argv[1]
except:
    print "Usage: %s <msgstore.db.crypt>" % __file__
    sys.exit(1)

key = "346a23652a46392b4d73257c67317e352e3372482177652c".decode('hex')
cipher = AES.new(key,1)
open('msgstore.db',"wb").write(cipher.decrypt(open(wafile,"rb").read()))

全面运行:

(scratch)ehtesh@ackee:/tmp/whatsapp$ mkvirtualenv whatsapp_decrypt
New python executable in whatsapp_decrypt/bin/python
Installing setuptools, pip...done.
(whatsapp_decrypt)ehtesh@ackee:/tmp/whatsapp$ pip install pycrypto >/dev/null
(whatsapp_decrypt)ehtesh@ackee:/tmp/whatsapp$ wget https://gist.githubusercontent.com/shurane/ffa15e959e2d134086c9/raw/bc99a9997123bea0ea0acde185e24c7e89133559/whatsapp_decrypt.py >/dev/null
(whatsapp_decrypt)ehtesh@ackee:/tmp/whatsapp$ ls
msgstore.db.crypt  whatsapp_decrypt.py
(whatsapp_decrypt)ehtesh@ackee:/tmp/whatsapp$ python whatsapp_decrypt.py msgstore.db.crypt
(whatsapp_decrypt)ehtesh@ackee:/tmp/whatsapp$ ls
msgstore.db.crypt  msgstore.db  whatsapp_decrypt.py
(whatsapp_decrypt)ehtesh@ackee:/tmp/whatsapp$ sqlite3 msgstore.db
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> PRAGMA table_info(messages);
0|_id|INTEGER|0||1
1|key_remote_jid|TEXT|1||0
2|key_from_me|INTEGER|0||0
3|key_id|TEXT|1||0
4|status|INTEGER|0||0
5|needs_push|INTEGER|0||0
6|data|TEXT|0||0
7|timestamp|INTEGER|0||0
8|media_url|TEXT|0||0
9|media_mime_type|TEXT|0||0
10|media_wa_type|TEXT|0||0
11|media_size|INTEGER|0||0
12|media_name|TEXT|0||0
13|media_hash|TEXT|0||0
14|media_duration|INTEGER|0||0
15|origin|INTEGER|0||0
16|latitude|REAL|0||0
17|longitude|REAL|0||0
18|thumb_image|TEXT|0||0
19|remote_resource|TEXT|0||0
20|received_timestamp|INTEGER|0||0
21|send_timestamp|INTEGER|0||0
22|receipt_server_timestamp|INTEGER|0||0
23|receipt_device_timestamp|INTEGER|0||0
24|raw_data|BLOB|0||0
25|recipient_count|INTEGER|0||0
sqlite>

Pritam Baral提出了一种更简单的方法:
openssl aes-192-ecb -d -in msgstore.db.crypt -out msgstore.db -K 346a23652a46392b4d73257c67317e352e3372482177652c

1
请告诉我间谍应用程序如何能够在不进行根操作的情况下读取Whatsapp发送和接收的消息? - Gvtha

3

对于已取得root权限的用户:WhatsApp把所有消息和联系人以明文格式存储在msgstore.db和wa.db文件中。这些文件可以在/data/data/com.whatsapp/databases/目录下找到。你可以使用任何SQLite数据库浏览器(如SQLite Database Browser)打开这些文件。


2
如果我们字面理解这个问题:
从Whatsapp获取所有消息。是否可以提取所有来自Whatsapp的消息?
那么简单的答案是,您可以从WhatsApp导出聊天记录(请参见FAQ)。
现在,您可以构建一个应用程序,监听WhatsApp共享事件并显示所有消息。对于一个简单的PWA,它可能看起来像这样:
    workbox.addEventListener("message", (m) => {
      if (_this.$route.query.hasOwnProperty("receiving-file-share")) {
        let files = m.data.file;
        _this.$refs.filehandler.processFileList(files, true);
      }
    });
    workbox.messageSW("SHARE_READY");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接