《教我兄弟学Android逆向15 xpose改机开发03-写一款自己的改机软件》

news2024/12/29 11:09:25

上一篇 《教我兄弟学Android逆向14 xpose改机开发02-改机代码基础编写》我带你熟悉了一下改机的流程,搭建了改机的基础代码,改机参数数据储存方面我们用的是SharedPreferences存储数据,界面方面写了一个一键新机的按钮,点一键新机的时候会随机生成imei数据存储到xml数据中,然后xpose代码hook到了getDeviceId函数会将返回值设置成xml文件读取的值,这样就完成了对imei的修改。

关于界面方面上节课也是粗略的写了一下,你可以根据自己想实现的功能去写自己想要的界面。
前面两节课我们配置了xpose开发的环境并且编写了xpose改机的第一个demo
那么本节课我会给你介绍一下改机的总体,以及改机点的寻找和编写。

要么学!要么不学!学和不学之间没有中间值 不学就放弃,学就要去认真的学!    --致选择

xpose改机的优缺点
优点
易上手,便于使用,所需时间成本比较少。
缺点
很容易被检测,只能在java层去操作,Native层,内核层,C库的一些函数无法被修改。
比如libc的函数open,fopen,access,rename,Unix的popen函数还有一些C层内核层获取设备信息的结构体这些都是无法通过xpose去改的。

那么如果想做一款比较好的改机有什么解决方案呢?
1.用xpose去配合一些可以hook so层函数的工具比如Inlinehook,frida等。
2.针对性修改,逆向出协议数据配合xpose模拟数据发包。
3.自定义安卓系统,全局修改。


一 .改机点介绍
1.硬件信息
手机的唯一标识imei,android,序列号serial,手机品牌,手机机型,制造商,蓝牙名,蓝牙MAC地址,系统版本,系统版本名称,开发代号,源码控制版本号,编译类型,CPU架构,无线电固件版本,设备版本号,主板名称,引导程序版本号,设备参数,设备地址,产品名称,ROM名称,硬件名称,指纹,开发ROM编译用户,设备的ROM生成的时间.....
2.手机卡信息
3.蓝牙信息
4.UA信息
5.电池电量
5.开机时间
6.手机内存的信息
7.屏幕大小
8.传感器
9.位置基站信息
10.wifi信息
11.文件信息
12.环境检测
13.设备信息真实性检测
......


看到这么多信息你应该有疑问了,上面说的这些点都是怎么去找到的?

二.改机点寻找
1.从百度google等搜索引擎去搜索xpose改机代码,github上面也有一些开源的xpose改机代码都可以去参考。
2.逆向一些app去看对方是怎么去获取设备信息的,怎么去检测环境信息的从而针对性的去完善改机代码。
3.研究分析安卓源码,找到一切可以获取设备信息的点,要知道大厂做安全的都是从研究Android源码开始的。

三.改机代码编写
1. 因为改机代码量比较大,所以我们首先写一个抽象类去继承XC_MethodHook后面的hook类都可以去继承这个类。
MethodHook.java

public abstract class MethodHook extends XC_MethodHook {
        protected String mpackageName;
        protected ClassLoader mclassLoader;
        protected DeviceInfoModel deviceInfoModel;
        public MethodHook(XC_LoadPackage.LoadPackageParam paramLoadPackageParam, DeviceInfoModel deviceInfoModel)
        {
            this.mpackageName = paramLoadPackageParam.packageName;
            this.mclassLoader = paramLoadPackageParam.classLoader;
            this.deviceInfoModel = deviceInfoModel;
        }
    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        super.afterHookedMethod(param);
    }
    public void hookMethodByClassMethodName(String paramString, String paramString2)
    {
        try
        {
            for (Method localMethod : XposedHelpers.findClass(paramString, this.mclassLoader).getDeclaredMethods())
                if ((localMethod.getName().equals(paramString2)) && (!Modifier.isAbstract(localMethod.getModifiers())))
                {
                    localMethod.setAccessible(true);
                    XposedBridge.hookMethod(localMethod, this);
                }
        }
        catch (Throwable localThrowable)
        {
            Log.e("xposed-MethodHook", "hookMethodByClassMethodName Exception " + paramString);
        }
    }
    public void hookMethodByClassMethodName(String paramString1, String paramString2, Object[] paramArrayOfObject)
    {
        try
        {
            Object[] arrayOfObject = new Object[1 + paramArrayOfObject.length];
            for (int i = 0; i < arrayOfObject.length; i++)
            {
                if (i == -1 + arrayOfObject.length)
                {
                    arrayOfObject[(-1 + arrayOfObject.length)] = this;
                    XposedHelpers.findAndHookMethod(paramString1, this.mclassLoader, paramString2, arrayOfObject);
                    return;
                }
                arrayOfObject[i] = paramArrayOfObject[i];
            }
        }
        catch (Throwable localThrowable)
        {
            Log.e("xposed-MethodHook", "addHookMethodWithParms Exception " + paramString1);
        }
    }
 
    public void hookMethodByClassMethodName(String paramString, Object[] paramArrayOfObject)
    {
        try
        {
            Object[] arrayOfObject = new Object[1 + paramArrayOfObject.length];
            for (int i = 0; i < arrayOfObject.length; i++)
            {
                if (i == -1 + arrayOfObject.length)
                {
                    arrayOfObject[(-1 + arrayOfObject.length)] = this;
                    XposedHelpers.findAndHookConstructor(paramString, this.mclassLoader, arrayOfObject);
                    return;
                }
                arrayOfObject[i] = paramArrayOfObject[i];
            }
        }
        catch (Throwable localThrowable)
        {
           Log.e("xposed-MethodHook", "addHookConWithParms Exception " + paramString);
        }
    }
 
    public void addHook(String paramString)
    {
        try
        {
            for (Constructor localConstructor : XposedHelpers.findClass(paramString, this.mclassLoader).getDeclaredConstructors())
                if (Modifier.isPublic(localConstructor.getModifiers()))
                    XposedBridge.hookMethod(localConstructor, this);
        }
        catch (Throwable localThrowable)
        {
            Log.e("Xhook", "addHook exception", localThrowable);
        }
    }
    public static Field setAccessible(Object arg4, String arg5) {
        Field[] v4 = arg4.getClass().getDeclaredFields();
        int v0 = v4.length;
        int v1;
        for(v1 = 0; v1 < v0; ++v1) {
            Field v2 = v4[v1];
            v2.setAccessible(true);
            if(v2.getType().toString().endsWith(arg5)) {
                return v2;
            }
        }
        return null;
    }
}

2.BuildHook.java
这里包含手机的一些硬件信息的修改和android系统属性的修改,但是缺点的话SystemProperties的get方法很多大厂都是通过native去调用底层的native_get方法检测,这样就要配合其他方式去修改了。

