首页
社区
课程
招聘
[原创] Xposed过滤某论坛APP广告
2023-7-6 23:50 5453

[原创] Xposed过滤某论坛APP广告

2023-7-6 23:50
5453

某屎黄色论坛广告太多了,特别最近更新的版本,被逼无奈怒学Xposed开发,写了个去广告模块,记录一下逆向以及开发模块的过程,可能部分内容和我的博客有一定雷同

C#和Java Web后端选手,非安卓开发,只有一点安卓逆向经验,如果有地方说的不对欢迎指正

某论坛肆无忌惮的广告

第一个目标是去除开屏广告,先在AndroidManifest.xml中找到启动类 gov.pianzong.androidnga.activity.LoadingActivity

图片描述

交叉引用查找一下LoadingActivity这个类,找到一个名叫ActivityLifecycleImpl的类,看名字应该跟生命周期有关

图片描述

一目了然了,就是在应用切换到前台和切换到后台的时候记录时间戳,然后在唤醒的时候判断应用在后台的累计时间,如果超过3分钟,就显示开屏广告

图片描述

SPUtil就是包装了一些sharedPreferences的操作,广告SDK的值储存在 dninfo.xml

图片描述

只要让判断广告要不要显示的逻辑一直为false就可以免开屏广告了,有很多种方法实现,可以直接Hook mg.b.a这个方法,让它的返回值始终小于180即可,不过我感觉这个类混淆过,有可能会随着版本变动,就退而求次选择Hook SPUtilgetInt方法,如果要读取AD_FORGROUND_TIME或者AD_BACKGROUND_TIME就直接返回0,这样计算的结果永远等于0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
 * 开屏广告钩子
 */
class SplashHook(classLoader: ClassLoader) : BaseHook(classLoader) {
 
    override fun startHook() {
        try {
            // 获取LoadingActivity类
            val clsLoadingActivity = XposedHelpers.findClass(
                "gov.pianzong.androidnga.activity.LoadingActivity",
                mClassLoader
            )
            // Hook toForeGround 方法
            XposedHelpers.findAndHookMethod(
                "com.donews.nga.interfaces.ActivityLifecycleImpl",
                mClassLoader,
                "toForeGround",
                Activity::class.java,
                object : XC_MethodHook() {
 
                    @Throws(Throwable::class)
                    override fun beforeHookedMethod(param: MethodHookParam?) {
                        super.beforeHookedMethod(param)
                        val activity = param?.args?.get(0) as Activity
                        if (activity.javaClass == clsLoadingActivity) {
                            Log.d("跳过启动页")
                            XposedHelpers.setBooleanField(activity, "canJump", true)
                            XposedHelpers.setBooleanField(activity, "isADShow", true)
                            XposedHelpers.callMethod(activity, "goHome")
                        }
                        //Log.d(activity.toString())
                    }
                })
 
            // 修改时间戳实现切屏无广告
            XposedHelpers.findAndHookMethod(
                "com.donews.nga.common.utils.SPUtil",
                mClassLoader,
                "getInt",
                String::class.java,
                Int::class.java,
                object : XC_MethodHook() {
                    @Throws(Throwable::class)
                    override fun afterHookedMethod(param: MethodHookParam) {
                        when (param.args[0] as String) {
                            "AD_FORGROUND_TIME" -> {
                                Log.d("FG " + param.result.toString())
                                param.result = 0
                            }
 
                            "AD_BACKGROUND_TIME" -> {
                                Log.d("BG " + param.result.toString())
                                param.result = 0
                            }
                        }
                    }
                })
 
            // 也可以Hook这个方法实现去开屏广告
            // 但是类名被混淆,会随着应用版本变动
            //XposedHelpers.findAndHookMethod(
            //    "mg.b",
            //    mClassLoader,
            //    "a",
            //    Context::class.java,
            //    object : XC_MethodReplacement() {
            //        override fun replaceHookedMethod(param: MethodHookParam?): Int {
            //            return 0;
            //        }
            //    })
        } catch (e: Exception) {
            Log.e(e)
        }
    }
}

可以看到还Hook了toForeGround这个方法,这是因为去掉了开屏广告,冷启动会显示黑屏,为了尽快跳过首屏加的(忘记为什么写了,大概是这个原因)

