吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1582|回复: 26
收起左侧

[Android 原创] 一个小白练手包简单逆向的记录

  [复制链接]
tuandgame 发表于 2025-4-6 19:01
如题,软件如下,外网的一个数学小游戏,主要是给小盆友玩
链接:https://caiyun.139.com/m/i?0g5CLHiJT1ymQ
提取码:e5LJ
复制内容打开移动云盘PC客户端,操作更方便哦


首先是定目标,老是要小盆友点视频加红心,这不科学。

那么就去广告,然后1次加个100红心吧。 然后就祭出ai大法,他当主力 我做辅助就行了



1、去广告第一步

通过字符串广告观看pv  定位到方法c  目的是为了 了解整个架构的流转,然后把方法代码丢ai 喊一句 帮我分析一下流转 得到以下结论

方法概览
方法名: c()V(返回类型为void)
寄存器: 使用了15个寄存器(v0-v14)
主要逻辑:
记录两个统计事件(埋点)
检查成员变量是否为特定Activity实例,并调用其方法。
代码解析
1. 埋点事件记录
第一个事件(对应Java代码行1):

const-string v2, "首页_点击练习_watchVideo"  
sget-object v0, Lc/c;->y:Lc/c;  
invoke-static/range {v0 .. v6}, Lc/c;->e(...)  
事件参数:
事件类型: "赚心途径pv"(可能是业务相关的统计分类)
事件标识: "首页_点击练习_watchVideo"(用户点击练习并观看视频)
其他参数: null、0、0、12(可能是附加数据或标志位)。
第二个事件(对应Java代码行2):

const-string v9, "首页_点练习_无心弹窗_watchVideo"  
sget-object v7, Lc/c;->y:Lc/c;  
invoke-static/range {v7 .. v13}, Lc/c;->e(...)  
事件参数:
事件类型: "广告观看pv"
事件标识: "首页_点练习_无心弹窗_watchVideo"(用户点击练习时触发的无“心”(游戏内货币?)弹窗广告)
其他参数同上。
推测:Lc/c;->e()是一个埋点工具方法,用于上报用户行为事件。参数可能包括事件类型、标识、附加信息、时间戳、配置项等。

2. Activity检查与方法调用
iget-object v0, p0, Lm9/e0;->a:Lp0/f;  
instance-of v1, v0, Lsimplemath/math/.../HomeActivity;  
if-eqz v1, :cond_27  
check-cast v0, Lsimplemath/math/.../HomeActivity;  
invoke-virtual {v0}, Lw8/b;->i()V  
逻辑:

获取当前对象的成员变量a(类型为Lp0/f)。
检查a是否是HomeActivity的实例。
如果是,调用HomeActivity的父类Lw8/b的i()方法。
推测:

a可能是一个上下文(Context)或Activity的引用。
i()方法可能是界面刷新、数据加载或弹窗关闭等操作(需结合上下文进一步分析)。
代码对应的Java伪代码
public void c() {  
    // 埋点1:用户点击练习并观看视频  
    StatHelper.e(StatHelper.y, "赚心途径pv", "首页_点击练习_watchVideo", null, 0, 0, 12);  
      
    // 埋点2:用户触发无“心”弹窗广告  
    StatHelper.e(StatHelper.y, "广告观看pv", "首页_点练习_无心弹窗_watchVideo", null, 0, 0, 12);  
      
    // 检查并调用Activity方法  
    if (this.a instanceof HomeActivity) {  
        ((HomeActivity) this.a).i(); // 可能是刷新界面或处理广告回调  
    }  
}  
关键点总结
埋点统计:

记录用户点击练习和观看广告的行为,用于数据分析。
事件标识符中包含中文,可能与业务逻辑强相关(如“心”是应用内货币)。
Activity逻辑:

当成员变量a指向HomeActivity时,触发其i()方法,可能是更新UI或处理广告观看后的奖励。
可能的应用场景
用户在首页点击“练习”按钮,触发观看视频广告(如获取游戏货币“心”)。
广告观看完成后,通过i()方法刷新用户货币余额或关闭弹窗。
进一步分析建议:

查看Lc/c;->e()的具体实现,确认埋点参数含义。
分析HomeActivity的i()方法,明确其实际作用。

2、去广告第二步,找到i方法,把i方法 丢ai 给我出修改方案

然后天生的打工人给出以下方案。

代码功能解析
该方法核心逻辑是加载并展示激励视频广告,并在广告播放完成后触发奖励回调。关键步骤分解如下:

1. 初始化广告组件
# 初始化广告管理器(Lw8/j)  
sget-object v0, Lw8/i;->c:Lw8/i$a;  
invoke-virtual {v0}, Lw8/i$a;->a()Lw8/j;  
move-result-object v0

# 设置广告回调监听器(Lw8/j$a)  
new-instance v1, Lw8/b$b;  
invoke-direct {v1, p0}, Lw8/b$b;-><init>(Lw8/b;)V  
iput-object v1, v0, Lw8/j;->a:Lw8/j$a;  
Lw8/j 是广告管理类,Lw8/j$a 是广告播放完成的回调接口。
回调方法 c()(在 Lw8/j$a 中定义)可能是奖励发放的入口。
2. 检查广告缓存状态
# 检查广告是否已缓存(Li7/c)  
if-eqz v1, :cond_4f  
iget-object v1, v1, Li7/c;->e:Lk7/c;  
invoke-virtual {v1}, Lk7/c;->j()Z  
move-result v1

# 如果广告已缓存(v1 == 1),直接触发奖励  
if-ne v1, v2, :cond_4f  
const/4 v1, 0x1  
:goto_50  
if-eqz v1, :cond_61  
  sget-object v1, Lu9/a;->a:Lu9/a$a;  
  const-string v2, "hasAD"  
  invoke-virtual {v1, v2}, Lu9/a$a;->b(Ljava/lang/String;)V

  # 触发奖励回调 c()  
  iget-object v0, v0, Lw8/j;->a:Lw8/j$a;  
  invoke-interface {v0}, Lw8/j$a;->c()V  
关键点:当广告已缓存时(hasAD 标记存在),直接调用 c() 发放奖励。
漏洞:可以通过强制让 hasAD 始终为真,无需播放广告即可触发奖励。
修改方案
目标
无需观看广告,直接触发奖励发放(c())

方案一:强制跳转到奖励分支
修改位置:if-eqz v1, :cond_61
将条件判断改为无条件跳转,强制进入奖励分支:

# 原始代码  
if-eqz v1, :cond_61

# 修改后(删除条件判断,直接跳转)  
goto :cond_61  
对应Smali修改:

# 定位到条件跳转指令(例如):  
if-eqz v1, :cond_61

# 替换为:  
goto :cond_61  
效果:无论广告是否加载完成,直接触发 c() 发放奖励。

方案二:伪造广告缓存状态
修改位置:广告缓存状态检查逻辑
强制让 Li7/c 的缓存检查返回 true:

# 原始代码  
iget-object v1, v1, Li7/c;->e:Lk7/c;  
invoke-virtual {v1}, Lk7/c;->j()Z  
move-result v1

# 修改后(直接返回1):  
const/4 v1, 0x1  
对应Smali修改:

# 定位到检查代码块:  
iget-object v1, v1, Li7/c;->e:Lk7/c;  
invoke-virtual {v1}, Lk7/c;->j()Z  
move-result v1

# 替换为:  
const/4 v1, 0x1  
效果:系统认为广告已缓存,自动触发奖励。

很好,就用第2套方案吧,测试通过。

3、广告现在去除了 然后就修改一次性红心加100吧。把自己需求告诉ai即可,ai拉着我跑了几个方法(过程略了),然后最终才定位到关键方法。

