第三方apk实时获取微信聊天消息记录

说明:纯属发烧而生
第一步:安装apk的手机进行root

因为需要读取微信聊天记录信息表,所以手机需要root,这样给apk开启更大的权限,这里进行root的工具有好多比如360root大师等相关的root工具。

第二步:用Root Explorer把db文件赋予更高的权限

手机上安装Root ExPlorer软件,设置/data/data/com.tencent.mm/MicroMsg/b93e23895b9f5b4a8d781ba8d702cfe8/EnMicroMsg.db这些文件以及文件夹下的EnMicroMsg.db进行权限设定,赋予所有的权限(说明:这里的包名b93e23895b9f5b4a8d781ba8d702cfe8每个用户都是不一样的,需要用户你进行自己查看设置。)
《第三方apk实时获取微信聊天消息记录》

第三步:开始撸代码啦,
由于微信的数据db文件进行加密操作所以咱们这边需要解密
获取手机序列号IMEI号,

 public static String getIMEI(Context context) {
        TelephonyManager manager = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
        if (manager.getDeviceId() != null && manager.getDeviceId().length() > 0) {
            return manager.getDeviceId();
        } else {
            return "";
        }
    }

获取微信用户信息号需要解析xml,这里解析xml用到的是XmlPullParser进行解析的
这里path路径是:/data/data/com.tencent.mm/shared_prefs/system_config_prefs.xml

