用Xposed框架拦截微信、人人、QQ等LBS应用的当前位置

最近在参加第八届全国大学生信息安全竞赛,成功杀入决赛。本人负责核心模块的hook,hook的实现还是用开源框架Xposed。其中的一个需求就是保护用户的敏感数据:当前位置信息。前期做了很多尝试都失败了,这里换一种角度思考,顿时眼前一亮。呵呵,不在这里扯淡了,开始进入正题。

LBS应用的定位原理

经常用微信、人人的用户会发现,这一类客户端有个比较有意思的功能,就是在你发状态的时候可以添加自己的位置,可以查找“附近的人”,而且定位得相对比较准确。即使不开启手机的GPS服务,它可以定位,用WiFi它仍然可以定位,用运营商的移动网络它依然可以定位,这个功能是不是很强大?

其实,像微信这一类应用的“找朋友”功能的实现上借助的是“基于位置的服务”(Location Based Service,LBS),它是通过电信移动运营商的无线电通讯网络(如GSM网、CDMA网、WIFI热点)或外部定位方式(如GPS)获取到用户实时所在的地理位置(地理坐标),在GIS(Geographic Information System,地理音讯系统)平台的支持下,为用户提供相应服务的一种功能。

LBS是借助手机基站来实现定位。每座手机基站都有自己的独立编号,手机在开机状态下会同时接收到多座基站的信号,往常打电话时它与只其中信号最佳的一座基站建立通讯衔接,但在需求定位时就会丈量周边3个或更多的基站信号,根据三角定位法,推算出手机所处的位置。

可以把手机基站的覆盖范围想像成一个个以基站为圆心的圆,需要定位时,手机就向周边多座基站发送测量信号,并计算这些测量信号抵达基站所需要的时间,推算出手机距离基站的直线距离,再经过数学运算,手机位置坐标就可由3个基站圆的交点来确定。手机定位的准确度与基站密度、现场环境有很大联系,市区内精度范围大致在200米左右,郊区精度范围大致在1000米~2000米左右,随着技术的不时开展,基站的密度增加。在某有些场所下,手机定位的精度已能到达50米。不过,我个人还是不是很理解这种三点定位的方式,呵呵。

原理部分已经介绍完毕,下面就进入我们的正题,如何拦截你的位置,that is a question……

拦截的思路



其实思路比较简单,既然已经知道LBS定位的原理是借助手机基站来实现的。每座手机基站都有自己的独立编号,手机在开机状态下会同时接收到多座基站的信号,在定位时会就会丈量周边neighbour基站的信号,然后利用三角定位的方式,推算出手机所处的位置。所以这类应用在定位的时候,会尝试读取周围基站的信号,那么我们可以这样思考,我们可以尝试着Hook安卓操作系统中有关该基站、网络定位的部分,将其内容全部置空。然后迫使该类应用只能通过GPS来实现定位,那么,我们可以考虑向相关的GPS接口中传入一个假的经纬度的值就可以实现完美的拦截。研究一下Android操作系统中有个基站、网络、GPS定位的源码[这里推荐几个网站,一个是GrepCode,一个是AndroidXref,这两个网站提供Android操作系统各个版本的源码,很强大,为广大程序员“Read the fucking source code”提供了很大的方便,呵呵]。仔细研究一下,会发现需要拦截的东西确实不多,主要是android.net.wifi.WifiManager类的getScanResults方法、android.telephony.TelephonyManager类的getCellLocation和getNeighboringCellInfo方法、以及android.location.LocationManager类的requestLocationUpdates方法、getGpsStatus方法。

需要多说一句,开发安全方面的应用,缺少不了一款开源神器Xprivacy,这款神器可以实时查看每个应用的调用过程,甚至内部的调用函数,可以为开发者寻找解决方案提供很有价值的参考信息,减少不少阻力。下面给出核心的编码实现,主要是针对微信、人人、QQ等提供LBS服务的应用。效果就是修改自己当前的位置信息,制造一个假的地理位置信息。

编码实现



核心实现的源码如下:

package com.whu.gpshook;

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

import android.app.Activity;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.util.Log;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Iterator;

