package biz.bokhorst.xprivacy; import java.lang.reflect.Field; import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import android.os.Binder; import android.util.Log; public class XNetworkInterface extends XHook { private Methods mMethod; private XNetworkInterface(Methods method, String restrictionName) { super(restrictionName, method.name(), "NetworkInterface." + method.name()); mMethod = method; } public String getClassName() { return "java.net.NetworkInterface"; } // Internet: // - public static NetworkInterface getByIndex(int index) // - public static NetworkInterface getByInetAddress(InetAddress address) // - public static NetworkInterface getByName(String interfaceName) // - public static Enumeration<NetworkInterface> getNetworkInterfaces() // Network: // - public byte[] getHardwareAddress() // - public Enumeration<InetAddress> getInetAddresses() // - public List<InterfaceAddress> getInterfaceAddresses() // libcore/luni/src/main/java/java/net/NetworkInterface.java // http://developer.android.com/reference/java/net/NetworkInterface.html // @formatter:off private enum Methods { getByIndex, getByInetAddress, getByName, getNetworkInterfaces, getHardwareAddress, getInetAddresses, getInterfaceAddresses }; // @formatter:on public static List<XHook> getInstances() { List<XHook> listHook = new ArrayList<XHook>(); listHook.add(new XNetworkInterface(Methods.getByIndex, PrivacyManager.cInternet)); listHook.add(new XNetworkInterface(Methods.getByInetAddress, PrivacyManager.cInternet)); listHook.add(new XNetworkInterface(Methods.getByName, PrivacyManager.cInternet)); listHook.add(new XNetworkInterface(Methods.getNetworkInterfaces, PrivacyManager.cInternet)); listHook.add(new XNetworkInterface(Methods.getHardwareAddress, PrivacyManager.cNetwork)); listHook.add(new XNetworkInterface(Methods.getInetAddresses, PrivacyManager.cNetwork)); listHook.add(new XNetworkInterface(Methods.getInterfaceAddresses, PrivacyManager.cNetwork)); return listHook; } @Override protected void before(XParam param) throws Throwable { // Do nothing } @Override protected void after(XParam param) throws Throwable { if (getRestrictionName().equals(PrivacyManager.cInternet)) { // Internet: fake offline state if (mMethod == Methods.getByIndex || mMethod == Methods.getByInetAddress || mMethod == Methods.getByName || mMethod == Methods.getNetworkInterfaces) { if (param.getResult() != null && isRestricted(param)) param.setResult(null); } else Util.log(this, Log.WARN, "Unknown method=" + param.method.getName()); } else if (getRestrictionName().equals(PrivacyManager.cNetwork)) { // Network NetworkInterface ni = (NetworkInterface) param.thisObject; if (ni != null) if (param.getResult() != null && isRestricted(param)) if (mMethod == Methods.getHardwareAddress) { String mac = (String) PrivacyManager.getDefacedProp(Binder.getCallingUid(), "MAC"); long lMac = Long.parseLong(mac.replace(":", ""), 16); byte[] address = ByteBuffer.allocate(8).putLong(lMac).array(); param.setResult(address); } else if (mMethod == Methods.getInetAddresses) { @SuppressWarnings("unchecked") Enumeration<InetAddress> addresses = (Enumeration<InetAddress>) param.getResult(); List<InetAddress> listAddress = new ArrayList<InetAddress>(); for (InetAddress address : Collections.list(addresses)) if (address.isAnyLocalAddress() || address.isLoopbackAddress()) listAddress.add(address); else listAddress.add((InetAddress) PrivacyManager.getDefacedProp(Binder.getCallingUid(), "InetAddress")); param.setResult(Collections.enumeration(listAddress)); } else if (mMethod == Methods.getInterfaceAddresses) { @SuppressWarnings("unchecked") List<InterfaceAddress> listAddress = (List<InterfaceAddress>) param.getResult(); for (InterfaceAddress address : listAddress) { // address try { Field fieldAddress = InterfaceAddress.class.getDeclaredField("address"); fieldAddress.setAccessible(true); fieldAddress.set(address, PrivacyManager.getDefacedProp(Binder.getCallingUid(), "InetAddress")); } catch (Throwable ex) { Util.bug(this, ex); } // broadcastAddress try { Field fieldBroadcastAddress = InterfaceAddress.class .getDeclaredField("broadcastAddress"); fieldBroadcastAddress.setAccessible(true); fieldBroadcastAddress.set(address, PrivacyManager.getDefacedProp(Binder.getCallingUid(), "InetAddress")); } catch (Throwable ex) { Util.bug(this, ex); } } } else Util.log(this, Log.WARN, "Unknown method=" + param.method.getName()); } } }