Android:解决关于如何使用Xposed拦截修改本机IP的问题

老样子,我们首先分析该如何获得手机的IP地址。

主要分为两种获取模式:手机流量上网,即2G/3G/4G环境下获取IP;手机使用WIFI上网时获取IP。

首先贴上博主的代码:

public static String getIPAddress(Context context) {
        NetworkInfo info = ((ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
        if (info != null && info.isConnected()) {
            if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络
                try {
                    
                    for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                        NetworkInterface intf = en.nextElement();
                        for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                            InetAddress inetAddress = enumIpAddr.nextElement();
                            if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                                return inetAddress.getHostAddress();
                            }
                        }
                    }
                } catch (SocketException e) {
                    e.printStackTrace();
                }

            } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                String ipAddress=Formatter.formatIpAddress(wifiInfo.getIpAddress());
                return ipAddress;
            }
        } else {

            //未连接网络,提示用户
            Toast.makeText(context,"无网络",Toast.LENGTH_SHORT).show();
        
        }
        return null;
    }

我们先看使用流量上网获取IP的代码,关键代码为:

 if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络
                try {
                    
                    for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                        NetworkInterface intf = en.nextElement();
                        for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                            InetAddress inetAddress = enumIpAddr.nextElement();
                            if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                                return inetAddress.getHostAddress();
                            }
                        }
                    }
                } catch (SocketException e) {
                    e.printStackTrace();
                }

            }

抛去多余的代码,直奔最关键的部位,我们发现在流量环境下是调用了InetAddress类的getHostAddress()方法获取了IP地址,所以我们需要Hook的目标类是InetAddress,目标方法为getHostAddress()。

流量模式下具体实现代码为:

XposedHelpers.findAndHookMethod(InetAddress.class, getHostAddress, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {

                //拦截到后执行的逻辑
                param.setResult("testing");
            }
        });

是不是觉得很简单,完全没有什么难点可言,只要找到目标类目标方法,进行针对拦截即可!

下面我们开始具体探索一下在WIFI模式下,该如何修改IP地址:

首先贴上WIFI模式下获取IP的关键代码:

else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();

                String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址

                return ipAddress;
            }

 /**
     * 将得到的int类型的IP转换为String类型
     *
     * @param ip
     * @return
     */
    public static String intIP2StringIP(int ip) {
        return (ip & 0xFF) + "." +
                ((ip >> 8) & 0xFF) + "." +
                ((ip >> 16) & 0xFF) + "." +
                (ip >> 24 & 0xFF);
    }

我们可以看到,首先程序获取了一个WifiManager的实例,然后调用WifiManager类的getConnectionInfo()方法获取到WifiInfo类的实例,之后调用WifiInfo类的getIpAddress()方法获取一个整形的IP,之后是一个自定义的转化格式函数,目的是把整形的IP转化成String类型。你也可以使用Formatter.formatIpAddress(wifiInfo.getIpAddress())来解析IP,这里不做具体的讲述。

通过以上的分析,我们可以看出,其中关键的代码为:wifiInfo.getIpAddress().

我们可以去看一下getIpAddress()方法的源码:

public int getIpAddress() {
        int result = 0;
        if (mIpAddress instanceof Inet4Address) {
            result = NetworkUtils.inetAddressToInt((Inet4Address)mIpAddress);
        }
        return result;
    }

从源码中我们看出,返回类型是一个整型,具体调用了NetworkUtils类的inetAddressToInt()方法。

那么问题来了,我们该怎么去拦截修改WIFI模式下的IP地址呢?

很明显的是,我们需要Hook住的目标类是WifiInfo类,目标方法是getIpAddress()方法,最主要的难点是拦截到该方法后,如何返回我们自己的结果?毕竟需要返回的是一个32位的整型IP地址,用户是一点都看不懂,包括博主本人也不是很懂,所以我们不能指望用户输入一个32位的整型IP去修改掉IP,只能让他们输入新的IP地址去修改。

解决办法:拦截到方法之后,进行IP格式转换,把新的IP地址(String型)转成一个整型IP,然后返回这个整型IP即可!

下面我们就具体的去尝试一下:

首先是Hook方法,具体的代码为:

XposedHelpers.findAndHookMethod(android.net.wifi.WifiInfo.class, methodName, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {

                //原先的整型IP
                XposedBridge.log("整形IP:"+param.getResult());

                //这里进行字符串分割,博主这里测试的新IP地址为“192.99.28.10”
                String []str ="192.99.28.10".split("\\.");

                //定义一个字符串,用来储存反转后的IP地址
                String ipAdress="";
                
                //for循环控制IP地址反转
                for (int i=3;i>=0;i--){
                    ipAdress=ipAdress+str[i]+".";
                }

                //去掉最后一位的“.”
                ipAdress=ipAdress.substring(0,ipAdress.length()-1);

                //返回新的整型Ip地址
                param.setResult((int)ipToLong(ipAdress));
            }
        });

具体的转化方法ipToLong()方法,代码如下:

public static long ipToLong(String strIp){
        long[] ip = new long[4];
        //先找到IP地址字符串中.的位置
        int position1 = strIp.indexOf(".");
        int position2 = strIp.indexOf(".", position1 + 1);
        int position3 = strIp.indexOf(".", position2 + 1);
        //将每个.之间的字符串转换成整型
        ip[0] = Long.parseLong(strIp.substring(0, position1));
        ip[1] = Long.parseLong(strIp.substring(position1+1, position2));
        ip[2] = Long.parseLong(strIp.substring(position2+1, position3));
        ip[3] = Long.parseLong(strIp.substring(position3+1));
        return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
    }

好了,相信你最大疑问就是IP地址(String)反转的问题了。

反转的意思是:把IP地址颠倒一下,例如博主这里测试的IP地址为“192.99.28.10”,反转变成“10.28.99.192”,然后把反转后的IP地址解析成整型IP。比较遗憾的是,我并不能告诉你为什么要这么做,因为我真的不知道为什么。。。。。。o(TヘTo)

博主一开始解析的都是正常顺序的IP地址,结果发现解析成整型总是错误的,后来搜了搜资料,意识到可能和顺序有关,于是测试了反转后的IP地址,发现解析结果才是正确的!

猜测:估计是解析算法中对域的解析顺序有关。如果你知道为什么要反转,请评论告知我,大家相互学习,非常感谢!

好了,这样我们完成了返回我们修改后的I整型IP,当然别的程序解析的时候,也就变成了我们设置的新IP地址!

以上两种模式下获取IP地址,我们都可以在自己的业务中进行拦截修改,怎么做就看你的了。

本文到此结束,如果引用本文请标明出处!

猜你喜欢

转载自blog.csdn.net/qq_34149335/article/details/81135964