2017-05-24 14:42:00 qq_30548105 阅读数 43712
  • Unity仿微信开发

    使用Unity仿微信开发IM即时通讯软件,探索IM开发技术、数据库设计、通用网络模块、音视频通讯等。 功能介绍: 1.支持Unity编辑器、PC、Mac、Android、IOS、UWP平台 2.实现文字、表情、图片、视频、语音、文件发送 3.实现好友、群组功能 4.本地消息存储、离线消息处理 5.实现好友、群组音视频通话

    57 人正在学习 去看看 谷世杰

最近一直在研究Xposed等一些hook框架,进行学习做一些demo,这次就正好拿微信练练手,学习学习,也可以学习微信手机本地数据库的表结构设计等。


好,废话不多说,直接开干。

前提是你的电脑已经安装了adb相关程序,如果你本身就是安卓开发者,想必肯定安装了Android Studio,那里直接就有adb相关程序。其次,你准备一台

已经root过的安卓手机(要安装的有使用过的微信应用,不然没有数据可看),不建议用小米系列等,比较root比较麻烦。这里像360手机助手就有root功能,怎么root看你自己了。


步骤一:查找到微信数据库


电脑连接手机,打开命令行,输入 adb shell 进入shell 命令


如果提示这个错误 error: unknown host service 说明你的adb还是有问题的,正确的如下图


这种基本命令跟数据为什么在data下就不解释了,这样就进入了data/data目录下


当你再操作时会发现如下错误


这个意思是你当前没有权限,这时我们来获取超级权限,输入su  root


然后输入ls,就会查出所有的文件,根据包名找到微信,微信的包名大家都知道,是 com.tencent.mm



这时我们就看到了微信的一些文件,有兴趣的可以去看看其他文件里的东西,这里我们需要打开第一个文件,叫MicroMsg。打开它



这里像这样很长一串的MD5加密后的字符串就是你这里使用的微信用户的相关微信数据了,我这里之所以两个,是因为我用过两个用户登录了微信,微信分别存储了下来


再次打开这个文件,我们就可以看到很多以db结尾的数据库了

这里我们需要用到EnMicroMsg.db这个数据库,先拷贝一份出来到sdcard

此时在手机里就能看到这个EnMicroMsg.db文件了,移动到桌面来,到这里我们的第一步就已经完成了。是不是很简单。




步骤二:使用sqlcipher打开EnMicroMsg.db文件

先运行sqlcipher,点击File 一> OpenDatabase 一> 选择桌面的那个EnMicroMsg.db文件,这时会出现这样一个对话框

这里是要求我们输入密码,因为微信本地数据库是加密的,那么密码是什么呢,规则很简单

具体如下:

(手机IMEI + 微信uin )取MD5的前7位

手机的IMEI获取:手机拨号盘输入:*#06#  ,你或者用android代码获取可以,怎么都行

微信uin的获取,我是通过网页版微信,我用的是win10的那个Edge浏览器,打开F12开发人员工具,选择网络,然后随便操作或者聊天,就可以看到了




然后百度打开在线md5加密:输入IMEI+wxuin,进行加密,选择32位小写的前七个字符串即可;



然后将这七位字符串输入到sqlcipher中,就顺利的打开了


接下来就可以愉快的查看表结构了,还可以选择Browse Data查看数据,也可以选择Execute SQL执行sql语句了。


到这里就已经彻底打开了微信手机本地的数据库了,其它几个数据库,我也用同样的方式打开了,你们也可以试试,仅供大家学习参考使用,其他用途后果自负。


本人个人原创,如有雷同,纯属巧合,或者与本人联系,做改动。请转载或者CV组合标明出处,谢谢!(如有疑问或错误欢迎指出,本人QQ:752231513)