Hook框架参考了BiliRoaming的一些设计,XposedInit.kt如下,为了兼容zygote做了一些处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class XposedInit : IXposedHookLoadPackage, IXposedHookZygoteInit {
    override fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam) {
        modulePath = startupParam.modulePath
        moduleRes = getModuleRes(modulePath)
    }
 
    @Throws(Throwable::class)
    override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
        if (Constant.NGA_PACKAGE_NAME == lpparam.packageName) {
            Log.d("NGA内运行" + lpparam.packageName)
            startHook(SplashHook(lpparam.classLoader))
            startHook(RewardHook(lpparam.classLoader))
            startHook(VipHook(lpparam.classLoader))
            startHook(AdHook(lpparam.classLoader))
        }
    }
 
    private fun startHook(hooker: BaseHook) {
        try {
            Log.i(MessageFormat.format("Hook {0} Start", hooker::class.java.name))
            hooker.startHook()
        } catch (e: Throwable) {
            Log.e(e)
        }
    }
 
    companion object {
        lateinit var modulePath: String
        lateinit var moduleRes: Resources
 
        @JvmStatic
        fun getModuleRes(path: String): Resources {
            return XModuleResources.createInstance(path, null)
        }
    }
}

装好插件,启用以后确实没有开屏广告了,然后处理比较棘手的页面内嵌广告

图片描述

用布局分析找了个广告区域的角标,查一下字符串引用ad_logo,定位到BannerPageAdapter

图片描述

看类名应该是适配器模式,逻辑大概是获取广告的内容然后以违和感比较低的形式显示出来,对应的位置是首页Banner,要往广告SDK里去找内容的来源

图片描述

反查一下广告事件的接口DnJGFeedAd

图片描述

看名字loadJGFeedAd这个方法应该跟广告加载有关,里面做了一些处理,直接Hook会导致下面的逻辑出错,跟进一下,里面调用了DnPreloadAdCallBack这个接口,接着查找引用,一个个找相关的接口

图片描述

一样有loadFeedAd方法,参数太多了Hook太麻烦,退而求次换个函数函数requestServerSuccess,看名字应该是请求到广告内容成功以后的回调,里面应该是调用适配器进行展示了,直接整个替换成空方法

图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * 广告钩子
 */
class AdHook(classLoader: ClassLoader) : BaseHook(classLoader) {
    override fun startHook() {
        try {
            XposedHelpers.findAndHookMethod(
                "com.donews.admediation.adimpl.feed.DnFeedAd",
                mClassLoader,
                "requestServerSuccess",
                object : XC_MethodReplacement() {
                    override fun replaceHookedMethod(param: MethodHookParam?) {
                        Log.i("DnFeedAd.requestServerSuccess")
                    }
                })
        } catch (e: Exception) {
            Log.e(e)
        }
    }
}

然后就没有原生广告了,最后用lsposed.jar打包成整合版,方便没有xposed环境的人

网页端编辑器也太卡了,字多了半天才显示

这个号高中注册的,但是还是第一次发帖,多多见谅


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞3
打赏
分享
最新回复 (6)
雪    币: 51
活跃值: (318)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
btmanbtman 2023-7-7 09:33
2
0
血压降血压升/手动扇子脸
雪    币: 19349
活跃值: (28971)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-7-7 09:36
3
0
感谢分享
雪    币: 1069
活跃值: (1286)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ChrQwQ 2023-7-7 13:35
4
0
btmanbtman 血压降血压升/手动扇子脸
今天喜提封号30天
雪    币: 1729
活跃值: (8702)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
你瞒我瞒 2023-7-11 16:00
5
0
然后处理比较棘手的页面内嵌广告,查看ad_load组件的信息的工具是什么呢,大佬,如看到信息希望告知。
雪    币: 1069
活跃值: (1286)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ChrQwQ 2023-7-11 16:45
6
0
你瞒我瞒 然后处理比较棘手的页面内嵌广告,查看ad_load组件的信息的工具是什么呢,大佬,如看到信息希望告知。
我用的autojs6,github有,类似的软件还有易开发
雪    币: 1729
活跃值: (8702)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
你瞒我瞒 2023-7-12 09:09
7
0
ChrQwQ 我用的autojs6,github有,类似的软件还有易开发
感谢
游客
登录 | 注册 方可回帖
返回