add lsposed

Signed-off-by: 孙志刚 <zhgsun@foxmail.com>
This commit is contained in:
孙志刚 2025-02-16 01:54:53 +08:00 committed by 孙志刚
parent 77579d2b5f
commit 4a913d0d95
7 changed files with 579 additions and 2 deletions

View File

@ -59,4 +59,6 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
compileOnly("de.robv.android.xposed:api:82")
compileOnly("de.robv.android.xposed:api:82:sources")
}

View File

@ -39,6 +39,17 @@
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config" />
</service>
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="xposeddescription" />
<meta-data
android:name="xposedminversion"
android:value="89" />
<meta-data
android:name="xposedscope"
android:resource="@array/scope" />
</application>
</manifest>

View File

@ -0,0 +1 @@
io.sixminutes.ridicule.hook

View File

@ -0,0 +1,556 @@
package io.sixminutes.ridicule;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
import de.robv.android.xposed.IXposedHookZygoteInit;
public class hook implements IXposedHookZygoteInit, IXposedHookLoadPackage{
private static final int screen_height = 2340;
private static final int screen_width = 2340;
private static final String device_model = "A001XM";
private static final String manufacturer = "Xiaomi";
private static final String os_version = "11";
private static final Integer SDK_INT = 30;
private static final String device_id = "1ac1af0be39f7991";
private static final String country_code = "JP";
private static final String carrier = "SoftBank";
private static final String CUSTOM_ADVERTISING_ID = "48442068-7132-4bd3-9349-707695891ce8";
public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
try {
XposedHelpers.setStaticObjectField(Build.class,"MODEL",device_model);
XposedHelpers.setStaticObjectField(Build.class,"MANUFACTURER",manufacturer);
XposedHelpers.setStaticObjectField(Build.class,"BRAND",manufacturer);
XposedHelpers.setStaticObjectField(Build.VERSION.class,"RELEASE",os_version);
XposedHelpers.setStaticIntField(Build.VERSION.class,"SDK_INT",SDK_INT);
// 修改Device ID
XposedHelpers.findAndHookMethod(
"android.telephony.TelephonyManager", lpparam.classLoader,
"getDeviceId",
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// 修改 getDeviceId 方法的返回值
param.setResult(device_id);
}
});
// 修改广告ID
XposedHelpers.findAndHookMethod(
"com.google.android.gms.ads.identifier.AdvertisingIdClient$Info",
lpparam.classLoader,
"getId",
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
// 返回伪造的广告ID
param.setResult(CUSTOM_ADVERTISING_ID);
}
}
);
XposedHelpers.findAndHookMethod(
"com.google.android.gms.ads.identifier.AdvertisingIdClient",
lpparam.classLoader,
"getAdvertisingIdInfo",
Context.class,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
try {
Object info = param.getResult();
if (info == null) return;
XposedHelpers.findAndHookMethod(
info.getClass(),
"getId",
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
param.setResult(CUSTOM_ADVERTISING_ID);
}
}
);
} catch (Throwable e) {
XposedBridge.log("Error in hooking getAdvertisingIdInfo: " + e);
}
}
}
);
// //修改分辨率
// // 修改全局DisplayMetrics
// XposedHelpers.findAndHookMethod(
// "android.content.res.Resources", // 目标类
// lpparam.classLoader, // 类加载器
// "getDisplayMetrics", // 方法名
// new XC_MethodHook() {
// @Override
// protected void afterHookedMethod(MethodHookParam param) {
// DisplayMetrics metrics = (DisplayMetrics) param.getResult();
// if (metrics == null) return;
//
// // 修改分辨率
// metrics.widthPixels = 1080; // 屏幕宽度
// metrics.heightPixels = 1920; // 屏幕高度
// metrics.density = 420 / 160f; // density = dpi / 160
// metrics.densityDpi = 420; // DPI
// metrics.scaledDensity = metrics.density; // 字体缩放密度通常与density一致
//
// param.setResult(metrics); // 返回修改后的metrics
// }
// }
// );
// // Hook WindowManager.getDefaultDisplay().getRealMetrics()
// XposedHelpers.findAndHookMethod(
// "android.view.Display", // 目标类
// lpparam.classLoader,
// "getRealMetrics",
// DisplayMetrics.class, // 参数类型
// new XC_MethodHook() {
// @Override
// protected void beforeHookedMethod(MethodHookParam param) {
// DisplayMetrics metrics = (DisplayMetrics) param.args[0];
// if (metrics == null) return;
//
// // 修改传入的DisplayMetrics对象
// metrics.widthPixels = 1080;
// metrics.heightPixels = 1920;
// metrics.densityDpi = 420;
// }
// }
// );
// // Hook Display.getRealSize()
// XposedHelpers.findAndHookMethod(
// "android.view.Display",
// lpparam.classLoader,
// "getRealSize",
// Point.class, // 参数类型为Point
// new XC_MethodHook() {
// @Override
// protected void beforeHookedMethod(MethodHookParam param) {
// Point point = (Point) param.args[0];
// if (point == null) return;
//
// point.x = 1080; // 修改宽度
// point.y = 1920; // 修改高度
// }
// }
// );
// // 修改运营商信息
// XposedHelpers.findAndHookMethod(
// "android.telephony.SubscriptionManager",
// lpparam.classLoader,
// "getActiveSubscriptionInfoList",
// new XC_MethodHook() {
// @Override
// protected void afterHookedMethod(MethodHookParam param) {
// // 创建一个伪造的 SubscriptionInfo 列表即使原列表为空
// List<SubscriptionInfo> fakeList = new ArrayList<>();
// fakeList.add(createFakeSubscriptionInfo());
// param.setResult(fakeList);
// }
// }
// );
// // Hook getNetworkOperator() 返回伪造的 MCC-MNC
// XposedHelpers.findAndHookMethod(
// "android.telephony.TelephonyManager",
// lpparam.classLoader,
// "getNetworkOperator",
// new XC_MethodHook() {
// @Override
// protected void afterHookedMethod(MethodHookParam param) {
// param.setResult("310260");
// }
// }
// );
//
//// Hook getSimOperator()
// XposedHelpers.findAndHookMethod(
// "android.telephony.TelephonyManager",
// lpparam.classLoader,
// "getSimOperator",
// new XC_MethodHook() {
// @Override
// protected void afterHookedMethod(MethodHookParam param) {
// param.setResult("310260");
// }
// }
// );
// XposedHelpers.findAndHookMethod(
// "android.telephony.ServiceState",
// lpparam.classLoader,
// "getOperatorNumeric",
// new XC_MethodHook() {
// @Override
// protected void afterHookedMethod(MethodHookParam param) {
// param.setResult("310260");
// }
// }
// );
//
// XposedHelpers.findAndHookMethod(
// "android.telephony.ServiceState",
// lpparam.classLoader,
// "getOperatorAlphaLong",
// new XC_MethodHook() {
// @Override
// protected void afterHookedMethod(MethodHookParam param) {
// param.setResult("Fake Carrier");
// }
// }
// );
// // 设置运营商 MCC-MNC
// XposedHelpers.callStaticMethod(
// lpparam.classLoader.loadClass("android.os.SystemProperties"),
// "set",
// "gsm.operator.numeric",
// "310,260"
// );
//
//// 设置运营商名称
// XposedHelpers.callStaticMethod(
// lpparam.classLoader.loadClass("android.os.SystemProperties"),
// "set",
// "gsm.operator.alpha",
// "Fake Carrier"
// );
//
//// 设置 SIM 卡状态为就绪
// XposedHelpers.callStaticMethod(
// lpparam.classLoader.loadClass("android.os.SystemProperties"),
// "set",
// "gsm.sim.state",
// "READY"
// );
// // Hook TelephonyManager.getSimState()
// XposedHelpers.findAndHookMethod(
// "android.telephony.TelephonyManager",
// lpparam.classLoader,
// "getSimState",
// new XC_MethodHook() {
// @Override
// protected void afterHookedMethod(MethodHookParam param) {
// param.setResult(TelephonyManager.SIM_STATE_READY); // SIM 卡已就绪
// }
// }
// );
// XposedHelpers.findAndHookMethod(
// "android.telephony.TelephonyManager",
// lpparam.classLoader,
// "getSimSerialNumber",
// new XC_MethodHook() {
// @Override
// protected void afterHookedMethod(MethodHookParam param) {
// param.setResult("89014103211118510720"); // 伪造的 ICCID
// }
// }
// );
} catch (Exception e) {
XposedBridge.log("修改设备型号时出错: " + e.getMessage());
}
}
// 通用Hook方法记录方法调用和堆栈
private void hookTelephonyMethod(String className, String methodName, ClassLoader classLoader) {
try {
XposedHelpers.findAndHookMethod(
className,
classLoader,
methodName,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
// 记录方法调用
String log = String.format(
"[Carrier Probe] Called: %s.%s() from %s",
className,
methodName,
getCallingPackage(param)
);
XposedBridge.log(log);
}
}
);
} catch (Throwable e) {
XposedBridge.log("Hook failed: " + e);
}
}
// 获取调用者包名
private String getCallingPackage(XC_MethodHook.MethodHookParam param) {
try {
return param.thisObject.getClass().getPackage().getName();
} catch (Exception e) {
return "unknown";
}
}
@Override
public void initZygote(IXposedHookZygoteInit.StartupParam startupParam) throws Throwable {
try {
// Hook WindowManager updateViewLayout 方法
XposedHelpers.findAndHookMethod(
"android.view.WindowManagerGlobal", null, "updateViewLayout",
android.view.View.class, android.view.ViewGroup.LayoutParams.class,
new XC_MethodHook() {
// @Override
// protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// android.view.ViewGroup.LayoutParams params = (android.view.ViewGroup.LayoutParams) param.args[1];
// // 修改布局参数的宽度和高度
// params.width = convertDpToPx(screen_width);
// params.height = convertDpToPx(screen_height);
// XposedBridge.log("Resolution modified in initZygote: " + screen_width + "dp x " + screen_height + "dp");
// }
});
} catch (Exception e) {
XposedBridge.log("Error hooking WindowManagerGlobal: " + e.getMessage());
}
}
// 辅助方法 dp 转换为 px
private int convertDpToPx(int dp) {
final float scale = android.util.TypedValue.applyDimension(
android.util.TypedValue.COMPLEX_UNIT_DIP, dp,
android.content.res.Resources.getSystem().getDisplayMetrics());
return (int) (scale + 0.5f);
}
// private SubscriptionInfo createFakeSubscriptionInfo(SubscriptionInfo original, LoadPackageParam lpparam) {
// return (SubscriptionInfo) Proxy.newProxyInstance(
// lpparam.classLoader,
// new Class[]{SubscriptionInfo.class},
// new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// String methodName = method.getName();
// // 修改关键字段的返回值
// switch (methodName) {
// case "getCarrierName":
// return "Fake Carrier"; // 运营商名称
// case "getMcc":
// return 310; // 伪造 MCC
// case "getMnc":
// return 260; // 伪造 MNC
// case "getCountryIso":
// return "us"; // 国家代码
// case "getNumber":
// return "+1234567890"; // 伪造手机号
// case "getDataRoaming":
// return 0; // 关闭数据漫游
// case "getSimSlotIndex":
// return 0;
// default:
// // 保留原始对象其他属性
// return method.invoke(original, args);
// }
// }
// }
// );
// }
private SubscriptionInfo createFakeSubscriptionInfo() {
try {
// 使用反射调用隐藏的 SubscriptionInfo 构造函数
Class<?> clazz = Class.forName("android.telephony.SubscriptionInfo");
Constructor<?> constructor = clazz.getDeclaredConstructor(
int.class, // subscriptionId
String.class, // iccId
int.class, // simSlotIndex
CharSequence.class, // displayName
CharSequence.class, // carrierName
int.class, // mcc
int.class, // mnc
String.class, // countryIso
int.class, // dataRoaming
Bitmap.class, // iconBitmap
String.class, // number
int.class, // dataRoaming
int.class, // mcc
int.class, // mnc
String.class, // countryIso
boolean.class, // isEmbedded
String.class, // cardString
String.class // groupUUID
);
constructor.setAccessible(true);
return (SubscriptionInfo) constructor.newInstance(
1, // subscriptionId
"89014103211118510720", // 伪造的 ICCID
0, // simSlotIndex (卡槽0)
"Fake Carrier", // displayName
"Fake Carrier", // carrierName
310, // MCC (美国)
260, // MNC (AT&T)
"us", // countryIso
0, // dataRoaming (关闭)
null, // iconBitmap (无图标)
"+1234567890", // 手机号
0, // dataRoaming
310, // mcc
260, // mnc
"us", // countryIso
false, // isEmbedded
"00000000", // cardString
"group-001" // groupUUID
);
} catch (Throwable e) {
XposedBridge.log("Failed to create fake SubscriptionInfo: " + e);
return null;
}
}
// private SubscriptionInfo createFakeSubscriptionInfo() {
// try {
// // 获取 Builder
// Class<?> builderClass = Class.forName("android.telephony.SubscriptionInfo$Builder");
// Object builder = XposedHelpers.newInstance(builderClass);
//
// // 链式调用设置参数
// XposedHelpers.callMethod(builder, "setId", 1);
// XposedHelpers.callMethod(builder, "setIccId", "89014103211118510720");
// XposedHelpers.callMethod(builder, "setSimSlotIndex", 0);
// XposedHelpers.callMethod(builder, "setDisplayName", "Fake Carrier");
// XposedHelpers.callMethod(builder, "setCarrierName", "Fake Carrier");
// XposedHelpers.callMethod(builder, "setMcc", 310);
// XposedHelpers.callMethod(builder, "setMnc", 260);
// XposedHelpers.callMethod(builder, "setCountryIso", "us");
// // ... 其他参数
//
// // 构建 SubscriptionInfo
// return (SubscriptionInfo) XposedHelpers.callMethod(builder, "build");
// } catch (Throwable e) {
// XposedBridge.log("Error using Builder: " + e);
// return null;
// }
// }
// private SubscriptionInfo createFakeSubscriptionInfo() {
// try {
// // 通过反射获取 Builder
// Class<?> subscriptionInfoClass = Class.forName("android.telephony.SubscriptionInfo");
// Class<?> builderClass = Class.forName("android.telephony.SubscriptionInfo$Builder");
//
// // 创建 Builder 实例
// Object builder = XposedHelpers.newInstance(builderClass);
//
// // 链式调用设置参数
// XposedHelpers.callMethod(builder, "setId", 1);
// XposedHelpers.callMethod(builder, "setIccId", "89014103211118510720");
// XposedHelpers.callMethod(builder, "setSimSlotIndex", 0);
// XposedHelpers.callMethod(builder, "setDisplayName", "Fake Carrier");
// XposedHelpers.callMethod(builder, "setCarrierName", "Fake Carrier");
// XposedHelpers.callMethod(builder, "setMcc", 310);
// XposedHelpers.callMethod(builder, "setMnc", 260);
// // ... 其他参数
//
// // 调用 build() 方法生成对象
// return (SubscriptionInfo) XposedHelpers.callMethod(builder, "build");
// } catch (Throwable e) {
// XposedBridge.log("Fallback to proxy due to error: " + e);
// return createFakeSubscriptionInfo(); // 回退到动态代理
// }
// }
// private SubscriptionInfo createFakeSubscriptionInfo(LoadPackageParam lpparam) {
// return (SubscriptionInfo) Proxy.newProxyInstance(
// lpparam.classLoader,
// new Class[]{SubscriptionInfo.class},
// (proxy, method, args) -> {
// String methodName = method.getName();
// switch (methodName) {
// case "getCarrierName":
// return "Fake Carrier";
// case "getMcc":
// return 310;
// case "getMnc":
// return 260;
// case "getSimSlotIndex":
// return 0;
// case "getSubscriptionId":
// return 1;
// case "toString":
// return "FakeSubscriptionInfo";
// default:
// // 返回默认值或抛出异常根据方法返回值类型
// Class<?> returnType = method.getReturnType();
// if (returnType == boolean.class) return false;
// if (returnType == int.class) return 0;
// return null;
// }
// }
// );
// }
private SubscriptionInfo createProxySubscriptionInfo(LoadPackageParam lpparam) {
return (SubscriptionInfo) Proxy.newProxyInstance(
lpparam.classLoader,
new Class[]{SubscriptionInfo.class},
(proxy, method, args) -> {
switch (method.getName()) {
case "getCarrierName": return "Fake Carrier";
case "getMcc": return 310;
case "getMnc": return 260;
case "getSimSlotIndex": return 0;
default:
// 处理其他方法返回合理默认值
if (method.getReturnType() == boolean.class) return false;
if (method.getReturnType() == int.class) return 0;
return null;
}
}
);
}
private void hookTelephonyMethods(ClassLoader classLoader) {
XposedHelpers.findAndHookMethod(
"android.telephony.TelephonyManager",
classLoader,
"getNetworkOperator",
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
param.setResult("310260");
}
}
);
XposedHelpers.findAndHookMethod(
"android.telephony.TelephonyManager",
classLoader,
"getSimState",
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
param.setResult(TelephonyManager.SIM_STATE_READY);
}
}
);
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="scope">
<item>io.sixminutes.breakingnews</item>
</string-array>
</resources>

View File

@ -1,6 +1,6 @@
#Thu Jan 23 16:34:58 CST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -14,6 +14,7 @@ pluginManagement {
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
maven { setUrl("https://maven.aliyun.com/repository/public") }
google()
mavenCentral()
}