正在查看: 万能钥匙 v1.1.23 应用的 Phantom.java JAVA 源代码文件
本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。
正在查看: 万能钥匙 v1.1.23 应用的 Phantom.java JAVA 源代码文件
本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。
package com.wifitutu.aab;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import com.google.android.inner_exoplayer2.metadata.id3.InternalFrame;
import com.google.gson.reflect.TypeToken;
import com.sdk.plus.data.manager.RalDataManager;
import com.wifitutu.aab.InterceptConfig;
import com.wifitutu.aab.Pine;
import com.wifitutu.aab.PineConfig;
import com.wifitutu.aab.callback.MethodHook;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class Phantom {
protected static final String EXTRA_BYPASS = "phantom_bypass_market_check";
private static int InterceptionType = 0;
private static final long REPORT_INTERVAL = 1000;
private static volatile Context appContext = null;
private static Bundle extraBundle = null;
private static volatile String lastFingerprint = "";
private static volatile long lastReportTime;
private static Context originalContext;
private static Intent pendingIntent;
private static final Object lock = new Object();
private static final Map<String, Map<String, Boolean>> reportConfigCache = new ConcurrentHashMap();
private static final Map<String, Boolean> defaultReportConfig = new HashMap<String, Boolean>() {
{
Boolean bool = Boolean.FALSE;
put("stack", bool);
put("no_block", bool);
}
};
private static final Map<Uri, String> QUICKAPP_PKG_CACHE = new ConcurrentHashMap();
public Phantom(Context context, PineConfig.ConfigProvider configProvider) {
if (context == null) {
throw new IllegalArgumentException("Context cannot be null");
}
synchronized (lock) {
try {
if (appContext == null) {
Context applicationContext = context.getApplicationContext();
if (applicationContext == null) {
throw new IllegalStateException("Cannot obtain Application Context");
}
appContext = applicationContext;
IntentHook();
configProvider.onInitialized(true);
} else {
Log.w("Phantom", "SDK already initialized");
configProvider.onInitialized(false);
}
} catch (Throwable th) {
throw th;
}
}
}
private static void IntentHook() {
try {
Class[] clsArr = {Activity.class, ContextWrapper.class, Class.forName("android.app.ContextImpl")};
for (int i = 0; i < 3; i++) {
hookMethod(clsArr[i], "startActivity", Intent.class, Bundle.class);
}
} catch (Exception e) {
LogUtil.e("Hook初始化失败", e);
}
}
private static String abbreviate(String str) {
if (str == null) {
return "null";
}
if (str.length() <= 15) {
return str;
}
return str.substring(0, 12) + "...";
}
private static String abbreviate(String str, int i) {
if (str.length() <= i) {
return str;
}
return str.substring(0, i - 3) + "...";
}
private static HashMap<String, String> buildIntentInfo(Intent intent, boolean z, String str) {
HashMap<String, String> hashMap = new HashMap<>();
if (str != null) {
hashMap.put("scene", str);
}
int i = InterceptionType;
if (i == 1) {
hashMap.put(RalDataManager.DB_TYPE, "appstore");
} else if (i == 2) {
hashMap.put(RalDataManager.DB_TYPE, "quickapp");
} else if (i == 3) {
hashMap.put(RalDataManager.DB_TYPE, "otherapp");
}
hashMap.put("intent_url", intent.toUri(4));
if (z) {
hashMap.put("stack", getStack());
}
return hashMap;
}
private static String buildMethodSignature(Method method) {
StringBuilder sb = new StringBuilder();
sb.append(method.getDeclaringClass().getSimpleName());
sb.append("#");
sb.append(method.getName());
sb.append("(");
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
if (i > 0) {
sb.append(", ");
}
sb.append(parameterTypes[i].getSimpleName());
}
sb.append(")");
return sb.toString();
}
private static Intent createDialogIntent(Context context, HashMap<String, String> hashMap) {
return new Intent(context, (Class<?>) DialogActivity.class).putExtra(DialogActivity.INTENT_MAP, hashMap).addFlags(343932928);
}
private static MethodHook createHook(final String str) {
return new MethodHook() {
@Override
public void beforeCall(Pine.CallFrame callFrame) {
String str2;
Intent intentFromArgs = Phantom.getIntentFromArgs(callFrame.args);
LogUtil.e("createHook " + str + ":" + intentFromArgs + "|fullUri=" + intentFromArgs.toUri(4));
if (intentFromArgs.getBooleanExtra(Phantom.EXTRA_BYPASS, false)) {
LogUtil.d("Phantom", "检测到绕过标记,不拦截");
return;
}
PineConfig.ConfigProvider configProvider = PineConfig.configProvider;
if (configProvider == null) {
LogUtil.e("未初始化ConfigProvider");
return;
}
String uri = intentFromArgs.toUri(4);
boolean isMarketIntent = Phantom.isMarketIntent(configProvider.getMarketPattern(), uri);
boolean isQuickAppIntent = Phantom.isQuickAppIntent(configProvider.getQuickappPattern(), uri);
boolean isOtherAppIntent = Phantom.isOtherAppIntent(configProvider.getAppPattern(), uri);
if (isMarketIntent || isQuickAppIntent || isOtherAppIntent) {
if (isMarketIntent) {
int unused = Phantom.InterceptionType = 1;
str2 = "应用商店";
} else if (isQuickAppIntent) {
int unused2 = Phantom.InterceptionType = 2;
str2 = "快应用";
} else {
int unused3 = Phantom.InterceptionType = 3;
str2 = "其他应用";
}
LogUtil.d("拦截到" + str2 + "跳转: " + intentFromArgs);
Bundle bundle = Phantom.getBundle(callFrame.args);
StringBuilder sb = new StringBuilder();
sb.append("Hit-isApp:\nURI: ");
sb.append(intentFromArgs.toUri(4));
sb.append("\nFlags: 0x");
sb.append(Integer.toHexString(intentFromArgs.getFlags()));
sb.append("\nPackage: ");
sb.append(intentFromArgs.getPackage());
sb.append("\nComponent: ");
sb.append(intentFromArgs.getComponent());
sb.append("\nExtras: ");
sb.append(bundle != null ? bundle.toString() : "null");
LogUtil.d(sb.toString());
if (Phantom.InterceptionType == 3) {
Phantom.processRuleGroups(InterceptConfig.parse(configProvider.getOtherapp(), InterceptConfig.ConfigType.OTHER_APP_CONFIG), intentFromArgs, callFrame, configProvider);
} else {
Phantom.processRuleGroups(InterceptConfig.parse(configProvider.getConfig(), InterceptConfig.ConfigType.MAIN_CONFIG), intentFromArgs, callFrame, configProvider);
}
}
}
};
}
private static String extractPackage(Intent intent) {
if (intent == null) {
return "";
}
String extractQuickAppPackage = extractQuickAppPackage(intent);
if (!extractQuickAppPackage.isEmpty()) {
return extractQuickAppPackage;
}
String extractPackageFromUri = extractPackageFromUri(intent);
return !extractPackageFromUri.isEmpty() ? extractPackageFromUri : intent.getComponent() != null ? intent.getComponent().getPackageName() : intent.getPackage() != null ? intent.getPackage() : "";
}
private static String extractPackageFromUri(Intent intent) {
Uri data;
String queryParameter;
return (intent == null || (data = intent.getData()) == null) ? "" : (!"market".equals(data.getScheme()) || (queryParameter = data.getQueryParameter("id")) == null) ? (!("https".equals(data.getScheme()) && "details".equals(data.getLastPathSegment())) && data.getQueryParameter("id") == null) ? "" : data.getQueryParameter("id") : queryParameter;
}
private static String extractQuickAppPackage(Intent intent) {
Uri data = intent.getData();
if (data == null) {
return "";
}
Map<Uri, String> map = QUICKAPP_PKG_CACHE;
String str = map.get(data);
if (str != null) {
return str;
}
List<String> pathSegments = data.getPathSegments();
String str2 = pathSegments.size() > 0 ? pathSegments.get(0) : "";
map.put(data, str2);
return str2;
}
private static String generateLightweightFingerprint(Intent intent) {
int i;
String str = "0";
String str2 = "";
if (intent == null) {
return "null|0";
}
try {
if (intent.getDataString() != null) {
str2 = intent.getDataString();
}
} catch (Exception e) {
LogUtil.e("获取DataString异常", e);
}
try {
ComponentName component = intent.getComponent();
if (component != null) {
str = String.valueOf(component.hashCode());
}
} catch (Exception e2) {
LogUtil.e("获取Component异常", e2);
}
try {
i = intent.getFlags();
} catch (Exception e3) {
LogUtil.e("获取Flags异常", e3);
i = 0;
}
return str2.hashCode() + "|" + str + "|" + i;
}
public static Intent getAndClearPendingIntent() {
Intent intent;
synchronized (lock) {
intent = pendingIntent;
pendingIntent = null;
}
return intent;
}
public static Context getAppContext() {
if (appContext == null) {
synchronized (lock) {
try {
if (appContext == null) {
throw new IllegalStateException("Must call initPhantom() first");
}
} finally {
}
}
}
return appContext;
}
public static Context getAppContextSafe() {
return appContext;
}
public static Bundle getBundle(Object[] objArr) {
for (Object obj : objArr) {
if (obj instanceof Bundle) {
return (Bundle) obj;
}
}
return null;
}
private static Context getContext(Pine.CallFrame callFrame) {
Object obj = callFrame.thisObject;
if (obj instanceof Context) {
return (Context) obj;
}
for (Object obj2 : callFrame.args) {
if (obj2 instanceof Context) {
return (Context) obj2;
}
}
return getAppContext();
}
public static synchronized Bundle getExtraBundle() {
Bundle bundle;
synchronized (Phantom.class) {
bundle = extraBundle;
}
return bundle;
}
private static String getInputValue(String str, Intent intent) {
String lowerCase = str.toLowerCase(Locale.US);
lowerCase.getClass();
switch (lowerCase) {
case "sys_version":
return String.valueOf(Build.VERSION.SDK_INT);
case "package":
return extractPackage(intent);
case "model":
String str2 = Build.MODEL;
return str2 != null ? str2 : "";
default:
return "";
}
}
private static String getInputValueApp(String str, Intent intent) {
String lowerCase = str.toLowerCase(Locale.US);
lowerCase.getClass();
switch (lowerCase) {
case "sys_version":
return String.valueOf(Build.VERSION.SDK_INT);
case "scheme":
return intent.toUri(4);
case "model":
String str2 = Build.MODEL;
return str2 != null ? str2 : "";
default:
return "";
}
}
public static Intent getIntentFromArgs(Object[] objArr) {
for (Object obj : objArr) {
if (obj instanceof Intent) {
return (Intent) obj;
}
}
return null;
}
public static synchronized Context getOriginalContext() {
Context context;
synchronized (Phantom.class) {
context = originalContext;
}
return context;
}
public static synchronized Intent getPendingIntent() {
Intent intent;
synchronized (Phantom.class) {
intent = pendingIntent;
}
return intent;
}
private static String getStack() {
StringBuilder sb = new StringBuilder();
StackTraceElement[] stackTrace = new Throwable().getStackTrace();
if (stackTrace != null) {
int i = 0;
for (StackTraceElement stackTraceElement : stackTrace) {
String className = stackTraceElement.getClassName();
if (!className.startsWith("java.") && !className.startsWith("android.") && !className.startsWith("sun.") && !className.startsWith("kotlin.") && !className.startsWith("com.wifitutu.aab")) {
sb.append(className);
sb.append(InternalFrame.ID);
sb.append(stackTraceElement.getFileName());
sb.append(InternalFrame.ID);
sb.append(stackTraceElement.getLineNumber());
sb.append(InternalFrame.ID);
sb.append(stackTraceElement.getMethodName());
sb.append("\n");
i++;
if (i >= 3) {
break;
}
}
}
}
if (sb.length() == 0) {
sb.append("No relevant stack trace found.");
}
return sb.toString();
}
private static void handleAction(int i, Intent intent, Pine.CallFrame callFrame, boolean z, boolean z2) {
if (i != 1) {
if (i == 2) {
LogUtil.w("handleAction 2: " + i);
callFrame.setResult(null);
PineConfig.configProvider.onInterception(buildIntentInfo(intent, z, "silent_block"));
return;
}
if (i != 3) {
LogUtil.w("未知动作类型: " + i);
return;
}
LogUtil.w("handleAction 3: " + i);
handleMarketJump(intent, callFrame, buildIntentInfo(intent, z, null));
return;
}
LogUtil.d("handleAction=1:\nURI: " + intent.toUri(4) + "\nFlags: 0x" + Integer.toHexString(intent.getFlags()) + "\nPackage: " + intent.getPackage() + "\nComponent: " + intent.getComponent());
if (z2) {
String generateLightweightFingerprint = generateLightweightFingerprint(intent);
long currentTimeMillis = System.currentTimeMillis();
if (!Objects.equals(generateLightweightFingerprint, lastFingerprint) || currentTimeMillis - lastReportTime > 1000) {
lastFingerprint = generateLightweightFingerprint;
lastReportTime = currentTimeMillis;
PineConfig.configProvider.onInterception(buildIntentInfo(intent, z, "no_block"));
}
}
}
private static void handleMarketJump(Intent intent, Pine.CallFrame callFrame, HashMap<String, String> hashMap) {
setPendingInfo(new Intent(intent).setFlags(intent.getFlags()), getBundle(callFrame.args), getContext(callFrame));
callFrame.args[0] = createDialogIntent(getContext(callFrame), hashMap);
}
private static void hookMethod(Class<?> cls, String str, Class<?>... clsArr) {
try {
Method declaredMethod = cls.getDeclaredMethod(str, clsArr);
String buildMethodSignature = buildMethodSignature(declaredMethod);
LogUtil.i(" 成功Hook方法: " + buildMethodSignature);
Pine.hook(declaredMethod, createHook(buildMethodSignature));
} catch (NoSuchMethodException e) {
LogUtil.i(" Hook失败: " + e);
}
}
public static boolean isMarketIntent(String str, String str2) {
if (str != null && !str.isEmpty() && str2 != null) {
try {
return Pattern.compile(str).matcher(str2).find();
} catch (PatternSyntaxException e) {
LogUtil.e("应用商店正则格式错误: " + str, e);
} catch (Exception e2) {
LogUtil.e("应用商店检测异常", e2);
}
}
return false;
}
public static boolean isOtherAppIntent(String str, String str2) {
if (str != null && !str.isEmpty() && str2 != null) {
try {
return Pattern.compile(str).matcher(str2).find();
} catch (PatternSyntaxException e) {
LogUtil.e("跳转其他app正则格式错误: " + str, e);
} catch (Exception e2) {
LogUtil.e("跳转其他app检测异常", e2);
}
}
return false;
}
public static boolean isQuickAppIntent(String str, String str2) {
if (str != null && !str.isEmpty() && str2 != null) {
try {
return Pattern.compile(str).matcher(str2).find();
} catch (PatternSyntaxException e) {
LogUtil.e("快应用正则格式错误: " + str, e);
} catch (Exception e2) {
LogUtil.e("快应用检测异常", e2);
}
}
return false;
}
private static boolean isQuickAppUri(Uri uri) {
if (uri == null) {
return false;
}
String scheme = uri.getScheme();
return "hap".equalsIgnoreCase(scheme) || "quickapp".equalsIgnoreCase(scheme);
}
private static boolean isTargetSystemPackage(Intent intent) {
return extractPackage(intent) != null;
}
private static boolean isValidThirdPartyScheme(String str) {
return (str == null || str.length() < 3 || str.contains(".")) ? false : true;
}
private static boolean matchAllRules(List<InterceptConfig.Rule> list, Intent intent) {
if (list == null || list.isEmpty()) {
return false;
}
for (InterceptConfig.Rule rule : list) {
if (!matchSingleRule(rule, intent)) {
LogUtil.d("规则组匹配失败: " + rule.getType());
return false;
}
}
LogUtil.d("规则组全部匹配成功");
return true;
}
private static boolean matchSingleRule(InterceptConfig.Rule rule, Intent intent) {
if (rule == null || rule.getRule() == null || rule.getType() == null) {
return false;
}
if (rule.getType().equals("dids")) {
HashSet<String> didArr = rule.getDidArr();
boolean z = didArr != null && didArr.contains(PineConfig.configProvider.getDid());
LogUtil.d("规则检查 => dis is matched " + z);
return z;
}
String inputValueApp = InterceptionType == 3 ? getInputValueApp(rule.getType(), intent) : getInputValue(rule.getType(), intent);
String trim = rule.getRule().trim();
try {
LogUtil.d(String.format("规则检查 => 类型:%-8s 输入:%-15s 正则:%-20s", rule.getType(), abbreviate(inputValueApp), abbreviate(trim)));
return Pattern.matches(trim, inputValueApp);
} catch (Exception unused) {
LogUtil.e("正则错误: " + trim);
return false;
}
}
private static Map<String, Boolean> parseReportConfig(String str) {
if (str == null || str.isEmpty()) {
return new HashMap(defaultReportConfig);
}
Map<String, Map<String, Boolean>> map = reportConfigCache;
if (map.containsKey(str)) {
LogUtil.d("命中report配置缓存");
return new HashMap(map.get(str));
}
try {
Map map2 = (Map) InterceptConfig.GSON_INSTANCE.fromJson(str, new TypeToken<Map<String, Boolean>>() {
}.getType());
HashMap hashMap = new HashMap(defaultReportConfig);
if (map2 != null) {
hashMap.putAll(map2);
}
map.put(str, new HashMap(hashMap));
return hashMap;
} catch (Exception e) {
LogUtil.e("解析report配置失败", e);
return new HashMap(defaultReportConfig);
}
}
public static void processRuleGroups(List<InterceptConfig.RuleGroup> list, Intent intent, Pine.CallFrame callFrame, PineConfig.ConfigProvider configProvider) {
if (list.isEmpty()) {
LogUtil.w("无有效规则组");
return;
}
Map<String, Boolean> parseReportConfig = parseReportConfig(configProvider.getReport());
boolean booleanValue = parseReportConfig.get("no_block").booleanValue();
boolean booleanValue2 = parseReportConfig.get("stack").booleanValue();
for (InterceptConfig.RuleGroup ruleGroup : list) {
if (matchAllRules(ruleGroup.getRules(), intent)) {
handleAction(ruleGroup.getAction(), intent, callFrame, booleanValue2, booleanValue);
return;
}
}
}
public static synchronized void setPendingInfo(Intent intent, Bundle bundle, Context context) {
Intent intent2;
synchronized (Phantom.class) {
if (intent != null) {
try {
intent2 = (Intent) intent.clone();
} catch (Throwable th) {
throw th;
}
} else {
intent2 = null;
}
pendingIntent = intent2;
extraBundle = bundle != null ? new Bundle(bundle) : null;
originalContext = context != null ? context.getApplicationContext() : null;
}
}
}