2017-09-16 15:27:48 luohe1234 阅读数 708
  • Unity仿微信开发

    使用Unity仿微信开发IM即时通讯软件,探索IM开发技术、数据库设计、通用网络模块、音视频通讯等。 功能介绍: 1.支持Unity编辑器、PC、Mac、Android、IOS、UWP平台 2.实现文字、表情、图片、视频、语音、文件发送 3.实现好友、群组功能 4.本地消息存储、离线消息处理 5.实现好友、群组音视频通话

    57 人正在学习 去看看 谷世杰

        这是第一次在博客上写东西,所以在内容上、格式上或者重点上可能把握不好,但主要的目的就是把自己遇到的问题分享出来,还有就是把问题记录下来,毕竟年纪大了,记忆力也会逐渐衰退的嘛!方便以后自己来总结!

        今天要说的问题就是自己最近对微信网页开发中遇到的问题,关于微信公众号中网页数据库连接的问题。首先就是先说一下微信中或者微信公众号中数据的处理过程,用户登录微信客户端发送数据,腾讯服务器接受微信客户端发送的数据进行逻辑处理,之后把处理的结果在返回给客户端,这其实就是微信的一个数据处理过程了,也就是相当于微信公众号给你回复了消息。所以在进行微信公众号等开发过程中,要使用自己搭建的第三方服务器,第三方服务器的作用就是对数据进行业务处理,其实就是把腾讯的逻辑处理拿到了我们第三方服务器上。

        那么在网页中遇到用户信息或者一些数据要存储在数据库中的话,就要进行数据库的连接,php中数据库连接的方法是

$scon=mysql_connect("localhost","root","");
mysql_select_db("数据库名");
mysql_query("set character set utf8");
mysql_query("set names utf8");
以前连接数据库的时候,你的程序在你的pc端,但你的数据库是在你的服务器上的,那么你连接数据库的地址就是你的服务器的地址了,那这个却不一样了,因为你的程序就是在你的服务器上,那你连接服务器上的数据库的时候就是类似于访问本机的数据库了,所以使用的就是localhost了。这是连接数据库的时候要注意的地方了。

2016-11-15 11:38:46 qq_24091555 阅读数 20093
  • Unity仿微信开发

    使用Unity仿微信开发IM即时通讯软件,探索IM开发技术、数据库设计、通用网络模块、音视频通讯等。 功能介绍: 1.支持Unity编辑器、PC、Mac、Android、IOS、UWP平台 2.实现文字、表情、图片、视频、语音、文件发送 3.实现好友、群组功能 4.本地消息存储、离线消息处理 5.实现好友、群组音视频通话

    57 人正在学习 去看看 谷世杰

           由于项目需要,需要接触微信开发,并要调用微信的JS-SDK里面的接口。

       因为经验缺乏,我百度一下关于微信开发的资料,但收集的资料都不尽人意。网上的主流的微信开发是采用PHP开发的,而本人学的Java。所以对PHP微信开发只能看懂思路。更有的是,网上一些微信开发视频,也是和PHP有关的,关于用Java开发的甚少。

       无奈之下,我只好苦啃微信开发文档。大家都知道,微信官方给的开发文档真的有点那个啥,一个功能实现非要分几个地方来说,看完这块,又得点击另一个页面看完另一块,甚是麻烦。这样的设定也让我走了好多坑。

但功夫不负有心,在研究透了微信开发文档之后,我顺利在在项目中完成微信开发。现在我将微信开发的经验分享一下,希望对大家有所帮助。

       微信JS-SDK是微信公众号平台面向网页开发这提供基于微信内的网页开发工具包。接口大类分为:基础接口、分享接口、图像接口、音频接口、智能接口、设备信息、地址位置、摇一摇周边、界面操作、微信扫一扫、微信小店、微信卡劵和微信支付。一般使用频率高的就是分享接口、地理微信、微信扫一扫和微信支付。

接下来,我将主要讲解如何调用微信分享接口。

