Skip to content
This repository has been archived by the owner on Sep 6, 2019. It is now read-only.

Better internet access block? #132

Closed
sorgelig opened this issue Jul 3, 2013 · 43 comments
Closed

Better internet access block? #132

sorgelig opened this issue Jul 3, 2013 · 43 comments

Comments

@sorgelig
Copy link

sorgelig commented Jul 3, 2013

Hi,

Is it possible to implement internet block that way so application will think there is no active connections at all?
Currently, it looks like application can see internet connection but cannot connect due to block. Some application refuse to work this way, some give exceptions like this:


E/Cloudcell(13711): Throwable: Permission denied (missing INTERNET permission?)

E/Cloudcell(13711): java.lang.SecurityException: Permission denied (missing INTERNET permission?)

E/Cloudcell(13711): at java.net.InetAddress.lookupHostByName(InetAddress.java:418)

E/Cloudcell(13711): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)

E/Cloudcell(13711): at java.net.InetAddress.getAllByName(InetAddress.java:214)

E/Cloudcell(13711): at libcore.net.http.HttpConnection.(HttpConnection.java:70)

E/Cloudcell(13711): at libcore.net.http.HttpConnection.(HttpConnection.java:50)

E/Cloudcell(13711): at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340)

E/Cloudcell(13711): at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)

E/Cloudcell(13711): at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)

E/Cloudcell(13711): at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:316)

E/Cloudcell(13711): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:461)

E/Cloudcell(13711): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)

E/Cloudcell(13711): at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)

E/Cloudcell(13711): at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)

E/Cloudcell(13711): at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)

E/Cloudcell(13711): at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:197)

E/Cloudcell(13711): at libcore.net.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:281)

E/Cloudcell(13711): at com.firemonkeys.cloudcellapi.HttpThread.run(CC_HttpPost_Class.java:211)

E/Cloudcell(13711): Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)

E/Cloudcell(13711): at libcore.io.Posix.getaddrinfo(Native Method)

E/Cloudcell(13711): at libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:59)

E/Cloudcell(13711): at java.net.InetAddress.lookupHostByName(InetAddress.java:405)

E/Cloudcell(13711): ... 16 more

E/Cloudcell(13711): Caused by: libcore.io.ErrnoException: getaddrinfo failed: EACCES (Permission denied)

E/Cloudcell(13711): ... 19 more


this is from Real Racing 3 v1.2.0

Youtube has similar behaviour: It crashes if you block internet access for it (but starts fine if there are really no active connections). Of course, it's useless to block Youtube, but i've just accidentally discovered it.

@sorgelig
Copy link
Author

sorgelig commented Jul 3, 2013

By the way, LBE Security Master can block internet for RR3 and app won't give exception. But actually, i want to move from LBE to XPrivacy.

@unclefab
Copy link

unclefab commented Jul 3, 2013

It happened to me with other apps as well, it's because xprivacy blocks the internet access.
If it could lure the app into believing there's no internet access eventhough there is then the app would work.

@M66B
Copy link
Owner

M66B commented Jul 3, 2013

I will see what I can do.

@M66B
Copy link
Owner

M66B commented Jul 4, 2013

This will be realized in the next release.
Bonus: fake unmounted state for sdcard

@M66B M66B closed this as completed Jul 4, 2013
@sorgelig
Copy link
Author

Both RealRacing 3 and Youtube still crash upon starting if i apply internet restriction to them. Did you implement new way to restrict internet already or not yet?

@sorgelig
Copy link
Author

RealRacing 3:
E/AndroidRuntime( 9669): FATAL EXCEPTION: Thread-455

E/AndroidRuntime( 9669): java.lang.SecurityException: Permission denied (missing INTERNET permission?)

Is it possible to not remove INTERNET permission, but still intercept "inet" framework access and report disconnected/not connected status?

@M66B
Copy link
Owner

M66B commented Jul 16, 2013

XPrivacy already reports internet as offline, but some applications ignore this.

@sorgelig
Copy link
Author

But it looks like XPrivacy also revokes android.permission.INTERNET making application crash.
Is it possible still grant android.permission.INTERNET, but intercept functions (like open socket, etc..) to return errors similar when there is no connections available?

@M66B
Copy link
Owner

M66B commented Jul 16, 2013

Maybe, I will look into it.

@M66B M66B reopened this Jul 16, 2013
@sorgelig
Copy link
Author

How about intercept functions of java.net.InetAddress ?
At least RR3 crashes here:

E/AndroidRuntime( 9669): java.lang.SecurityException: Permission denied (missing INTERNET permission?)

