當(dāng)系統(tǒng)進(jìn)程加載WebView時會報錯:UnsupportedOperationException:
如下
java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes
at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:96)
at android.webkit.WebView.getFactory(WebView.java:2194)
at android.webkit.WebView.ensureProviderCreated(WebView.java:2189)
at android.webkit.WebView.setOverScrollMode(WebView.java:2248)
at android.view.View.<init>(View.java:3588)
at android.view.View.<init>(View.java:3682)
at android.view.ViewGroup.<init>(ViewGroup.java:497)
at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:55)
at android.webkit.WebView.<init>(WebView.java:544)
at android.webkit.WebView.<init>(WebView.java:489)
at android.webkit.WebView.<init>(WebView.java:472)
at android.webkit.WebView.<init>(WebView.java:459)
at android.webkit.WebView.<init>(WebView.java:449)
通過log分析原因是:
因為安全問題钧大,WebView禁止在系統(tǒng)進(jìn)程中加載翰撑。這肯定是因為WebView眾所周知的安全漏洞,可以通過JSBridge調(diào)Android內(nèi)部函數(shù)啊央,從而引起安全問題
有興趣詳細(xì)了解這個問題可以移步這里眶诈。WebView詳解及安全問題
源碼分析:
在源碼中看下異常拋出的位置
WebViewFactory.jpg
代碼具體位置AndroidXref 注:android 8.0
通過代碼發(fā)現(xiàn)當(dāng)WebView啟動時調(diào)到這個getProvide函數(shù),然后會判斷進(jìn)程的uid瓜饥,如果是上面那幾種就掛了逝撬。
解決辦法 -- HOOK
思路-1:在使用 WebView 之前,我們先 Hook WebViewFactory乓土,創(chuàng)建 sProviderInstance 對象宪潮,從而繞過系統(tǒng)檢查。
public static void hookWebView() {
int sdkInt = Build.VERSION.SDK_INT;
try {
Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");
Field field = factoryClass.getDeclaredField("sProviderInstance");
field.setAccessible(true);
Object sProviderInstance = field.get(null);
if (sProviderInstance != null) {
log.debug("sProviderInstance isn't null");
return;
}
Method getProviderClassMethod;
if (sdkInt > 22) {
getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
} else if (sdkInt == 22) {
getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
} else {
log.info("Don't need to Hook WebView");
return;
}
getProviderClassMethod.setAccessible(true);
Class<?> providerClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);
Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");
Constructor<?> providerConstructor = providerClass.getConstructor(delegateClass);
if (providerConstructor != null) {
providerConstructor.setAccessible(true);
Constructor<?> declaredConstructor = delegateClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
sProviderInstance = providerConstructor.newInstance(declaredConstructor.newInstance());
log.debug("sProviderInstance:{}", sProviderInstance);
field.set("sProviderInstance", sProviderInstance);
}
log.debug("Hook done!");
} catch (Throwable e) {
log.error(e);
}
}
思路-2 : Hook進(jìn)程UID
從源碼中可以看出其uid的獲取方式
final int uid = android.os.Process.myUid();
所以HOOK這個函數(shù),使其返回的UID不在下面UID之列即可坎炼。
我是用Xposed HOOK的,不過應(yīng)該可以按著這個思路用其他方式HOOK拦键。
XposedBridge.hookAllMethods(Process.class, "myUid", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Throwable t = new Throwable();
StackTraceElement[] traces = t.getStackTrace();
if(traces.length < 4)
return;
StackTraceElement trace = traces[3];
if(WebViewFactoryClassName.equals(trace.getClassName()) && GetProviderMethodName.equals(trace.getMethodName())){
param.setResult(10010);
}
}
});
最后谣光, 同學(xué)點個贊吧!7椅萄金! 加個關(guān)注好么
參考文章
https://blog.csdn.net/codingnotes/article/details/79020542