第一步,准备内网映射工具,ngrok。不清楚这个的同学可以去百度一下。https://ngrok.com为ngrok官网。要进行微信开发,内网映射工具是不可少。毕竟,我们程序员进行开发,要测试开发的产品是否能用,都先在自己的电脑跑一下。但由于ngrok的服务器在外国的,鉴于天朝的墙太高,访问可能不稳定。所以我推荐的是国内的natapp,免费和收费的都有,服务毕竟稳定可靠,只不过要想自定义二级域名就得交费成为VIP咯。

第二步,配置JS接口安全域名。登录要进行开发的公众号,点击公众设置--->功能设置。设置JS接口安全域名,要注意三点:①填写域名前面不需加上http://,例如你的域名是http://test.com,直接填写test.com即可;②域名默认80端口,只支持80和443端口,所以域名后面不能添加端口号。③该域名为你调用微信JS-SDK接口域名。

第三步,引用JS文件。在需要调用JS接口的页面引入http://res.wx.qq.com/open/js/jweixin-1.0.0.js 。


第四步,通过config接口注入权限验证配置 。具体参数有什么用处,在截图都有注释讲解。其中jsApiList为我们要使用的接口,我在下面共引用了五个接口,分别为微信好友分享、QQ好友分享、腾讯微博分享、QQ空间分享和朋友圈分享。调用的都是分享的接口。至于其他接口列表,可以去微信开发文档那浏览一下。这里就不详说。

        第五步,在服务器生成相关参数传到调用JS-SDK页面,完成授权。这是最重要的一步。如上图所示,appId,timestamp,nonceStr,signature都为必填参数。下面我将会详细说说如何生成这些参数并传回页面。

appId为开发的微信公众号的AppID(应用ID),我们可以在登录微信公众号,在开发选项中点击基本配置来查看。

timestamp为系统生成的时间戳。


nonceStr为服务器随机生成的字符串。



signature为微信JS-SDK使用权限算法。在生成signature之前,我们要拿到jsapi_ticket。官方文档是这样解释的:


我们要注意三个地方。jsapi_ticket要缓存两个小时,每过两个小时,向微信那边请求一次。获取jsapi_ticket要通过access_token。那么我们该如何获取access_token呢?


从文档可以看出,access_token需要AppID和AppSercet两个参数。而且access_token和jsapi_ticket一样,有效期皆为两小时。这就要求我们服务器要缓存access_token和jsapi_ticket,当有效期一过,就重新请求。有的人采用是用数据库来存取这两个参数,而我采用的是用Quartz定时器。关于Quartz定时器的使用,可浏览我上篇博客《SSH与Quartz集成》,里面有关于Quartz的使用方法。

AppSercet可在与APPID同一页面获取。接下来,调用接口,获取access_token。



接下来,我们用access_token去获取jsapi_ticket。


获取jsapi_ticket,就可以进行生成签名。在此之前,先看一下官方文档的签名算法。



用代码实现。


第六步,传生成的参数给网页。



第七步,调用已授权的JS接口。


第八步,利用微信Web开发者工具调试,看看是否授权成功。(微信web开发者工具可在微信开发下载)。



2017-01-12 13:20:12 hycfire 阅读数 4660
  • Unity仿微信开发

    使用Unity仿微信开发IM即时通讯软件,探索IM开发技术、数据库设计、通用网络模块、音视频通讯等。 功能介绍: 1.支持Unity编辑器、PC、Mac、Android、IOS、UWP平台 2.实现文字、表情、图片、视频、语音、文件发送 3.实现好友、群组功能 4.本地消息存储、离线消息处理 5.实现好友、群组音视频通话

    57 人正在学习 去看看 谷世杰

 特别声明:本文章只是用于技术交流,不可用于非法行为。

以前,我们或许就知道项目数据库的目录是在sdcard中 data/data目录下。确实是如此,但你只能打开模拟机中的这个文件夹。在真机中,你会发现data目录下是空的,那是因为你没有权限。本章讲的是如何获得权限,并取到数据库文件

1.首先,你要给你的手机root权限,下个KingRoot就能搞定。

2.手机连上你的开发工具,stuido和eclipse都行,打开DDMS。