public class BuildHook extends MethodHook
{
    public BuildHook(XC_LoadPackage.LoadPackageParam paramLoadPackageParam, DeviceInfoModel deviceInfoModel, final Context context) {
        super(paramLoadPackageParam, deviceInfoModel);
        hookMethodByClassMethodName("android.os.SystemProperties", "set");
        hookMethodByClassMethodName("android.os.SystemProperties", "get");
        //hookMethodByClassMethodName("android.os.SystemProperties", "getString");
        hookMethodByClassMethodName(Settings.System.class.getName(), "putStringForUser");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
            hookMethodByClassMethodName(Settings.Secure.class.getName(), "putStringForUser");
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            hookMethodByClassMethodName(Settings.Global.class.getName(), "putStringForUser");
        }
        hookMethodByClassMethodName(Settings.System.class.getName(), "getStringForUser");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
            hookMethodByClassMethodName(Settings.Secure.class.getName(), "getStringForUser");
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            hookMethodByClassMethodName(Settings.Global.class.getName(), "getStringForUser");
        }
        hookMethodByClassMethodName("android.provider.Settings$NameValueCache", "getStringForUser");
    }
 
    @SuppressLint("SuspiciousIndentation")
    private void setBuilds() {
        XposedHelpers.setStaticObjectField(Build.class, "BOOTLOADER", "unkown");
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildBrand()))
            XposedHelpers.setStaticObjectField(Build.class, "BRAND", this.deviceInfoModel.getBuildBrand());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildBoard()))
            XposedHelpers.setStaticObjectField(Build.class, "BOARD", this.deviceInfoModel.getBuildBoard());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildModel()))
            XposedHelpers.setStaticObjectField(Build.class, "MODEL", this.deviceInfoModel.getBuildModel());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getDisplayId()))
            XposedHelpers.setStaticObjectField(Build.class, "DISPLAY", this.deviceInfoModel.getDisplayId());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildProduct()))
            XposedHelpers.setStaticObjectField(Build.class, "PRODUCT", this.deviceInfoModel.getBuildProduct());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildManufacturer()))
            XposedHelpers.setStaticObjectField(Build.class, "MANUFACTURER", this.deviceInfoModel.getBuildManufacturer());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildDevice()))
            XposedHelpers.setStaticObjectField(Build.class, "DEVICE", this.deviceInfoModel.getBuildDevice());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildRelease()))
            XposedHelpers.setStaticObjectField(Build.VERSION.class, "RELEASE", this.deviceInfoModel.getBuildRelease());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildSdk()))
            XposedHelpers.setStaticObjectField(Build.VERSION.class, "SDK", this.deviceInfoModel.getBuildSdk());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildFingerprint()))
            XposedHelpers.setStaticObjectField(Build.class, "FINGERPRINT", this.deviceInfoModel.getBuildFingerprint());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildHardware()))
            XposedHelpers.setStaticObjectField(Build.class, "HARDWARE", this.deviceInfoModel.getBuildHardware());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildCodename()))
            XposedHelpers.setStaticObjectField(Build.VERSION.class, "CODENAME", this.deviceInfoModel.getBuildCodename());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildIncremental()))
            XposedHelpers.setStaticObjectField(Build.VERSION.class, "INCREMENTAL", this.deviceInfoModel.getBuildIncremental());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildHost()))
            XposedHelpers.setStaticObjectField(Build.class, "HOST", this.deviceInfoModel.getBuildHost());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildId()))
            XposedHelpers.setStaticObjectField(Build.class, "ID", this.deviceInfoModel.getBuildId());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildType()))
            XposedHelpers.setStaticObjectField(Build.class, "TYPE", this.deviceInfoModel.getBuildType());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildUser()))
            XposedHelpers.setStaticObjectField(Build.class, "USER", this.deviceInfoModel.getBuildUser());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildSerialno()))
            XposedHelpers.setStaticObjectField(Build.class, "SERIAL", this.deviceInfoModel.getBuildSerialno());
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildTags()))
            XposedHelpers.setStaticObjectField(Build.class, "TAGS", this.deviceInfoModel.getBuildTags());
        if (this.deviceInfoModel.getBuildUtc() > 0L)
            XposedHelpers.setStaticObjectField(Build.class, "TIME", Long.valueOf(this.deviceInfoModel.getBuildUtc()));
 
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildAbi())){
            XposedHelpers.setStaticObjectField(Build.class, "CPU_ABI", this.deviceInfoModel.getBuildAbi());
        }
 
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildAbi2())){
            XposedHelpers.setStaticObjectField(Build.class, "CPU_ABI2", this.deviceInfoModel.getBuildAbi2());
        }
        if (!TextUtils.isEmpty(this.deviceInfoModel.getBuildSdk())){
            if(Integer.parseInt(this.deviceInfoModel.getBuildSdk())<26){
                XposedHelpers.setStaticIntField(Build.VERSION.class, "SDK_INT", Integer.parseInt(this.deviceInfoModel.getBuildSdk()));
            }
        }
        if (!TextUtils.isEmpty(this.deviceInfoModel.getSecurity_patch())){
            XposedHelpers.setStaticObjectField(Build.VERSION.class, "SECURITY_PATCH", this.deviceInfoModel.getSecurity_patch());
        }
    }
 
    public static Object IIl1lIIlll(DeviceInfoModel arg4, String arg5) {
        if("ro.product.model".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildModel())) {
                return arg4.getBuildModel();
 
            }
        }
 
        if("ro.boot.serialno".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getSerialno())) {
                Log.i("TestYY", "ro.boot.serialno");
                return arg4.getSerialno();
            }
        }
 
 
        else if("ro.build.id".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildId())) {
                return arg4.getBuildId();
            }
        }
        else if("ro.build.display.id".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getDisplayId())) {
                return arg4.getDisplayId();
            }
        }
        else if("ro.build.type".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildType())) {
                return arg4.getBuildType();
            }
        }
        else if("ro.build.user".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildUser())) {
                return arg4.getBuildUser();
            }
        }
        else if("ro.build.host".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildHost())) {
                return arg4.getBuildHost();
            }
        }
        else if("ro.build.tags".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildTags())) {
                return arg4.getBuildTags();
            }
        }
        else if("ro.product.brand".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildBrand())) {
                return arg4.getBuildBrand();
            }
        }
        else if("ro.product.device".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildDevice())) {
                return arg4.getBuildDevice();
            }
        }
        else if("ro.product.board".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildBoard())) {
                return arg4.getBuildBoard();
            }
        }
        else if("ro.product.name".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildName())) {
                return arg4.getBuildName();
            }
        }
        else if("ro.product.manufacturer".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildManufacturer())) {
                return arg4.getBuildManufacturer();
            }
        }
        else if("ro.hardware".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildHardware())) {
                return arg4.getBuildHardware();
            }
        }
        else if("c".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildSerialno())) {
                return arg4.getBuildSerialno();
            }
        }
        else if("ro.build.version.incremental".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildIncremental())) {
                return arg4.getBuildIncremental();
            }
        }
        else if("ro.build.version.release".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildRelease())) {
                return arg4.getBuildRelease();
            }
        }
        else if("ro.build.version.sdk".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildSdk())) {
                return arg4.getBuildSdk();
            }
        }
        else if("ro.build.version.codename".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildCodename())) {
                return arg4.getBuildCodename();
            }
        }
        else if("ro.build.fingerprint".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildFingerprint())) {
                return arg4.getBuildFingerprint();
            }
        }
        else if("ro.build.date.utc".equals(arg5)) {
            if(arg4.getBuildUtc() > 0) {
                return Long.valueOf(arg4.getBuildUtc());
            }
        }
        else if("gsm.operator.numeric".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getSimOperator())) {
                return arg4.getSimOperator();
            }
        }
        else if(!TextUtils.isEmpty(((CharSequence)arg5)) && (arg5.contains("recovery_id"))) {
            return arg4.getRecoveryId();
        }
 
        else if(("gsm.operator.numeric".equals(arg5)) || ("gsm.sim.operator.numeric".equals(arg5)) || ("gsm.apn.sim.operator.numeric".equals(arg5))) {
            if(TextUtils.isEmpty(arg4.getSimOperator())) {
                return arg4.getSimOperator();
            }
        }
 
 
        else if("gsm.operator.iso-country".equals(arg5) || "gsm.sim.operator.iso-country".equals(arg5)) {
            if(TextUtils.isEmpty(arg4.getSimCountryIso())) {
                return arg4.getSimCountryIso();
            }
 
        }
 
        else if("gsm.operator.alpha".equals(arg5) || "gsm.operator.orig.alpha".equals(arg5)) {
            if(TextUtils.isEmpty(arg4.getSimOperatorName())) {
                return arg4.getSimOperatorName();
            }
        }
 
 
 
        else if("ro.build.brand".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildBrand())) {
                return arg4.getBuildBrand();
            }
        }
        else if("ro.build.board".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildBoard())) {
                return arg4.getBuildBoard();
            }
        }
        else if("net.hostname".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getNetHostname())) {
                return arg4.getNetHostname();
            }
        }
        else if("dalvik.vm.heapsize".equals(arg5)) {
            return arg4.getVmHeapSize();
        }
 
        else if("ro.build.selinux".equals(arg5)) {
            return "1";
        }
 
        else if("ro.board.platform".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBoardPlat())) {
                return arg4.getBoardPlat();
            }
        }
        else if("ro.product.cpu.abi".equals(arg5)) {
            if(!TextUtils.isEmpty(arg4.getBuildAbi())) {
                return arg4.getBuildAbi();
            }
        }
        else if("ro.product.cpu.abi2".equals(arg5)) {
            if(TextUtils.isEmpty(arg4.getBuildAbi2())) {
                arg4.setBuildAbi2("armeabi");
            }
 
            return arg4.getBuildAbi2();
        }
        else {
            if(!arg5.contains("gsm.version.baseband") && !arg5.contains("ro.baseband") && !arg5.contains("ro.boot.baseband")) {
                return null;
            }
 
            if(TextUtils.isEmpty(arg4.getBuildRadioVersion())) {
                return null;
            }
 
            return arg4.getBuildRadioVersion();
        }
 
        return null;
    }
 
 
    @Override
    protected void afterHookedMethod(final XC_MethodHook.MethodHookParam xc_MethodHook$MethodHookParam) throws Throwable {
        int v3 = 3;
        Object v0_1;
        String name = xc_MethodHook$MethodHookParam.method.getName();
        String v1 = xc_MethodHook$MethodHookParam.method.getDeclaringClass().getName();
 
        if ("get".startsWith(name)) {
            v0_1 = this.IIl1lIIlll(this.deviceInfoModel, (String) xc_MethodHook$MethodHookParam.args[0]);
 
            if (v0_1 != null) {
                xc_MethodHook$MethodHookParam.setResult(v0_1);
            }
 
            if ("android.provider.Settings$NameValueCache".equals(v1)) {
                this.setAccessible(xc_MethodHook$MethodHookParam.thisObject, "mValues");
                v0_1 = XposedHelpers.getObjectField(xc_MethodHook$MethodHookParam.thisObject, "mValues");
 
                if ("android_id".equals(xc_MethodHook$MethodHookParam.args[0])) {
                    ((HashMap) v0_1).put("android_id", this.deviceInfoModel.getAndroidId());
                    xc_MethodHook$MethodHookParam.setResult(this.deviceInfoModel.getAndroidId());
                }
 
                if ("accessibility_enabled".equals(xc_MethodHook$MethodHookParam.args[0])) {
                    ((HashMap) v0_1).put("accessibility_enabled", "0");
                    name = "0";
                    xc_MethodHook$MethodHookParam.setResult(name);
 
                }
 
                if ("enabled_accessibility_services".equals(xc_MethodHook$MethodHookParam.args[0])) {
                    super.afterHookedMethod(xc_MethodHook$MethodHookParam);
                    ((HashMap) v0_1).put("enabled_accessibility_services", null);
                    xc_MethodHook$MethodHookParam.setResult(null);
                }
            }
 
 
            if ("android_id".equals(xc_MethodHook$MethodHookParam.args[0])) {
                xc_MethodHook$MethodHookParam.setResult((Object) this.deviceInfoModel.getAndroidId());
            }
            if ("adb_enabled".equals(xc_MethodHook$MethodHookParam.args[0])) {
                xc_MethodHook$MethodHookParam.setResult((Object) 0);
            }
            if ("data_roaming".equals(xc_MethodHook$MethodHookParam.args[0])) {
                xc_MethodHook$MethodHookParam.setResult((Object) 0);
            }
 
           /* if ("wifi_on".equals(xc_MethodHook$MethodHookParam.args[0])) {
                if (this.DeviceInfoModel.getType() != 1) {
                    v3 = 0;
                }
                RLog.m("Test---get--othier2:wifi_on");
                xc_MethodHook$MethodHookParam.setResult(v3);
            }*/
 
            if ("bluetooth_address".equals(xc_MethodHook$MethodHookParam.args[0])) {
                if (TextUtils.isEmpty(this.deviceInfoModel.getBtAddress())) {
                    super.afterHookedMethod(xc_MethodHook$MethodHookParam);
                    xc_MethodHook$MethodHookParam.setResult(this.deviceInfoModel.getBtAddress());
                }
            }
 
 
            if ("bluetooth_name".equals(xc_MethodHook$MethodHookParam.args[0])) {
                if (TextUtils.isEmpty(this.deviceInfoModel.getBtName())) {
                    super.afterHookedMethod(xc_MethodHook$MethodHookParam);
                    xc_MethodHook$MethodHookParam.setResult(this.deviceInfoModel.getBtName());
                }
            }
 
            if ("accessibility_enabled".equals(xc_MethodHook$MethodHookParam.args[0])) {
                xc_MethodHook$MethodHookParam.setResult(0);
            }
 
            if ("enabled_accessibility_services".equals(xc_MethodHook$MethodHookParam.args[0])) {
                xc_MethodHook$MethodHookParam.setResult(null);
                super.afterHookedMethod(xc_MethodHook$MethodHookParam);
            }
 
            if (xc_MethodHook$MethodHookParam.args[0].toString().contains("accessibility")) {
                xc_MethodHook$MethodHookParam.setResult(null);
            }
        }
 
        else {
            if("getStringForUser".equals(name)) {
                if ("android.provider.Settings$NameValueCache".equals(v1)) {
                    //RLog.m("Test---get--othier:enter android.provider.Settings$NameValueCache222");
                    this.setAccessible(xc_MethodHook$MethodHookParam.thisObject, "mValues");
                    v0_1 = XposedHelpers.getObjectField(xc_MethodHook$MethodHookParam.thisObject, "mValues");
 
                    if ("android_id".equals(xc_MethodHook$MethodHookParam.args[1])) {
                        ((HashMap) v0_1).put("android_id", this.deviceInfoModel.getAndroidId());
                        xc_MethodHook$MethodHookParam.setResult(this.deviceInfoModel.getAndroidId());
                    }
 
                    if ("accessibility_enabled".equals(xc_MethodHook$MethodHookParam.args[1])) {
                        ((HashMap) v0_1).put("accessibility_enabled", "0");
                        name = "0";
                        xc_MethodHook$MethodHookParam.setResult(name);
 
                    }
 
                    if ("enabled_accessibility_services".equals(xc_MethodHook$MethodHookParam.args[1])) {
                        ((HashMap) v0_1).put("enabled_accessibility_services", null);
                        xc_MethodHook$MethodHookParam.setResult(null);
                    }
                    super.afterHookedMethod(xc_MethodHook$MethodHookParam);
                }
 
                if ("android_id".equals(xc_MethodHook$MethodHookParam.args[1])) {
                    xc_MethodHook$MethodHookParam.setResult((Object)this.deviceInfoModel.getAndroidId());
                }
                if ("adb_enabled".equals(xc_MethodHook$MethodHookParam.args[1])) {
                    xc_MethodHook$MethodHookParam.setResult((Object) 0);
                }
                if ("data_roaming".equals(xc_MethodHook$MethodHookParam.args[1])) {
                    xc_MethodHook$MethodHookParam.setResult((Object) 0);
                }
 
                if ("bluetooth_address".equals(xc_MethodHook$MethodHookParam.args[1])) {
                    if (TextUtils.isEmpty(this.deviceInfoModel.getBtAddress())) {
                        super.afterHookedMethod(xc_MethodHook$MethodHookParam);
                        xc_MethodHook$MethodHookParam.setResult(this.deviceInfoModel.getBtAddress());
                    }
                }
 
 
                if ("bluetooth_name".equals(xc_MethodHook$MethodHookParam.args[1])) {
                    if (TextUtils.isEmpty(this.deviceInfoModel.getBtName())) {
                        super.afterHookedMethod(xc_MethodHook$MethodHookParam);
                        xc_MethodHook$MethodHookParam.setResult(this.deviceInfoModel.getBtName());
                    }
                }
 
                if ("accessibility_enabled".equals(xc_MethodHook$MethodHookParam.args[1])) {
                    xc_MethodHook$MethodHookParam.setResult(0);
                }
 
                if ("enabled_accessibility_services".equals(xc_MethodHook$MethodHookParam.args[1])) {
                    xc_MethodHook$MethodHookParam.setResult(null);
                    super.afterHookedMethod(xc_MethodHook$MethodHookParam);
                }
 
                if (xc_MethodHook$MethodHookParam.args[1].toString().contains("accessibility")) {
                    xc_MethodHook$MethodHookParam.setResult(null);
                }
            }
 
            if("set".equals(name)) {
                Log.i("SysPropertyHook", "SystemProperties set : " + xc_MethodHook$MethodHookParam.args[0] + " , " + xc_MethodHook$MethodHookParam.args[1]);
            }
 
            if(!"getInt".equals(name)) {
            }
 
            if("ro.build.version.sdk".equals(xc_MethodHook$MethodHookParam.args[0])) {
                xc_MethodHook$MethodHookParam.setResult(this.deviceInfoModel.getBuildSdk());
            }
        }
    }
 
    @Override
   protected void beforeHookedMethod(XC_MethodHook.MethodHookParam paramMethodHookParam) throws Throwable {
        super.beforeHookedMethod(paramMethodHookParam);
        String str1 = paramMethodHookParam.method.getName();
        Class localClass = paramMethodHookParam.method.getDeclaringClass();
        if ("putStringForUser".equals(str1)) {
            Class[] arrayOfClass = new Class[3];
            arrayOfClass[0] = ContentResolver.class;
            arrayOfClass[1] = String.class;
            arrayOfClass[2] = Integer.TYPE;
            Method localMethod = localClass.getDeclaredMethod("getStringForUser", arrayOfClass);
            Object[] arrayOfObject = new Object[3];
            arrayOfObject[0] = paramMethodHookParam.args[0];
            arrayOfObject[1] = paramMethodHookParam.args[1];
            arrayOfObject[2] = paramMethodHookParam.args[3];
            String str2 = (String) localMethod.invoke(localClass, arrayOfObject);
            String str3 = localClass.getSimpleName() + "," + paramMethodHookParam.args[1] + "," + paramMethodHookParam.args[2] + "," + str2;
            Log.i("SysPropertyHook"," Settings putStringForUser : "+str3);
        }else if("get".equals(str1)){
            setBuilds();
        }
    }
    }

