吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 142|回复: 3
上一主题 下一主题
收起左侧

[Android 原创] xx快跑逆向记录

[复制链接]
跳转到指定楼层
楼主
Ma5k 发表于 2026-3-12 16:09 回帖奖励

前言

水一篇贴。声明:该帖用于技术交流分享,严禁恶意利用。

工具

必须:ida jadx frida il2cppdumper

前期分析


oppo壳加固,这里可以脱壳修改静态逻辑,但是为了图方便直接分析so动态hook

脱壳可参考这篇:https://www.52pojie.cn/thread-2049364-1-1.html

这里提取方式很多种,鄙人用adb pull
提取apk:adb pull /storage/emulated/0/NP/apks/2.apk  ...(你的目录)

因为是unity,先提取相关资源分析

新手可以参考下述教程了解unity逆向(其实是鄙人懒狗):
https://xianyuuuan.space/2024/07/30/Unity%E5%87%BA%E9%A2%98-%E9%80%86%E5%90%91%E6%80%9D%E8%B7%AF%E7%AF%87/

https://mrwq.github.io/aggregate-paper/butian/%E6%B5%85%E8%B0%88CTF%E4%B8%AD%E7%9A%84unity%E6%B8%B8%E6%88%8F%E9%80%86%E5%90%91/

4.4.0新版本把global-metadata.dat加密了,lib文件太多没法定位加密,老版本可以直接dump
老规矩,丢ida修复符号表(分析Assembly-CSharp),然后就是结合各文件分析函数逻辑frida hook

分析&Hook

dump.cs是Unity游戏中IL2CPP方式打包后生成的文件,它包含了游>戏的类型、方法、字段等信息。

这里从dump.cs入手,ce修改unity也是同样思路,去找gamemanager
可以看到实例的创建以及gameinfo

// Namespace: 
public class BearGameManager // TypeDefIndex: 5104
{
    // Fields
    private static BearGameManager instance; // 0x0
    public BearGameInf mInf; // 0x10

    // Methods

    // RVA: 0x9AB138 Offset: 0x9AB138 VA: 0x9AB138
    public void initialize(BearGameInf inf) { }

    // RVA: 0x9AB140 Offset: 0x9AB140 VA: 0x9AB140
    private void .ctor() { }

    // RVA: 0x9AB148 Offset: 0x9AB148 VA: 0x9AB148
    public static BearGameManager getInstance() { }
}

先修改无敌吧,info跟踪过去找到onhurt(其余方法同理)
这里因为是void方法可以hook后直接返回retn达到无伤效果

public class BearGameInfimpl : BearGameInf // TypeDefIndex: 5103
{
    // ......
    // RVA: 0x9A9BC4 Offset: 0x9A9BC4 VA: 0x9A9BC4 Slot: 52
    public void OnHurt() { }
    // ......
}

随后发现了 Jewel (珠宝),也就是我们最终的修改目标

// Namespace: 
public class JewelManager : MonoBehaviour // TypeDefIndex: 5123
{
    // Fields
    public static JewelManager instance; // 0x0
    public string ActivityID; // 0x18
    public int MaxCoinCount; // 0x20
    public int MinCoinCount; // 0x24
    public int CoinCount; // 0x28
    public int minPineAppleNew; // 0x2C
    public int maxPineAppleNew; // 0x30
    public int PineAppleCountNew; // 0x34
    public int minStrawBerryNew; // 0x38
    public int maxStrawBerryNew; // 0x3C
    public int StrawBerryCountNew; // 0x40
    public int minOrangeNew; // 0x44
    public int maxOrangeNew; // 0x48
    public int orangeCountNew; // 0x4C
    public int minPineapple; // 0x50
    public int maxPineapple; // 0x54
    public int PineappleCount; // 0x58
    public int minBanana; // 0x5C
    public int maxBanana; // 0x60
    public int BananaCount; // 0x64
    public int minLollipop; // 0x68
    public int maxLollipop; // 0x6C
    public int LollipopCount; // 0x70
    public int minRedEnvelope; // 0x74
    public int maxRedEnvelope; // 0x78
    public int RedEnvelopeCount; // 0x7C
    public bool isOpenActivity; // 0x80
    public bool isFromLackFragmentUI; // 0x81
    // .....
}

中间的过程比较杂乱,记录下自己找到的关键类和方法

public class Item // TypeDefIndex: 4215
{
    // Fields
    private const string KEY_COUNT = "itemNum";
    private const string KEY_LEVEL = "itemLevel";
    public int itemId; // 0x10
    public string name; // 0x18
    public string spriteName; // 0x20
    public int price; // 0x28
    public string description; // 0x30
    public string commond; // 0x38
    public string tag; // 0x40
    private string CountStr; // 0x48
    public int quality; // 0x50
    private string LevelStr; // 0x58

    // Methods

    // RVA: 0x1330870 Offset: 0x1330870 VA: 0x1330870
    public void .ctor() { }