3.打开DOC,定位到sdk目录下的platform-tools。有人或许对这个DOC不熟悉,你也可以在如图下的位置空白处,Shift+鼠标右键,选择——在此处打开命令窗口。

4.在DOC输入命令:

adb shell su -c "chmod 777 /data"(给予data目录操作权限,虽然我也不知道777是多大的权限)

adb shell su -c "chmod 777 /data/data"(给予data/data目录操作权限)

如果(为什么我说如果,因为有可能不成功,我会讲的,不要急)这两句命令成功执行,那么此刻你能打开data/data目录,发现有个文件夹叫:com.tencent.mm。打开它,你会发现打不开,里面是空的,骚年,不要沮丧,继续给读写权限!

adb shell su -c "chmod 777 /data/data/com.tencent.mm"

如果命令执行成功,你又能打开了,但是还是只能看看,里面有好多文件夹,却打不开。举一反三,继续给权限,

adb shell su -c "chmod 777 /data/data/com.tencent.mm/databases"

adb shell su -c "chmod 777 /data/data/com.tencent.mm/MicroMsg"

你想打开哪个给哪个命令。(目标东西在MD5加密后的字符串为名的文件夹下面,下一篇会讲到,现在你就手敲吧)

好,讲一下如果执行不成功,不成功最大的可能是adb端口被占用,输入命令查找谁是占了。命令:

netstat -ano | findstr "5037"

(这也是有时候解决手机连不上eclipse的其中解决办法)。

输入命令后你会找到是谁占了你的adb,如下图:


是720,但720又是什么鬼?打开任务管理器找找,网版网管都玩过任务管理器。


看见PID为720的是360Mobilel..那货。(有人电脑默认不显示PID,选择 查看-->选择列-->勾选PID)我的被360占了,我常用360看流量,卸载腾讯的东西。既然找到了谁占了我的ADB,那结束这个任务,360比较顽强,结束不了怎么办?卸载呗,我的电脑,我的手机我做主!

5.导出数据库文件

是不是看到这儿就觉得剩下的都不是事?那你试试在DDMS, pull a file from device 把数据库文件导出来。你能不能做到我不知道,反正我是做不到,如果有人做到麻烦告诉我一声,谢谢。(我听说,那只能导出来系统文件,导不出用户区的东西,虽然你的手机被root了,但你电脑adb没有被root啊),我被虐了千百遍,只好曲线钓妹。

6.曲线钓妹

思路是,先把文件拷贝到你可操作的sdcard区域下面,然后再用adb 把它pull到电脑。具体DOC命令

6.1进入adb 命令:

adb shell

6.2 给权限 命令

su

6.3 定位到指定位置 命令

cd /data/data/com.tencent.mm/MicroMsg/xxxxxxxx(就那个MD5加密后的字符串为名的文件夹全名)

6.3 复制文件到sdcard可操作区域 命令

cp EnMicroMsg.db /sdcard/

6.4 返回到 platform-tools,并复制数据库文件,复制命令

adb pull /sdcard/EnMicroMsg.db

请参考下图


然后你就会在 platform-tools 下面找打这个数据库文件,把它剪切到任何你想让它去的地方。

这就是曲线钓妹的思路,如果你不能直接钓到妹子,那么就把她介绍给我,我一定不会再还给你的。

还有步骤二,打开数据库,请看我的下篇博文。

欢迎加QQ群:36075538 讨论




2017-01-05 00:21:20 njweiyukun 阅读数 35388
  • Unity仿微信开发

    使用Unity仿微信开发IM即时通讯软件,探索IM开发技术、数据库设计、通用网络模块、音视频通讯等。 功能介绍: 1.支持Unity编辑器、PC、Mac、Android、IOS、UWP平台 2.实现文字、表情、图片、视频、语音、文件发送 3.实现好友、群组功能 4.本地消息存储、离线消息处理 5.实现好友、群组音视频通话

    57 人正在学习 去看看 谷世杰