3.RobuildHook.java
这里会通过Build类的getString获取到一些系统属性的值。

public class RobuildHook extends MethodHook {
    public RobuildHook(XC_LoadPackage.LoadPackageParam paramLoadPackageParam, DeviceInfoModel deviceInfoModel) {
        super(paramLoadPackageParam, deviceInfoModel);
        hookMethodByClassMethodName("android.os.Build", "getString");
        hookMethodByClassMethodName("android.os.Build", "getRadioVersion");
    }
    @Override
    protected void afterHookedMethod(XC_MethodHook.MethodHookParam paramMethodHookParam) throws Throwable {
        final String name = paramMethodHookParam.method.getName();
        if ("getRadioVersion".equals(name)) {
            if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildRadioVersion())) {
                paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildRadioVersion());
            }
        }
        else if ("getString".equals(name)) {
 
            final String s = (String)paramMethodHookParam.args[0];
            if ("net.hostname".equals(s)) {
                paramMethodHookParam.setResult("android-" + this.deviceInfoModel.getBuildHost());
            }
 
            if ("ro.product.model".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildModel())) {
                    //FileUtil.writeContent2FileForceUtf8(FilePathCommon.phoneTagPath,createfile.getRgPhoneNo());//标记是否hook成功
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildModel());
                }
            }
            else if ("ro.build.id".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildId())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildId());
                }
            }
            else if ("ro.build.display.id".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getDisplayId())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getDisplayId());
                }
            }
            else if ("ro.build.type".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildType())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildType());
                }
            }
            else if ("ro.build.user".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildUser())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildUser());
                }
            }
            else if ("ro.build.host".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildHost())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildHost());
                }
            }
            else if ("ro.build.tags".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildTags())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildTags());
                }
            }
            else if ("ro.product.brand".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildTags())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildBrand());
                }
            }
            else if ("ro.product.device".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildDevice())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildDevice());
                }
            }
            else if ("ro.product.board".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildBoard())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildBoard());
                }
            }
            else if ("ro.product.name".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildName())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildName());
                }
            }
            else if ("ro.product.manufacturer".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildManufacturer())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildManufacturer());
                }
            }
            else if ("ro.hardware".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildHardware())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildHardware());
                }
            }
            else if ("ro.serialno".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildSerialno())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildSerialno());
                }
            }
            else if ("ro.build.version.incremental".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildIncremental())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildIncremental());
                }
            }
            else if ("ro.build.version.release".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildRelease())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildRelease());
                }
            }
            else if ("ro.build.version.sdk".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildSdk())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildSdk());
                }
            }
            else if ("ro.build.version.codename".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildCodename())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildCodename());
                }
            }
            else if ("ro.build.fingerprint".equals(s)) {
                if (!TextUtils.isEmpty((CharSequence)this.deviceInfoModel.getBuildFingerprint())) {
                    paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildFingerprint());
                }
            }
            else if ("ro.build.date.utc".equals(s) && this.deviceInfoModel.getBuildUtc() > 0L) {
                paramMethodHookParam.setResult((Object)this.deviceInfoModel.getBuildUtc());
            }
        }
        super.afterHookedMethod(paramMethodHookParam);
    }
 
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        super.beforeHookedMethod(param);
    }

