本文内容摘自吾爱破解论坛正己的《安卓逆向这档事》系列教程,略有删改、补充。
工具
- 教程Demo
- MT管理器
- 算法助手
- 雷电模拟器
- 开发助手
广告类型
一般有三种类型的广告:
- 启动广告
- 弹窗广告
- 横幅广告
启动广告
原理
启动广告流程:启动Activity->广告Activity->主页Activity
安卓四大组件
组件 | 描述 |
---|---|
Activity(活动) | 在应用中的一个Activity可以用来表示一个界面,意思可以理解为“活动”,即一个活动开始,代表 Activity组件启动,活动结束,代表一个Activity的生命周期结束。一个Android应用必须通过Activity来运行和启动,Activity的生命周期交给系统统一管理。 |
Service(服务) | Service它可以在后台执行长时间运行操作而没有用户界面的应用组件,不依赖任何用户界面,例如后台播放音乐,后台下载文件等。 |
Broadcast Receiver(广播接收器) | 一个用于接收广播信息,并做出对应处理的组件。比如我们常见的系统广播:通知时区改变、电量低、用户改变了语言选项等。 |
Content Provider(内容提供者) | 作为应用程序之间唯一的共享数据的途径,Content Provider主要的功能就是存储并检索数据以及向其他应用程序提供访问数据的接口。Android内置的许多数据都是使用Content Provider形式,供开发者调用的(如视频,音频,图片,通讯录等) |
定位方法
Activity 切换定位
MT管理器的 Activity记录 功能,能够将当前的 Activity 记录下来。
打开侧边栏->Activity记录->启动服务,就会有一个悬浮框弹出,它会记录下当前的 Activity:
打开任意一款软件,可以看到一系列 Activity 被记录了下来:
记录下来的 Activity 可以在MT管理器里看到,长按可以复制结果:
将复制下来的Activity类名到 classes.dex 文件中进行搜索,可以快速定位到启动广告。
去除方法
一、修改加载时间
定位到程序广告加载时间的逻辑,将其改为0。
二、修改 Intent 的 Activity 类名
AndroidMainifest.xml:
<!---声明实现应用部分可视化界面的 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 中往往要执行一些初始化操作,如果直接把它替换掉,可能会导致各种奇怪的问题产生,因此不推荐这种方法。
三、修改切换 activity 的代码
从 classes.dex 搜索 activity 的类名,复制出该 activity 在 smali 代码中的名称进行代码搜索来进一步定位。用 smali 代码中的名称搜索,搜到的结果会更多。
在其他类中进一步定位找到切换该 activity 的代码,并进行修改。因为切换 activity 一般都是由别的类调用的,所以自身的类中的代码可以排除,直接到其他类中找切换的代码。
弹窗广告
原理
一般在 Activity 的 onCreate 方法初始化时创建 Dialog,调用 show 方法来显示弹框。
Activity 生命周期
这些函数都是 Activity 的回调函数,只有当 Activity 到达对应生命周期时才会被调用,无法主动调用。
函数名称 | 描述 |
---|---|
onCreate() | 一个 Activity 启动后第一个被调用的函数,常用来在此方法中进行 Activity 的一些初始化操作。例如创建 View,绑定数据,注册监听,加载参数等。 |
onStart() | 当 Activity 显示在屏幕上时,此方法被调用但此时还无法进行与用户的交互操作。 |
onResume() | 这个方法在 onStart() 之后调用,也就是在 Activity 准备好与用户进行交互的时候调用,此时的 Activity 一定位于 Activity 栈顶,处于运行状态。 |
onPause() | 这个方法是在系统准备去启动或者恢复另外一个 Activity 的时候调用,通常在这个方法中执行一些释放资源的方法,以及保存一些关键数据。 |
onStop() | 这个方法是在 Activity 完全不可见的时候调用的。 |
onDestroy() | 这个方法在 Activity 销毁之前调用,之后 Activity 的状态为销毁状态。 |
onRestart() | 当 Activity 从停止 stop 状态恢进入 start 状态时调用状态。 |
去除方法
一、修改 xml 中的 versionCode(针对更新弹框)
部分更新弹框的逻辑会比对后台的版本号与当前 app 里的 versionCode 是否一致,不一致就弹出更新弹框。
对于这种更新弹框,修改 AndroidManifest.xml 中的 versionCode 可以去除。比如,将下图的 versionCode=”1″ 改成 “2”:
二、Hook 弹窗
这里用的是算法助手来 hook 弹窗,也可以用别的有类似功能的软件。
算法助手里开启弹窗定位,可以让弹窗被返回键取消(即使弹窗劫持了返回键)。
屏蔽关键词弹窗,可以把带有关键词的弹框屏蔽掉。
三、修改 dex 弹窗代码
通过算法助手的弹窗定位功能,在日志里可以看到弹框的一些调试信息。
根据调试信息在 classes.dex 中可以定位到弹框的代码,然后进行修改。
一般弹框都会调用 show 方法来显示,只要注释掉对应语句即可。比如:
四、抓包修改响应体(也可以路由器拦截)
略,后面会讲
横幅广告
原理
横幅广告指出现在 UI 布局中的广告,在资源目录下的 XML 文件中有对应元素。
去除方法
使用开发助手的布局查看功能,抓取对应广告布局,得到对应的 16 进制 id:
将得到的 id 到MT管理器中通过XML搜索定位到对应的 XML 文件,然后在文件中搜索 id 定位到 XML 代码。
需要注意的是,复制下来的 id 开头带有 0x,在到 XML 代码中搜索时要去掉 0x 前缀。
如果还是搜索不到的话,看下是否开启了ID转名称,开启了的把它关掉就可以搜到了。
比如这里搜到的布局元素是这样的:
<ImageView
android:id="@7f0801ca"
android:background="@7f0d0017"
android:layout_width="wrap_content"
android:layout_height="150dp"
android:layout_marginTop="100dp" />
一、将宽高改为 0
把 layout_width 或 layout_height 改为 0。比如这里就把上面搜到的元素的 layout_width 改成了 0:
<ImageView
android:id="@7f0801ca"
android:background="@7f0d0017"
android:layout_width="0dp"
android:layout_height="150dp"
android:layout_marginTop="100dp" />
二、将可见性改为不可见
在对应元素中增加下面这样的语句:
android:visibility="gone"
比如对于上面搜到的元素增加后的代码是这样的:
<ImageView
android:id="@7f0801ca"
android:background="@7f0d0017"
android:layout_width="wrap_content"
android:layout_height="150dp"
android:layout_marginTop="100dp"
android:visibility="gone" />