2017-02-15 16:49:59 qiaoxin6666 阅读数 4627

xposed框架-微信二次开发【微信群发】

基于xposed框架的微信二次开发模块,方便开发者用微信做一些扩展功能(如微信机器人微信群发、多群转播(直播)等。。。)
目前支持功能:
发文本消息
发图片消息
发语音消息
获取微信好友列表
群列表
支持群发消息
[注:本模块为开发版,是用于开发者做二次开发的,所提到的功能只是提供接口,并不是安装模块就可以使用这些功能,开发者可以使用这些接口来开发相应功能的软件,如果你不是开发者,请下载提供的示例软件测试相关功能]
更多功能更新中。。。


微信模块 http://repo.xposed.info/module/com.easy.wtool 


微信机器人demo下载地址:https://github.com/weechatfly/wtoolsdkrobot/raw/master/%E5%BE%AE%E4%BF%A1%E6%9C%BA%E5%99%A8%E4%BA%BA-wtoolsdkDemo.apk

加QQ群:153770839 讨论群 
2016-12-02 23:35:13 a472770699 阅读数 14990

1.源码

使用的方法是以咕咚为跳板,先修改咕咚的计步数据然后上传微信。

其中:

使用的手机是 小米3+miui8首先要满足xposed可以运行的条件,其次系统一定要是android6.0+,原因会在后面详细说明

里面带了一些调试输出,用于查看过程中传感器数据的变化不需要的话可以把log.e全部删掉

l sensor.getName().equals("Step Counter")会由于权限问题报错eclipse代码左侧提示小图标点一下无视就好

package com.example.testxposedhook;
import static de.robv.android.xposed.XposedHelpers.findClass;

import java.lang.reflect.Field;

import android.hardware.Sensor;
import android.util.Log;
import android.util.SparseArray;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;

public class Main implements IXposedHookLoadPackage {
	private static int stepCount = 23333;//must lower than 98800
	private static int acclCount = 1;//accelerate sensor count
	@Override
	public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
		// TODO Auto-generated method stub
		if(!lpparam.packageName.equals("com.codoon.gps")){
			return;
		}
		final Class<?> sensorEL = findClass("android.hardware.SystemSensorManager$SensorEventQueue", lpparam.classLoader);

        XposedBridge.hookAllMethods(sensorEL, "dispatchSensorEvent", new XC_MethodHook() {

            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
              //  ((float[]) param.args[1])[0] = ((float[]) param.args[1])[0] + 1168 * stepCount;
              //  stepCount++;
            	try{
            		 //先拿manager
	                Field mfield = param.thisObject.getClass().getSuperclass().getDeclaredField("mManager");
	                mfield.setAccessible(true);
	                Object mManager= mfield.get(param.thisObject);
	                //再拿mmanager下的sensor
	                Field field = param.thisObject.getClass().getEnclosingClass().getDeclaredField("mHandleToSensor");
	                field.setAccessible(true);
	                int handle = (Integer) param.args[0];
	                Sensor sensor = ((SparseArray<Sensor>) field.get(mManager)).get(handle);
	                
            		if(sensor.getName().equals("Step Counter"))//StepCounter sensor
            		{            		           			
		            	Log.e("mytest","args = " + ((float[]) param.args[1])[0]+" "+ ((float[]) param.args[1])[1]+" "+ ((float[]) param.args[1])[2]+" "+ ((float[]) param.args[1])[3]);
		                ((float[]) param.args[1])[0] = stepCount;
		                Log.e("mytest","sensor = " + sensor);
            		}
            		else{//accelerate sensor
            			if(acclCount%100>=80){
            				Log.e("mytest", "a loop end");
            				acclCount++;
            				return;
            			}
            			((float[]) param.args[1])[0] = 20;
            			((float[]) param.args[1])[1] = 10;
            			((float[]) param.args[1])[2] = 30;
            			acclCount++;
            			if(acclCount%20==0){
            				Log.e("mytest","running accelerate");
            			}
            		}
	            }
            	catch(Exception e){
            		Log.e("mytest",Log.getStackTraceString(e)); 
            	}
            }
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            	// TODO Auto-generated method stub
//            	super.afterHookedMethod(param);
            	Field mfield = param.thisObject.getClass().getSuperclass().getDeclaredField("mManager");
                mfield.setAccessible(true);
                Object mManager= mfield.get(param.thisObject);
                //再拿mmanager下的sensor
                Field field = param.thisObject.getClass().getEnclosingClass().getDeclaredField("mHandleToSensor");
                field.setAccessible(true);
                int handle = (Integer) param.args[0];
                Sensor sensor = ((SparseArray<Sensor>) field.get(mManager)).get(handle);
                if(!sensor.getName().equals("Step Counter"))
                	return;
            	Log.e("mytest", "after hook : "+((float[])param.args[1])[0]);
            }
        });

	}
}


2.过程详解

方法来源于陈浩的博客-《基于Xposed修改微信运动步数》

但发现有几个问题:

1.首先实测时小米3+miui8下微信并不能直接从手机获取计步器数据而咕咚获取的传感器数据不只是Step Counter,还有加速度传感器,因此判断咕咚是对两个传感器的数据进行了综合分析;

2.其次是android 5.X-android 6.0+的变化使得原来获取sensor数据的部分报错无法获取

其中

Field field = param.thisObject.getClass().getEnclosingClass().getDeclaredField("sHandleToSensor");  
                field.setAccessible(true);  
  
                int handle = (Integer) param.args[0];  
                Sensor sensor = ((SparseArray<Sensor>) field.get(0)).get(handle);  
                XposedBridge.log("sensor = " + sensor);  

这段代码不知道原作者有没有实测过,按照我的理解

Sensor sensor = ((SparseArray<Sensor>) field.get(0)).get(handle);

这段应该写成

Sensor sensor = ((SparseArray<Sensor>) field.get(null)).get(handle);

详细原因可以参照java.lang.reflectapi文档:Field api文档

Field.get 返回参数指定对象上此 Field表示的字段的值。如果该值是一个基本类型值,则自动将其包装在一个对象中。

因此0参数类型将为Integer,而写成null是可以的,因为在android5.X-的代码中sHandleToSensor的修饰符为final staticFiled.get在获取static型成员时可以直接使用null作为参数。

而在android6.0+的代码中SystemSensorManager有部分变动,相关代码结构变成了以下结构:

public class SystemSensorManager{
	private final String mHandleToSensor="mHandleToSensor";//只是个示例实际这里的类型是SparseArray<Sensor>
	static abstract class BasicQueue{
		private final SystemSensorManager mManager=new SystemSensorManager();
	}
	static class SensorQueue extends BasicQueue{
		public void dispatchSensorEvent(){}//这里是我们hook的地方所处的作用域
	}
}

其中相比android5.X-的代码变化主要有以下两点

l sHandleToSensor改名为mHandleToSensor

l sHandleToSensor的修饰符由private static final变为private final

名字改了好说,直接在Filed生成时改一下获取名就可以了,由于static关键字被取消导致无法再通过空对象反射的方法获取sensor就比较麻烦了,通过观察SystemSensorManager的源码可以发现可以先获取SensorQueue的父类BasicQueue中的mManager然后用这个mManager来去获取mHandleToSensor。代码如下

 

        //先拿manager
        Field mfield = param.thisObject.getClass().getSuperclass().getDeclaredField("mManager");
        mfield.setAccessible(true);
        Object mManager= mfield.get(param.thisObject);
	//再拿mmanager下的sensor
	Field field = param.thisObject.getClass().getEnclosingClass().getDeclaredField("mHandleToSensor");
	field.setAccessible(true);
	int handle = (Integer) param.args[0];
	Sensor sensor = ((SparseArray<Sensor>) field.get(mManager)).get(handle);

在修改计步器方面,最初是把所有的sensorvalues[0]全部设为一个大数

 ((float[]) param.args[1])[0] = stepCount;//stepCount=23333

但是发现在咕咚实测的时候会变为每次只加3000步就停了,又联想到咕咚使用了两种传感器,而加速度传感器在之前也是用来做计步器的(详见xbase-《一个稳定好用的android计步器源代码》)。参考这篇文章猜测是用加速度传感器的三轴数据来判断运动状态,于是模拟了一个间歇性运动的过程

if(acclCount%100>=80){
    Log.e("mytest", "a loop end");
    acclCount++;
    return;
}
((float[]) param.args[1])[0] = 20;
((float[]) param.args[1])[1] = 10;
((float[]) param.args[1])[2] = 30;
acclCount++;
if(acclCount%20==0){
     Log.e("mytest","running accelerate");
}

其中三轴的数据刚开始用的全是8发现实测无效,随便改了一组可以了就没再研究咕咚具体的算法实现,有时间可以考虑逆向一下咕咚看一下具体的算法实现。至此整个功能就实现了。

附一张结果图,大写的23333:


2018-08-08 13:45:47 StopKidding 阅读数 1512

友情提示:阅读本文需要稍微有一点点Xposed开发基础,一点点Android逆向的基础,以及一点点Kotlin基础

鸣谢:本项目基于@Gh0u1L5,开源的Xposedhook框架—-WechatSpellbook,感谢,很不错的框架,推荐一波(虽然我用的东西都是基于WechatMagician魔改得到的)。

由于之前的基于itchat开发的微信公众号采集工具使用的账号被封号了,就很郁闷。