4.ScreenHook.java
屏幕信息数据的修改

public class ScreenHook extends MethodHook
{
 
    public ScreenHook(XC_LoadPackage.LoadPackageParam xc_LoadPackage$LoadPackageParam, DeviceInfoModel deviceInfoModel) {
        super(xc_LoadPackage$LoadPackageParam, deviceInfoModel);
        this.hookMethodByClassMethodName(Display.class.getName(), "getMetrics", new Object[] { DisplayMetrics.class.getName() });
        this.hookMethodByClassMethodName(Display.class.getName(), "getWidth", new Object[0]);
        this.hookMethodByClassMethodName(Display.class.getName(), "getHeight", new Object[0]);
        this.hookMethodByClassMethodName(Resources.class.getName(), "getDisplayMetrics", new Object[0]);
    }
            
}
 
    @Override
    protected void afterHookedMethod(XC_MethodHook.MethodHookParam xc_MethodHook$MethodHookParam) {
        final String name = xc_MethodHook$MethodHookParam.method.getName();
        if ("getWidth".equals(name)) {
            if (this.deviceInfoModel.getWidth() > 0) {
                xc_MethodHook$MethodHookParam.setResult((Object)this.deviceInfoModel.getWidth());
 
            }
        }
        else if ("getHeight".equals(name)) {
            if (this.deviceInfoModel.getHeight() > 0) {
                xc_MethodHook$MethodHookParam.setResult((Object)this.deviceInfoModel.getHeight());
            }
        }
        else if ("getDisplayMetrics".equals(name)) {
            if (this.deviceInfoModel.getWidth() > 0 && this.deviceInfoModel.getHeight() > 0) {
                final DisplayMetrics result = (DisplayMetrics)xc_MethodHook$MethodHookParam.getResult();
                result.heightPixels = this.deviceInfoModel.getHeight();
                result.widthPixels = this.deviceInfoModel.getWidth();
                result.densityDpi = this.deviceInfoModel.getDensityDpi();
                xc_MethodHook$MethodHookParam.setResult((Object)result);
            }
        }
        else if ("getMetrics".equals(name)) {
            final Object o = xc_MethodHook$MethodHookParam.args[0];
            if (this.deviceInfoModel.getWidth() > 0 && this.deviceInfoModel.getHeight() > 0) {
                ((DisplayMetrics)o).widthPixels = this.deviceInfoModel.getWidth();
                ((DisplayMetrics)o).heightPixels = this.deviceInfoModel.getHeight();
                ((DisplayMetrics)o).densityDpi = this.deviceInfoModel.getDensityDpi();
            }
        }
 
 
        if(Filec.readToString("/sdcard/.hm_diamond/zhuce").length()>3){
            //if(true){
            final String name = xc_MethodHook$MethodHookParam.method.getName();
            if ("getWidth".equals(name)) {
                if (this.deviceInfoModel.getWidth() > 0) {
                    xc_MethodHook$MethodHookParam.setResult((Object)this.deviceInfoModel.getWidth());
                }
            }
            else if ("getHeight".equals(name)) {
                if (this.deviceInfoModel.getHeight() > 0) {
                    xc_MethodHook$MethodHookParam.setResult((Object)this.deviceInfoModel.getHeight());
                }
            }
            else if ("getDisplayMetrics".equals(name)) {
                if (this.deviceInfoModel.getWidth() > 0 && this.deviceInfoModel.getHeight() > 0) {
                    final DisplayMetrics result = (DisplayMetrics)xc_MethodHook$MethodHookParam.getResult();
                    result.heightPixels = this.deviceInfoModel.getHeight();
                    result.widthPixels = this.deviceInfoModel.getWidth();
                    result.densityDpi = this.deviceInfoModel.getDensityDpi();
                    xc_MethodHook$MethodHookParam.setResult((Object)result);
 
                }
            }
            else if ("getMetrics".equals(name)) {
                final Object o = xc_MethodHook$MethodHookParam.args[0];
                if (this.deviceInfoModel.getWidth() > 0 && this.deviceInfoModel.getHeight() > 0) {
                    ((DisplayMetrics)o).widthPixels = this.deviceInfoModel.getWidth();
                    ((DisplayMetrics)o).heightPixels = this.deviceInfoModel.getHeight();
                    ((DisplayMetrics)o).densityDpi = this.deviceInfoModel.getDensityDpi();
                }
            }
        }
 
    }
}

