改变App的运行逻辑去除广告

逆向App之篡改

上几篇介绍了如何抓包App的网络请求,以及脱壳和反编译App,以及如何Hook App的代码,也理清了App的调用顺序和逻辑,下面介绍下如何修复脱壳后的Dex,继而篡改App逻辑去除广告。

脱壳修复

修复主要是用mt管理器来实现,之前我们通过mt管理器知道该App使用了百度加固,然后通过BlackDex工具进行了脱壳还原dex文件,先将App文件和脱壳后的dex文件拷贝到模拟器指定目录。

image-20260611114053552

image-20260611114136478

mt管理器,左边视图打开App查看,右边视图选中脱壳后的三个dex文件,长按点击添加到左边App里面去。

image-20260611114529306

image-20260611114726616

删除左边视图原来的classes.dex文件,删除192.25kb的加固残余文件,否则会闪退,它里面包含了,ab.yucom.baiduyu.yu.yu等百度加固相关的代码。

image-20260611115455193

将剩余两个cookie开头的dex文件重命名为classes.dexclasses2.dex

image-20260612153408717

删除baiduk开头相关的加固残余。

image-20260612153459089

image-20260612153617107

替换入口文件将com.sagittarius.v6.StubApplication修改为com.dsdqjx.tvhd.activity.MyApplication,去除签名重新前后安装即可完美运行。

image-20260612153825085

去除图片广告弹窗

image-20260612164122658

前面通过抓包http://xxx.yxtv.cc/api/get_status2024.php请求,并解密响应后知道,知道adData字段里面包含了广告图片地址。

image-20260612154725334

那么我们可以找这个字段在哪里用到了,进而发现展示图片广告的逻辑在GovIjkPlayerActivityonCreate方法调用initAd()展示广告方法。

image-20260612154836455

image-20260612155028792

那么,我们通过mt管理器,注释掉该逻辑即可。

.line 427
    invoke-direct {p0}, Lcom/dsdqjx/tvhd/activity/GovIjkPlayerActivity;->initAd()V

image-20260612160903393

去除首页广告频道

image-20260612164229855

首页直接播放的是广告频道,同上抓包数据返回的"lastEname": "tvad1"就是最后播放的频道这里是广告台,搜索该关键字,找到StartActivity类的goGovAct方法,找配置文件中最后播放频道,如果最后频道没有值则默认播放cctv1hd,再通过数据库查询频道的chid值,通过查询SQLite数据库,cctv1hdchid值为1,那么我们通过修改逻辑,直接将intent.putExtra("chid", str);chid焊死为1,那么就不会播放广告台而是中央1台了。

image-20260612162455222

我们通过mt管理器,修改下该逻辑直接给变量v0赋值为1即可。

# 修改前
.line 808
    const-string v2, "chid"

    invoke-virtual {v1, v2, v0}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;

# 修改后
.line 808
    const-string v2, "chid"

    const-string v0, "1"

    invoke-virtual {v1, v2, v0}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;

去除列表广告频道

image-20260612164332779

通过查看下载的直播频道文件channel_list.txt,里面就已经包含了广告频道。

image-20260615111943153

进一步分析,该文件内容,最终是被插入到了SQlite数据库中。

image-20260615112118432

image-20260615112231788

我们通过mt管理器,在StartActivity类中的initListData插入数据库方法中修改逻辑,在插入channel_list_table表格数据之后,将广告频道做删除操作即可。

# 修改前
.line 1001
    const-string v0, "DELETE FROM source_list_table"

    invoke-virtual {v9, v0}, Landroid/database/sqlite/SQLiteDatabase;->execSQL(Ljava/lang/String;)V
    :try_end_16e
    .catch Ljava/lang/Exception; {:try_start_d2 .. :try_end_16e} :catch_52c

    const/4 v0, 0x0

# 修改后
.line 1001
    const-string v0, "DELETE FROM source_list_table"

    invoke-virtual {v9, v0}, Landroid/database/sqlite/SQLiteDatabase;->execSQL(Ljava/lang/String;)V

    const-string v0, "DELETE FROM channel_list_table where ename like \'tvad%\'"

    invoke-virtual {v9, v0}, Landroid/database/sqlite/SQLiteDatabase;->execSQL(Ljava/lang/String;)V
    :try_end_173
    .catch Ljava/lang/Exception; {:try_start_d2 .. :try_end_173} :catch_531

    const/4 v0, 0x0

image-20260615113046636

image-20260615170744860

去除空白弹窗

image-20260612164257572

这里我们通过搜索小云TV关键字,可以搜到使用到的是app_name,再进一步搜索该字段,发现有两个类使用到了该字段,查阅代码后猜测大概率是ChannelService类。

image-20260615171154505

image-20260615171238283

然后再通过Hook技术,确定该空白弹窗具体是DialogPopupWindow还是其他控件,经过不断尝试最后发现是Service前台通知,具体通过startForegroundService提升为前台服务,Hook脚本如下。

if (Java.available) {
    Java.perform(function () {
        console.log("✅ 启动加固兼容模式");

        // 循环查找(每 1 秒查一次,直到找到类)
        var timer = setInterval(function () {
            try {				
				// ============== 3. Hook Service类,拦截 startForeground 不让它绑定前台通知 ==============
				let Service = Java.use("android.app.Service");
				Service.startForeground.implementation = function(id, notification) {
					console.log("🔴 拦截 startForeground 前台服务通知 id=" + id);
					console.log("│ 调用堆栈2:");
						console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));
					// 不调用原方法 = 不显示通知、不悬浮、不进通知栏
					// this.startForeground(id, notification);
				};

                console.log("🎯 所有方法 Hook 成功!");

                clearInterval(timer); // 找到就停止

            } catch (e) {}
        }, 1000);
    });
}

我们通过mt管理器,在ChannelServiceLiveService类中注释掉startForeground方法即可。

# channelservice类
.line 89
    invoke-virtual {p0, v1, v0}, Lcom/dsdqjx/tvhd/service/ChannelService;->startForeground(ILandroid/app/Notification;)V
	# cond不要删是条件的结束语句
    :cond_39
    
.line 97
    iget-object p2, p0, Lcom/dsdqjx/tvhd/service/ChannelService;->notification:Landroid/app/Notification;

    invoke-virtual {p0, p1, p2}, Lcom/dsdqjx/tvhd/service/ChannelService;->startForeground(ILandroid/app/Notification;)V
	# cond不要删是条件的结束语句
    :cond_f
  
# liveservice类
.line 44
    invoke-direct {p0}, Lcom/dsdqjx/tvhd/service/LiveService;->startForegroundService()V