/**
 * @author Li Jiansong
 * @date:2015-7-15  上午10:39:39
 * @version :
 *
 *借助Xprivacy应用查看各个类的调用过程
 *hook com.tencent.mm
 *android.net.wifi.WifiManager的getScanResults
 *android.telephony.TelephonyManager的getCellLocation和getNeighboringCellInfo方法
 *android.location.LocationManager的requestLocationUpdates方法、getGpsStatus方法
 *
 *北京经纬度:(116.449535,39.862559)
 *
 */
public class GPSHooker implements IXposedHookLoadPackage{

    private final String TAG = "Xposed";
    private LoadPackageParam mLpp;
    private static Share share = new Share();

    public void log(String s){
        Log.d(TAG, s);
        XposedBridge.log(s);
    }

    //不带参数的方法拦截
    private void hook_method(Class<?> clazz, String methodName, Object... parameterTypesAndCallback)
    {
        try {
            XposedHelpers.findAndHookMethod(clazz, methodName, parameterTypesAndCallback);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
    }

    //不带参数的方法拦截
    private void hook_method(String className, ClassLoader classLoader, String methodName,
            Object... parameterTypesAndCallback)
    {
        try {
            XposedHelpers.findAndHookMethod(className, classLoader, methodName, parameterTypesAndCallback);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
    }

    //带参数的方法拦截
    private void hook_methods(String className, String methodName, XC_MethodHook xmh)
    {
        try {
            Class<?> clazz = Class.forName(className);

            for (Method method : clazz.getDeclaredMethods())
                if (method.getName().equals(methodName)
                        && !Modifier.isAbstract(method.getModifiers())
                        && Modifier.isPublic(method.getModifiers())) {
                    XposedBridge.hookMethod(method, xmh);
                }
        } catch (Exception e) {
            XposedBridge.log(e);
        }
    }

    @Override
    public void handleLoadPackage(LoadPackageParam lpp) throws Throwable {
        // TODO Auto-generated method stub
        mLpp = lpp;
        share.reloadX();
      HashMap<String, String> gpslist=share.getallX("gps");
      XposedBridge.log("----------gps"+gpslist.toString());
       if(gpslist.containsKey(mLpp.packageName))
                return;
        XposedBridge.log("-----------没有保护,所以获取是假地址:"+mLpp.packageName);

        hook_method("android.net.wifi.WifiManager", mLpp.classLoader, "getScanResults",
                new XC_MethodHook(){
            /**
             * Android提供了基于网络的定位服务和基于卫星的定位服务两种
             * android.net.wifi.WifiManager的getScanResults方法
             * Return the results of the latest access point scan.
             * @return the list of access points found in the most recent scan.
             */
            @Override
            protected void afterHookedMethod(MethodHookParam param)
                    throws Throwable {
                // TODO Auto-generated method stub
                //super.afterHookedMethod(param);
                param.setResult(null);//return empty ap list, force apps using gps information
            }
        });

        hook_method("android.telephony.TelephonyManager", mLpp.classLoader, "getCellLocation",
                new XC_MethodHook(){
            /**
             * android.telephony.TelephonyManager的getCellLocation方法
             * Returns the current location of the device.
             * Return null if current location is not available.
             */
            @Override
            protected void afterHookedMethod(MethodHookParam param)
                    throws Throwable {
                // TODO Auto-generated method stub
                //super.afterHookedMethod(param);
                param.setResult(null);//return empty cell id list
            }
        });

        hook_method("android.telephony.TelephonyManager", mLpp.classLoader, "getNeighboringCellInfo",
                new XC_MethodHook(){
            /**
             * android.telephony.TelephonyManager类的getNeighboringCellInfo方法
             * Returns the neighboring cell information of the device.
             */
            @Override
            protected void afterHookedMethod(MethodHookParam param)
                    throws Throwable {
                // TODO Auto-generated method stub
                //super.afterHookedMethod(param);
                param.setResult(null);//// return empty neighboring cell info list
            }
        });

        hook_methods("android.location.LocationManager", "requestLocationUpdates",
                new XC_MethodHook() {
            /**
             * android.location.LocationManager类的requestLocationUpdates方法
             * 其参数有4个:
             * String provider, long minTime, float minDistance,LocationListener listener
             * Register for location updates using the named provider, and a pending intent
             */
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

                if (param.args.length == 4 && (param.args[0] instanceof String)) {
                    //位置监听器,当位置改变时会触发onLocationChanged方法
                    LocationListener ll = (LocationListener)param.args[3];

                    Class<?> clazz = LocationListener.class;
                    Method m = null;
                    for (Method method : clazz.getDeclaredMethods()) {
                        if (method.getName().equals("onLocationChanged")) {
                            m = method;
                            break;
                        }
                    }

                    try {
                        if (m != null) {
                        //  mSettings.reload();

                            Object[] args = new Object[1];
                            Location l = new Location(LocationManager.GPS_PROVIDER);

//                          double la = Double.parseDouble(mSettings.getString("latitude", "-10001"));
//                          double lo = Double.parseDouble(mSettings.getString("longitude","-10001"));

                            double la=39.862559;//帝都的经纬度
                            double lo=116.449535;
                            l.setLatitude(la);
                            l.setLongitude(lo);

                            args[0] = l;

                            //invoke onLocationChanged directly to pass location infomation
                            m.invoke(ll, args);

                            XposedBridge.log("fake location: " + la + ", " + lo);
                        }
                    } catch (Exception e) {
                        XposedBridge.log(e);
                    }
                }
            }
        });

        hook_methods("android.location.LocationManager", "getGpsStatus",
                new XC_MethodHook(){
            /**
             * android.location.LocationManager类的getGpsStatus方法
             * 其参数只有1个:GpsStatus status
             * Retrieves information about the current status of the GPS engine.
             * This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged}
             * callback to ensure that the data is copied atomically.
             *
             */
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                GpsStatus gss = (GpsStatus)param.getResult();
                if (gss == null)
                    return;

                Class<?> clazz = GpsStatus.class;
                Method m = null;
                for (Method method : clazz.getDeclaredMethods()) {
                    if (method.getName().equals("setStatus")) {
                        if (method.getParameterTypes().length > 1) {
                            m = method;
                            break;
                        }
                    }
                }

                //access the private setStatus function of GpsStatus
                m.setAccessible(true);

                //make the apps belive GPS works fine now
                int svCount = 5;
                int[] prns = {1, 2, 3, 4, 5};
                float[] snrs = {0, 0, 0, 0, 0};
                float[] elevations = {0, 0, 0, 0, 0};
                float[] azimuths = {0, 0, 0, 0, 0};
                int ephemerisMask = 0x1f;
                int almanacMask = 0x1f;

                //5 satellites are fixed
                int usedInFixMask = 0x1f;

                try {
                    if (m != null) {
                        m.invoke(gss,svCount, prns, snrs, elevations, azimuths, ephemerisMask, almanacMask, usedInFixMask);
                        param.setResult(gss);
                    }
                } catch (Exception e) {
                    XposedBridge.log(e);
                }
            }
        });
    }

}