5.PhoneSubInfoHook.java
这里修改了手机卡相关的一些信息。

public class PhoneSubInfoHook extends MethodHook
{
    private static  XC_LoadPackage.LoadPackageParam lpp;
    public PhoneSubInfoHook(XC_LoadPackage.LoadPackageParam paramLoadPackageParam, DeviceInfoModel deviceInfoModel)
    {
        super(paramLoadPackageParam, deviceInfoModel);
        lpp = paramLoadPackageParam;
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getDeviceId", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getSimSerialNumber", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getSubscriberId", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getLine1Number", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "hasIccCard", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "isSmsCapable", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getDataState", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getIsimImpi", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getIsimDomain", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getIsimImpu", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getLine1AlphaTag", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getMsisdn", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getVoiceMailAlphaTag");
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getMmsUserAgent");
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getMmsUAProfUrl");
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getDeviceSoftwareVersion");
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getProccmdline");
        hookMethodByClassMethodName("com.android.internal.telephony.PhoneSubInfo", "getDeviceId");
        hookMethodByClassMethodName("com.android.internal.telephony.PhoneSubInfo", "getImei");
        hookMethodByClassMethodName("com.android.internal.telephony.PhoneSubInfo", "getDeviceSvn");
        hookMethodByClassMethodName("com.android.internal.telephony.PhoneSubInfo", "getIccSerialNumber");
        hookMethodByClassMethodName("com.android.internal.telephony.PhoneSubInfo", "getLine1Number");
        hookMethodByClassMethodName("com.android.internal.telephony.PhoneSubInfo", "getSubscriberId");
        hookMethodByClassMethodName("com.android.internal.telephony.PhoneSubInfo", "getLine1AlphaTag");
        hookMethodByClassMethodName("android.telephony.MSimTelephonyManager", "getDeviceId");
        hookMethodByClassMethodName("android.telephony.MSimTelephonyManager", "getSubscriberId");
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getCallState", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getNetworkType", new Object[0]);*/
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getPhoneType", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getNetworkClass", new Object[] { Integer.TYPE.getName() });
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getSimCountryIso", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getSimOperator", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getSimOperatorName", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getNetworkCountryIso", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getNetworkOperator", new Object[0]);
        hookMethodByClassMethodName(TelephonyManager.class.getName(), "getNetworkOperatorName", new Object[0]);
    }
 
    @Override
    protected void afterHookedMethod(XC_MethodHook.MethodHookParam paramMethodHookParam) throws Throwable {
        String str1 = paramMethodHookParam.method.getName();
        String str2 = paramMethodHookParam.method.getDeclaringClass().getName();
        System.out.println("getString-->str0"+str1);
        if("asInterface".equals(str1)) {
            paramMethodHookParam.setResult(null);
        }
 
        if ("hasIccCard".equals(str1)){
            paramMethodHookParam.setResult(Boolean.valueOf(true));
        }
        if ("isSmsCapable".equals(str1))
        {
            paramMethodHookParam.setResult(Boolean.valueOf(true));
        }
        if ("getDataState".equals(str1))
        {
            paramMethodHookParam.setResult(Integer.valueOf(2));
        }
        if ("getCallState".equals(str1))
        {
            paramMethodHookParam.setResult(Integer.valueOf(0));
        }
 
        if (("getLine1AlphaTag".equals(str1)) || ("getMsisdn".equals(str1)))
        {
            paramMethodHookParam.setResult(this.deviceInfoModel.getLine1Number());
        }
        if ("getLine1Number".equals(str1))
        {
            paramMethodHookParam.setResult(this.deviceInfoModel.getLine1Number());
        }
        if ("getState".equals(str1))
        {
            paramMethodHookParam.setResult(Integer.valueOf(0));
        }
        if ("getDataActivity".equals(str1))
        {
            paramMethodHookParam.setResult(Integer.valueOf(0));
        }
        if (("getVoiceMailAlphaTag".equals(str1)) || ("getVoiceMailNumber".equals(str1)))
        {
            paramMethodHookParam.setResult(this.deviceInfoModel.getLine1Number());
        }
 
        if ("getDeviceSoftwareVersion".equals(str1))
        {
            paramMethodHookParam.setResult("00");
        }
        if ("getProccmdline".equals(str1))
        {
            String str =  Filec.readToString(PathFileUtil.ownPath+"proccmdline");
            paramMethodHookParam.setResult(str);
        }
 
        if ("getImei".equals(str1))
        {
            paramMethodHookParam.setResult(this.deviceInfoModel.getDeviceId());
        }
        if ("getDeviceId".equals(str1))
        {
            paramMethodHookParam.setResult(this.deviceInfoModel.getDeviceId());
        }
        if ("getIccSerialNumber".equals(str1))
        {
            paramMethodHookParam.setResult(this.deviceInfoModel.getSimSerialNumber());
        }
        super.afterHookedMethod(paramMethodHookParam);
    }
}

6.CellIdentityGsmHook.java
基站和位置的信息修改,这里需要注意的是基站信息的真实性,附近基站的模拟。

public class CellIdentityGsmHook extends MethodHook
{
    public CellIdentityGsmHook(XC_LoadPackage.LoadPackageParam paramLoadPackageParam, DeviceInfoModel deviceInfoModel)
    {
        super(paramLoadPackageParam, deviceInfoModel);
        hookMethodByClassMethodName("android.telephony.CellIdentityCdma", "getSystemId"); //mnc
        hookMethodByClassMethodName("android.telephony.CellIdentityCdma", "getNetworkId"); //lac
        hookMethodByClassMethodName("android.telephony.CellIdentityCdma", "getLongitude");  //getLongitude
        hookMethodByClassMethodName("android.telephony.CellIdentityCdma", "getLatitude");  //getLatitude
        hookMethodByClassMethodName("android.telephony.CellIdentityCdma", "getBaseStationId"); //ci
        hookMethodByClassMethodName("android.telephony.CellIdentityGsm", "getLac");
        hookMethodByClassMethodName("android.telephony.CellIdentityGsm", "getCid");
        hookMethodByClassMethodName("android.telephony.CellIdentityGsm", "getMcc");
        hookMethodByClassMethodName("android.telephony.CellIdentityGsm", "getMnc");
        hookMethodByClassMethodName("android.telephony.CellIdentityLte", "getTac");
        hookMethodByClassMethodName("android.telephony.CellIdentityLte", "getCi");
        hookMethodByClassMethodName("android.telephony.CellIdentityLte", "getMcc");
        hookMethodByClassMethodName("android.telephony.CellIdentityLte", "getMnc");
        hookMethodByClassMethodName("android.telephony.CellIdentityWcdma", "getLac");
        hookMethodByClassMethodName("android.telephony.CellIdentityWcdma", "getCid");
        hookMethodByClassMethodName("android.telephony.CellIdentityWcdma", "getMcc");
        hookMethodByClassMethodName("android.telephony.CellIdentityWcdma", "getMnc");
    }
 