最近在公司接了一个任务,需要在几百台手机上安装一个app,目的是获取微信里面的通讯录,并且定时的把他发送到我们的服务器上。当时依次尝试的如下几个方案:

  1.通过群控,将好友截图发送到服务端(python),利用python的图像识别库来获取好友的信息。

  2.开发一个app,使用android自带AccessibilityService,模拟用户操作微信,然后获取屏幕中的内容。

  3.破解微信的本地数据库。


难过非常尴尬的是前两个都失败了,否则也不会想到第三个方案了。第一个失败的原因是,利用图像识别,有些很相近的文字(i,1,l,h,n)识别成功率不高;第二个失败的原因是在于模拟用户操作的阶段无法达到预计的效果,也就导致了获取不到想要的屏幕内容。(前两个失败有可能是因为个人技术问题,无法实现)

但是重点来了:第三个我们成功了得意



我们是怎么知道微信把用户以及聊天的信息存到了本地数据库呢?

当我们打开手机的飞行模式的时候,打开微信,依旧可以看到里面的通讯录以及聊天记录。那么就说明微信肯定是将你能看到的所有信息都保存在了本地数据库里面,只是他将本地数据库加了密。既然存在了本地,我们就有办法把它取出来。


本地数据库的密码是什么呢?

请具体参考大神的文章,他通过反编译获取到微信的加密规则,特别厉害!

上述文章讲解主要是静态破解数据库,我们就基于他的静态破解方法,介绍下如何在代码中动态破解。不想看的同学们,我就直接介绍下微信本地数据库的加密规则了:

  1.获取手机IMEI码

  2.获取当前登录微信账号的uin(存储在sp里面)

  3.拼接IMEI和uin

  4.将拼接完的字符串进行md5加密

  5.截取加完密的字符串的前七位(字母必须为小写)

 那七位字符串就是数据库的密码了。因为微信已经有数亿的用户了,并且本地数据库又是存在用户的手机上,所以微信肯定不会轻易的对数据库进行大规模修改,所以密码的加密规则也是不可能变的,大家就放心用吧!大笑


适用范围:已经获取root权限的手机

如果你的手机没有root,那下面的代码对你手机都是无效的哦~

下面正式进入主题

一、大致浏览下微信的目录

1.连接上你的手机,打开开发者模式
2.打开Android Device Monitor


3.进入到File Explorer子页,查看微信目录 /data/data/com.tencent.mm


如果你发现文件夹打不开,或者发现点击/data目录里面没有内容,可能是因为没有权限,请在Command中依次执行如下命令:


大概的介绍下微信的目录结构,本地数据库都在MicroMsg文件夹里面,SharedPerferences文件都在shared_prefs文件夹里面。之前说的获取数据库密码时候需要的uin就是存在微信的SharedPreferences里面,对应的是 /data/data/com.tencent.mm/shared_prefs文件夹。


微信的本地数据库存放在 /data/data/com.tencent.mm/MicroMsg里面的一长串字符串的目录里面



注意:如果你登录过多个账号就会出现多个此类的文件夹,所以我们在之后的代码中会通过循环来查找当前登录用户对应的数据库文件


二、授予当前app管理员权限以及修改微信目录的读写权限

最好在app一启动就执行下面的代码,并且在每次获取数据库内容的时候也要再次执行,避免出现无权限读取微信相关文件的异常
public static final String WX_ROOT_PATH = "/data/data/com.tencent.mm/";
execRootCmd("chmod 777 -R " + WX_ROOT_PATH);
/**
 * 执行linux指令
 *
 * @param paramString
 */
