按键精灵安卓版去广告伪装详解

本帖最后由 TommyFFF 于 2019-9-15 09:24 编辑

如题,先看效果图吧,左边是去广告之前   右边是伪装去广告之后

下面开始一步步讲解:

步骤如下:
1、把你打包出来的安卓小精灵给拆包了
2、修改源码的资源(修改包名跟名称跟图片,也就是很多人为了防封所做的简单伪装)
3、修改源码的smali文件(去广告关键步骤)
4、完成修改重新打包
5、重新打完包之后重新签名


1、把你打包出来的安卓小精灵给拆包了
可以参考博客地址:拆包打包地址 https://blog.csdn.net/qq_30552993/article/details/83028285
下载 apktool 跟 signapk 工具,由于工具包有点大 17M左右所以附上下载地址吧(或者自行百度下载都可以):
工具下载链接 https://download.csdn.net/download/u010381752/11743596
由于拆包工具是基于 java 编写的,所以电脑上必须安装了 java,并且已经设置了全局变量
win + R cmd 回车,输入 java 回车如下图所示为正常安装 java



如果不是如截图所示,请安装java并且设置全局环境变量



实在不会弄,百度一下 java 环境变量设置 应该有一大堆文章说明

接下来开始拆包:
首先把目标apk复制到apktool根目录中, 名称改为 test.apk (为什么要改名,方便敲命令,如果你不想改下面的test全部写你自己包的名字也行)
apktool 文件夹下 cmd 刷出命令框,然后输入命令 : apktool.bat d -f test.apk -o test
运行完成之后,生成一个test的文件夹,生成之后到文件夹下去修改想要修改的东西然后再运行命令将其打包
重新打包命令: apktool.bat b test (在你修改完东西之前先别急着打包)
说明下,这里的 apktool.bat xxxxx  看源码可知: 可以直接用 java -jar 命令写,如最后的打包:
java -jar apktool_2.4.0.jar b test

2、修改源码的资源
第一步中拆包完成后 test 文件夹下找到 AndroidManifest.xml 文件 该文件为 app的入口清单配置文件 包名可以在此修改
打开 文件 开头代码片段如下:
[HTML] 纯文本查看 复制代码

<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" [color=#ff0000][b]package="com.namomhmemnjijhjkjijhjk.tommy.test"[/b][/color] platformBuildVersionCode="27" platformBuildVersionName="8.1.0">



其中的 package = “com.namomhmemnjijhjkjijhjk.tommy.test” 冒号里面这堆就是包名了 我上面要伪装成 ofo 所以包名自然要换成 ofo的包名(so.ofo.labofo),至于ofo的包名如何获取按上面的步骤给反编译出来即可。
包名改了,还要改名称改图片logo等 这些都差不多
名称在目录下:..\test\res\values\string.xml 文件中修改,打开string文件,所示 app_name 找到app的名称,修改即可。



文件的东西修改完成之后记得保存。

logo目录如下:
..\test\res\drawable-hdpi-v4
..\test\res\drawable-ldpi-v4
..\test\res\drawable-xhdpi-v4
..\test\res\drawable-xxhdpi-v4
这四个目录下面的 ic_launcher.png 文件 换成你要换的 logo

闪屏图片目录如下:
..\test\res\drawable-xhdpi-v4
这个目录中的 img_splash_logo.png 文件就是 小精灵启动的图片 查看了属性这是一张 1080*1920 的图片,你也换一张这个大小的就行

当然如果你是安卓开发工程师,上面说的这些都是多余的,你想怎么改怎么换您随意,小白可以看看。做完这些就可以把包重新打包,用第一步中提到的命令:apktool.bat b test
重新打完包,再签名,就可以正常安装了,安装之后logo什么的都换了,但是广告还是有的,当然要是有钱,续一个去广告的vip,到这里可以正常打包完成了。


4、完成修改重新打包
apktool 文件夹下 cmd 刷出命令框,然后输入命令 : apktool.bat b test
完成重新打包之后,会生成一个 dist 文件夹 该文件夹中的 apk 文件才是你修改之后,重新打包生成的,这里要注意一下
5、重新打完包之后重新签名
因为我的工具包把 apktool 跟 signapk 的东西都放一起了,所以签名的时候 要从 dist 文件夹中,复制test.apk出来,覆盖原来的,然后运行下面的命令
打包命令:java -jar signapk.jar testkey.x509.pem testkey.pk8 test.apk test_signed.apk
打包完成后,生成的 test_signed.apk文件就是你修改之后并且打包生成的 可以直接安装。

