一、基本概念
1.1 安卓四大组件
组件 | 描述 |
---|---|
Activity(活动) | 在应用中的一个Activity可以用来表示一个界面,意思可以理解为“活动”,即一个活动开始,代表 Activity组件启动,活动结束,代表一个Activity的生命周期结束。一个Android应用必须通过Activity来运行和启动,Activity的生命周期交给系统统一管理。 |
Service(服务) | Service它可以在后台执行长时间运行操作而没有用户界面的应用组件,不依赖任何用户界面,例如后台播放音乐,后台下载文件等。 |
Broadcast Receiver(广播接收器) | 一个用于接收广播信息,并做出对应处理的组件。比如我们常见的系统广播:通知时区改变、电量低、用户改变了语言选项等。 |
Content Provider(内容提供者) | 作为应用程序之间唯一的共享数据的途径,Content Provider主要的功能就是存储并检索数据以及向其他应用程序提供访问数据的接口。Android内置的许多数据都是使用Content Provider形式,供开发者调用的(如视频,音频,图片,通讯录等) |
1.2 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;
}
1.3 Activity生命周期
函数名称 | 描述 |
---|---|
onCreate() | 一个Activity启动后第一个被调用的函数,常用来在此方法中进行Activity的一些初始化操作。例如创建View,绑定数据,注册监听,加载参数等。 |
onStart() | 当Activity显示在屏幕上时,此方法被调用但此时还无法进行与用户的交互操作。 |
onResume() | 这个方法在onStart()之后调用,也就是在Activity准备好与用户进行交互的时候调用,此时的Activity一定位于Activity栈顶,处于运行状态。 |
onPause() | 这个方法是在系统准备去启动或者恢复另外一个Activity的时候调用,通常在这个方法中执行一些释放资源的方法,以及保存一些关键数据。 |
onStop() | 这个方法是在Activity完全不可见的时候调用的。 |
onDestroy() | 这个方法在Activity销毁之前调用,之后Activity的状态为销毁状态。 |
onRestart() | 当Activity从停止stop状态恢进入start状态时调用状态。 |
1.4 弹窗定位&堆栈分析
修改方法:
1.修改xml中的versioncode
2.Hook弹窗(推荐算法助手开启弹窗定位)
3.修改dex弹窗代码
4.抓包修改响应体(也可以路由器拦截)
1.5 布局优化
1.开发者助手抓布局
2.MT管理器xml搜索定位
3.修改xml代码
android:visibility="gone"
二、练习
2.1 去开屏广告
首先定位到这个Activity
弹出的广告的是com.zj.wuaipojie.ui.AdActivity
,mt管理器进行搜索类名
.method private final loadAd()V
.registers 5
.line 27
new-instance v0, Landroid/os/Handler;
invoke-direct {v0}, Landroid/os/Handler;-><init>()V
new-instance v1, Lcom/zj/wuaipojie/ui/AdActivity$$ExternalSyntheticLambda0;
invoke-direct {v1, p0}, Lcom/zj/wuaipojie/ui/AdActivity$$ExternalSyntheticLambda0;-><init>(Lcom/zj/wuaipojie/ui/AdActivity;)V
// v2赋值0xbb8 即3000毫秒 = 3秒
const-wide/16 v2, 0xbb8
// 调用延时的方法postDelayed 意为3秒后广告结束 切入主窗口
// 这里的参数 vo 代表 Handler的引用 v1 表示Runnable的引用 v2表示时长的引用 v3没有用到忽略
invoke-virtual {v0, v1, v2, v3}, Landroid/os/Handler;->postDelayed(Ljava/lang/Runnable;J)Z
return-void
.end method
2.1.1 修改广告时长
了解v2
寄存器存储广告时长后可以直接赋值为0x0
变相实现跳过
但其实还是会跳转到AdActivity
2.1.2 修改Activity切换
重新搜索Lcom/zj/wuaipojie/ui/AdActivity;
类型选择代码,目的是定位在smali层面哪里调用了AdActivity
就可以找到切换Activity
的逻辑。
2.1.3 修改AndroidManifest
将启动类的名称直接修改为ChallengeThird
不推荐,容易跳过应用内部加载数据的逻辑
2.2 跳弹窗广告
2.2.1 版本更新广告
方式一:修改AndroidManifest.xml
中的versionCode
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"># 由1改成2即可过
</manifest>
方式二:直接注释掉弹窗代码
1.直接根据文件内容搜索有新版本需要更新
得到布局文件为y4.xml
2.使用Arsc编辑器
打开resources.arsc
得到布局名称为fragment_update
,再在Dex编辑器++中根据代码搜索,得到对应的资源Id0x7f0b003a
在搜索整数十六进制,拿到关键类DialogUtilsKt
,这是一个工具类,只需要找到在主Activity中调用的位置进行注释即可。
3.定位DialogUtilsKt的使用
注释掉即可。
2.2.2 普通弹窗
分别是可回退跳过和不可回退跳过的类型。
2.2.2.1 算法助手的使用
勾选上后原先无法使用回退的弹窗也可以进行返回取消了。
查看使用日志
分析发现是在ChallengeThird.onCreate
生命周期内调用的方法。
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(2131427361);
Context context = (Context) this;
Builder builder = new Builder(context);
builder.setTitle("这是二号广告标题");
builder.setMessage("这是二号广告内容");
builder.setCancelable(false);
String str = "前往论坛";
builder.setPositiveButton(str, new ExternalSyntheticLambda1(this));
String str2 = "退出软件";
builder.setNegativeButton(str2, ExternalSyntheticLambda2.INSTANCE);
builder.show();
new CommonDialog.Builder(context).setMessage("一号广告弹窗已就位").setNegativeButton(str2, ExternalSyntheticLambda3.INSTANCE).setMessageColor(-16777216).setPositiveButton(str, new ExternalSyntheticLambda0(this)).setWith(0.8f).create().show();
checkUpdate();
}
直接切到smali
下将两个show
的调用注释即可。
2.3 去横幅遮挡广告
1.首先定位元素
Id(Hex):0x7f0801ca
直接将宽高改为0dp
或添加属性android:visibility="gone"
三、课后作业
这里发现有三个方法 三处show调用。
方法一: show全部注释掉即可。
方法二:查看每个方法的调用找到真正的函数调用,并从调用处解决
引用
1.《安卓逆向这档事》四、恭喜你获得广告&弹窗静默卡:https://www.52pojie.cn/thread-1706691-1-1.html
2.吾爱破解安卓逆向入门教程《安卓逆向这档事》四、恭喜你获得广告&弹窗静默卡:https://www.bilibili.com/video/BV14v4y1D7yA/
3.算法助手!基于Xposed的通用Hook工具:https://bbs.kanxue.com/thread-267985.htm
评论 (0)