    protected void afterHookedMethod(XC_MethodHook.MethodHookParam paramMethodHookParam)
    {
        paramMethodHookParam.method.getDeclaringClass().getName();
        String str = paramMethodHookParam.method.getName();
        if ("getSystemId".equals(str))
        {
            paramMethodHookParam.setResult(this.deviceInfoModel.getMnc());
        }
        if ("getNetworkId".equals(str))
        {
            paramMethodHookParam.setResult(Integer.valueOf(this.deviceInfoModel.getLac()));
            return;
        }
        if ("getLongitude".equals(str))
        {
            paramMethodHookParam.setResult(Double.valueOf(this.deviceInfoModel.getLongitude()));
            return;
        }
        if ("getLatitude".equals(str))
        {
            paramMethodHookParam.setResult(Double.valueOf(this.deviceInfoModel.getLatitude()));
            return;
        }
        if ("getBaseStationId".equals(str))
        {
            paramMethodHookParam.setResult(Integer.valueOf(this.deviceInfoModel.getCi()));
            return;
        }
        if (("getLac".equals(str)) || ("getTac".equals(str)))
        {
            paramMethodHookParam.setResult(Integer.valueOf(this.deviceInfoModel.getLac()));
            return;
        }
        if (("getCid".equals(str)) || ("getCi".equals(str)))
        {
            paramMethodHookParam.setResult(Integer.valueOf(this.deviceInfoModel.getCi()));
            return;
        }
        if ("getMcc".equals(str)) {
            paramMethodHookParam.setResult(Integer.valueOf(460));
            return;
        }
        if (!"getMnc".equals(str));
            paramMethodHookParam.setResult(this.deviceInfoModel.getMnc());
    }
}

7.StorageHook.java
这里修改了设备内存的一些数据,包括一些xpose的防检测代码,native层也有一些内存的检测,还有一些C层的结构体也会检测手机存储这些信息

public StorageHook(XC_LoadPackage.LoadPackageParam paramLoadPackageParam, DeviceInfoModel deviceInfoModel) {
        super(paramLoadPackageParam, deviceInfoModel);
        Object[] arrayOfObject1 = new Object[1];
        arrayOfObject1[0] = ActivityManager.MemoryInfo.class.getName();
 
        if(true){
            hookMethodByClassMethodName("android.app.ActivityManager", "getMemoryInfo", arrayOfObject1);  //内存
            hookMethodByClassMethodName("android.content.pm.ApplicationInfo", "getApplicationInfo", new Object[0]);
            hookMethodByClassMethodName("com.android.internal.os.PowerProfile", "getAveragePower");
            hookMethodByClassMethodName("com.google.android.gles_jni.GLImpl", "glGetString");
            hookMethodByClassMethodName("android.net.TrafficStats", "getMobileRxBytes");
            hookMethodByClassMethodName("android.net.TrafficStats", "getMobileTxBytes");
            hookMethodByClassMethodName("android.net.TrafficStats", "getTotalTxBytes");
            hookMethodByClassMethodName("android.net.TrafficStats", "getTotalRxBytes");
            String str = Intent.class.getName();
            Object[] arrayOfObject2 = new Object[2];
            arrayOfObject2[0] = String.class;
            arrayOfObject2[1] = Integer.TYPE;
            hookMethodByClassMethodName(str, "getIntExtra", arrayOfObject2);
            hookMethodByClassMethodName(Window.class.getName(), "getAttributes", new Object[0]);
            this.hookMethodByClassMethodName(WebView.class.getName(), "loadUrl");
            this.hookMethodByClassMethodName(URLConnection.class.getName(), "getInputStream");
            this.hookMethodByClassMethodName(HttpURLConnection.class.getName(), "getResponseCode");
        }
 
 
        XposedHelpers.findAndHookMethod("android.os.Debug", paramLoadPackageParam.classLoader, "isDebuggerConnected", XC_MethodReplacement.returnConstant(false));
        hookMethodByClassMethodName(Thread.class.getName(), "getStackTrace", new Object[0]);
        hookMethodByClassMethodName(Throwable.class.getName(), "getStackTrace", new Object[0]);
        this.hookMethodByClassMethodName(Modifier.class.getName(), "isNative");
        hookMethodByClassMethodName(File.class.getName(), "lastModified", new Object[0]);
        hookMethodByClassMethodName("com.google.android.gms.ads.identifier.AdvertisingIdClient.Info", "getId");
        hookMethodByClassMethodName(SystemClock.class.getName(), "elapsedRealtime", new Object[0]);
        hookMethodByClassMethodName("java.lang.System", "getProperty");
    }
 
 
    @Override
    protected void afterHookedMethod(XC_MethodHook.MethodHookParam xc_MethodHook$MethodHookParam) throws Throwable {
        int i = 0;
        int v0_2 = 0;
        super.afterHookedMethod(xc_MethodHook$MethodHookParam);
        final String name = xc_MethodHook$MethodHookParam.method.getName();
        if ("getMemoryInfo".equals(name)) {
            final ActivityManager.MemoryInfo activityManager$MemoryInfo = (ActivityManager.MemoryInfo)xc_MethodHook$MethodHookParam.args[0];
            if (this.deviceInfoModel.getMemTotal() > 0L && this.deviceInfoModel.getMemAvailable() > 0L) {
                XposedHelpers.setLongField((Object)activityManager$MemoryInfo, "totalMem", this.deviceInfoModel.getMemTotal());
                XposedHelpers.setLongField((Object)activityManager$MemoryInfo, "availMem", this.deviceInfoModel.getMemAvailable());
            }
        }
 
        else {
            if ("glGetString".equals(name)) {
              final int intValue = (int)xc_MethodHook$MethodHookParam.args[0];
 
                String[] v1_1 = IIl1lIIlll[new Random().nextInt(IIl1lIIlll.length)].split("|");
                if(intValue == 7937) {
                    xc_MethodHook$MethodHookParam.setResult(v1_1[0]);
                }
                if(intValue != 7936) {
                    return;
                }
            }
            else {
                if ("getIntExtra".equals(name)) {
                    final Intent intent = (Intent)xc_MethodHook$MethodHookParam.thisObject;
                    if (!TextUtils.isEmpty((CharSequence)intent.getAction()) && "android.intent.action.BATTERY_CHANGED".equals(intent.getAction()) && "level".equals(xc_MethodHook$MethodHookParam.args[0])) {
                        xc_MethodHook$MethodHookParam.setResult((Object)this.deviceInfoModel.getBatteryLevel());
                    }
                }
     
                else if ("getProperty".equals(name)) {
                    final String s = (String)xc_MethodHook$MethodHookParam.args[0];
           
                    if (s.equals("user.name")) {
                        xc_MethodHook$MethodHookParam.setResult((Object)"");
                    }
                    if (s.equals("java.class.path")) {
                        xc_MethodHook$MethodHookParam.setResult((Object)((String)xc_MethodHook$MethodHookParam.getResult()).replaceAll("XposedBridge.jar", ""));
                    }
                }
                else {
                    if ("getAttributes".equals(name)) {
                        final WindowManager.LayoutParams result2 = (WindowManager.LayoutParams)xc_MethodHook$MethodHookParam.getResult();
                        result2.screenBrightness = (float)(0.01 + 0.01 * Math.random());
 
                        //result2.screenBrightness = (float)0.07;
                        xc_MethodHook$MethodHookParam.setResult((Object)result2);
                        return;
                    }
                    if ("elapsedRealtime".equals(name)) {
                        xc_MethodHook$MethodHookParam.setResult((Object)(1990000L + (System.currentTimeMillis() - this.deviceInfoModel.getBuildUtc())));
                        return;
                    }
                 
 
                    if ("isNative".equals(name)) {
                        xc_MethodHook$MethodHookParam.setResult(false);
                        return;
                    }
 
 
                    if ("getStackTrace".equals(name) && xc_MethodHook$MethodHookParam.getResult() instanceof StackTraceElement[]) {
                        final StackTraceElement[] array = (StackTraceElement[])xc_MethodHook$MethodHookParam.getResult();
                        final LinkedHashMap<Integer, StackTraceElement> linkedHashMap = new LinkedHashMap<Integer, StackTraceElement>();
                        final int length = array.length;
                        int j = 0;
                        int n = 0;
                        int n2 = 0;
                        while (j < length) {
                            final StackTraceElement stackTraceElement = array[j];
                            int n3;
                            if (!stackTraceElement.getClassName().startsWith("org.apache.pog")&&!stackTraceElement.getMethodName().equals("afterHookedMethod") && !stackTraceElement.getMethodName().equals("beforeHookedMethod")) {
                                linkedHashMap.put(n2, stackTraceElement);
                                n3 = n2 + 1;
                            }
                            else {
                                n3 = n2;
                            }
                            if (n != 0 && "getStackTrace".equals(stackTraceElement.getMethodName())) {
                                --n3;
                                linkedHashMap.remove(n3);
                            }
                            if ("getStackTrace".equals(stackTraceElement.getMethodName())) {
                                n = 1;
                            }
                            ++j;
                            n2 = n3;
                        }
                        final StackTraceElement[] result3 = new StackTraceElement[n2];
                        for (int k = 0; k < n2; ++k) {
                            result3[k] = linkedHashMap.get(k);
                        }
                        xc_MethodHook$MethodHookParam.setResult((Object)result3);
                    }
                }
            }
        }
    }