================================================================================================================
注意:前方高能,可能会导致某些人不适,请在大人的陪同下观看
3、修改源码的smali文件(去广告关键步骤)
反编译工具: jadx-0.6.1-dev-build226
工具目录bin下,打开jadx-gui.bat,找到你的 apk 确定



首先找到程序的入口点
如何查找?前面说到的清单文件打开查看便可



图中的 android:name="com.cyjh.elfin.activity.news.SplashActivity" 就是入口点

去广告处理流程,请注意 下面照顾不了小白了,必须要有安卓开发功底才能看懂了。
逻辑分析
看完启动入口的逻辑后发现,handler消息作为主要控制源,启动app之后运行流程如下: 19 -》21 -》20
消息进入19去网络请求验证信息,验证完成之后加载广告,加载完广告之后跳21,然后跳20,跳20之后就正常进入脚本业务了。
那么做法很多,条条大路通罗马,我这里在请求广告之前,修改代码跳到21,然后就可以过掉启动页面的闪屏广告了。



1.首页闪屏广告
找到app的入口点,通过Androidmanifest.xml可知,入口activity为:com.cyjh.elfin.activity.news.SplashActivity
找到 loadAdOrCallNextPage() 这个方法
private void loadAdOrCallNextPage() {
        if (this.isLoadCompleteTemplateVerify && !this.isLoadCompleteStartup) {
            this.mHandler.obtainMessage(21).sendToTarget();
        }
        if (ParamsWrap.getParamsWrap().isFreeAd()) {
            IntentUtils.toCallElfinFreeActivity(this);
            finish();
            return;
        }
        loadAdMessage();
    }
屡了一波逻辑发现 进来走了 initAfter方法 第一次走进来的时候 this.isLoadCompleteTemplateVerify && !this.isLoadCompleteStartup 哥俩不满足条件 以及 ParamsWrap.getParamsWrap().isFreeAd() 也不满足条件 所以 会走到 loadAdMessage() 去各种加载广告所以 修改为
一进来就让 第一个 if 判断满足 让消息发 21
对应smali代码
    const/4 v0, 0x1
    .line 551
    iput-boolean v0, p0, Lcom/cyjh/elfin/activity/news/SplashActivity;->isLoadCompleteTemplateVerify:Z

解释下 smali 语法


把 0x1 赋值给 vo 寄存器 然后下面的 iput 就是把 v0 这个值压入 isLoadCompleteTemplateVerify 这个变量
这里的 0x1 为 True  0x0 为 False

.method private loadAdOrCallNextPage()V
    .locals 2




    const/4 v0, 0x1
    .line 551
    iput-boolean v0, p0, Lcom/cyjh/elfin/activity/news/SplashActivity;->isLoadCompleteTemplateVerify:Z
    const/4 v0, 0x0
    .line 551
    iput-boolean v0, p0, Lcom/cyjh/elfin/activity/news/SplashActivity;->isLoadCompleteStartup:Z




    .line 552
    iget-boolean v0, p0, Lcom/cyjh/elfin/activity/news/SplashActivity;->isLoadCompleteTemplateVerify:Z




    if-eqz v0, :cond_0




    iget-boolean v0, p0, Lcom/cyjh/elfin/activity/news/SplashActivity;->isLoadCompleteStartup:Z




    if-nez v0, :cond_0




    .line 554
    iget-object v0, p0, Lcom/cyjh/elfin/activity/news/SplashActivity;->mHandler:Lcom/cyjh/elfin/activity/news/SplashActivity$MyHandler;




    const/16 v1, 0x15




    invoke-virtual {v0, v1}, Lcom/cyjh/elfin/activity/news/SplashActivity$MyHandler;->obtainMessage(I)Landroid/os/Message;




    move-result-object v0




    invoke-virtual {v0}, Landroid/os/Message;->sendToTarget()V




    .line 556
    :cond_0
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;




    move-result-object v0




    invoke-virtual {v0}, Lcom/cyjh/elfin/entity/ParamsWrap;->isFreeAd()Z




    move-result v0




    if-nez v0, :cond_1




    .line 558
    invoke-direct {p0}, Lcom/cyjh/elfin/activity/news/SplashActivity;->loadAdMessage()V




    goto :goto_0




    .line 561
    :cond_1
    invoke-static {p0}, Lcom/cyjh/elfin/util/IntentUtils;->toCallElfinFreeActivity(Landroid/content/Context;)V




    .line 562
    invoke-virtual {p0}, Lcom/cyjh/elfin/activity/news/SplashActivity;->finish()V




    :goto_0
    return-void