    // RVA: 0x13308F8 Offset: 0x13308F8 VA: 0x13308F8
    public void .ctor(int itemId) { }

    // RVA: 0x1330994 Offset: 0x1330994 VA: 0x1330994 Slot: 4
    public virtual void Init() { }

    // RVA: 0x1330AC4 Offset: 0x1330AC4 VA: 0x1330AC4 Slot: 5
    public virtual void InitOld() { }

    // RVA: 0x132EE20 Offset: 0x132EE20 VA: 0x132EE20
    public int get_Count() { }

    // RVA: 0x132F090 Offset: 0x132F090 VA: 0x132F090
    public void set_Count(int value) { }

    // RVA: 0x1330BCC Offset: 0x1330BCC VA: 0x1330BCC
    public int get_Level() { }

    // RVA: 0x1330BE8 Offset: 0x1330BE8 VA: 0x1330BE8
    public void set_Level(int value) { }

    // RVA: 0x1330C1C Offset: 0x1330C1C VA: 0x1330C1C
    public void Save() { }
}

接下来就是拷打氛围式编程了,通过frida动态hook

setImmediate(function () {

    function hook() {

        var base = Module.findBaseAddress("libil2cpp.so");
        console.log("
  • libil2cpp base:", base);         function addr(rva){             return base.add(rva);         }         // =========================         // 无敌 OnHurt()         // RVA 0x9A9BC4         // =========================         Interceptor.replace(addr(0x9A9BC4), new NativeCallback(function(){             console.log("Block Hurt");         }, 'void', ['pointer']));         // =========================         // 无限复活 IsSurrection()         // RVA 0x9A93E8         // =========================         Interceptor.replace(addr(0x9A93E8), new NativeCallback(function(){             return 1;         }, 'bool', ['pointer']));         // =========================         // 不计死亡 AddDeadNum()         // RVA 0x9A93E4         // =========================         Interceptor.replace(addr(0x9A93E4), new NativeCallback(function(){             console.log("No death count");         }, 'void', ['pointer']));         // =========================         // 双倍金币         // RVA 0x9A8304         // =========================         Interceptor.replace(addr(0x9A8304), new NativeCallback(function(){             return 1;         }, 'bool', ['pointer']));         // =========================         // 游戏时间双倍金币         // RVA 0x9A842C         // =========================         Interceptor.replace(addr(0x9A842C), new NativeCallback(function(){             return 1;         }, 'bool', ['pointer']));         // =========================         // 全图吸铁         // RVA 0x9A8554         // =========================         Interceptor.replace(addr(0x9A8554), new NativeCallback(function(){             return 1;         }, 'bool', ['pointer']));         // =========================         // 道具时间 9999         // RVA 0x9A867C         // =========================         Interceptor.replace(addr(0x9A867C), new NativeCallback(function(){             return 9999;         }, 'float', ['pointer','int']));         // =========================         // Item.get_Count()         // RVA 0x132EE20         // =========================         Interceptor.attach(addr(0x132EE20), {             onLeave: function(retval){                 retval.replace(9999);             }         });         // =========================         // Item.get_Level()         // RVA 0x1330BCC         // =========================         Interceptor.attach(addr(0x1330BCC), {             onLeave: function(retval){                 retval.replace(99);             }         });         // =========================         // JewelManager.GetJewelValue()         // RVA 0x87391C         // =========================         Interceptor.attach(addr(0x87391C), {             onLeave: function(retval){                 retval.replace(9999);             }         });         // =========================         // AddJewel() 掉落 x100         // RVA 0x873A04         // =========================         Interceptor.attach(addr(0x873A04), {             onEnter: function(args){                 var value = args[2].toInt32();                 args[2] = ptr(value * 100);                 console.log("Jewel x100");             }         });         // =========================         // AddJewelInGame()         // RVA 0x873A7C         // =========================         Interceptor.attach(addr(0x873A7C), {             onEnter: function(args){                 args[2] = ptr(999);             }         });         // =========================         // DeductJewelAndPearl()         // RVA 0x874774         // =========================         Interceptor.replace(addr(0x874774), new NativeCallback(function(){             console.log("No resource cost");         }, 'void', ['pointer','int']));         console.log("
  • Cheat Loaded");     }     function wait(){         var m = Process.findModuleByName("libil2cpp.so");         if(m){             hook();         }else{             setTimeout(wait,100);         }     }     wait(); });
  • frida -U -f com.xxx.xxx -l x.js

    成果展示


    广告去除还没考虑,可以进一步优化

    题外话:第一次做春节论坛题目,学到了很多,也再次安利正己老师的安卓逆向课程

    发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

    推荐
    Command 发表于 2026-3-12 22:21
    ? 熊大快跑吗 (
    3#
    liuhai7435 发表于 2026-3-12 22:43
    4#
    smshiwadai 发表于 2026-3-13 05:25
    您需要登录后才可以回帖 登录 | 注册[Register]

    本版积分规则

    返回列表

    RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

    GMT+8, 2026-3-13 06:00

    Powered by Discuz!

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表