8.WifiHook.java
手机wifi信息的修改,包括名称,地址,速度,是否开启wifi等

hookMethodByClassMethodName(NetworkInfo.class.getName(), "getDetailedState", new Object[0]);
hookMethodByClassMethodName(NetworkInfo.class.getName(), "getExtraInfo", new Object[0]);
hookMethodByClassMethodName(NetworkInfo.class.getName(), "getTypeName", new Object[0]);
hookMethodByClassMethodName(NetworkInfo.class.getName(), "getType", new Object[0]);
hookMethodByClassMethodName(NetworkInfo.class.getName(), "isRoaming", new Object[0]);
hookMethodByClassMethodName(NetworkInfo.class.getName(), "isConnected", new Object[0]);
hookMethodByClassMethodName(NetworkInfo.class.getName(), "isAvailable", new Object[0]);
hookMethodByClassMethodName(NetworkInfo.class.getName(), "isConnectedOrConnecting", new Object[0]);
hookMethodByClassMethodName(NetworkInfo.class.getName(), "getSubtypeName");
hookMethodByClassMethodName(NetworkInfo.class.getName(), "getSubtype");
hookMethodByClassMethodName(ConnectivityManager.class.getName(), "getNetworkInfo", new Object[] { Integer.TYPE.getName() });
hookMethodByClassMethodName(ConnectivityManager.class.getName(), "getMobileDataEnabled", new Object[0]);
//hookMethodByClassMethodName(ConnectivityManager.class.getName(), "getActiveNetworkInfo", new Object[0]);
hookMethodByClassMethodName(NetworkInterface.class.getName(), "getHardwareAddress", new Object[0]);
hookMethodByClassMethodName(NetworkInterface.class.getName(), "getInetAddresses", new Object[0]);
hookMethodByClassMethodName(NetworkInterface.class.getName(), "getInterfaceAddresses", new Object[0]);
hookMethodByClassMethodName(NetworkInterface.class.getName(), "getNetworkInterfaces");
hookMethodByClassMethodName(NetworkInterface.class.getName(), "getName");
hookMethodByClassMethodName(InetAddress.class.getName(), "getHostAddress", new Object[0]);
hookMethodByClassMethodName("android.net.wifi.WifiInfo", "getLinkSpeed");
hookMethodByClassMethodName("android.net.wifi.WifiInfo", "getNetworkId");
hookMethodByClassMethodName("android.net.wifi.WifiInfo", "getRssi");
hookMethodByClassMethodName("android.net.wifi.WifiInfo", "getBSSID");
hookMethodByClassMethodName("android.net.wifi.WifiInfo", "getMacAddress");
hookMethodByClassMethodName("android.net.wifi.WifiInfo", "getSSID");
hookMethodByClassMethodName("android.net.wifi.WifiInfo", "getIpAddress");
hookMethodByClassMethodName("android.net.wifi.WifiManager", "getWifiState");
hookMethodByClassMethodName("android.net.wifi.WifiManager", "isWifiEnabled");
hookMethodByClassMethodName("android.net.wifi.WifiManager", "getDhcpInfo");

9.HideHook.java
xpose防检测等一些代码

XposedHelpers.findAndHookMethod(classLoaderClazz, "loadClass", String.class, new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
            if ("org.apache.pog.qianxun.XposedBridge".equals(param.args[0])) {
                isHookComing = true;
                //Hide
                param.args[0] = null;
            }
        }
    });
    XposedHelpers.findAndHookMethod(classClazz, "getDeclaredField", String.class, new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
            if ("disableHooks".equals(param.args[0])) {
                Log.d(TAG, "\"disableHooks\" found.");
                if (isHookComing) {
                    param.args[0] = null;
                    isHookComing = false;
                }
            }
        }
    });
 
    XposedHelpers.findAndHookMethod(classClazz, "getDeclaredFields", new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            if (XposedBridge.class.equals(param.thisObject)) {
                param.setResult(null);
            }
        }
    });
    Class<?> clazz = null;
    try {
        clazz = Runtime.getRuntime().exec("echo").getClass();
    } catch (IOException ignore) {
    }
    if (clazz != null) {
        XposedHelpers.findAndHookMethod(
                clazz,
                "getInputStream",
                new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) {
                        InputStream is = (InputStream) param.getResult();
                        if (is instanceof FilterXpInputStream) {
                            param.setResult(is);
                        } else {
                            param.setResult(new FilterXpInputStream(is));
                        }
                    }
                }
        );
    }
 
    XposedHelpers.findAndHookMethod(
            Throwable.class,
            "getStackTrace",
            hookStack
    );
    XposedHelpers.findAndHookMethod(
            Thread.class,
            "getStackTrace",
            hookStack
    );
    XC_MethodHook hookClass = new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            String packageName = (String) param.args[0];
            if (packageName.matches("de\\.robv\\.android\\.xposed\\.Xposed+.+")) {
                param.setThrowable(new ClassNotFoundException(packageName));
            }
        }
    };
    // FIXME: 18-6-23 w568w: It's very dangerous to hook these methods, thinking to replace them.
    XposedHelpers.findAndHookMethod(
            ClassLoader.class,
            "loadClass",
            String.class,
            boolean.class,
            hookClass
    );
    XposedHelpers.findAndHookMethod(
            Class.class,
            "forName",
            String.class,
            boolean.class,
            ClassLoader.class,
            hookClass
    );
}
XC_MethodHook hookStack = new XC_MethodHook() {
    @Override
    protected void afterHookedMethod(MethodHookParam param) {
        StackTraceElement[] elements = (StackTraceElement[]) param.getResult();
        List<StackTraceElement> clone = new ArrayList<>();
        for (StackTraceElement element : elements) {
            if (!element.getClassName().toLowerCase().contains("xposed")) {
                clone.add(element);
            }if (!element.getClassName().toLowerCase().contains("ZygoteInit")) {
                clone.add(element);
            }
        }
        param.setResult(clone.toArray(new StackTraceElement[0]));
    }
};

10.BatteryManagerHook.java
电池电量相关的代码

public class BatteryManagerHook extends MethodHook
{
    public BatteryManagerHook(XC_LoadPackage.LoadPackageParam paramLoadPackageParam, DeviceInfoModel deviceInfoModel)
    {
        super(paramLoadPackageParam, deviceInfoModel);
        //电池电量
        hookMethodByClassMethodName("android.os.BatteryManager", "getIntProperty");
    }
 
    @Override
    protected void afterHookedMethod(XC_MethodHook.MethodHookParam xc_MethodHook$MethodHookParam) throws Throwable {
        if ("getIntProperty".equals(xc_MethodHook$MethodHookParam.method.getName())) {
            final int intValue = (int)xc_MethodHook$MethodHookParam.args[0];
            if (intValue == 2) {
                xc_MethodHook$MethodHookParam.setResult((Object)(-306394));
            }
            else if (intValue == 4) {
                xc_MethodHook$MethodHookParam.setResult((Object)this.deviceInfoModel.getBatteryLevel());
            }
        }
        super.afterHookedMethod(xc_MethodHook$MethodHookParam);
    }
 
