安卓逆向那点事(2)

初识smali,vip终结者
一、课程目标

1.了解JVM、Dalvik、ART
2.初识smali语法
3.实战修改smali

二、工具

1.教程Demo(更新)
2.MT管理器/NP管理器
3.雷电模拟器
4.jadx-gui
5.核心破解

三、课程内容

1.什么是JVM、Dalvik、ART

JVM是JAVA虚拟机,运行JAVA字节码程序
Dalvik是Google专门为Android设计的一个虚拟机,Dalvik有专属的文件执行格式dex(Dalvik executable)
Art(Android Runtime)相当于Dalvik的升级版,本质与Dalvik无异

2.smali及其语法

smali是Dalvik的寄存器语言,smali代码是dex反编译而来的。

关键字

名称注释
.class类名
.super父类名,继承的上级类名名称
.source源名
.field变量
.method方法名
.register寄存器
.end method方法名的结束
public公有
protected半公开,只有同一家人才能用
private私有,只能自己使用
.parameter方法参数
.prologue方法开始
.line xxx位于第xxx行

数据类型对应

smali类型java类型注释
Vvoid无返回值
Zboolean布尔值类型,返回0或1
Bbyte字节类型,返回字节
Sshort短整数类型,返回数字
Cchar字符类型,返回字符
Iint整数类型,返回数字
Jlong (64位 需要2个寄存器存储)长整数类型,返回数字
Ffloat单浮点类型,返回数字
Ddouble (64位 需要2个寄存器存储)双浮点类型,返回数字
stringString文本类型,返回字符串
Lxxx/xxx/xxxobject对象类型,返回对象

常用指令

关键字注释
const重写整数属性,真假属性内容,只能是数字类型
const-string重写字符串内容
const-wide重写长整数类型,多用于修改到期时间。
return返回指令
if-eq全称equal(a=b),比较寄存器ab内容,相同则跳
if-ne全称not equal(a!=b),ab内容不相同则跳
if-eqz全称equal zero(a=0),z即是0的标记,a等于0则跳
if-nez全称not equal zero(a!=0),a不等于0则跳
if-ge全称greater equal(a>=b),a大于或等于则跳
if-le全称little equal(a<=b),a小于或等于则跳
goto强制跳到指定位置
switch分支跳转,一般会有多个分支线,并根据指令跳转到适当位置
iget获取寄存器数据

其余指令可用语法工具查询

定位方法:搜索弹窗关键字、抓取按钮id

3.寄存器

在smali里的所有操作都必须经过寄存器来进行:本地寄存器用v开头数字结尾的符号来表示,如v0、 v1、v2。 参数寄存器则使用p开头数字结尾的符号来表示,如p0、p1、p2。特别注意的是,p0不一定是函数中的第一个参数,在非static函数中,p0代指“this",p1表示函数的第一个 参数,p2代表函数中的第二个参数。而在static函数中p0才对应第一个参数(因为Java的static方法中没有this方法)

我们下面来查看第二关任务

image-20221123145703998

任务目标:收集硬币并完成一键三连;但是我们一键三连点击后出现提示:请先充值大会员哦!

我们去jadk-jui里搜索一下

image-20221123150003128

如果没有出现,就打开文件——>首选项——>unicode字符转义关掉

image-20221123150201843

这个方法名是onCreate$lambda,前面的数字和字母在反编译的时候开启了一个反混淆

我们去smali里也找到这个方法去

image-20221123150528940

我们分析一下这个smali语句:

//一个私有、静态、不可变的方法   方法名
.method private static final onCreate$lambda-2(Lkotlin/jvm/internal/Ref$IntRef;Lcom/zj/wuaipojie/ui/ChallengeSecond;Landroid/widget/ImageView;Landroid/widget/ImageView;Landroid/widget/ImageView;Landroid/view/View;)Z //(这里面是方法的参数)这里是方法返回值类型,表示布尔值类型,返回假或真
    .registers 7  //寄存器数量
    
    .line 33  //代码所在的行数
    iget p0, p0, Lkotlin/jvm/internal/Ref$IntRef;->element:I  //读取p0(第一个参数,参考寄存器知识)中element的值赋值给p0
        
    const/4 p5, 0x1  //p5赋值1
    const/16 v0, 0xa //v0赋值10,在16进制里a表示10
    if-ge p0, v0, :cond_15  //判断p0的值是否大于或等于v0的值(即p0的值是否大于或等于10),如果大于或等于则跳转到:cond_15
    .line 34  //以下是常见的Toast弹窗代码
    check-cast p1, Landroid/content/Context; //检查Context对象引用
    const-string p0, "请先获取10个硬币哦" //弹窗文本信息,把""里的字符串数据赋值给p0
    check-cast p0, Ljava/lang/CharSequence; //检查CharSequence对象引用
    invoke-static {p1, p0, p5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; 
    //将弹窗文本、显示时间等信息传给p1
    move-result-object p0  //结果传递给p0
    invoke-virtual {p0}, Landroid/widget/Toast;->show()V  //当看到这个Toast;->show你就应该反应过来这里是弹窗代码
    goto :goto_31  //跳转到:goto_31
        
    :cond_15 //跳转的一个地址
    invoke-virtual {p1}, Lcom/zj/wuaipojie/ui/ChallengeSecond;->isvip()Z  //判断isvip方法的返回值是否为真(即结果是否为1)
    move-result p0  //结果赋值给p0
    if-eqz p0, :cond_43 //如果结果为0则跳转cond_43地址
    const p0, 0x7f0d0018  //在arsc中的id索引,这个值可以进行查询
    .line 37
    invoke-virtual {p2, p0}, Landroid/widget/ImageView;->setImageResource(I)V //设置图片资源
    const p0, 0x7f0d0008
    .line 38
    invoke-virtual {p3, p0}, Landroid/widget/ImageView;->setImageResource(I)V
    const p0, 0x7f0d000a
    .line 39
    invoke-virtual {p4, p0}, Landroid/widget/ImageView;->setImageResource(I)V
    .line 40
    sget-object p0, Lcom/zj/wuaipojie/util/SPUtils;->INSTANCE:Lcom/zj/wuaipojie/util/SPUtils; 
    check-cast p1, Landroid/content/Context;
    const/4 p2, 0x2 //p2赋值2
    const-string p3, "level" //sp的索引
    invoke-virtual {p0, p1, p3, p2}, Lcom/zj/wuaipojie/util/SPUtils;->saveInt(Landroid/content/Context;Ljava/lang/String;I)V //写入数据
    goto :goto_50 //跳转地址
    :cond_43
    check-cast p1, Landroid/content/Context;
    const-string p0, "\u8bf7\u5148\u5145\u503c\u5927\u4f1a\u5458\u54e6\uff01" //请先充值大会员哦!
    check-cast p0, Ljava/lang/CharSequence;
    invoke-static {p1, p0, p5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    move-result-object p0
    invoke-virtual {p0}, Landroid/widget/Toast;->show()V
    :goto_50
    return p5  //返回p5的值
.end method //方法结束

//判断是否是大会员的方法
.method public final isvip()Z
    .registers 2
    const/4 v0, 0x0 //v0赋值0
    return v0 //返回v0的值
.end method

修改方法:修改判断、强制跳转、修改寄存器的值

image-20221123153014984
  1. 修改判断

    image-20221123153244219

    这里有个判断,判断是否够10个硬币

    image-20221123153414109 image-20221123153431384

    下面这个判断用来判断是否是大会员

    我最好的办法就是把这个判断删除掉,但由于jadx不能直接修改,所以这里需要MT管理器的会员功能。

    image-20221123155012150

    我们把if-ge改成if-le,就变成了小于等于跳转

    image-20221123155227295

    下面判断它是不是vip,我们直接把这个判断用#注释掉,就能直接跳过这个判断了

    image-20221123155500759

    然后我们保存,安装。

    image-20221123155932622

    这样我们就修改完成了。

  2. 修改寄存器的值

    image-20221123160140902

    这里是po和10作比较,我们这里直接改掉v0的值为0,就符合大于等于的判断标准了

    image-20221123160246415

    我们对isvip长按,选择跳转,跳转到这个方法

    image-20221123160346190

    image-20221123160439031

    我们把0改为1,这样它就会返回1,也就是真了。

    保存退出,再安装。

    image-20221123160616297

    这样我们也破解成功了。

    3.强制跳转

    image-20221127164059495

    我们把这里的判断改成强制跳转,不用让他判断直接跳转,这里就需要用到goto语句

    image-20221127164334782

    这样他就会直接跳转到下面这个地方来

    image-20221127164408338

    下面还有一个判断vip的地方,我们直接把它注释掉,这样不管他是不是为真,它都会直接走下面这段逻辑了。

    image-20221127164618789

    保存退出,重新安装

    image-20221127164718434
恭喜你获得广告&弹窗静默卡
一、课程目标

1.了解安卓四大组件、Activity生命周期
2.弹窗定位、去更新
3.广告分析与布局优化

二、工具

1.教程Demo(更新)
2.MT管理器/NP管理器
3.算法助手
4.雷电模拟器
5.开发助手

三、课程内容

1.广告类型

启动广告 弹窗&更新广告 横幅广告

2.安卓四大组件
组件描述
Activity(活动)在应用中的一个Activity可以用来表示一个界面,意思可以理解为“活动”,即一个活动开始,代表 Activity组件启动,活动结束,代表一个Activity的生命周期结束。一个Android应用必须通过Activity来运行和启动,Activity的生命周期交给系统统一管理。
Service(服务)Service它可以在后台执行长时间运行操作而没有用户界面的应用组件,不依赖任何用户界面,例如后台播放音乐,后台下载文件等。
Broadcast Receiver(广播接收器)一个用于接收广播信息,并做出对应处理的组件。比如我们常见的系统广播:通知时区改变、电量低、用户改变了语言选项等。
Content Provider(内容提供者)作为应用程序之间唯一的共享数据的途径,Content Provider主要的功能就是存储并检索数据以及向其他应用程序提供访问数据的接口。Android内置的许多数据都是使用Content Provider形式,供开发者调用的(如视频,音频,图片,通讯录等)

activity的切换

        <!---声明实现应用部分可视化界面的 Activity,必须使用 AndroidManifest 中的 <activity> 元素表示所有 Activity。系统不会识别和运行任何未进行声明的Activity----->
        <activity  
            android:label="@string/app_name"  
            android:name="com.zj.wuaipojie.ui.MainActivity"  
            android:exported="true">  <!--当前Activity是否可以被另一个Application的组件启动:true允许被启动;false不允许被启动-->
            <!---指明这个activity可以以什么样的意图(intent)启动--->
            <intent-filter>  
                <!--表示activity作为一个什么动作启动,android.intent.action.MAIN表示作为主activity启动--->
                <action  
                    android:name="android.intent.action.MAIN" />  
                <!--这是action元素的额外类别信息,android.intent.category.LAUNCHER表示这个activity为当前应用程序优先级最高的Activity-->
                <category  
                    android:name="android.intent.category.LAUNCHER" />  
            </intent-filter>  
        </activity>  
        <activity  
            android:name="com.zj.wuaipojie.ui.ChallengeFirst" />
        <activity  
            android:name="com.zj.wuaipojie.ui.ChallengeFifth"  
            android:exported="true" />  
        <activity  
            android:name="com.zj.wuaipojie.ui.ChallengeFourth"  
            android:exported="true" />  
        <activity  
            android:name="com.zj.wuaipojie.ui.ChallengeThird"  
            android:exported="false" />  
        <activity  
            android:name="com.zj.wuaipojie.ui.ChallengeSecond"  
            android:exported="false" />  
        <activity  
            android:name="com.zj.wuaipojie.ui.AdActivity" />  

启动广告流程:
启动Activity->广告Activity->主页Activity

修改方法:
1.修改加载时间
2.Acitivity切换定位,修改Intent的Activity类名

        switch (position) {  
            case 0:  
                Intent intent = new Intent();  
                intent.setClass(it.getContext(), ChallengeFirst.class);  
                it.getContext().startActivity(intent);  
                return;  
            case 1:  
                Intent intent2 = new Intent();  
                intent2.setClass(it.getContext(), ChallengeSecond.class);  
                it.getContext().startActivity(intent2);  
                return;  
            case 2:  
                Intent intent3 = new Intent();  //new一个Intent,
                intent3.setClass(it.getContext(), AdActivity.class);  //传入要切换的Acitivity的类名
                it.getContext().startActivity(intent3);  //启动对应的Activity
                return;  
            case 3:  
                Intent intent4 = new Intent();  
                intent4.setClass(it.getContext(), ChallengeFourth.class);  
                it.getContext().startActivity(intent4);  
                return; 
            default:  
                return;  
        }
3.Activity生命周期
函数名称描述
onCreate()一个Activity启动后第一个被调用的函数,常用来在此方法中进行Activity的一些初始化操作。例如创建View,绑定数据,注册监听,加载参数等。
onStart()当Activity显示在屏幕上时,此方法被调用但此时还无法进行与用户的交互操作。
onResume()这个方法在onStart()之后调用,也就是在Activity准备好与用户进行交互的时候调用,此时的Activity一定位于Activity栈顶,处于运行状态。
onPause()这个方法是在系统准备去启动或者恢复另外一个Activity的时候调用,通常在这个方法中执行一些释放资源的方法,以及保存一些关键数据。
onStop()这个方法是在Activity完全不可见的时候调用的。
onDestroy()这个方法在Activity销毁之前调用,之后Activity的状态为销毁状态。
onRestart()当Activity从停止stop状态恢进入start状态时调用状态。
image-20221124101522887
4.弹窗定位&堆栈分析

修改方法:
1.修改xml中的versiocode
2.Hook弹窗(推荐算法助手开启弹窗定位)
3.修改dex弹窗代码
4.抓包修改响应体(也可以路由器拦截)

5.布局优化

1.开发者助手抓布局
2.MT管理器xml搜索定位
3.修改xml代码

android:visibility="gone"
四、操作

第四关的任务:去除广告全家桶

image-20221124103422945

我们打开MT管理器,开启Activity记录

image-20221124103204178

我们回到第四关可以发现是一个AD跳转到广告的,我们停止Activity记录,并找到这个Activity

image-20221124103738200

这个就是我们刚才定位到的一个广告的Activity,我们复制一下。

提取安装包

image-20221124103955167 image-20221124104036022

我们这里需要将其转为Java,但是由于这个需要会员功能,所以我们改用NP,需要的朋友可以自己开个会员。

image-20221124104230861

相同的操作我们将其转为Java看一下

image-20221124104425345

我们可以确定loadAD()方法是加载广告的。然后我们返回smali里找到这个方法。

image-20221124123459517

我们把0xbb8改成0x0(bb8是3000的十六进制),然后保存,再转为java看一下

image-20221124123648598

三千毫秒变成了0。我们保存安装完看一下有没有效果。

image-20221124123958420

直接就进入了这个页面,没有了3秒钟的等待时间。我们这里不是不经过这个Activity,而是经过,但是时间非常的短,我们看不到而已。如果想要证明可以通过Activity记录再次看一下。

我们换种方式

搜索刚才的记录,然后长按——复制,找到下图所示的内容复制,然后搜索,类型选择代码。

image-20221124125840232

我们可以看到结果有很多

image-20221124130007271

我们选择除了它以外的这个,看看它在哪里调用了这个。

image-20221124130104694 image-20221124130425308

我们转为java看一下

image-20221124130527542

我们可以看到第三关new了一个Intent,传入要切换的Acitivity的类名,启动对应的Activity。

我们可以把它调用广告的类名换成别的关的类名,比如第二关。然后保存退出重新安装

image-20221127104917731

更新的弹窗是版本不一样的时候就会弹出,我们直接去xml里就版本1改成2就能去掉了。

去掉更新弹窗后,出现了又一个弹窗

image-20221127105154831

这个我们可以用返回键关掉

image-20221127105312452

这时出现第二个广告弹窗,但是这个返回键被劫持了,我们不能用返回键关掉。

我们这里使用算法助手,进入算法助手,打开应用总开关和弹窗定位功能

image-20221127111440157 image-20221127111419740

点击右上角运行按钮,这时我们两个弹窗都可以用返回关掉了

image-20221127111539610

我们还有个功能——屏蔽关键词弹窗

image-20221127111625198

我们输入刚才出现的弹窗上的字

image-20221127111741037

我们再运行,进来后可以发现两个弹窗都没有了,算法助手对我们来说是一个神器了。

我们关掉弹窗拦截,运行后返回算法助手,查看日志,找到最新的弹窗

image-20221127112706120 image-20221127112908426

看到调用堆栈最上面,是一个onCreate方法。我们复制这个

image-20221127113042587

我们回到MT管理器的dex文件搜索刚才复制的那句话,类型选择方法名

image-20221127113239645

我们可以看到搜索结果有很多,我们选择最下面那个最准确的

image-20221127113344639

我们可以看到这个方法下面有一号广告和二号广告

image-20221127113601138

来到最下面,我们可以看到一个show方法,这种广告弹窗最后一般都会调用一个show方法来显示。

image-20221127113845011

一个很简单的方法就是把这个show方法这一行删掉或注释掉:我们在这句前打个#号就可以把这句话注释掉了。

image-20221127114033162

保存退出,重新安装。我们就可以看到1号弹窗已经不见了。

我们刚才看见一号二号都是在那个文件里的,所以我们回到那里,找到二号的show

image-20221127114333354

同理我们把它注释掉,然后保存退出,重新安装。

image-20221127114854920

两个广告弹窗都消失了。这种方法的关键是定位弹窗。

我们最后一个方法是抓包修改响应体(也可以路由器拦截),这个我们放在后面来说。接下来是横幅广告,我们要用到开发助手这个工具。

image-20221127115128702

我们主要用到的就是这个布局查看功能。

image-20221127115924061

我们复制16进制数,然后回到MT管理器的安装包,右上角XML搜索这个

image-20221127120036197 image-20221127120013820

进入文件

image-20221127120316798

有两种改法,第一种是把它的宽度或者高度改为0.

image-20221127161803065

保存退出安装,我们就可以看到横幅广告不见了。

image-20221127161903913

第二种方法需要用到一句代码

android:visibility="gone"

用这句代码把那个布局隐藏起来

image-20221127162415936

也可以实现横幅广告的消除。

image-20221127162504950

ps://typorazhd.oss-cn-beijing.aliyuncs.com/image-20221127120316798.png" alt=“image-20221127120316798” style=“zoom:67%;” />

有两种改法,第一种是把它的宽度或者高度改为0.

image-20221127161803065

保存退出安装,我们就可以看到横幅广告不见了。

image-20221127161903913

第二种方法需要用到一句代码

android:visibility="gone"

用这句代码把那个布局隐藏起来

image-20221127162415936

也可以实现横幅广告的消除。

image-20221127162504950
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游子无寒衣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值