起因是因为需要做模拟定位的功能,最终是过金融类app的定位 ,root、框架分分钟被砍死
迫于无奈,直接从操作系统入手,反正hook也不过是hook那几个系统里的类,直接改系统的类和函数应该一样的效果吧
在android6.0下已经过三大地图、过短视频平台
在android7.0下目前只过了自己的测试app,也能扰乱三大地图的精准定位,但是不能像6.0一样模拟自己的位置信息
所以感觉是7.0对比6.0 谷歌开放了一些获取gps底层数据的地方 如若有知道的 还望赐教
先总体说一下都改了什么吧,筛选wifi列表(除了白名单的app,其他一律返回null),自定义上次连接的wifi网卡地址,WIFI模拟成流量、禁止返回wifi任何信息、wifi配置信息返回null、GSM基站信息写入、CDMA基站信息写入、GPS修改、有效卫星修改
一共改了这些地方,
众所周知目前依靠wifi和你附近wifi列表就可以给你精准定位了,比如我在未做修改的时候,wifi列表有附近周围的wifi,导航就直接精准定位我在哪栋楼了,而我屏蔽周围wifi以后,导航只能定位到小区门口去了
所以从framework层禁止向app返回相关wifi信息是必须要做得,然后就是其他相关类进行反编译和修改 然后push到手机就可以了
说些准备工作,首先你要知道android系统在5.0起就用了art来把代码提前优化,所以需要在system/framework下 找到对应手机架构的oat文件,查看手机架构的命令是shell 下 getprop ro.product.cpu.abi
如果你手机是arm64架构 就去arm64文件夹下找oat文件,如果是arm就去arm下把oat文件找到
在android6.0下, 这个文件是boot.oat,在这里文件里就可以提取出所有安卓的系统代码(java层的)也就是framework层
在android7.0下,不同的包被拆分成不同的oat文件,所以在这个文件夹下会有许多的oat文件,
这里是EMUI系统的oat文件, 我们只需要解包这些oat就可以,目录下的art文件我们用不到
用oat2dex.jar工具来解包这些oat文件 java -jar oat2dex.jar -h
解包后就拿到了包含源代码的dex文件,dex直接拖进jadx-gui就看到了友商的系统源码,当然只是framework层
修改java代码自然是用smali了 smali-2.5.2和baksmali-2.5.2分别负责把dex文件输出为smali文件和回编成dex文件
但是需要注意framework-boot.oat解包后 你会发现一般这个oat下包含两个dex文件 classes.dex和classes2.dex
而其他oat下一般只包含一个,这个原因是因为一个dex文件内最多包含65535个函数,超过这个函数,就需要classes2.dex了
所以我们在添加自己的类时,需要把类放在classes2.dex里面,比如我把读取配置文件的类,写在了classes2里,这个类主要是负责读取/sdcard/下的一个文本文档,这里面写的就是各种gps坐标、虚拟wifi信息等
以修改location举例,我们知道,在framework层,获取到的经纬度坐标,最终来自于一个Location对象,这个类在classes.dex里,路径是android.location.location;
有人可能会问,你怎么知道是来自这个对象呢,比如我们知道在app代码里如果要获取一个地理位置,通常我们调用
mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
那么好,我们打开系统源码,可以看到这个location管理类调用的方法,调来调去,最终是到达了这个地方
马赛克的地方是我刚才说的读取配置文件的类,那行代码的意思就是读取配置文件36行内容,作用是验证调用这个代码的app的包名,是否是白名单,如果是白名单就返回系统原来的数据,如果不是白名单就返回自己的数据
location
=
Location
.
CREATOR
.
createFromParcel
[color=](
_reply
[color=])
;
return
location
;
从这里我们看到返回的这个location对象,实际创建于Location
[color=].
[color=]CREATOR
[color=].
[color=]createFromParcel
[color=](
[color=]_reply
[color=])
[color=];
于是我们只要在Location对象创建的时候动动手脚就可以返回给所有非白名单app一个我们改过的location对象
红色部分是系统原本创建location对象的代码部分,而在那下面,就是我们根据配置文件信息来修改系统创建的这个对象里的各种属性的值,这些属性就包含经纬度、时间戳、速度、海拔等一系列的相关内容
那么其他的地方也是同样的道理,这样改完以后,效果与hook应当是一致的
我在6.0的系统下,过导航过短视频平台都没问题
但是在7.0下,并不能很好的定位到我自己的坐标
我目前知道
在android7.0下 开放了gps原始数据的获取 通过监听OnNmeaMessageListener 最终会使得系统在GnssStatusListenerTransport类里创建原始数据的对象
包括坐标信息和卫星信息 是字符串形式的 如下
2022-03-01 16:42:59.544 7929-7942/getinfo.com.info E/GNSSmNmea2: $GPGGA,084259.50,3745.8492,N,12124.9751,E,0,,100.000,0.000,M,,M,0,*4E2022-03-01 16:42:59.544 7929-7942/getinfo.com.info E/GNSSmNmea2: $GNGSA,A,1,,,,,,,,,,,,,,,,,,,,,100.000,100.000,100.000*2F2022-03-01 16:42:59.544 7929-7942/getinfo.com.info E/GNSSmNmea2: $GPGSA,A,1,,,,,,,,,,,,,,,,,,,,,100.000,100.000,100.000*312022-03-01 16:42:59.545 7929-7942/getinfo.com.info E/GNSSmNmea2: $GLGSA,A,1,,,,,,,,,,,,,,,,,,,,,100.000,100.000,100.000*2D2022-03-01 16:42:59.545 7929-7942/getinfo.com.info E/GNSSmNmea2: $BDGSA,A,1,,,,,,,,,,,,,,,,,,,,,100.000,100.000,100.000*202022-03-01 16:42:59.545 7929-7942/getinfo.com.info E/GNSSmNmea2: $QZGSA,A,1,,,,,,,,,,,,,,,,,,,,,100.000,100.000,100.000*2D2022-03-01 16:42:59.545 7929-7942/getinfo.com.info E/GNSSmNmea2: $GPGSV,5,1,20,1,73,176,,3,9,156,,7,31,215,,8,39,70,*742022-03-01 16:42:59.545 7929-7942/getinfo.com.info E/GNSSmNmea2: $GPGSV,5,2,20,10,7,31,,11,11,243,,14,44,307,,17,21,269,*742022-03-01 16:42:59.545 7929-7942/getinfo.com.info E/GNSSmNmea2: $GPGSV,5,3,20,19,5,,,21,64,62,,27,8,79,,30,40,245,*422022-03-01 16:42:59.545 7929-7942/getinfo.com.info E/GNSSmNmea2: $GLGSV,5,4,20,67,10,68,,68,56,29,,69,46,290,,77,23,41,*5C2022-03-01 16:42:59.545 7929-7942/getinfo.com.info E/GNSSmNmea2: $GLGSV,5,5,20,78,28,99,,83,46,226,,84,42,306,,85,6,339,*60
可以看到这里包含北纬和东经的坐标信息3745.8492,N,12124.9751,E
于是我在系统创建完以后,立刻替换了坐标信息, 用自己的app来监听,取得的Nmea数据的确是修改过的
可依然不能模拟定位,剩下的只有wifi和基站信息,我目前没有插卡,那么应该不存在基站信息定位
所以只考虑有可能是单wifi被定位到小区门口
从系统直接返回虚拟信息给上层app应该是最安全的一种办法了(个人认为),因为我们不需要任何框架、不需要ROOT、不需要第三方app
最后附一段location对象里各种成员变量的含义