    protected void beforeHookedMethod(XC_MethodHook.MethodHookParam paramMethodHookParam) throws Throwable {
        super.beforeHookedMethod(paramMethodHookParam);
    }
}

最终效果

四.总结
本节课我们讲解了xpose改机的优缺点,介绍了改机常用的三种方案,包括一些xpose的改机点以及这些改机点如何去寻找,由于本节课代码量比较多,希望你课下好好去消化一下,想做一款好的改机每一个hook点最好都去看一下对应的Android源码,看一下代码底层是怎么实现的,有没有其他更好的方式去修改它。


课后作业
1.利用xpose开发一款自己的改机软件
2.分析每一个改机点的源代码
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1418819.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

isctf---re

crackme 解压得到crackme.exe 运行得到flag babyRe 先猜e65537的rsa 先用Z3强行求出p、q&#xff0c;算出常规rsa中的phi&#xff0c;然后套用公式求出m exp #babyre wp from z3 import * import libnum from Crypto.Util.number import * p,q,cInts(p q c) S Solver() S…

【前端web入门第一天】02 HTML图片标签 超链接标签 音频标签 视频标签

文章目录: 1.HTML图片标签 1.1 图像标签-基本使用1.2 图像标签-属性1.3 路径 1.3.1 相对路径 1.3.2 绝对路径 2.超链接标签 3.音频标签 4.视频标签 1.HTML图片标签 1.1 图像标签-基本使用 作用:在网页中插入图片。 <img src"图片的URL">src用于指定图像…

前端框架---Vue2学习教程(上)

从HTML到现在一路跟过来的小伙伴们&#xff0c;坚持固然不容易&#xff0c;但我相信大家已经学到了不少&#xff0c;那么我们开始马不停蹄的进入前端的框架吧&#xff0c;下面讲的是Vue2&#xff0c;大家继续加油鸭&#xff01;&#xff01;&#xff01;&#xff01; Vue2 Vu…

遗传算法优化最大化效应的某些需求点可不配送的vrptw问题

标题&#xff1a;遗传算法优化最大化效应的某些需求点可不配送的vrptw问题 摘要&#xff1a; 在可不配送的车辆路径配送问题&#xff08;VRPTW&#xff09;中&#xff0c;我们面临着优化路径规划以最大化效用的挑战。本文提出了一种基于遗传算法的方法&#xff0c;旨在解决具…

【Shell实战案例面试题】输入网卡的名字,来输出网卡的IP

1.问题 参数后判断要加"" 名字为空时显示ip 2.分析 把本机的所有网卡名列出来&#xff0c;来引导用户输入 使用命令列出所有网卡信:ifconfig/ip a 设计一个函数&#xff0c;把网卡名作为参数&#xff0c;函数返回网卡的IP 在获取某个网卡IP时&#xff0c;考虑网…

Redis面试(三)

1.Redis报内存不足怎么处理 Redis内存不足的集中处理方式&#xff1a; 修改配置文件redis.cof的maxmemory参数&#xff0c;增加Redis的可用内存通过命令修改set maxmemory动态设置内存上限修改内存淘汰策略&#xff0c;及时释放内存使用Redis集群&#xff0c;及时进行扩容 2…

基于springboot的美发管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

让Unity迭代器性能提升5倍

最近在研究Unity il2cpp的代码生成和编译优化&#xff0c;结合之前遇到过的一个优化案例&#xff0c;给大家讲讲在Unity中迭代器相关代码生成的底层原理&#xff0c;以及在写代码过程中需要注意的一些特殊情况。 案例 首先我们来看一个非常简单的案例&#xff0c;代码如下&am…

3338 蓝桥杯 wyz的数组IV 简单

3338 蓝桥杯 wyz的数组IV 简单 //C风格解法1&#xff0c;通过率50% #include<bits/stdc.h>int main(){std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout.tie(nullptr);int n; std::cin >> n;int ans 0;std::vector<int>a(n);for(auto &am…

Docker本地部署APITable结合内网穿透实现公网访问

文章目录 前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台&#xff0c;是一款面向 API 的智能多维表格。它将复杂的可视化数据库、电子表格、实时在线协同、低代码开发技术四合为一&am…

【C语言】socket编程接收问题

一、recv()函数接收到的返回值为0表示对端已经关闭 在TCP套接字编程中&#xff0c;通过recv()函数接收到的返回值为0通常表示对端已经关闭了套接字的发送部分。这是因为TCP是一个基于连接的协议&#xff0c;其中有定义明确的连接建立和终止流程&#xff1b;当对端调用close()或…

C语言指针进阶(1)(超详细)

前言&#xff1a; 指针其实就是地址&#xff0c;而凡是存储在内存中的值都会有属于自己的地址&#xff0c;指针指向地址&#xff0c;这样我们就能通过指针间接操作变量。我们在指针初阶中介绍了指针的基本概念&#xff1a;如指针大小、野指针问题、指针间的关系运算等&#xff…

Hugging Face创始人分享:企业如何在ChatGPT浪潮下实现战略布局

Hugging Face创始人兼首席执行官 Clem Delangue在IBM一年一度的 THINK大会中研讨了当前人工智能发展趋势&#xff0c;特别是ChatGPT模型以及其对行业的影响。他的演讲还涉及到一个关键的议题&#xff0c;在ChatGPT这样的通用模型出现后&#xff0c;企业如何在人工智能领域找到自…

自定义vue通用左侧菜单组件(未完善版本)

使用到的技术: vue3、pinia、view-ui-plus 实现的功能: 传入一个菜单数组数据,自动生成一个左侧菜单栏。菜单栏可以添加、删除、展开、重命名,拖动插入位置等。 效果预览: 代码: c-menu-wrap.vue <template><div class="main-container">&l…

【嵌入式学习】C++QT-Day3-C++基础

笔记 见我的博客&#xff1a;https://lingjun.life/wiki/EmbeddedNote/19Cpp 作业 设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函…

当包容结构体遇见灵活的内存管理

&#x1f308;个人主页&#xff1a;小田爱学编程 &#x1f525; 系列专栏&#xff1a;c语言从基础到进阶 &#x1f3c6;&#x1f3c6;关注博主&#xff0c;随时获取更多关于c语言的优质内容&#xff01;&#x1f3c6;&#x1f3c6; &#x1f600;欢迎来到小田代码世界~ &#x…

课时7:shell基础_shell简介

1.3.1 shell简介 学习目标 这一节&#xff0c;我们从 运维、shell语言、小结 三个方面来学习。 运维 简介 运维是什么&#xff1f;所谓的运维&#xff0c;其实就是公司的内部项目当中的一个技术岗位而已&#xff0c;它主要做的是项目的维护性工作。它所涉及的内容范围非常…

方法、数组

方法 是语句的集合&#xff0c;在一起执行一个功能 它是解决一类问题的步骤的有序集合 包含于类或对象中 在程序中创建&#xff0c;在其他地方被引用 设计方法的原则&#xff1a;方法的本意是功能块&#xff0c;就是实现某一个功能的语句块的集合。设计时&#xff0c;最好保持…

基于go mod模式创建项目最佳实践

希望能带给你成功的喜悦&#xff01; 除go get、vendor这两种方式外&#xff0c;Go版本在1.11之后推出了go module模式来管理依赖&#xff0c;使用go mod时下载的依赖文件在$GOPATH/pkg/mod/下。本文以两种办法介绍如何创建go mod项目。 目录 goland开启玩法 本地手动创建项目…

###C语言程序设计-----C语言学习(6)#

前言&#xff1a;感谢老铁的浏览&#xff0c;希望老铁可以一键三连加个关注&#xff0c;您的支持和鼓励是我前进的动力&#xff0c;后续会分享更多学习编程的内容。 一. 主干知识的学习 1. while语句 除了for语句以外&#xff0c;while语句也用于实现循环&#xff0c;而且它…