package biz.bokhorst.xprivacy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import android.net.DhcpInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.os.Binder;
import android.os.Build;
public class XWifiManager extends XHook {
private Methods mMethod;
private String mClassName;
private static final String cClassName = "android.net.wifi.WifiManager";
private XWifiManager(Methods method, String restrictionName, String className) {
super(restrictionName, method.name().replace("Srv_", ""), "WiFi." + method.name());
mMethod = method;
mClassName = className;
}
public String getClassName() {
return mClassName;
}
// @formatter:off
// public List<WifiConfiguration> getConfiguredNetworks()
// public WifiInfo getConnectionInfo()
// public DhcpInfo getDhcpInfo()
// public List<ScanResult> getScanResults()
// public WifiConfiguration getWifiApConfiguration()
// frameworks/base/wifi/java/android/net/wifi/WifiManager.java
// frameworks/base/wifi/java/android/net/wifi/WifiInfo.java
// frameworks/base/core/java/android/net/DhcpInfo.java
// http://developer.android.com/reference/android/net/wifi/WifiManager.html
// public java.util.List<android.net.wifi.BatchedScanResult> getBatchedScanResults(java.lang.String callingPackage)
// public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks()
// public android.net.wifi.WifiInfo getConnectionInfo()
// public android.net.DhcpInfo getDhcpInfo()
// public java.util.List<android.net.wifi.ScanResult> getScanResults(java.lang.String callingPackage)
// public android.net.wifi.WifiConfiguration getWifiApConfiguration()
// http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/com/android/server/wifi/WifiService.java
// http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.0.0_r1/com/android/server/wifi/WifiServiceImpl.java
// @formatter:on
// @formatter:off
private enum Methods {
getConfiguredNetworks, getConnectionInfo, getDhcpInfo, getScanResults, getWifiApConfiguration,
Srv_getBatchedScanResults, Srv_getConfiguredNetworks, Srv_getConnectionInfo, Srv_getDhcpInfo, Srv_getScanResults, Srv_getWifiApConfiguration
};
// @formatter:on
public static List<XHook> getInstances(String className, boolean server) {
List<XHook> listHook = new ArrayList<XHook>();
if (!cClassName.equals(className)) {
if (className == null)
className = cClassName;
String srvClassName;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
srvClassName = "com.android.server.wifi.WifiServiceImpl";
else
srvClassName = "com.android.server.wifi.WifiService";
for (Methods wifi : Methods.values())
if (wifi.name().startsWith("Srv_")) {
if (server)
listHook.add(new XWifiManager(wifi, PrivacyManager.cNetwork, srvClassName));
} else
listHook.add(new XWifiManager(wifi, PrivacyManager.cNetwork, className));
listHook.add(new XWifiManager(Methods.getScanResults, PrivacyManager.cLocation, className));
if (server)
listHook.add(new XWifiManager(Methods.Srv_getScanResults, PrivacyManager.cLocation, srvClassName));
// This is to fake "offline", no permission required
listHook.add(new XWifiManager(Methods.getConnectionInfo, PrivacyManager.cInternet, className));
if (server)
listHook.add(new XWifiManager(Methods.Srv_getConnectionInfo, PrivacyManager.cInternet, srvClassName));
}
return listHook;
}
@Override
protected void before(XParam param) throws Throwable {
// Do nothing
}
@Override
@SuppressWarnings("rawtypes")
protected void after(XParam param) throws Throwable {
switch (mMethod) {
case Srv_getBatchedScanResults:
if (param.getResult() != null)
if (isRestricted(param))
param.setResult(new ArrayList());
break;
case getConfiguredNetworks:
case Srv_getConfiguredNetworks:
if (param.getResult() != null)
if (isRestricted(param))
param.setResult(new ArrayList<WifiConfiguration>());
break;
case getConnectionInfo:
case Srv_getConnectionInfo:
if (param.getResult() != null)
if (isRestricted(param)) {
WifiInfo result = (WifiInfo) param.getResult();
WifiInfo wInfo = WifiInfo.class.getConstructor(WifiInfo.class).newInstance(result);
if (getRestrictionName().equals(PrivacyManager.cInternet)) {
// Supplicant state
try {
Field fieldState = WifiInfo.class.getDeclaredField("mSupplicantState");
fieldState.setAccessible(true);
fieldState.set(wInfo, SupplicantState.DISCONNECTED);
} catch (Throwable ex) {
Util.bug(this, ex);
}
} else {
// BSSID
try {
Field fieldBSSID = WifiInfo.class.getDeclaredField("mBSSID");
fieldBSSID.setAccessible(true);
fieldBSSID.set(wInfo, PrivacyManager.getDefacedProp(Binder.getCallingUid(), "MAC"));
} catch (Throwable ex) {
Util.bug(this, ex);
}
// IP address
try {
Field fieldIp = WifiInfo.class.getDeclaredField("mIpAddress");
fieldIp.setAccessible(true);
fieldIp.set(wInfo, PrivacyManager.getDefacedProp(Binder.getCallingUid(), "InetAddress"));
} catch (Throwable ex) {
Util.bug(this, ex);
}
// MAC address
try {
Field fieldMAC = WifiInfo.class.getDeclaredField("mMacAddress");
fieldMAC.setAccessible(true);
fieldMAC.set(wInfo, PrivacyManager.getDefacedProp(Binder.getCallingUid(), "MAC"));
} catch (Throwable ex) {
Util.bug(this, ex);
}
// SSID
String ssid = (String) PrivacyManager.getDefacedProp(Binder.getCallingUid(), "SSID");
try {
Field fieldSSID = WifiInfo.class.getDeclaredField("mSSID");
fieldSSID.setAccessible(true);
fieldSSID.set(wInfo, ssid);
} catch (Throwable ex) {
try {
Field fieldWifiSsid = WifiInfo.class.getDeclaredField("mWifiSsid");
fieldWifiSsid.setAccessible(true);
Object mWifiSsid = fieldWifiSsid.get(wInfo);
if (mWifiSsid != null) {
// public static WifiSsid
// createFromAsciiEncoded(String
// asciiEncoded)
Method methodCreateFromAsciiEncoded = mWifiSsid.getClass().getDeclaredMethod(
"createFromAsciiEncoded", String.class);
fieldWifiSsid.set(wInfo, methodCreateFromAsciiEncoded.invoke(null, ssid));
}
} catch (Throwable exex) {
Util.bug(this, exex);
}
}
}
param.setResult(wInfo);
}
break;
case getDhcpInfo:
case Srv_getDhcpInfo:
if (param.getResult() != null)
if (isRestricted(param)) {
DhcpInfo result = (DhcpInfo) param.getResult();
DhcpInfo dInfo = DhcpInfo.class.getConstructor(DhcpInfo.class).newInstance(result);
dInfo.ipAddress = (Integer) PrivacyManager.getDefacedProp(Binder.getCallingUid(), "IPInt");
dInfo.gateway = dInfo.ipAddress;
dInfo.dns1 = dInfo.ipAddress;
dInfo.dns2 = dInfo.ipAddress;
dInfo.serverAddress = dInfo.ipAddress;
param.setResult(dInfo);
}
break;
case getScanResults:
case Srv_getScanResults:
if (param.getResult() != null)
if (isRestricted(param))
param.setResult(new ArrayList<ScanResult>());
break;
case getWifiApConfiguration:
case Srv_getWifiApConfiguration:
if (param.getResult() != null)
if (isRestricted(param))
param.setResult(null);
break;
}
}
}