E/AndroidRuntime( 9669): at java.net.InetAddress.lookupHostByName(InetAddress.java:418)

E/AndroidRuntime( 9669): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)

E/AndroidRuntime( 9669): at java.net.InetAddress.getAllByName(InetAddress.java:214)


I'm not sure is Youtube crash on the same function or not, but you can start from investigating Youtube crash since it's pre-installed already.

@sorgelig
Copy link
Author

Sorry, to spam the topic. Just as an idea: Probably if you intercept DNS queries and return error while resolving address then most applications should give up to connect.

@sorgelig
Copy link
Author

I'm ready to experiment by myself. I've download source code and it compiles fine. The only problem - i don't know how to trow exception to original application. InetAddress functions trigger exception if host name cannot be resolved. So, i need simulate this exception to original application.
I cannot find info about it in XProsed forums/google.. :(

@Tungstwenty
Copy link
Contributor

@M66B
Copy link
Owner

M66B commented Jul 16, 2013

@sorgelig if you want to chat (so I can help you), send me a XDA PM to exchange addresses.
@Tungstwenty thanks for helping here.

@sorgelig
Copy link
Author

Ok, it looks like working :)

  1. I've added hooks to 2 classes (see below). NetworkInterface is not used by these apps, but i think it should be hooked in case of usage by other applications. Probably, there are other functions exist for checking connections. Need to use and see. Actually, need to block functions for socket/port opening for completeness.
  2. I've removed "inet" permission from "Internet" group. I think, it should be moved to other group, because many applications with INTERNET permission will crash with this option marked. So, to simplify group marking it's better to not include "inet" into "Internet" group.

Now both RR3 and Youtube start fine and cannot see any connections! :)
With RR3 while starting i see some short activity of connection, but i think it's called from native code and cannot be blocked.

@M66B, thanks for help offering. I will contact you at XDA if i will have further thoughts/questions about XPrivacy.
My name is "sorg" on XDA if you would like to contact me.
@Tungstwenty thanks for help with Throwables.

package biz.bokhorst.xprivacy;

import java.lang.reflect.Field;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;

import de.robv.android.xposed.XC_MethodHook.MethodHookParam;

public class XInetAddress extends XHook {

    public XInetAddress(String methodName, String restrictionName, String[] permissions) {
        super(methodName, restrictionName, permissions, null);
    }

    // static InetAddress[] getAllByName(String host)
    // static InetAddress   getByAddress(byte[] ipAddress)
    // static InetAddress   getByAddress(String hostName, byte[] ipAddress)
    // static InetAddress   getByName(String host)
    // static InetAddress   getLocalHost()
    // libcore/luni/src/main/java/java/net/InetAddress.java

    @Override
    protected void before(MethodHookParam param) throws Throwable {
        if (isRestricted(param)) {
            String methodName = param.method.getName();
            if (methodName.equals("getAllByName") || 
                methodName.equals("getByAddress"))
            {
                param.setThrowable(new UnknownHostException("Unable to resolve host"));
            }
            else if (methodName.equals("getByName"))
            {
                if(param.args[0] != null)
                {
                    String name = (String)param.args[0];
                    if(name.equals("localhost"))
                    {
                        InetAddress addr = getLoopback();
                        if(addr != null)
                        {
                            param.setResult(addr);
                            return;
                        }
                    }
                }
                param.setThrowable(new UnknownHostException("Unable to resolve host"));
            }
            else if (methodName.equals("getLocalHost"))
            {
                InetAddress addr = getLoopback();
                if(addr != null)
                {
                    param.setResult(addr);
                    return;
                }
                param.setThrowable(new UnknownHostException("Unable to resolve host"));
            }
        }
    }

    InetAddress getLoopback()
    {
        try
        {
            Field f = Inet4Address.class.getDeclaredField("LOOPBACK");
            f.setAccessible(true);
            return (InetAddress) f.get(Inet4Address.class);
        }
        catch (Exception e)
        {
        }

        return null;
    }

    @Override
    protected void after(MethodHookParam param) throws Throwable 
    {
    }

}

package biz.bokhorst.xprivacy;

import de.robv.android.xposed.XC_MethodHook.MethodHookParam;

public class XNetworkInterface2 extends XHook {

    public XNetworkInterface2(String methodName, String restrictionName, String[] permissions) {
        super(methodName, restrictionName, permissions, null);
    }

    // static NetworkInterface  getByInetAddress(InetAddress address)
    // static NetworkInterface  getByName(String interfaceName)
    // static Enumeration<NetworkInterface>     getNetworkInterfaces()

    // libcore/luni/src/main/java/java/net/NetworkInterface.java

