实时获取微信聊天消息记录

来源:互联网 发布:mac地址查询 编辑:程序博客网 时间:2024/05/17 09:08

由于微信的数据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 "";        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

获取微信用户信息号需要解析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 "";    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

有上面两个字符串计算出打开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();
  • 1
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 "";    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

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

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();            }        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145

在初始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();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

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



------------------------------------------------------------------------------


个人简介:


花名:nexttake


精通Android NDK 与 SDK开发,熟悉Java服务器端技术,对新技术有热情,有较强的源码分析能力 。希望和大家一起分享技术,


技术交流群 171740554
原创粉丝点击