.end method

    public void startupSuc(AppStartupResponse appStartupResponse) {

        AuthorRelatedInfo authorRelatedInfo = appStartupResponse.AuthorInfo;

        if (authorRelatedInfo.ServicePackStatus == 0) {

            this.isLoadCompleteStartup = true;

            DialogManager.getInstance().displayDialogMessage(authorRelatedInfo.ServicePackStatus, authorRelatedInfo.ServicePackPrompt, this, new MyKnownButtonListener());

            return;

        }

        ParamsWrap.getParamsWrap().isFreeAd = authorRelatedInfo.IsFreeAd;

        ParamsWrap.getParamsWrap().engineToken = authorRelatedInfo.EngineToken;

        appStartupResponse = appStartupResponse.AppInfo;

        ParamsWrap.getParamsWrap().dailyTryTimes = appStartupResponse.DailyTryTimes;

        ParamsWrap.getParamsWrap().feedbackTips = appStartupResponse.FeedbackTips;

        ParamsWrap.getParamsWrap().onceTryMinute = appStartupResponse.OnceTryMinute;

        ParamsWrap.getParamsWrap().crateCollect();

        if (appStartupResponse.BuyRegCodeConfig != null) {

            ParamsWrap.getParamsWrap().mBuyRegCodeConfigInfos.addAll(appStartupResponse.BuyRegCodeConfig);

        }

        if (appStartupResponse.FlySetting != null) {

            ParamsWrap.getParamsWrap().mFlySettingInfos.addAll(appStartupResponse.FlySetting);

        }

        if (appStartupResponse.RecommendSetting != null) {

            ParamsWrap.getParamsWrap().mRecommendSettingInfos.addAll(appStartupResponse.RecommendSetting);

        }

        if (authorRelatedInfo.AdList != null) {

            ParamsWrap.getParamsWrap().mAdInfos.addAll(authorRelatedInfo.AdList);

        }

        this.isLoadCompleteStartup = true;

        if (authorRelatedInfo.ServicePackStatus == 1) {
loadAdOrCallNextPage();

        } else if (authorRelatedInfo.ServicePackStatus == 2) {

            DialogManager.getInstance().displayDialogMessage(authorRelatedInfo.ServicePackStatus, authorRelatedInfo.ServicePackPrompt, this, new MyKnownButtonListener());

        }

    }
发了21就会走到这里 再load进去 都第二个 if 这样就可以跳了,但是我们前面设置了无限跑到第一个if判断去所以这里改为

    public void startupSuc(AppStartupResponse appStartupResponse) {
        AuthorRelatedInfo authorRelatedInfo = appStartupResponse.AuthorInfo;
        if (authorRelatedInfo.ServicePackStatus == 0) {
            this.isLoadCompleteStartup = true;
            DialogManager.getInstance().displayDialogMessage(authorRelatedInfo.ServicePackStatus, authorRelatedInfo.ServicePackPrompt, this, new MyKnownButtonListener());
            return;
        }
        ParamsWrap.getParamsWrap().isFreeAd = authorRelatedInfo.IsFreeAd;
        ParamsWrap.getParamsWrap().engineToken = authorRelatedInfo.EngineToken;
        appStartupResponse = appStartupResponse.AppInfo;
        ParamsWrap.getParamsWrap().dailyTryTimes = appStartupResponse.DailyTryTimes;
        ParamsWrap.getParamsWrap().feedbackTips = appStartupResponse.FeedbackTips;
        ParamsWrap.getParamsWrap().onceTryMinute = appStartupResponse.OnceTryMinute;
        ParamsWrap.getParamsWrap().crateCollect();
        if (appStartupResponse.BuyRegCodeConfig != null) {
            ParamsWrap.getParamsWrap().mBuyRegCodeConfigInfos.addAll(appStartupResponse.BuyRegCodeConfig);
        }
        if (appStartupResponse.FlySetting != null) {
            ParamsWrap.getParamsWrap().mFlySettingInfos.addAll(appStartupResponse.FlySetting);
        }
        if (appStartupResponse.RecommendSetting != null) {
            ParamsWrap.getParamsWrap().mRecommendSettingInfos.addAll(appStartupResponse.RecommendSetting);
        }
        if (authorRelatedInfo.AdList != null) {
            ParamsWrap.getParamsWrap().mAdInfos.addAll(authorRelatedInfo.AdList);
        }
        this.isLoadCompleteStartup = true;
        if (authorRelatedInfo.ServicePackStatus == 1) {
            IntentUtils.toCallElfinFreeActivity(this);
         finish();
        } else if (authorRelatedInfo.ServicePackStatus == 2) {
            DialogManager.getInstance().displayDialogMessage(authorRelatedInfo.ServicePackStatus, authorRelatedInfo.ServicePackPrompt, this, new MyKnownButtonListener());
        }
    }