    @Override
    protected void before(MethodHookParam param) throws Throwable {
        if (isRestricted(param)) {
            String methodName = param.method.getName();
            if (methodName.equals("getByInetAddress") || 
                methodName.equals("getByName") ||
                methodName.equals("getNetworkInterfaces"))
            {
                param.setResult(null);
            }
        }
    }

    @Override
    protected void after(MethodHookParam param) throws Throwable 
    {
    }
}

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

Thanks for your code contribution.
Rest assured I will look into it, but I cannot do everything at the same time.

@sorgelig
Copy link
Author

I've found more functions to block. ConnectivityManager, for example.
I will provide you full patch later. You can concentrate on other issues for now :)

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

Why do you replace localhost by loopback?
(it requires getting a private field, which might not always be available)

Why do you hook getByInetAddress, getByName and getNetworkInterfaces?

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

InetAddress has no loopback and loopback is the same as localhost:

public static final InetAddress LOOPBACK = new Inet4Address(new byte[] { 127, 0, 0, 1 }, "localhost");

public static final InetAddress LOOPBACK = new Inet6Address(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, "localhost", 0);

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

Internet restricting will probably not work if an application uses IP addresses instead of domain names.
I will add DNS blocking as a separate method 'dns' in the category internet, since it can be useful in some situations.

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

DNS restriction will be part of the next release, thanks @sorgelig
https://github.com/M66B/XPrivacy/blob/master/src/biz/bokhorst/xprivacy/XInetAddress.java

@M66B M66B closed this as completed Jul 17, 2013
@sorgelig
Copy link
Author

"Why do you replace localhost by loopback?"

because, according to description from SDK, localhost will have 127.0.0.1 if there is no connections. If there is connection, then it may have some real IP address:
http://developer.android.com/reference/java/net/InetAddress.html#getLocalHost%28%29
Thus, some applications can use it for connection detection.

"Why do you hook getByInetAddress, getByName and getNetworkInterfaces?"
Because applications not always detect connection by "isConnected", but trying to blindly connect first.

@sorgelig
Copy link
Author

about revoking permissions:

.method public isFeintServerReachable()Z
    .locals 5

    .prologue
    const/4 v2, 0x1

    .line 1173
    const-string v3, "android.permission.ACCESS_NETWORK_STATE"

    invoke-virtual {p0}, Lcom/openfeint/internal/OpenFeintInternal;->getContext()Landroid/content/Context;

    move-result-object v4

    invoke-static {v3, v4}, Lcom/openfeint/internal/Util;->noPermission(Ljava/lang/String;Landroid/content/Context;)Z

    move-result v3

    if-eqz v3, :cond_1

    .line 1178
    :cond_0
    :goto_0
    return v2

    .line 1176
    :cond_1
    invoke-virtual {p0}, Lcom/openfeint/internal/OpenFeintInternal;->getContext()Landroid/content/Context;

    move-result-object v3

    const-string v4, "connectivity"

    invoke-virtual {v3, v4}, Landroid/content/Context;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;

    move-result-object v1

    check-cast v1, Landroid/net/ConnectivityManager;

    .line 1177
    .local v1, conMan:Landroid/net/ConnectivityManager;
    invoke-virtual {v1}, Landroid/net/ConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo;

    move-result-object v0

    .line 1178
    .local v0, activeNetwork:Landroid/net/NetworkInfo;
    if-eqz v0, :cond_2

    invoke-virtual {v0}, Landroid/net/NetworkInfo;->isConnected()Z

    move-result v3

    if-nez v3, :cond_0

    :cond_2
    const/4 v2, 0x0

    goto :goto_0
.end method

As you see, if you revoke this permission, then application automatically assume there is network connection (but hidden)..
So, it's not a good idea to revoke any NETWORK/INTERNET permissions.

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

Loopback address: I covered this in another way.
XPrivacy doesn't revoke permissions, this is the way it is done:
https://github.com/M66B/XPrivacy/blob/master/src/biz/bokhorst/xprivacy/XPackageManagerService.java#L83

@sorgelig
Copy link
Author

"Internet restricting will probably not work if an application uses IP addresses instead of domain names."
I've checked java socket functions - they require InetAddress as address. So, either by name or by IP address, application has to go through acquiring InetAddress through already blocked functions.

In your code, if there is connection then getLocalHost will return exception (because it won't equal to loopback address) - i think it's unexpected (although valid) return of this function. SDK states, it should return loopback address in case of no connection. not exception.
Although, SDK said that typically android device will return loopback even if connected.. Well.. May be don't hook this function at all. It's up to u :)

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

