吾爱破解安卓逆向入门教程学习

00x1 校验

apk签名

看app包名

复制代码
    .line 194
    invoke-virtual {p1}, Landroid/content/pm/PackageManager$NameNotFoundException;->printStackTrace()V

    const-string p1, ""

    return-object p1
.end method

.method protected onCreate(Landroid/os/Bundle;)V
    .registers 13

    .line 38
    invoke-super {p0, p1}, Landroidx/appcompat/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V

    const p1, 0x7f0b001c

    .line 39
    invoke-virtual {p0, p1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->setContentView(I)V

    const p1, 0x7f08006d

    .line 40
    invoke-virtual {p0, p1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object p1

    check-cast p1, Landroid/widget/Button;

    const v0, 0x7f08006c

    .line 41
    invoke-virtual {p0, v0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v0

    move-object v2, v0

    check-cast v2, Landroid/widget/TextView;

    const v0, 0x7f08006a

    .line 42
    invoke-virtual {p0, v0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v0

    move-object v4, v0

    check-cast v4, Landroid/widget/TextView;

    const v0, 0x7f080066

    .line 43
    invoke-virtual {p0, v0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v0
java 复制代码
.method protected onCreate(Landroid/os/Bundle;)V
    .registers 13

    .line 38
    invoke-super {p0, p1}, Landroidx/appcompat/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V

    const p1, 0x7f0b001c

    .line 39
    invoke-virtual {p0, p1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->setContentView(I)V

    const p1, 0x7f08006d

    .line 40
    invoke-virtual {p0, p1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object p1

    check-cast p1, Landroid/widget/Button;

    const v0, 0x7f08006c

    .line 41
    invoke-virtual {p0, v0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v0

    move-object v2, v0

    check-cast v2, Landroid/widget/TextView;

    const v0, 0x7f08006a

    .line 42

也就是说他的xml本身就是不同的用处,你不是一个xml有不同的东西。

java 复制代码
 protected void onCreate(Bundle bundle) {
//oncreate 消息响应函数,是用来"表示一个窗口正在生成"。
//标准动作,恢复保存,框架启动
        super.onCreate(bundle);
//显示视图
//2131427356 xml视图
//加载视图内容
        setContentView(2131427356);
//‌findViewById 是 Android 开发中用于在布局文件中查找并获取视图组件的核心方法
//查找核心组件
//寻找上面的东西 
//xml类型bt
        Button button = (Button) findViewById(2131230829);
        TextView textView = (TextView) findViewById(2131230828);
        TextView textView2 = (TextView) findViewById(2131230826);
        TextView textView3 = (TextView) findViewById(2131230822);
        TextView textView4 = (TextView) findViewById(2131230824);
        TextView textView5 = (TextView) findViewById(2131230827);
        TextView textView6 = (TextView) findViewById(2131230825);
//long转换
//字符串xml
        long parseLong = Long.parseLong(getString(2131755054));
//获取hase
        getHash();
//视图监听
        button.setOnClickListener(new ExternalSyntheticLambda0(textView, this, textView2, textView3, textView6, textView4, parseLong, textView5));
    }
java 复制代码
private final void getHash() {
//ServiceCreator创建代理
//create创建
//获取Hash,enqueue((Callback) new 1(this)执行网络请求
        ((AppService) ServiceCreator.INSTANCE.create(AppService.class)).getAppHash().enqueue((Callback) new 1(this));
    }
java 复制代码
.method protected onCreate(Landroid/os/Bundle;)V
    .registers 15

    .line 44
    invoke-super {p0, p1}, Landroidx/appcompat/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V

    const p1, 0x7f0b001c

    .line 45
    invoke-virtual {p0, p1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->setContentView(I)V

    const p1, 0x7f080076

    .line 46
    invoke-virtual {p0, p1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object p1

    check-cast p1, Landroid/widget/Button;

    const v0, 0x7f080062

    .line 47
    invoke-virtual {p0, v0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    const v1, 0x7f080075

    .line 48
    invoke-virtual {p0, v1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v1

    move-object v3, v1

    check-cast v3, Landroid/widget/TextView;

    const v1, 0x7f080073

    .line 49
    invoke-virtual {p0, v1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v1

    move-object v5, v1

    check-cast v5, Landroid/widget/TextView;

    const v1, 0x7f08006e

    .line 50
    invoke-virtual {p0, v1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v1

    move-object v6, v1

    check-cast v6, Landroid/widget/TextView;

    const v1, 0x7f080070

    .line 51
    invoke-virtual {p0, v1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v1

    move-object v8, v1

    check-cast v8, Landroid/widget/TextView;

    const v1, 0x7f080074

    .line 52
    invoke-virtual {p0, v1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v1

    move-object v11, v1

    check-cast v11, Landroid/widget/TextView;

    const v1, 0x7f080072

    .line 53
    invoke-virtual {p0, v1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v1

    move-object v7, v1

    check-cast v7, Landroid/widget/TextView;

    const v1, 0x7f080071

    .line 54
    invoke-virtual {p0, v1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->findViewById(I)Landroid/view/View;

    move-result-object v1

    move-object v12, v1

    check-cast v12, Landroid/widget/TextView;

    const v1, 0x7f10002f

    .line 55
    invoke-virtual {p0, v1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->getString(I)Ljava/lang/String;

    move-result-object v1

    invoke-static {v1}, Ljava/lang/Long;->parseLong(Ljava/lang/String;)J

    move-result-wide v9

    .line 56
    move-object v1, p0

    check-cast v1, Landroid/content/Context;

    invoke-direct {p0, v1}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->checkSign(Landroid/content/Context;)Z

    move-result v2

    if-nez v2, :cond_79

    const/4 v2, 0x0

    .line 57
    invoke-static {v2}, Ljava/lang/System;->exit(I)V

    .line 59
    :cond_79
    invoke-virtual {p0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->check_root()Z

    move-result v2

    if-eqz v2, :cond_8b

    const-string v2, "root"

    .line 60
    check-cast v2, Ljava/lang/CharSequence;

    const/4 v4, 0x1

    invoke-static {v1, v2, v4}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v1

    invoke-virtual {v1}, Landroid/widget/Toast;->show()V

    .line 62
    :cond_8b
    sget-object v1, Lcom/zj/wuaipojie/ui/ChallengeFifth$$ExternalSyntheticLambda1;->INSTANCE:Lcom/zj/wuaipojie/ui/ChallengeFifth$$ExternalSyntheticLambda1;

    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    .line 67
    invoke-direct {p0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->getHash()V

    .line 68
    invoke-direct {p0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->getappsign()Ljava/lang/String;

    .line 69
    new-instance v0, Lcom/zj/wuaipojie/ui/ChallengeFifth$$ExternalSyntheticLambda0;

    move-object v2, v0

    move-object v4, p0

    invoke-direct/range {v2 .. v12}, Lcom/zj/wuaipojie/ui/ChallengeFifth$$ExternalSyntheticLambda0;-><init>(Landroid/widget/TextView;Lcom/zj/wuaipojie/ui/ChallengeFifth;Landroid/widget/TextView;Landroid/widget/TextView;Landroid/widget/TextView;Landroid/widget/TextView;JLandroid/widget/TextView;Landroid/widget/TextView;)V

    invoke-virtual {p1, v0}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    return-void
.end method
java 复制代码
protected void onCreate(Bundle bundle) {
//启动框架,生成窗口
        super.onCreate(bundle);
//加载渲染
        setContentView(2131427356);
//寻找组件xml
        Button button = (Button) findViewById(2131230838);
        Button button2 = (Button) findViewById(2131230818);
        TextView textView = (TextView) findViewById(2131230837);
        TextView textView2 = (TextView) findViewById(2131230835);
        TextView textView3 = (TextView) findViewById(2131230830);
        TextView textView4 = (TextView) findViewById(2131230832);
        TextView textView5 = (TextView) findViewById(2131230836);
        TextView textView6 = (TextView) findViewById(2131230834);
        TextView textView7 = (TextView) findViewById(2131230833);
//寻找字符串xml,long转换
        long parseLong = Long.parseLong(getString(2131755055));
//获取上下文(字典管理,环境管理,资源地址),类似session
        Context context = (Context) this;
//没有签名验证函数
        if (!checkSign(context)) {
//这里,退出
            System.exit(0);
        }
//检查包含,root,以及兼容
        if (check_root()) {
//输出
            Toast.makeText(context, "root", 1).show();
        }
//事件监听
        button2.setOnClickListener(ExternalSyntheticLambda1.INSTANCE);
//获取哈希
        getHash();
        getappsign();
        button.setOnClickListener(new ExternalSyntheticLambda0(textView, this, textView2, textView3, textView6, textView4, parseLong, textView5, textView7));
    }

关键

可以改一下

java 复制代码
private final boolean checkSign(Context context) {
        try {
//遍历
//getPackageInfo 是一个在多个平台中用于获取应用包(Package)信息的函数
//获取应用签名(一般只有一个)
            for (Signature signature : context.getPackageManager().getPackageInfo(context.getPackageName(), 64).signatures) {
//获取对象
                MessageDigest instance = MessageDigest.getInstance("SHA");
//更新转化
                instance.update(signature.toByteArray());
//instance.digest() 是 Java 中 MessageDigest 对象的方法,用于完成哈希计算并返回最终的摘要字节数组(byte[])
//转化字符串
                String encodeToString = Base64Utils.INSTANCE.encodeToString(instance.digest());

                Log.e("zj2595", "sign:" + encodeToString);
//可以调试伪造,调试法,对比
                if (!Intrinsics.areEqual(this.SIGNATURE, encodeToString)) {
                    return false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
java 复制代码
private final String SIGNATURE = "h99Ici0iopj8tC6NkfqyJgs73ss=";
java 复制代码
invoke-virtual {调用者, 参数...}, 方法的所属类;->方法名(参数类型)返回值类型
格式

所以把v0改成1,就是一种很诡异的绕过,因为签名输出越过导致异常报错,而异常报错又会返回t

或者替换硬编码

还有改跳转逻辑

java 复制代码
method public final checkSignature(Landroid/content/Context;Ljava/lang/String;)Z
    .registers 6
//修改这里
    const/4 v0, 0x0
//Signature signature : context.getPackageManager().getPackageInfo(context.getPackageName(), 64).signatures
    .line 285
    :try_start_1//开始符号,try开始
//invoke-virtual调用虚方法,(可以被子类重写的方法,也就是普通的非静态、非私有、非构造方法)
//p1 拥有这个方法的对象
//context.getPackageManager()
//invoke-virtual {p1}, Landroid/content/Context对象调用方法所在的类
//getPackageManager//方法名()参数列表(传参)//Landroid/content/pm/PackageManager;//返回类型
    invoke-virtual {p1}, Landroid/content/Context;->getPackageManager()Landroid/content/pm/PackageManager;

//在方法调用后获取并存储返回的‌对象引用‌。
//上面产生的结果存储
//存储v1
    move-result-object v1

    .line 286
//调用

    invoke-virtual {p1}, Landroid/content/Context;->getPackageName()Ljava/lang/String;
//存储
    move-result-object p1


//赋值64
    const/16 v2, 0x40
//context.getPackageManager(),context.getPackageName(),64
//getPackageInfo
//v1调用者,p1, v2传参
//context.getPackageManager().getPackageInfo(context.getPackageName(), 64).signatures
    invoke-virtual {v1, p1, v2}, Landroid/content/pm/PackageManager;->getPackageInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;

//存储
    move-result-object p1

    .line 287
// iget-object指令类型
//p1目标寄存器(存储的地方),p1源寄存器从字段上面读取
//一个p1存储特定结果,一个p1存储所有结果
//同一个,覆盖获取
//context.getPackageName()
    iget-object p1, p1, Landroid/content/pm/PackageInfo;->signatures:[Landroid/content/pm/Signature;

//赋值
    const-string v1, "SHA-256"

// MessageDigest instance = MessageDigest.getInstance("SHA");
//MessageDigest.getInstance
    .line 288
    invoke-static {v1}, Ljava/security/MessageDigest;->getInstance(Ljava/lang/String;)Ljava/security/MessageDigest;

//存储
    move-result-object v1

    .line 289
// instance.update(signature.toByteArray());
//aget-object p1, p1, v0 是 Smali 语法指令,表示从对象数组 p1 的索引 v0 处获取一个对象引用,并存回 p1。‌‌
//for (Signature signature : //context.getPackageManager().getPackageInfo(context.getPackageName(), 64).signatures)
   
//p1=p1[p0]
//因为for循环
     aget-object p1, p1, v0
//
    invoke-virtual {p1}, Landroid/content/pm/Signature;->toByteArray()[B
//存储
    move-result-object p1
//instance.update(signature.toByteArray());
    invoke-virtual {v1, p1}, Ljava/security/MessageDigest;->update([B)V

    .line 290
//instance.digest()
    invoke-virtual {v1}, Ljava/security/MessageDigest;->digest()[B
//存储
    move-result-object p1
//赋值
    const-string v1, "zj595"

    .line 291
//sget-object 是 Smali(Android Dalvik 字节码)中用于从静态字段读取对象引用并存入寄存器的指令
//Base64Utils.INSTANCE.encodeToString(instance.digest());

    sget-object v2, Lcom/zj/wuaipojie/util/Base64Utils;->INSTANCE:Lcom/zj/wuaipojie/util/Base64Utils;

//Base64Utils.INSTANCE.instance.digest() 
///Base64Utils.INSTANCE.encodeToString(instance.digest()); 
//
    invoke-virtual {v2, p1}, Lcom/zj/wuaipojie/util/Base64Utils;->encodeToString([B)Ljava/lang/String;

//存储
    move-result-object v2

//调用静态方法传入寄存器
//String encodeToString = Base64Utils.INSTANCE.encodeToString(instance.digest());
 //  Log.e("zj2595", "sign:" + encodeToString);
    invoke-static {v1, v2}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I

    .line 292
// if (!Intrinsics.areEqual(this.SIGNATURE, encodeToString)) {
                   // return false;
                //}
//
    sget-object v1, Lcom/zj/wuaipojie/util/Base64Utils;->INSTANCE:Lcom/zj/wuaipojie/util/Base64Utils;

//静态方法调用,p2是参数,v1调用者
//decode解码

//p2被解码
    invoke-virtual {v1, p2}, Lcom/zj/wuaipojie/util/Base64Utils;->decode(Ljava/lang/String;)[B

//存储
    move-result-object p2

    .line 293
//对比
//V数组
//Z返回值
    invoke-static {p1, p2}, Ljava/util/Arrays;->equals([B[B)Z
//存储结果
    move-result p1
//try
    :try_end_39
    .catch Ljava/lang/Exception; {:try_start_1 .. :try_end_39} :catch_3a

//返回对比结果
    return p1
//出错
    :catch_3a
//返回 v0
    return v0
.end method
java 复制代码
· Smali 版:p2 解码,两个 byte[] 比。
· Java 版:p1 编码,两个 String 比。
java 复制代码
public final boolean check_root() {
//有一个不满足才可以
        if (!(checkRootMethod1() || checkRootMethod2())) {
            if (!checkRootMethod3()) {
                return false;
            }
        }
        return true;
    }
java 复制代码
public final boolean checkRootMethod1() {
//在 Android(Java/Kotlin)中‌:android.os.Build.TAGS 是一个‌运行时字符串‌(如 "release-keys" 或 "test-keys"),表示系统镜像的签名类型,由系统编译时设定,‌非可编程构建标签‌。
        String str = Build.TAGS;
//不是空,并且检查包含,忽略大小写,没有默认参数
//$default编译自带
//所以掩码只是一个机制,默认的时候有用。
        return str != null && StringsKt.contains$default(str, "test-keys", false, 2, null);
    }
java 复制代码
public final boolean checkRootMethod2() {
        /*
        // Can't load method instructions: Load method exception: android.s.ۦۤ۟ۨ cannot be cast to android.s.yv in method: com.zj.wuaipojie.ui.ChallengeFifth.checkRootMethod2():boolean, dex: 
        */
//nsupportedOperationException是一个运行时异常,通常在尝试对不支持操作的集合或数据结构执行某些操作时抛出。
//检查兼容
        throw new UnsupportedOperationException("Method not decompiled: com.zj.wuaipojie.ui.ChallengeFifth.checkRootMethod2():boolean");
    }
java 复制代码
public final boolean checkRootMethod3() {
        boolean z = false;
        Process process = null;
        try {
//代码执行
//检查环境是不是root
            process = Runtime.getRuntime().exec(new String[]{"/system/xbin/which", "su"});
//一行一行读取数据流
            if (new BufferedReader(new InputStreamReader(process.getInputStream())).readLine() != null) {
                z = true;
            }
        } catch (Throwable unused) {
            if (process != null) {
                process.destroy();
            }
//返回
            return z;
        }
    }

pm代理

原包签名信息

io重定向

校验代码

java 复制代码
   public static final void m455onCreate$lambda1(TextView textView, ChallengeFifth challengeFifth, TextView textView2, TextView textView3, TextView textView4, TextView textView5, long j, TextView textView6, TextView textView7, View view) {
//获取挑战五
        ChallengeFifth challengeFifth2 = challengeFifth;
        String str = "通过";
        textView.setText(challengeFifth.checkSign(challengeFifth2) ? str : "不通过");
        textView2.setText(challengeFifth.checkPMProxy() ? str : "不通过");
        textView3.setText(challengeFifth.checkApplication() ? str : "不通过");
        textView4.setText(challengeFifth.useNewAPICheck() ? str : "不通过");
        textView5.setText(challengeFifth.check_crc(j) ? str : "不通过");
        textView6.setText(challengeFifth.check_Hash(challengeFifth2) ? str : "不通过");
        if (!SecurityUtil.getSecret(challengeFifth2)) {
            str = "不通过";
        }
        textView7.setText(str);
    }

普通签名校验

java 复制代码
//签名校验
    
private final boolean checkSign(Context context) {
        Signature[] signatureArr;
        try {
//遍历签名,获取包信息下面的签名
            for (Signature signature : context.getPackageManager().getPackageInfo(context.getPackageName(), 64).signatures) {
//获取类
                MessageDigest messageDigest = MessageDigest.getInstance("SHA");
//更新,添加字节签名
                messageDigest.update(signature.toByteArray());
//字符串化
//MessageDigest.digest() 是 Java 中 java.security.MessageDigest 类的方法,用于完成哈希计算并返回固定长度的字节数组
                String encodeToString = Base64Utils.INSTANCE.encodeToString(messageDigest.digest());
                Log.e("zj2595", "sign:" + encodeToString);
//对比
                if (!Intrinsics.areEqual(this.SIGNATURE, encodeToString)) {
                    return false;
                }
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
    }

// 系统源码 android.app.ApplicationPackageManager

IPackageManager mPM; // 这个是真正的系统服务接口

```

它存在于系统框架层,不在你的 APK 反编译代码里,所以搜索当前代码找不到。

java 复制代码
    private final boolean checkPMProxy() {
        String str;
        try {
//获取实例
//getPackageManager() 是 Android Context 中的方法,用于获取 PackageManager 实例,以访问设备上已安装应用的元数据(如版本、权限、图标等)
            PackageManager packageManager = getPackageManager();
//反射获取字段
//反射机制中用于获取类指定字段的方法,能访问包括私有字段在内的所有字段,但不包含继承的字段‌。‌‌‌
            Field declaredField = packageManager.getClass().getDeclaredField("mPM");
//setAccessible‌ 是 Java 反射中 AccessibleObject 类提供的方法,主要用于批量或单独设置访问权限标志,‌开启后能绕过语言的访问控制检查
//暴力获取私有字段开关
            declaredField.setAccessible(true);
//‌packageManager‌ 通常指 ‌Android 开发中的核心管理类‌
//获取类名
            str = declaredField.get(packageManager).getClass().getName();
        } catch (Exception e) {
            e.printStackTrace();
            str = "";
        }
//返回比较(替换法?)
        return Intrinsics.areEqual("android.content.pm.IPackageManager$Stub$Proxy", str);
    }
java 复制代码
  private final boolean checkApplication() {
//获取上下文类简短名称,比较
        return Intrinsics.areEqual("MainApplication", getApplication().getClass().getSimpleName());
    }
java 复制代码
private final boolean useNewAPICheck() {
        String str;
        Signature[] signatureArr;
        try {
            if (Build.VERSION.SDK_INT >= 28) {
                signatureArr = getPackageManager().getPackageInfo(getPackageName(), 134217728).signingInfo.getApkContentsSigners();
            } else {
                signatureArr = getPackageManager().getPackageInfo(getPackageName(), 64).signatures;
            }
            str = MD5Utils.INSTANCE.MD5(Base64Utils.INSTANCE.encodeToString(signatureArr[0].toByteArray()));
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            str = "";
        }
//这里拼接str
        Log.e("zj2595", "newsign:" + str);
//这里比较,硬编码,直接改
        return Intrinsics.areEqual("074f64af5821ae6aa1ac1779ad5687ad", str);
    }

    public final boolean check_crc(long j) {
        try {
            ZipEntry entry = new ZipFile(getPackageCodePath()).getEntry("classes.dex");
            Log.e("zj2595", "dexCrc:" + entry.getCrc());
            return entry.getCrc() == j;
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
    }
java 复制代码
public static /* synthetic */ void $r8$lambda$9qXr8aOuCuEvSBHyRMO0tTgIToY(TextView textView, ChallengeFifth challengeFifth, TextView textView2, TextView textView3, TextView textView4, TextView textView5, long j, TextView textView6, TextView textView7, View view) {
        m455onCreate$lambda1(textView, challengeFifth, textView2, textView3, textView4, textView5, j, textView6, textView7, view);
    }
java 复制代码
public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_challenge_fifth);
        Button button = (Button) findViewById(R.id.check_sign_btn);
        Button button2 = (Button) findViewById(R.id.btn_smali);
        final TextView textView = (TextView) findViewById(R.id.check_sign);
        final TextView textView2 = (TextView) findViewById(R.id.check_pm);
        final TextView textView3 = (TextView) findViewById(R.id.check_application);
        final TextView textView4 = (TextView) findViewById(R.id.check_crc);
        final TextView textView5 = (TextView) findViewById(R.id.check_sha1);
        final TextView textView6 = (TextView) findViewById(R.id.check_new_sign);
        final TextView textView7 = (TextView) findViewById(R.id.check_native_sign);
//这里
//每一次修改编译打包后会变化
// public static final int crc = 0x7f10002f;硬编码的j

        final long parseLong = Long.parseLong(getString(R.string.crc));
        ChallengeFifth challengeFifth = this;
        if (!checkSign(challengeFifth)) {
            System.exit(0);
        }
        if (check_root()) {
            Toast.makeText(challengeFifth, "root", 1).show();
        }
        button2.setOnClickListener(ChallengeFifth$$ExternalSyntheticLambda1.INSTANCE);
        getHash();
        getappsign();
        button.setOnClickListener(new View.OnClickListener() { // from class: com.zj.wuaipojie.ui.ChallengeFifth$$ExternalSyntheticLambda0
            @Override // android.view.View.OnClickListener
            public final void onClick(View view) {
//这玩意儿被混淆了,也不知道为什么他没有被混淆。
//以后遇到这样我该怎么回溯?
                ChallengeFifth.$r8$lambda$9qXr8aOuCuEvSBHyRMO0tTgIToY(textView, this, textView2, textView3, textView6, textView4, parseLong, textView5, textView7, view);
            }
        });
    }
java 复制代码
    public final boolean check_crc(long j) {
        try {
//获取压缩包classes.dex
            ZipEntry entry = new ZipFile(getPackageCodePath()).getEntry("classes.dex");
            Log.e("zj2595", "dexCrc:" + entry.getCrc());
//getCrc()‌ 返回该压缩条目的 ‌CRC-32 校验和(long 类型)‌,用于校验解压后数据完整性
//根据
//改返回
//entry.getCrc()会变动
            return entry.getCrc() == j;
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
    }
java 复制代码
public final boolean check_Hash(Context context) {
        String apkPath = getApkPath(this);
        FileInputStream fileInputStream = null;
        try {
            try {
                MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
                byte[] bArr = new byte[1024];
                Ref.IntRef intRef = new Ref.IntRef();
                FileInputStream fileInputStream2 = new FileInputStream(new File(apkPath));
                while (true) {
                    try {
                        int read = fileInputStream2.read(bArr);
                        intRef.element = read;
                        if (read <= 0) {
                            break;
                        }
                        messageDigest.update(bArr, 0, intRef.element);
                    } catch (Exception e) {
                        e = e;
                        fileInputStream = fileInputStream2;
                        e.printStackTrace();
                        if (fileInputStream != null) {
                            try {
                                fileInputStream.close();
                            } catch (IOException e2) {
                                e2.printStackTrace();
                            }
                        }
                        return false;
                    } catch (Throwable th) {
                        th = th;
                        fileInputStream = fileInputStream2;
                        if (fileInputStream != null) {
                            try {
                                fileInputStream.close();
                            } catch (IOException e3) {
                                e3.printStackTrace();
                            }
                        }
                        throw th;
                    }
                }
                String bigInteger = new BigInteger(1, messageDigest.digest()).toString(16);
                Log.e("zj2595", "hash:" + bigInteger);
                boolean areEqual = Intrinsics.areEqual(bigInteger, this.ApkHash);
                try {
                    fileInputStream2.close();
                } catch (IOException e4) {
                    e4.printStackTrace();
                }
                return areEqual;
            } catch (Throwable th2) {
                th = th2;
            }
        } catch (Exception e5) {
            e = e5;
        }
    }
java 复制代码
 public static native boolean getSecret(Context context)

hook

java 复制代码
sget-object p10, Lcom/zj/wuaipojie/util/ContextUtils;->INSTANCE:Lcom/zj/wuaipojie/util/ContextUtils;
invoke-virtual {p10}, Lcom/zj/wuaipojie/util/ContextUtils;->getContext()Landroid/content/Context;
move-result-object p10
invoke-static {p10}, Lcom/zj/wuaipojie/util/SecurityUtil;->hook(Landroid/content/Context;)V

java对应

java 复制代码
// 1. 拿到 ContextUtils 这个单例工具的实例
ContextUtils utils = ContextUtils.INSTANCE;

// 2. 调用它的 getContext() 方法,获取 Application 级别的上下文
Context appContext = utils.getContext();

// 3. 把上下文传进去,执行核心的攻击逻辑
SecurityUtil.hook(appContext);

从定向肯定是校验之前就已经转走了。

java 复制代码
.line 75
    invoke-virtual {p1, p6, p7}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->check_crc(J)Z

    move-result p0

    if-eqz p0, :cond_47

    move-object p0, v1

    goto :goto_48

    :cond_47
    move-object p0, v2

    :goto_48
    check-cast p0, Ljava/lang/CharSequence;

    invoke-virtual {p5, p0}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 76
    invoke-virtual {p1, p10}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->check_Hash(Landroid/content/Context;)Z

    move-result p0

    if-eqz p0, :cond_55

    move-object p0, v1

    goto :goto_56

    :cond_55
    move-object p0, v2

    :goto_56
    check-cast p0, Ljava/lang/CharSequence;

    invoke-virtual {p8, p0}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 77
    invoke-static {p10}, Lcom/zj/wuaipojie/util/SecurityUtil;->getSecret(Landroid/content/Context;)Z

    move-result p0

    if-eqz p0, :cond_62

    goto :goto_63

    :cond_62
    move-object v1, v2

    :goto_63
    check-cast v1, Ljava/lang/CharSequence;

    invoke-virtual {p9, v1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    return-void
.end method

.method private final useNewAPICheck()Z
    .registers 4

    .line 156
    :try_start_0
    sget v0, Landroid/os/Build$VERSION;->SDK_INT:I

    const/16 v1, 0x1c

    if-lt v0, v1, :cond_1b

    .line 157
    invoke-virtual {p0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->getPackageManager()Landroid/content/pm/PackageManager;

    move-result-object v0

    .line 158
    invoke-virtual {p0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->getPackageName()Ljava/lang/String;

    move-result-object v1

    const/high16 v2, 0x8000000

    .line 157
    invoke-virtual {v0, v1, v2}, Landroid/content/pm/PackageManager;->getPackageInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;

    move-result-object v0

    .line 161
    iget-object v0, v0, Landroid/content/pm/PackageInfo;->signingInfo:Landroid/content/pm/SigningInfo;

    invoke-virtual {v0}, Landroid/content/pm/SigningInfo;->getApkContentsSigners()[Landroid/content/pm/Signature;

    move-result-object v0

    goto :goto_2b

    .line 163
    :cond_1b
    invoke-virtual {p0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->getPackageManager()Landroid/content/pm/PackageManager;

    move-result-object v0

    .line 164
    invoke-virtual {p0}, Lcom/zj/wuaipojie/ui/ChallengeFifth;->getPackageName()Ljava/lang/String;

    move-result-object v1

    const/16 v2, 0x40

    .line 163
    invoke-virtual {v0, v1, v2}, Landroid/content/pm/PackageManager;->getPackageInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;

    move-result-object v0

    .line 167
    iget-object v0, v0, Landroid/content/pm/PackageInfo;->signatures:[Landroid/content/pm/Signature;

    .line 169
    :goto_2b
    sget-object v1, Lcom/zj/wuaipojie/util/Base64Utils;->INSTANCE:Lcom/zj/wuaipojie/util/Base64Utils;

    const/4 v2, 0x0

    aget-object v0, v0, v2

    invoke-virtual {v0}, Landroid/content/pm/Signature;->toByteArray()[B

    move-result-object v0

    invoke-virtual {v1, v0}, Lcom/zj/wuaipojie/util/Base64Utils;->encodeToString([B)Ljava/lang/String;

    move-result-object v0

    .line 170
    sget-object v1, Lcom/zj/wuaipojie/util/MD5Utils;->INSTANCE:Lcom/zj/wuaipojie/util/MD5Utils;

    invoke-virtual {v1, v0}, Lcom/zj/wuaipojie/util/MD5Utils;->MD5(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v0
    :try_end_3e
    .catch Landroid/content/pm/PackageManager$NameNotFoundException; {:try_start_0 .. :try_end_3e} :catch_3f

    goto :goto_45

    :catch_3f
    move-exception v0

    .line 172
    invoke-virtual {v0}, Landroid/content/pm/PackageManager$NameNotFoundException;->printStackTrace()V

    const-string v0, ""

    .line 174
    :goto_45

也就是说在即将校验的方法之前加上这个代码,重定向

哈希没有过

我大概懂了,就是他读取的逻辑先读取你没有修改的源apk,修改的就找过了。

对APP进行路径拦截,重定向

或者这个

有些签名是根据文件值来进行签名,你改签名这些(文件里的东西)会变动,不改就不会变动。

隐藏root

一是修改逻辑返回

二是算法助手(没成功)

模拟器检测等等

////

java 复制代码
public static final void m478onCreate$lambda0(SmaliLearn smaliLearn, TextView textView, TextView textView2, TextView textView3, View view) {
//直接改isVip返回
        int isVip = smaliLearn.isVip();
        if (isVip == 0) {
            textView.setText("非会员");
        } else if (isVip == 1) {
            textView.setText("会员");
        } else if (isVip == 4) {
            textView.setText("大会员");
        } else if (isVip == 16) {
            textView.setText("超级会员");
        } else if (isVip == 99) {
            textView.setText("至尊会员");
        }
        long time = new Date().getTime();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        if (smaliLearn.vipEndTime() < time) {
            textView2.setText("已过期");
        } else {
            textView2.setText(simpleDateFormat.format(Long.valueOf(smaliLearn.vipEndTime())));
        }
//
        int i = smaliLearn.vip_coin;
        if (i != 0) {
            textView3.setText(String.valueOf(i));
        }
    }
}
java 复制代码
 public final int getVip_coin() {
        return this.vip_coin;
    }

private final int vip_coin;
//赋值?
java 复制代码
 public final int isVip() {
        return 0;
    }
java 复制代码
public final long vipEndTime() {
//改
        return 1671889481513L;
    }
java 复制代码
method private static final onCreate$lambda-0(Lcom/zj/wuaipojie/ui/SmaliLearn;Landroid/widget/TextView;Landroid/widget/TextView;Landroid/widget/TextView;Landroid/view/View;)V
    .registers 9

    .line 21
    invoke-virtual {p0}, Lcom/zj/wuaipojie/ui/SmaliLearn;->isVip()I
//返回0
    move-result p4
//判断
//if-eqz 是 Smali(Android Dalvik/ART 字节码的汇编语言)中的条件跳转指令
//跳转
    if-eqz p4, :cond_35//非会员

    const/4 v0, 0x1

    if-eq p4, v0, :cond_2d

    const/4 v0, 0x4

    if-eq p4, v0, :cond_25

    const/16 v0, 0x10

    if-eq p4, v0, :cond_1d

    const/16 v0, 0x63

    if-eq p4, v0, :cond_15

    goto :goto_3c

    :cond_15
    const-string p4, "至尊会员"

    .line 26
    check-cast p4, Ljava/lang/CharSequence;

    invoke-virtual {p1, p4}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    goto :goto_3c

    :cond_1d
    const-string p4, "超级会员"

    .line 25
    check-cast p4, Ljava/lang/CharSequence;

    invoke-virtual {p1, p4}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    goto :goto_3c

    :cond_25
    const-string p4, "大会员"

    .line 24
    check-cast p4, Ljava/lang/CharSequence;

    invoke-virtual {p1, p4}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    goto :goto_3c

    :cond_2d
    const-string p4, "会员"

    .line 23
    check-cast p4, Ljava/lang/CharSequence;

    invoke-virtual {p1, p4}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    goto :goto_3c

    :cond_35
    const-string p4, "非会员"

    .line 22
    check-cast p4, Ljava/lang/CharSequence;

    invoke-virtual {p1, p4}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 28
    :goto_3c
    new-instance p1, Ljava/util/Date;

    invoke-direct {p1}, Ljava/util/Date;-><init>()V

    invoke-virtual {p1}, Ljava/util/Date;->getTime()J

    move-result-wide v0

    .line 29
    new-instance p1, Ljava/text/SimpleDateFormat;

    const-string p4, "yyyy-MM-dd"

    invoke-direct {p1, p4}, Ljava/text/SimpleDateFormat;-><init>(Ljava/lang/String;)V

    .line 30
    invoke-virtual {p0}, Lcom/zj/wuaipojie/ui/SmaliLearn;->vipEndTime()J

    move-result-wide v2

    cmp-long p4, v2, v0

    if-gez p4, :cond_5c

    const-string p1, "已过期"

    .line 31
    check-cast p1, Ljava/lang/CharSequence;

    invoke-virtual {p2, p1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    goto :goto_6d

    .line 33
    :cond_5c
    invoke-virtual {p0}, Lcom/zj/wuaipojie/ui/SmaliLearn;->vipEndTime()J

    move-result-wide v0

    invoke-static {v0, v1}, Ljava/lang/Long;->valueOf(J)Ljava/lang/Long;

    move-result-object p4

    invoke-virtual {p1, p4}, Ljava/text/SimpleDateFormat;->format(Ljava/lang/Object;)Ljava/lang/String;

    move-result-object p1

    check-cast p1, Ljava/lang/CharSequence;

    invoke-virtual {p2, p1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 35
    :goto_6d
    iget p0, p0, Lcom/zj/wuaipojie/ui/SmaliLearn;->vip_coin:I

    if-eqz p0, :cond_7a

    .line 36
    invoke-static {p0}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;

    move-result-object p0

    check-cast p0, Ljava/lang/CharSequence;

    invoke-virtual {p3, p0}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    :cond_7a
    return-void
.end method
java 复制代码
.method public final isVip()I
//表示当前方法总共使用 2 个寄存器
    .registers 2

    const/4 v0, 0x0
//限制进制
//返回0
    return v0
.end method

改钻石黑屏了

这个方法没有用

成功

黑屏原因

第2个P0相当于这个类的实例地址

如果前面先给他复值了,他就会把这个东西当成地址引用从而报错

java 复制代码
const/16 p0, 0x63
//第二个p0=this
//this.SmaliLearn.vip_coin
iget p0, p0, Lcom/zj/wuaipojie/ui/SmaliLearn;->vip_coin:I
java 复制代码
.line 35
    :goto_6d
    iget p0, p0, Lcom/zj/wuaipojie/ui/SmaliLearn;->vip_coin:I

    const/16 p0, 0x63

    if-eqz p0, :cond_7c
java 复制代码
.method public final getVip_coin()I
    .registers 2

    const/16 p1, 0x0

    .line 12
//iget读取字段
//读取vip_coin赋值
//p0是实例
//v0存储
    iget v0, p0, Lcom/zj/wuaipojie/ui/SmaliLearn;->vip_coin:I
//返回p1
    return p1
.end method
java 复制代码
 .line 31
//检查是否可以强制转化
    check-cast p1, Ljava/lang/CharSequence;
//
    invoke-virtual {p2, p1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    goto :goto_6d
java 复制代码
   .line 35
    :goto_6d
//存储判断是否大于0
    iget p0, p0, Lcom/zj/wuaipojie/ui/SmaliLearn;->vip_coin:I
//会卡死
  if-nez p0, :cond_7a



.line 35
    :goto_6d
    iget p0, p0, Lcom/zj/wuaipojie/ui/SmaliLearn;->vip_coin:I

    if-eqz p0, :cond_7a
java 复制代码
 :cond_7a
    return-void
.end method
java 复制代码
   int i = smaliLearn.vip_coin;
        if (i != 0) {
            textView3.setText(String.valueOf(i));
        }
java 复制代码
  .line 31
//检查类型,强制转化
    check-cast p1, Ljava/lang/CharSequence;
//设置显示
    invoke-virtual {p2, p1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    goto :goto_6d

.line 35
    :goto_6d
//赋值
    iget p0, p0, Lcom/zj/wuaipojie/ui/SmaliLearn;->vip_coin:I
//如果是0
    if-eqz p0, :cond_7a

    .line 36
//静态方法获取,p0转化字符串
//const/16 p0, 0x63
    invoke-static {p0}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
//删除然后写一个新的?

//赋值
    move-result-object p0
//检查类型,强转
    check-cast p0, Ljava/lang/CharSequence;
//设置显示
    invoke-virtual {p3, p0}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    :cond_7a
//这里,直接完了
    return-void
.end method

查找调用静态字段

是看看哪里对他进行赋值,因为他是去那个判断的。

反调试

java 复制代码
.method protected attachBaseContext(Landroid/content/Context;)V
    .registers 2

    .line 11
    invoke-super {p0, p1}, Landroid/app/Application;->attachBaseContext(Landroid/content/Context;)V

    .line 13
//反调试
    invoke-virtual {p0}, Lcom/zj/wuaipojie/MainApplication;->checkForDebugger()V

    return-void
.end method

.method public final checkForDebugger()V
    .registers 2

    .line 18
    invoke-static {}, Landroid/os/Debug;->isDebuggerConnected()Z

    move-result v0

    if-eqz v0, :cond_a

    const/4 v0, 0x0

    .line 20
    invoke-static {v0}, Ljava/lang/System;->exit(I)V

    :cond_a
    return-void
.end method
相关推荐
噜噜噜阿鲁~1 小时前
python学习笔记 | 12.0、错误、调试和测试
笔记·python·学习
三品吉他手会点灯1 小时前
C语言学习笔记 - 46.运算符和表达式 - 运算符4 - 对初学运算符的一些建议
c语言·开发语言·笔记·学习
wangqiaowq2 小时前
Rerank模型学习
学习
呉師傅2 小时前
EPSON爱普生 L3118打印头【喷头】清洗方法
运维·服务器·网络·学习·电脑
在学了加油2 小时前
Inception v3学习笔记
笔记·学习
Upsy-Daisy2 小时前
IOTA 学习笔记(十一):共享对象与多用户交互
笔记·学习
元直数字电路验证2 小时前
【CXL】开篇导读 --- CXL是什么以及如何学习
学习·pcie·cxl
我命由我123452 小时前
Excel - Excel 单元格格式同时设置日期时间
运维·学习·职场和发展·excel·求职招聘·职场发展·学习方法
J.Kuchiki2 小时前
【PostgreSQL内核学习 —— 外部排序生成与归并】
数据库·学习·postgresql