安卓虚拟定位
前言
安卓虚拟定位技术已经出现很多年了,对于现在来说并不是什么新鲜技术,但是实际上我自己并没有使用过,因为暂时没有需求。然而最近需求来了,想找个现成的工具居然要我开会员,无奈只好自己学习一下相关的知识。
无Root虚拟定位
很多人(包括我自己)可能想当然的认为安卓上的虚拟定位必须依赖于Root权限,其实不然,在非Root的情况下也能实现一定程度上的虚拟定位,那就是借助开发者模式中的模拟位置功能。可以参考这篇文章。
开发者模式中提供了模拟位置的接口,能够自己开发一个用于模拟位置的app,只要在Manifest中声明权限"android.permission.ACCESS_MOCK_LOCATION"
后,即可在开发者选项-选择模拟位置信息应用
中选择这个app,具体任何模拟位置则由app中的实现决定,我暂时没有亲自试过,可以知道的是,使用这种方法能够实现百度地图的虚拟定位,但是对于其他很多主流app是无法生效的,所以其实算是比较鸡肋,因为这个功能原来就是设计给开发者使用的。
Root虚拟定位
在有Root的情况下,理论上虚拟定位能够对所有app生效。不讨论某些大厂的极端情况,一般来说,应用获取位置信息的来源有3个:
- 移动网络
- WIFI
- GPS
我们只要能够篡改这三个来源的数据就能实现虚拟定位的功能。我们需要知道的就是与这三个来源相关的所有API,并对其进行合理的篡改。参考这篇文章,我们可以知道很多相关的重要接口以及篡改思路,并且文末有个xposed插件,可以实现企业微信的虚拟定位。但是由于代码中写死了企业微信的包名,所以只能对企业微信生效,其实现在有LSPosed可以指定模块只对特定的app生效,所以已经没必要用以往的包名限定写法来写xposed插件了。这边我将其hook的对象包名改成com.tencent.mm
即微信,测试后证明了该插件经久不衰,即使时隔多年也依然能对最新版本的微信生效后,我阅读了它的源码,并参考其主要hook逻辑,实现了对应的frida版本,虽然没有100%对所有的API进行hook,但是已经能够生效。
代码如下:
var Latitude = 30
var Longitude = 120
Java.perform(()=>{
var telMng = Java.use("android.telephony.TelephonyManager")
var ArrayList = Java.use("java.util.ArrayList")
telMng.getCellLocation.implementation = function(){
console.log("getCellLocation")
return null
}
telMng.getNeighboringCellInfo.implementation = function(){
console.log("getNeighboringCellInfo")
return null
}
telMng.getAllCellInfo.implementation = function(){
console.log("getAllCellInfo")
return null
}
telMng.getPhoneCount.implementation = function(){
console.log("getPhoneCount")
return 1
}
var phoneStateListener = Java.use("android.telephony.PhoneStateListener")
phoneStateListener.onCellLocationChanged.implementation = function(){
console.log("onCellLocationChanged")
}
// phoneStateListener.onCellInfoChanged.implementation = function(){
// console.log("onCellInfoChanged")
// return this.onCellInfoChanged.apply(this,arguments)
// }
var WifiManager = Java.use("android.net.wifi.WifiManager")
WifiManager.getScanResults.implementation = function(){
console.log("getScanResults")
return ArrayList.$new()
}
WifiManager.getWifiState.implementation = function(){
console.log("getWifiState")
return 1
}
WifiManager.isWifiEnabled.implementation = function(){
console.log("isWifiEnabled")
return true
}
var WifiInfo = Java.use("android.net.wifi.WifiInfo")
WifiInfo.getMacAddress.implementation = function(){
console.log("getMacAddress")
return "00-00-00-00-00-00-00-00"
}
WifiInfo.getSSID.implementation = function(){
console.log("getSSID")
return null
}
WifiInfo.getBSSID.implementation = function(){
console.log("getBSSID")
return "00-00-00-00-00-00-00-00"
}
var NetworkInfo = Java.use("android.net.NetworkInfo")
NetworkInfo.getTypeName.implementation = function(){
console.log("getTypeName")
return "WIFI"
}
NetworkInfo.isConnectedOrConnecting.implementation = function(){
console.log("isConnectedOrConnecting")
return true
}
NetworkInfo.isConnected.implementation = function(){
console.log("isConnected")
return true
}
NetworkInfo.isAvailable.implementation = function(){
console.log("isAvailable")
return true
}
var CellInfo = Java.use("android.telephony.CellInfo")
CellInfo.isRegistered.implementation = function(){
console.log("isRegistered")
return true
}
var LocationManager = Java.use("android.location.LocationManager")
var Location = Java.use("android.location.Location")
LocationManager.getLastLocation.implementation = function(){
console.log("getLastLocation")
var location = Location.$new(LocationManager.GPS_PROVIDER.value)
location.setLatitude(Latitude)
location.setLongitude(Longitude)
location.setAccuracy(100)
location.setTime(new Date().getTime())
return location
}
LocationManager.getLastKnownLocation.implementation = function(){
console.log("getLastKnownLocation")
var location = Location.$new(LocationManager.GPS_PROVIDER.value)
location.setLatitude(Latitude)
location.setLongitude(Longitude)
location.setAccuracy(100)
location.setTime(new Date().getTime())
return location
}
LocationManager.getProviders.overload('boolean').implementation = function(){
console.log("getProviders1")
var array = ArrayList.$new()
array.add("gps")
return array
}
LocationManager.getProviders.overload('android.location.Criteria', 'boolean').implementation = function(){
console.log("getProviders2")
var array = ArrayList.$new()
array.add("gps")
return array
}
LocationManager.getBestProvider.implementation = function(){
console.log("getBestProvider")
return "gps"
}
LocationManager.addGpsStatusListener.implementation = function(args){
console.log("addGpsStatusListener")
var ret = this.addGpsStatusListener(args)
if(args != null){
args.onGpsStatusChanged(1)
args.onGpsStatusChanged(3)
}
return ret
}
LocationManager.addNmeaListener.overload('android.location.GpsStatus$NmeaListener').implementation = function(){
console.log("addNmeaListener")
return false
}
// LocationManager.getGpsStatus.implementation = function(){
// console.log("getGpsStatus")
// }
})
相关文章
- LibreOffice 7.5 发布:漂亮的新应用图标和酷炫功能
- elementary OS 7 发布
- Windows 应用兼容层 Wine 8.1 发布:默认启用“Windows 10”前缀
- 微软正测试新功能:当 Windows 11 有新的小组件可用时会提醒通知
- 解析分布式存储选型和应用九个典型问题
- ClickHouse在自助行为分析场景的实践应用
- Chrome DevTools 远程调试安卓网页的原理
- Uni-app + Vue3 页面如何跳转及传参?
- 微软证实系统还原点会损坏 Windows 11 22H2 版本应用程序
- 巧用 Transition 实现短视频 APP 点赞动画
- 初学者试试,HarmonyOS应用开发者基础认证
- 媒体实测微软 Windows 开发工具包 2023:存在不兼容 HDR 显示器、某些应用无法运行等问题
- 快速了解Navigator API SetAppBadge
- 微软 Windows 11 Dev 预览版 Build 25276 发布,应用兼容问题对话框 UI 改进
- 基于Next.js、Prisma、Postgres和Fastfy构建全栈APP
- 开始菜单搜索框变圆角,微软 Windows 11 Beta 预览版 22621.1095 和 22623.1095 发布
- 2022-2023 十大应用开发趋势
- 观远数据发布业内首部《移动BI白皮书》,深入业务数字化场景重新定义移动BI
- Windows 10 学院:不借助第三方工具如何卸载 Windows 10 预装应用
- 正处高质量发展期,我国大数据产业突破1.3万亿元