### 终极总结:红心修改全流程
1. 核心问题定位
目标:点击按钮时,红心增加量从 1 → 100。
关键障碍:
隐藏上限:原代码限制红心数≥5时不增加。
寄存器冲突:p2 参数被后续代码覆盖。
多调用点干扰:7处调用需统一修改逻辑。
2. 完整解决方案
步骤1:移除红心上限检查
在 Ld9/c;->b() 方法中,删除红心上限判断代码:

# 删除以下两行:  
iget v0, p0, Ld9/c;->g:I  
const/4 v1, 0x5  
if-lt v0, v1, :cond_6  
return-void  
步骤2:修复寄存器冲突
修改 Ld9/c;->b() 方法,避免覆盖 p2 参数:

# 原错误代码(覆盖p2):  
sget-object p2, Lu9/b;->b:Lu9/b$a;

# 修复后代码(使用v1):  
sget-object v1, Lu9/b;->b:Lu9/b$a;  
步骤3:统一修改调用点
根据需求选择方案:

方案A(精准修改):定位所有7处调用 Ld9/c;->b() 的代码,将参数改为100:
# 所有调用点修改示例:  
const/16 vX, 0x64  # 0x64=100  
invoke-virtual {v3, p1, vX}, Ld9/c;->b(Landroid/content/Context;I)V  
方案B(全局生效):直接修改 Ld9/c;->b() 内部逻辑,强制每次增加100:
# 在方法内部忽略参数p2,固定增加100:  
add-int/lit16 v0, v0, 0x64  # 0x64=100  
3. 验证与调试
验证方式        操作步骤        预期结果
静态反编译验证        使用 JADX 检查 Ld9/c;->b() 和调用点代码        无上限检查,参数为100
动态日志注入        在代码中插入 Log 语句输出红心变化值        日志显示 红心+100
FrIDA 监控        拦截 Ld9/c;->b() 方法,打印传入参数和结果        参数=100,红心累计正确
SharedPreferences 检查        使用 adb shell 查看 pi_rh 键值对        值 = 原值 + 100
4. 高频问题与修复
问题现象        原因分析        解决方案
修改后仍只+1        调用点未全部修改        检查所有7处调用点或改用方案B
应用闪退        寄存器数量声明不足        调整 .registers 数量
红心值未保存        SharedPreferences 键名错误        确认 pi_rh 键名一致性
部分场景红心未变化        代码混淆导致多个副本        全项目搜索 Ld9/c;->b( 确保唯一
5. 终极推荐方案
新手友好:使用 方案B(全局修改),直接修改 Ld9/c;->b() 内部逻辑。
精准控制:使用 方案A + Frida 监控,确保所有调用点参数为100。
代码混淆应对:全项目搜索 Ld9/c;->b(,统一修改所有副本。

很好 就用新手友好吧。

全局终,谢谢观看。

总结ai时代 想逆向 小白只需要驾驭ai就能跨越很大的鸿沟,所以善用ai,御剑术,人御剑不是剑御人,所以方向把握的好 就是逆向的关键,而人负责方向,ai负责打工即可。

免费评分

参与人数 5吾爱币 +10 热心值 +4 收起 理由
SeanDcitonary + 1 谢谢@Thanks!
as698522 + 1 我很赞同!
IcePlume + 1 + 1 我很赞同!
正己 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
dahai1983 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

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

aoxuehanshuang 发表于 2025-4-7 23:21
学习一下
IcePlume 发表于 2025-4-8 04:11
lauzw 发表于 2025-4-8 08:28
pc466 发表于 2025-4-8 08:42
AI可以节省人工
laotzudao0 发表于 2025-4-8 10:09
全年ai
Ascent 发表于 2025-4-8 10:52
AI大法来帮助工作是十分的完美啊
longxy001 发表于 2025-4-8 11:55
已经很厉害了,向你学习
Xx0337 发表于 2025-4-8 12:11
已经很厉害了,向你学习还在新手阶段
wanglei122333 发表于 2025-4-8 12:26
厉害!共同学习
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-4-30 14:56

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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