Thanks for your insights!

I guess you are right about getting InetAddress, although there are no public ways to create one that is not restricted.

getLocalHost is not hooked in my code.
(should it be hooked and why?)

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

I will added getByInetAddress, getByName and getNetworkInterfaces to the internet category for the next release to better hide that there is a connection.

@sorgelig
Copy link
Author

more to restrict ;)

package biz.bokhorst.xprivacy;

import de.robv.android.xposed.XC_MethodHook.MethodHookParam;

public class XConnectivityManager extends XHook {

    public XConnectivityManager(String methodName, String restrictionName, String[] permissions) {
        super(methodName, restrictionName, permissions, null);
    }

    // NetworkInfo  getActiveNetworkInfo()
    // NetworkInfo[]    getAllNetworkInfo()
    // boolean  getBackgroundDataSetting()
    // NetworkInfo  getNetworkInfo(int networkType)
    // boolean  requestRouteToHost(int networkType, int hostAddress)

    // android.net.ConnectivityManager

    @Override
    protected void before(MethodHookParam param) throws Throwable {
        if (isRestricted(param)) {
            String methodName = param.method.getName();
            if (methodName.equals("getActiveNetworkInfo") || 
                methodName.equals("getAllNetworkInfo") ||
                methodName.equals("getNetworkInfo"))
            {
                param.setResult(null);
            }
            else if (methodName.equals("getBackgroundDataSetting") ||
                    methodName.equals("requestRouteToHost"))
            {
                param.setResult(false);
            }
        }
    }

    @Override
    protected void after(MethodHookParam param) throws Throwable 
    {
    }
}

@sorgelig
Copy link
Author

It's good to block reception of ConnectivityManager.CONNECTIVITY_ACTION as well, but i don't know how.

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

Can you make a pull request for this?
(it is not that I am lazy, but it is a little bit stupid to do this again if you have already done it ;-) )
https://help.github.com/articles/using-pull-requests

Take a look how I have integrated both internet and network in the same class:
https://github.com/M66B/XPrivacy/blob/master/src/biz/bokhorst/xprivacy/XNetworkInterface.java#L43

@sorgelig
Copy link
Author

I didn't setup my repository online yet. Actually, i'm not very familiar with git.. So, forgive me ;) I will setup my repository later.

@sorgelig
Copy link
Author

i didn't understand this:

hook(new XNetworkInterface(net, PrivacyManager.cNetwork, new String[] { "ACCESS_NETWORK_STATE" }),
                    "java.net.NetworkInterface");

I don't understand the role of specifying permission. Some functions of this interface marked as required permission (in SDK), some - not. So, will this hook work for all specified functions or not? Is it mandatory to specify the permission?

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

It is very simple:

  • install git on your PC
  • create a GitHub account if you don't have one (it is free)
  • fork XPrivacy (there is a button on GitHub for that)
  • clone the forked XPrivacy local: git clone (it is right/middle on the forked page)
  • change some code ;-)
  • git commit
  • git push
  • on the forked page there is a button to do a pull request

If you use Eclipse:

  • clone the fork in another place than the current workspace project
  • close Eclipse
  • remove the project from the workspace (delete all files)
  • move the cloned project to the workspace

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

The permissions are used by the user interface.
Although not all of these functions do no need internet permission, it is specified here to make the UI consistent.
Basically the category requires internet permission. These new functions are used aid to hide connectivity.
Not specifying a permission will mean the category cannot be filtered on permission anymore.

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

"As of ICE_CREAM_SANDWICH, availability of background data depends on several combined factors, and this method will always return true."

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

I see no need to restrict requestRouteToHost to hide internet connectivity or do I miss something?

getLocalHost is not hooked in my code.
(should it be hooked and why?)

@sorgelig
Copy link
Author

Well, i know how to use git locally. I just never pushed back :)
by the way, please don't split internet access functions to different categories (like DNS and others). From regular user view, it will be to complicated. I, personally, would like to tick one mark to block all internet functions than 2 separate for DNS, Internet.
I know, about background data, but it won't be bad to explicitly tell to application about it ;)

@sorgelig
Copy link
Author

No need to hook getLocalHost. Let it go alone.
Ok, please stop to update internet blocking code.. I will fork your project, will modify and ask for pull request. Then you can review it and go further. Ok?

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

I want to have as little as possible categories, so these new functions are part of the category internet.

@M66B
Copy link
Owner

M66B commented Jul 17, 2013

Please commit all small changes you make separately to make it easier to cherry pick when needed.

@sorgelig
Copy link
Author

Ok. i will try my best

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants