前言本操作是利用 开发者位置模拟+hook app方法,来实现位置修改。一、简单尝试最近有一个需要修改位置的需求,简单进行了尝试。以“咕咚”为例,实现位置修改。由于定位都是由android.location.Location这个类提供的,查阅了一下开发文档,发现主要是getLatitude()和getLatitude() 于是借助xposed hook一下这两个方法,并在LSP里面勾选“咕咚” 此时发现,咕咚位置发生了变化,但是当我们开始跑步时,定位又消失了 也就是说还没开始的时候是通过getLatitude()和getLatitude()获取到了位置,但是开始跑之后,就不是通过这两个方法获取位置??还是什么情况?于是打印了一下堆栈 可以看到,app使用的是高德的SDK,并且是在onLocationChanged()时调用。也就是说,要我先主动触发位置改变,才会被监听到,从而修改位置。那就不能通过hook Location去修改位置了,要去主动创建线程去一直模拟位置才行。二、创建位置模拟线程去了解了一下,大概有两种方法:1、通过root权限,hook安卓HAL、JNI层的系统代码实现。2、通过系统提供的模拟位置权限实现。第一种最彻底,应该是hook hardware\qcom\gps\loc_api\libloc_api\gps.c里面的方法,类似FakeLocation。但是我也不会啊,所以决定在第二种的基础上做一些改善。第二种有现成的“影梭”,感谢ZCShou作者的开源。稍微修改一下key的配置就能直接用了。开始跑步,结果还是没有位置。而且连跑步之前的位置都变成了实际的位置。也就是说模拟的位置对app无效!!!三、过检测猜测主要是1、影梭对咕咚做了屏蔽。2、咕咚对模拟位置有检测。检查了一遍影梭的代码,发现没有什么问题,对高德地图也是生效的,那就是咕咚有模拟定位检查。查了高德和安卓的文档,里面有检查的就只有这三个方法。那直接上hook代码返回false 成功显示!!之后就可以自定义位置信息啦。此方法只能在检测不严的情况下使用,对于严格的app会检测hook就需要更深入的研究。四、更多信息海拔:海拔也是Location里面的一个属性,可以直接提供。但是app会对比气压计传的数据,所以在提供设定的altitude时,还要hook android.hardware.Sensor修改气压计的海拔步数:步数获取的方法有很多,大多数会通过SensorManager.getDefaultSensor(int type)来获取的,type主要有两个,分别是TYPE_STEP_DETECTOR和TYPE_STEP_COUNTER。而跑步软件则大多是用加速度传感器来实现,通过hook dispatchSensorEvent实现,float[] values里的值分别是xyz的加速度,修改对应值,模拟运动时的加速度就可以了。  |