public void execRootCmd(String paramString) {
    try {
        Process localProcess = Runtime.getRuntime().exec("su");
        Object localObject = localProcess.getOutputStream();
        DataOutputStream localDataOutputStream = new DataOutputStream((OutputStream) localObject);
        String str = String.valueOf(paramString);
        localObject = str + "\n";
        localDataOutputStream.writeBytes((String) localObject);
        localDataOutputStream.flush();
        localDataOutputStream.writeBytes("exit\n");
        localDataOutputStream.flush();
        localProcess.waitFor();
        localObject = localProcess.exitValue();
    } catch (Exception localException) {
        localException.printStackTrace();
    }
}
每次准备读取数据库之前都需要执行一次该命令。Process localProcess = Runtime.getRuntime().exec("su")先通过这个命令,使得当前app获取到root权限,然后再通过chmod命令来修改微信的data目录的读写权限,因为我们需要操作读取微信的数据库文件以及sp文件,所以必须要有微信文件的操作权限。


三、获取手机IMEI

IMEI的获取方法就很简单了
/**
 * 获取手机的imei码
 *
 * @return
 */
private void initPhoneIMEI() {
    TelephonyManager tm = (TelephonyManager) MyApplication.getContextObject().getSystemService(TELEPHONY_SERVICE);
    mPhoneIMEI = tm.getDeviceId();
}
记得添加权限
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

四、获取微信的uin

微信的uin是存储在SharedPerferences里面,所以我们要在微信目录的shared_prefs文件夹里面查找其存放的xml文件,然后去解析它。
private static final String WX_SP_UIN_PATH = WX_ROOT_PATH + "shared_prefs/auth_info_key_prefs.xml";
/**
 * 获取微信的uid
 * 微信的uid存储在SharedPreferences里面
 * 存储位置\data\data\com.tencent.mm\shared_prefs\auth_info_key_prefs.xml
 */