效果演示



本人的真实地理位置信息是在湖北武汉:

打开微信客户端,查看自己当前位置,可以发现显示的是帝都的位置:

打开人人,查找附近的人,也是在帝都:

工程源码

下载

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-15 12:53:07

用Xposed框架拦截微信、人人、QQ等LBS应用的当前位置的相关文章

用Xposed框架拦截Android操作系统的短信接收

短信接收原理 关于Android操作系统短信的接收和发送流程的文章网上有一大堆,但是真正说得很清楚的不多,这篇blog写得不错.其实要想真正弄懂Android操作系统短信的流程,还是Linus的那句话: Read the fucking source code.呵呵 在Android操作系统中,大部分敏感信息的传递过程都是基于binder机制的,当然SMS也不例外.对于SMS的接收流程的描述从Framework层和Application层这两个层面进行介绍. Framework层 当短信到达Fr

Android中Xposed框架篇-微信实现本地视频发布到朋友圈功能

微信非常庞大,还好有一些强大的工具,下面就来总结收获的知识. 一.使用adb shell dumpsys activity top命令快速定位页面 二.使用Jadx进行方法跟踪时候如果发现没有结果,可能这个方法是抽象的,需要找到这个抽象方法最原始的定义的地方继续跟踪 项目在github:https://github.com/houjingyi233/WechatUploadVideo

[转载] Android中Xposed框架篇---利用Xposed框架实现拦截系统方法