这样就满足条件了.
对应到smali代码
.method public startupSuc(Lcom/cyjh/share/bean/response/AppStartupResponse;)V
    .locals 5

    .line 515
    iget-object v0, p1, Lcom/cyjh/share/bean/response/AppStartupResponse;->AuthorInfo:Lcom/cyjh/share/bean/response/AuthorRelatedInfo;

    .line 516
    iget v1, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->ServicePackStatus:I

    const/4 v2, 0x0

    const/4 v3, 0x1

    if-nez v1, :cond_0

    .line 517
    iput-boolean v3, p0, Lcom/cyjh/elfin/activity/news/SplashActivity;->isLoadCompleteStartup:Z

    .line 518
    invoke-static {}, Lcom/cyjh/elfin/dialog/DialogManager;->getInstance()Lcom/cyjh/elfin/dialog/DialogManager;

    move-result-object p1

    iget v1, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->ServicePackStatus:I

    iget-object v0, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->ServicePackPrompt:Ljava/lang/String;

    new-instance v3, Lcom/cyjh/elfin/activity/news/SplashActivity$MyKnownButtonListener;

    invoke-direct {v3, p0, v2}, Lcom/cyjh/elfin/activity/news/SplashActivity$MyKnownButtonListener;-><init>(Lcom/cyjh/elfin/activity/news/SplashActivity;Lcom/cyjh/elfin/activity/news/SplashActivity$1;)V

    invoke-virtual {p1, v1, v0, p0, v3}, Lcom/cyjh/elfin/dialog/DialogManager;->displayDialogMessage(ILjava/lang/String;Landroid/content/Context;Lcom/cyjh/elfin/listener/BaseTextViewKnownListener;)V

    goto/16 :goto_0

    .line 521
    :cond_0
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;

    move-result-object v1

    iget v4, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->IsFreeAd:I

    iput v4, v1, Lcom/cyjh/elfin/entity/ParamsWrap;->isFreeAd:I

    .line 522
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;

    move-result-object v1

    iget-object v4, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->EngineToken:Ljava/lang/String;

    iput-object v4, v1, Lcom/cyjh/elfin/entity/ParamsWrap;->engineToken:Ljava/lang/String;

    .line 523
    iget-object p1, p1, Lcom/cyjh/share/bean/response/AppStartupResponse;->AppInfo:Lcom/cyjh/share/bean/response/AppRelatedInfo;

    .line 524
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;

    move-result-object v1

    iget v4, p1, Lcom/cyjh/share/bean/response/AppRelatedInfo;->DailyTryTimes:I

    iput v4, v1, Lcom/cyjh/elfin/entity/ParamsWrap;->dailyTryTimes:I

    .line 525
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;

    move-result-object v1

    iget-object v4, p1, Lcom/cyjh/share/bean/response/AppRelatedInfo;->FeedbackTips:Ljava/lang/String;

    iput-object v4, v1, Lcom/cyjh/elfin/entity/ParamsWrap;->feedbackTips:Ljava/lang/String;

    .line 526
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;

    move-result-object v1

    iget v4, p1, Lcom/cyjh/share/bean/response/AppRelatedInfo;->OnceTryMinute:I

    iput v4, v1, Lcom/cyjh/elfin/entity/ParamsWrap;->onceTryMinute:I

    .line 527
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;

    move-result-object v1

    invoke-virtual {v1}, Lcom/cyjh/elfin/entity/ParamsWrap;->crateCollect()V

    .line 528
    iget-object v1, p1, Lcom/cyjh/share/bean/response/AppRelatedInfo;->BuyRegCodeConfig:Ljava/util/List;

    if-eqz v1, :cond_1

    .line 529
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;

    move-result-object v1

    iget-object v1, v1, Lcom/cyjh/elfin/entity/ParamsWrap;->mBuyRegCodeConfigInfos:Ljava/util/List;

    iget-object v4, p1, Lcom/cyjh/share/bean/response/AppRelatedInfo;->BuyRegCodeConfig:Ljava/util/List;

    invoke-interface {v1, v4}, Ljava/util/List;->addAll(Ljava/util/Collection;)Z

    .line 531
    :cond_1
    iget-object v1, p1, Lcom/cyjh/share/bean/response/AppRelatedInfo;->FlySetting:Ljava/util/List;

    if-eqz v1, :cond_2

    .line 532
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;

    move-result-object v1

    iget-object v1, v1, Lcom/cyjh/elfin/entity/ParamsWrap;->mFlySettingInfos:Ljava/util/List;

    iget-object v4, p1, Lcom/cyjh/share/bean/response/AppRelatedInfo;->FlySetting:Ljava/util/List;

    invoke-interface {v1, v4}, Ljava/util/List;->addAll(Ljava/util/Collection;)Z

    .line 534
    :cond_2
    iget-object v1, p1, Lcom/cyjh/share/bean/response/AppRelatedInfo;->RecommendSetting:Ljava/util/List;

    if-eqz v1, :cond_3

    .line 535
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;

    move-result-object v1

    iget-object v1, v1, Lcom/cyjh/elfin/entity/ParamsWrap;->mRecommendSettingInfos:Ljava/util/List;

    iget-object p1, p1, Lcom/cyjh/share/bean/response/AppRelatedInfo;->RecommendSetting:Ljava/util/List;

    invoke-interface {v1, p1}, Ljava/util/List;->addAll(Ljava/util/Collection;)Z

    .line 537
    :cond_3
    iget-object p1, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->AdList:Ljava/util/List;

    if-eqz p1, :cond_4

    .line 538
    invoke-static {}, Lcom/cyjh/elfin/entity/ParamsWrap;->getParamsWrap()Lcom/cyjh/elfin/entity/ParamsWrap;

    move-result-object p1

    iget-object p1, p1, Lcom/cyjh/elfin/entity/ParamsWrap;->mAdInfos:Ljava/util/List;

    iget-object v1, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->AdList:Ljava/util/List;

    invoke-interface {p1, v1}, Ljava/util/List;->addAll(Ljava/util/Collection;)Z

    .line 541
    :cond_4
    iput-boolean v3, p0, Lcom/cyjh/elfin/activity/news/SplashActivity;->isLoadCompleteStartup:Z

    .line 542
    iget p1, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->ServicePackStatus:I

    if-ne p1, v3, :cond_5

    .line 543
    invoke-static {p0}, Lcom/cyjh/elfin/util/IntentUtils;->toCallElfinFreeActivity(Landroid/content/Context;)V

    invoke-virtual {p0}, Lcom/cyjh/elfin/activity/news/SplashActivity;->finish()V

    goto :goto_0

    .line 544
    :cond_5
    iget p1, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->ServicePackStatus:I

    const/4 v1, 0x2

    if-ne p1, v1, :cond_6

    .line 545
    invoke-static {}, Lcom/cyjh/elfin/dialog/DialogManager;->getInstance()Lcom/cyjh/elfin/dialog/DialogManager;

    move-result-object p1

    iget v1, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->ServicePackStatus:I

    iget-object v0, v0, Lcom/cyjh/share/bean/response/AuthorRelatedInfo;->ServicePackPrompt:Ljava/lang/String;

    new-instance v3, Lcom/cyjh/elfin/activity/news/SplashActivity$MyKnownButtonListener;

    invoke-direct {v3, p0, v2}, Lcom/cyjh/elfin/activity/news/SplashActivity$MyKnownButtonListener;-><init>(Lcom/cyjh/elfin/activity/news/SplashActivity;Lcom/cyjh/elfin/activity/news/SplashActivity$1;)V

    invoke-virtual {p1, v1, v0, p0, v3}, Lcom/cyjh/elfin/dialog/DialogManager;->displayDialogMessage(ILjava/lang/String;Landroid/content/Context;Lcom/cyjh/elfin/listener/BaseTextViewKnownListener;)V

    :cond_6
    :goto_0
    return-void
.end method
为什么不直接进来 在initView的时候就跳转呢?
不行,因为后面有网络请求认证,不走网络请求是可以直接进去,可是脚本启动不了
protected void onResume() {
        super.onResume();
        MobclickAgent.onResume(this);
        if (this.isClickerFirst) {
            toCall();
        }
    }
获取焦点的时候 调用了 toCall 这个也是跳广告的 直接删除掉
至此 闪屏广告去掉完毕.

脚本启动页的广告去掉有点复杂,因为源码设置了多种触发模式,时间关系有空再写。当然,按照上面的方法,只要看得懂 里面的逻辑 自己改也完全没什么问题了。

==============================================================================================================
下方是我修改的smali文件
当然,有小部分小白看不懂上面的东西,我下面附上了修改过的 smali 代码源文件,只要复制替换掉你的就可以了
复制 SplashActivity.smali 文件到目录:..\test\smali\com\cyjh\elfin\activity\news 下面覆盖掉你的。  【这个文件去掉的是,闪屏广告】

THE END
喜欢就支持以下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称