private void initCurrWxUin() {
    mCurrWxUin = null;
    File file = new File(WX_SP_UIN_PATH);
    try {
        FileInputStream in = new FileInputStream(file);
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(in);
        Element root = document.getRootElement();
        List<Element> elements = root.elements();
        for (Element element : elements) {
            if ("_auth_uin".equals(element.attributeValue("name"))) {
                mCurrWxUin = element.attributeValue("value");
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
        LogUtil.log("获取微信uid失败,请检查auth_info_key_prefs文件权限");
    }
}
微信的uin是存放在sharedPerferences文件夹里面的,具体路径为\data\data\com.tencent.mm\shared_prefs\auth_info_key_prefs.xml。让我们来打开这个xml文件看看里面到底是什么样子的,还有我们需要的uin到底是存放在什么地方:



我们解析xml用的dom4j这个库里面的SAXReader,如果没有这个库的同学可以去这里下载

五、生成数据库密码

/**
 * 根据imei和uin生成的md5码,获取数据库的密码(去前七位的小写字母)
 *
 * @param imei
 * @param uin
 * @return
 */
private void initDbPassword(String imei, String uin) {
    if (TextUtils.isEmpty(imei) || TextUtils.isEmpty(uin)) {
        LogUtil.log("初始化数据库密码失败:imei或uid为空");
        return;
    }
    String md5 = md5(imei + uin);
    String password = md5.substring(0, 7).toLowerCase();
    mDbPassword = password;
}
    /**
     * md5加密
     *
     * @param content
     * @return
     */
    private String md5(String content) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
            md5.update(content.getBytes("UTF-8"));
            byte[] encryption = md5.digest();//加密
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < encryption.length; i++) {
                if (Integer.toHexString(0xff & encryption[i]).length() == 1) {
                    sb.append("0").append(Integer.toHexString(0xff & encryption[i]));
                } else {
                    sb.append(Integer.toHexString(0xff & encryption[i]));
                }
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
这一步比较容易,通过拼接字符串以及md5加密后就可以获取到数据库的密码

六、查找微信目录下的数据库文件

因为我们需要通过密码来连接微信的EnMicroMsg.db文件,所以我们需要先通过匹配算法把我们需要的db文件给查找出来。如果该手机的用户切换过登录账号,那么每个账号都会生成一个EnMicroMsg.db,所以我们要把所有的db文件都给匹配出来。
public static final String WX_ROOT_PATH = "/data/data/com.tencent.mm/";
public static final String WX_ROOT_PATH = "/data/data/com.tencent.mm/";
private static final String WX_DB_DIR_PATH = WX_ROOT_PATH + "MicroMsg";
private List<File> mWxDbPathList = new ArrayList<>();
private static final String WX_DB_FILE_NAME = "EnMicroMsg.db";
File wxDataDir = new File(WX_DB_DIR_PATH);
mWxDbPathList.clear();
searchFile(wxDataDir, WX_DB_FILE_NAME);
/**
 * 递归查询微信本地数据库文件
 *
 * @param file     目录
 * @param fileName 需要查找的文件名称
 */
private void searchFile(File file, String fileName) {
    if (file.isDirectory()) {
        File[] files = file.listFiles();
        if (files != null) {
            for (File childFile : files) {
                searchFile(childFile, fileName);
            }
        }
    } else {
        if (fileName.equals(file.getName())) {
            mWxDbPathList.add(file);
        }
    }
}
通过searchFile我们会对MicroMsg这个文件夹进行遍历查询,将所有的EnMicroMsg.db文件路劲存储在mWxDbPathList中,以便于我们后期连接的时候使用

七、连接数据库

终于到了最关键的一步了。这时候需要注意两点:
  1.我们千万不可以直接通过net.sqlcipher.database.SQLiteDatabase这个类来连接我们上一步里面查找到的微信目录下的EnMicroMsg.db文件,可能是因为一个数据库文件不能被多次连接的情况,只要我们一成功连接上那个db文件,微信的客户端就会自动退出登录,并且会出现异常。所有我现在的做法是把这个db文件拷贝到我们自己的app目录下,再进行连接。
  2.当我们有多账号登录过,就会存在多个EnMicroMsg.db文件,但是我们的数据库密码只有一个,也就是说通过这个密码能连接成功的数据库就表明是当前微信登录用户的数据库。因为sqlcipher这个库中没有提供校验密码的方法,所以我们只能每次通过强行连接来判断密码是否正确,如果正确的话代码就会正常执行,错误的话就会抛出异常,因此我们要在这个方法外面加上try-catch来处理密码错误的异常。(如果有更好的方法,请留言,谢谢!)
2017-09-08更新:感谢暖气片儿L在评论中提供的方法。之前如果用户登陆过多个微信账号,那么每一个微信账号都会在各自的文件夹下生成一个EnMicroMsg.db文件,用于存储当前账号的联系人和聊天记录等信息。但是我们解析出来的密码只有一个(最后登陆的微信账号的密码),之前是通过撞库(所有db文件都尝试连接一次,直到成功为止),现在通过一个方法可以准确的定位到uin对应的EnMicroMsg.db文件,MD5("mm"+auth_info_key_prefs.xml中解析出微信的uin码) 生成的md5就是EnMicroMsg.db所处的父级文件夹的名称。

private String mCurrApkPath = "/data/data/" + MyApplication.getContextObject().getPackageName() + "/";
private static final String COPY_WX_DATA_DB = "wx_data.db";
//处理多账号登陆情况
for (int i = 0; i < mWxDbPathList.size(); i++) {
    File file = mWxDbPathList.get(i);
    String copyFilePath = mCurrApkPath + COPY_WX_DATA_DB;
    //将微信数据库拷贝出来,因为直接连接微信的db,会导致微信崩溃
    copyFile(file.getAbsolutePath(), copyFilePath);
    File copyWxDataDb = new File(copyFilePath);
    openWxDb(copyWxDataDb);
}
/**
 * 复制单个文件
 *
 * @param oldPath String 原文件路径 如:c:/fqf.txt
 * @param newPath String 复制后路径 如:f:/fqf.txt
 * @return boolean
 */
public void copyFile(String oldPath, String newPath) {
    try {
        int byteRead = 0;
        File oldFile = new File(oldPath);
        if (oldFile.exists()) { //文件存在时
            InputStream inStream = new FileInputStream(oldPath); //读入原文件
            FileOutputStream fs = new FileOutputStream(newPath);
            byte[] buffer = new byte[1444];
            while ((byteRead = inStream.read(buffer)) != -1) {
                fs.write(buffer, 0, byteRead);
            }
            inStream.close();
        }
    } catch (Exception e) {
        System.out.println("复制单个文件操作出错");
        e.printStackTrace();

    }
}
/**
 * 连接数据库
 *
 * @param dbFile
 */
private void openWxDb(File dbFile) {
    Context context = MyApplication.getContextObject();
    SQLiteDatabase.loadLibs(context);
    SQLiteDatabaseHook hook = new SQLiteDatabaseHook() {
        public void preKey(SQLiteDatabase database) {
        }

        public void postKey(SQLiteDatabase database) {
            database.rawExecSQL("PRAGMA cipher_migrate;"); //兼容2.0的数据库
        }
    };

    try {
        //打开数据库连接
        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, mDbPassword, null, hook);
        //查询所有联系人(verifyFlag!=0:公众号等类型,群里面非好友的类型为4,未知类型2)
        Cursor c1 = db.rawQuery("select * from rcontact where verifyFlag = 0 and type != 4 and type != 2 and nickname != '' limit 20, 9999", null);
        while (c1.moveToNext()) {
            String userName = c1.getString(c1.getColumnIndex("username"));
            String alias = c1.getString(c1.getColumnIndex("alias"));
            String nickName = c1.getString(c1.getColumnIndex("nickname"));
        }
        c1.close();
        db.close();
    } catch (Exception e) {
        LogUtil.log("读取数据库信息失败" + e.toString());
//            e.printStackTrace();
    }
}
通过上述的代码,先进行db文件的拷贝,然后再通过SQLCipher这个库来连接加密的数据库,之后我们就可以进行我们需要的sql查询了。上述代码中的sql查询加了一些条件,是因为做了一些业务逻辑的判断,去除了公众号、微信群这些联系人,正常测试可以直接使用“select * from rcontact”就可以了。
记得在gradle中引用库:
compile 'net.zetetic:android-database-sqlcipher:3.5.4@aar'
关于SQLCipher的详细使用方法可以参考其官网https://www.zetetic.net/sqlcipher/sqlcipher-for-android/

八、sqlcipher图形工具的使用

通过这个工具,我们可以快速的查看微信的db文件里面有哪些表,每个表里面有哪些字段,然后我们就可以在代码中写出相应的sql语句来查询我们需要的数据了
sqlcipher的下载传送门来咯~http://download.csdn.net/detail/njweiyukun/9729084
使用方法也很简单
  1.首先我们要通过Android Device Monitor里面的File Explorer将微信EnMicroMsg.db文件拷贝出来




  2.将拷贝出来的db文件用sqlcipher.exe打开并输入密码


Database Structure里面都是表结构,Browser Data里面则是表里面的数据了。
常用库介绍:【rcontact】联系人表,【message】聊天消息表

九、总结

总结一下步骤:
  1.让当前app获取su权限,以及修改微信目录的读写权限。
  2.获取手机的IMEI码。
  3.从\data\data\com.tencent.mm\shared_prefs\auth_info_key_prefs.xml中解析出微信的uin码。
  4.获取数据库密码:拼接IMEI和uin,通过md5加密后,取前7位小写的字符串。
  5.从/data/data/com.tencent.mm/MicroMsg中遍历查找所有的微信数据文件EnMicroMsg.db。
  6.将EmMicroMsg.db文件拷贝到当前app目录,然后通过SQLCipher连接数据库。

通过上述的常规代码我们已经可以在代码里面获取微信数据库的所有内容了。我们从微信的sp和db文件中也可以获取到微信当前登录的用户信息,并且我们可以启一个service,利用一些保活措施,让我们的程序不被轻易杀死,这样可以保证不停的将联系人数据库发送到服务器。也可以做一个开机启动等等等,这些代码有需要的可以自行添加,留言也可以。

如果有哪里写错和疏忽的地方,请及时提出可怜


没有更多推荐了,返回首页