本文转载自: http://www.wjdiankong.cn/android%E4%B8%ADxposed%E6%A1%86%E6%9E%B6%E7%AF%87-%E5%88%A9%E7%94%A8xposed%E6%A1%86%E6%9E%B6%E5%AE%9E%E7%8E%B0%E6%8B%A6%E6%88%AA%E7%B3%BB%E7%BB%9F%E6%96%B9%E6%B3%95/ 一.前言 关于Xposed框架相信大家应该不陌生了,他是Android中Hook技术的一个著名的框架,还

Android中Xposed框架篇---利用Xposed框架实现拦截系统方法

一.前言 关于Xposed框架相信大家应该不陌生了,他是Android中Hook技术的一个著名的框架,还有一个框架是CydiaSubstrate,但是这个框架是收费的,而且个人觉得不怎么好用,而Xposed框架是免费的而且还是开源的,网上也有很多文章介绍了Xposed框架的原理实现,不了解的同学可以自行查阅即可,本文主要介绍如何通过这个框架来进行系统方法的拦截功能,比如我们开发过程中,对于一些测试环境很难模拟,特别是测试同学有时候像随机改变设备的imei,mcc等信息用来模拟不同测试场景,这时候

MediaRecorder实现微信、QQ、人人、易信等语音录制功能工具:MediaUtilAPI

本文介绍使用MediaRecorder进行录制音频.录制视频学习,熟悉MediaRecorder执行流程,通过简单的Demo结合解释运行效果,最后封装MediaRecorder的API工具,实现常见比如:微信.QQ.易信.人人.支付宝等录音功能模块开发,最后测试效果. 点击查看详情

[转]Android中Xposed框架篇—利用Xposed框架实现拦截系统方法

一.前言 关于Xposed框架相信大家应该不陌生了,他是Android中Hook技术的一个著名的框架,还有一个框架是CydiaSubstrate,但是这个框架是收费的,而且个人觉得不怎么好用,而Xposed框架是免费的而且还是开源的,网上也有很多文章介绍了Xposed框架的原理实现,不了解的同学可以自行查阅即可,本文主要介绍如何通过这个框架来进行系统方法的拦截功能,比如我们开发过程中,对于一些测试环境很难模拟,特别是测试同学有时候像随机改变设备的imei,mcc等信息用来模拟不同测试场景,这时候

android黑科技系列——Xposed框架实现拦截系统方法详解

一.前言 关于Xposed框架相信大家应该不陌生了,他是Android中Hook技术的一个著名的框架,还有一个框架是CydiaSubstrate,但是这个框架是收费的,而且个人觉得不怎么好用,而Xposed框架是免费的而且还是开源的,网上也有很多文章介绍了Xposed框架的原理实现,不了解的同学可以自行查阅即可,本文主要介绍如何通过这个框架来进行系统方法的拦截功能,比如我们开发过程中,对于一些测试环境很难模拟,特别是测试同学有时候像随机改变设备的imei,mcc等信息用来模拟不同测试场景,这时候

Android中Xposed框架篇---修改系统位置信息实现自身隐藏功能

一.前言 前文已经介绍了Xposed框架的基本使用规则,本文主要来介绍一个实际案例就是如何通过这个框架来修改系统的地理位置信息来实现隐藏功能,在如今社交工具的发展特别是微信,他有一个实时位置共享功能,那么对于那些不是单身狗的同学来说可能会有些蛋疼,哪天媳妇要查岗发送位置,结果你不在她期望的位置这时候就尴尬了,而且朋友圈在分享内容的时候可以选择当前位置,有的屌丝就像我一样没钱但是又想到处旅游,那么这时候咋们就可以一本正经的装个逼了. 二.定位原理 看到上面说的那么多,感觉这个功能必须要搞起来了,好

Android中Xposed框架篇---基于Xposed的一款脱壳神器ZjDroid工具原理解析

一.前言 在前文中我们介绍了如何使用Xposed框架修改地理位置信息来进行自身的隐藏功能,本文将继续介绍Xposed框架的另外一个功能就是实现应用的简单脱壳,其实说是Xposed的作用其实也不是,主要是模块编写的好就可以了,主要是利用Xposed的牛逼Hook技术实现的,下面就先来介绍一下这个脱壳模块工具ZjDroid的原理,因为他是开源的,所以咋们直接分析源码即可,源码的下载地址:https://github.com/halfkiss/ZjDroid 不过可惜的时候他只公开了Java层的代码,