恰巧此时我正在研究Xposed Hook 微信,所以就打算拿Android版微信来试试,需求是怎么样的呢?就是微信推送一条公众号消息,我们就接受一条,并且将其发送到对应的接口进行保存,以便于后续浏览。刚准备做的时候我还觉得没啥,直接去把微信数据库里的东西down出来就可以了嘛,太简单了好吧,然而。

naive.jpg

naive!!!

从微信数据表“message”中导出的数据是包含乱码的一堆鬼东西,而且解析出来的url也不全,比如一次推送中的五篇文章,只能取到三篇的url,这就让人感觉很难受。

image.png

但是难受归难受,问题总还是要解决的,怎么解决呢?看源码!

之前我将微信的几个dex包的代码分别反编译出来以后放到了一个文件夹下,然后使用VSCode打开,用于平时的查看,

虽然微信反编译出来的源码乱七八糟, 但是有的代码能看的。

我们看到上面导出来的数据是存在一些乱码的,那么我猜测微信内部实现了一个解码工具,如果我们能够hook到这个解码工具,是不是就可以获取到解码之后的正确数据了呢?

说到解码,根据微信以往的数据传输来看,这些数据很有可能是以XML的格式进行传输的,既然涉及到xml,那就一定是键值对的形式,我们去到的数据中除了有乱七八糟的小方块,还有诸如“.msg.appmsg.mmreader.category.item”这类看起来有用的内容。

我打开vscode,全局搜索“.msg.appmsg.mmreader.category.item”,令人高兴的是,搜索出来的结果并不多,这说明这个值确实是有意义的值,挨个查看这些源码,在一个包为:“

com.tencent.mm.plugin.biz;”下中一个名为“a”的类中,我发现了一些有意思的东西。

image.png

方法名为wS的一个方法,接收了一个String类型的值,且其内部做了一些数据取出的工作。

难道这个str参数就是我想要的标准xml吗?

经过hook验证,打印其参数后发现,并不是,参数内容的格式和之前数据库中的格式是一致的。

image.png

那么我们就将目光放在后第一行的Map上,是不是ay.WA(String str)这个方法做了解析操作呢?

我对com.tencent.mm.sdk.platformtools.ay中WA()这个方法进行了hook,取得其返回值,这个返回值是一个Map类型的数据,在打印出其内容后,我的猜想被验证了。

WA()这个方法将刚才的内容解析成了一个便于我们读取的map。其中包含了该条推送包含的图文消息数量,以及公众号的id,名称,对应的文章url,图片url,文章描述等信息。

晚餐总算可以加鸡腿了。啊哈哈哈哈。

本文章只用于研究学习,请正确食用,谢谢。

贴一下相关的hook代码

这里写图片描述

2017-02-15 17:39:00 weixin_30879169 阅读数 97

xposed模块-开发版[微信机器人】

 

基于xposed框架的微信二次开发模块,方便开发者用微信做一些扩展功能(如微信机器人微信群发、多群转播(直播)等。。。)
目前支持功能:
发文本消息
发图片消息
发语音消息(如果要发送任意mp3为微信语音,下载 (PC版)MP3与微信语音转换工具转换)
发视频消息
获取微信好友列表
群列表
支持群发消息
[注:本模块为开发版,是用于开发者做二次开发的,所提到的功能只是提供接口,并不是安装模块就可以使用这些功能,开发者可以使用这些接口来开发相应功能的软件,如果你不是开发者,请下载提供的示例软件测试相关功能]
更多功能更新中。。。

微信模块 http://repo.xposed.info/module/com.easy.wtool 


微信机器人demo下载地址:https://github.com/weechatfly/wtoolsdkrobot/raw/master/%E5%BE%AE%E4%BF%A1%E6%9C%BA%E5%99%A8%E4%BA%BA-wtoolsdkDemo.apk

转载于:https://www.cnblogs.com/qx666/p/6402458.html

2017-02-20 15:24:05 z79n7pj5 阅读数 1166

xposed源代码-微信二次开发

基于xposed框架的微信二次开发模块,方便开发者用微信做一些扩展功能(如微信机器人、微信群发、多群转播(直播)等。。。)
目前支持功能:
发文本消息
发图片消息
发语音消息
获取微信好友列表
群列表
支持群发消息
[注:本模块为开发版,是用于开发者做二次开发的,所提到的功能只是提供接口,并不是安装模块就可以使用这些功能,开发者可以使用这些接口来开发相应功能的软件,如果你不是开发者,请下载提供的示例软件测试相关功能]
更多功能更新中。。。

 

微信模块 http://repo.xposed.info/module/com.easy.wtool 


微信机器人demo下载地址:https://github.com/weechatfly/wtoolsdkrobot/raw/master/%E5%BE%AE%E4%BF%A1%E6%9C%BA%E5%99%A8%E4%BA%BA-wtoolsdkDemo.apk

 

加QQ群:153770839 讨论群 

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