public static String getUin(String path) {
        try {
            FileInputStream inputStream = new FileInputStream(new File(path));
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(inputStream, "UTF-8");
            int eventType = parser.getEventType();// 产生第一个事件
            while (eventType != XmlPullParser.END_DOCUMENT) { //处理事件,不碰到文档结束就一直处理
                switch (eventType) {
                    case XmlPullParser.START_DOCUMENT:
                        // 不做任何操作或初开始化数据
                        break;
                    case XmlPullParser.START_TAG:
                        // 解析XML节点数据
                        // 获取当前标签名字
                        String tagName = parser.getName();
                        if ("int".equals(parser.getName())) {
                            String name = parser.getAttributeValue(0);
                            String value = parser.getAttributeValue(1);
                            Log.e("int", "name:" + name + ",value:" + value);
                            return value;
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        // 单节点完成,可往集合里边添加新的数据
                        break;
                    case XmlPullParser.END_DOCUMENT:
                        break;
                }
                // 别忘了进入下一个元素并触发相应事件 ,不然就会死循环
                eventType = parser.next();
            }
        } catch (FileNotFoundException e) {
            Log.e("FileNotFoundException:", e.toString());
        } catch (XmlPullParserException e) {
            Log.e("XmlPullParserException:", e.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

有上面两个字符串计算出打开db的密码,
这里的计算需要用到md5算法进行计算操作先把md5这段代码贴出来
计算密码调用与这几段代码进行配合

        String password= (MD5Util.md5(XmlUtil.getIMEI(context)+XmlUtil.getUin("/data/data/com.tencent.mm/shared_prefs/system_config_prefs.xml"))).substring(0,7).toLowerCase();
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/** * author: * date: 2016/10/25 20:59 */
public class MD5Util { 

    public static final char HEX_DIGITS[] = {
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'A', 'B', 'C', 'D', 'E', 'F'};

    public static String toHexString(byte[] b) {  //String to byte
        StringBuilder sb = new StringBuilder(b.length * 2);
        for (int i = 0; i < b.length; i++) {
            sb.append(HEX_DIGITS[(b[i] & 0xf0) >>> 4]);
            sb.append(HEX_DIGITS[b[i] & 0x0f]);
        }
        return sb.toString();
    }

    public static String md5(String s) {
        try {
            // Create MD5 Hash
            MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
            digest.update(s.getBytes());
            byte messageDigest[] = digest.digest();

            return toHexString(messageDigest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        return "";
    }
}

拿到密码后可以对数据库的读写进行操作



import android.content.Context; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; import net.sqlcipher.Cursor; import net.sqlcipher.database.SQLiteDatabase; import net.sqlcipher.database.SQLiteDatabaseHook; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; /** * Created by zxf on 2016/10/25. */ public class DataHelp {  /** * 操作数据库读取微信消息 * @param context * @param path */ public static void readWeChatDatabase(Context context,String path) { SQLiteDatabase.loadLibs(context); String password= (MD5Util.md5(XmlUtil.getIMEI(context)+XmlUtil.getUin(Constants.uinPath))).substring(0,7).toLowerCase(); Log.e("password", "password:"+password ); SQLiteDatabaseHook hook = new SQLiteDatabaseHook(){ public void preKey(SQLiteDatabase database){ } public void postKey(SQLiteDatabase database){ database.rawExecSQL("PRAGMA cipher_migrate;"); //最关键的一句!!! } }; try { long time=System.currentTimeMillis(); SQLiteDatabase db = SQLiteDatabase.openDatabase(path, password, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS, hook); long time2=System.currentTimeMillis(); long time_1=time2-time; Toast.makeText(context,"time_3:"+time_1, Toast.LENGTH_SHORT).show(); Log.e("readWeChatDatabase", "time_3:"+time_1 ); int count=0; Cursor c = db.rawQuery("select * from message" , null); while (c.moveToNext()) { int _id = c.getInt(c.getColumnIndex("msgId")); String content= c.getString(c.getColumnIndex("content")); count++; Log.e("readWeChatDatabase", "content:"+content ); } c.close(); db.close(); long time_2=System.currentTimeMillis()-time2; Toast.makeText(context,"time_4:"+time_2+",count:"+count , Toast.LENGTH_SHORT).show(); Log.e("readWeChatDatabase", "time_4:"+time_2+",count:"+count ); } catch (Exception e) { Log.e("e", "readWeChatDatabase: "+e.toString() ); } } /** * 复制单个文件 * @param oldPath String 原文件路径 如:c:/fqf.txt * @param newPath String 复制后路径 如:f:/fqf.txt * @return boolean */ public static void copyFile(Context context,String oldPath, String newPath) { long time=System.currentTimeMillis(); deleteFolderFile(newPath,true); long time2=System.currentTimeMillis(); long time_1=time2-time; Log.e("copyFile", "time_1:"+time_1 ); InputStream inStream=null; FileOutputStream fs=null; try { int bytesum = 0; int byteread = 0; File oldfile = new File(oldPath); if (oldfile.exists()) { //文件存在时 inStream = new FileInputStream(oldPath); //读入原文件 fs = new FileOutputStream(newPath); byte[] buffer = new byte[2048]; while ( (byteread = inStream.read(buffer)) != -1) { bytesum += byteread; //字节数 文件大小 fs.write(buffer, 0, byteread); } long time_2=System.currentTimeMillis()-time2; Log.e("copyFile", "time_2:"+time_2); readWeChatDatabase(context,newPath);//对copy出来的数据进行操作 } }catch (Exception e) { System.out.println("复制单个文件操作出错"); e.printStackTrace(); }finally { try { if (inStream!=null) { inStream.close(); } if (fs!=null){ fs.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * 删除指定目录下文件及目录 * * @param deleteThisPath * @return */ public static void deleteFolderFile(String filePath, boolean deleteThisPath) { if (!TextUtils.isEmpty(filePath)) { try { File file = new File(filePath); if (file.isDirectory()) { // 处理目录 File files[] = file.listFiles(); for (int i = 0; i < files.length; i++) { deleteFolderFile(files[i].getAbsolutePath(), true); } } if (deleteThisPath) { if (!file.isDirectory()) { // 如果是文件,删除 file.delete(); } else { // 目录 if (file.listFiles().length == 0) { // 目录下没有文件或者目录,删除 file.delete(); } } } } catch (Exception e) { e.printStackTrace(); } } } } 

在初始activity调用

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.xilexuan.wechatcrack.util.DataHelp;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity { 
    Timer timer;
    TimerTask mTimerTask;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        timer = new Timer();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final String old_path="/data/data/com.tencent.mm/MicroMsg/b93e23895b9f5b4a8d781ba8d702cfe8/EnMicroMsg.db";
        final String new_path="/data/data/copy到你的文件夹下比如com...../EnMicroMsg.db";

        DataHelp.copyFile(this,old_path,new_path);
        mTimerTask =new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        DataHelp.copyFile(MainActivity.this,old_path,new_path);
                    }
                });
            }
        };
        timer.schedule(mTimerTask, 0, 10000);//10秒一获取
       //Toast.makeText(this, pwd, Toast.LENGTH_SHORT).show();
    }
}

最后在log内就能看到你截取到的微信聊天记录,这里设置的10秒获取一次。
这里只是发烧而已,

    原文作者:lamboo_cn
    原文地址: https://blog.csdn.net/lamboo_cn/article/details/52947290
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