专栏首页Android 开发学习反编译一款小说阅读软件 android逆向(三)

反编译一款小说阅读软件 android逆向(三)

声明下,本文的内容仅用于技术讨论,不涉及到商业用途,如果用于商业用途请自行负责。

1 背景

最近无聊时,就去追小说玩,想使用免费的小说阅读软件,下载的时候阅读发现有Banner广告,这里多一句嘴,怎么实现bannner广告呢?(歪楼了,不过我想记录下,因为最近就用到过这个小的技巧,下一部分会提到)。继续说banner广告,特别烦,我司的app去年前的也是靠这个赚钱,去年年底考虑到用户体验就撤了,原因和我使用这个小说阅读软件类似,就是特别烦!!!

2 banner广告实现

貌似自己给自己挖坑。原理很简单,就是在 DecorView上添加view,因为该view是FrameLayout,故添加时,就在整个view的上层。这里再次歪下楼,android的几大布局中具有层次结构的FrameLayout, 还有个隐藏比较深的RelativeLayout,做动画的时候,奇葩的产品会有不同层次的设计。代码呢,请参考:http://blog.csdn.net/goodding/article/details/8562985。 这里给最主要的一句,中间省略细节处理。 addFloatView((FrameLayout) getWindow().getDecorView());

private void addFloatView(FrameLayout parent) {
        if (mFloatView == null || (mFloatView.getParent() == null)) {
            if (!mIsAdded) {
                initFloatView();
                FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
                parent.addView(mFloatView,lp);
                mIsAdded = true;
            }
        }

    }

很简单,就是拿到DecorView,然后在其上添加相应布局,于是这里就可以实现浮层引导页面,还有就是应用内悬浮窗口了,叨叨完。

3 正式进入反编译

再次重复使用我上篇提到的工具,http://www.jianshu.com/p/d57c542b5949 这里我也介绍下,还有个反编译工具---jadx,这个阅读反编译出来的代码后,显示得到源代码,比较清晰,不像android killer 反编译后,查看源代码的jd 工具,代码条理较乱。怎么导入,本文省略,不了解请参考上篇。我们来看下,整个工程使用android killer 查看运行图如下:

Paste_Image.png

看软件文件名就能猜到是哪家公司了,这里补一句,个人开发的小伙伴找不到图,就可以直接反编译下软件,在res资源下就是图片资源了,恩,注意这里仅仅是技术讨论。

1 这个软件用了哪些三方技术呢?

a 一看 alipay 你猜。 b baidu的 c google的是gson我这里不好截图,包太多了。 d multipletheme 这个就是切换主题的三方包,实现换肤功能。(感兴趣的小伙伴,可以详细阅读下这里) e 还有就是侧滑的三方了,slidingmenu f sina和qq的一看就是三方登录和分享了

Paste_Image.png

2. 自己的技术呢?

Paste_Image.png

恩,看文件,就知道ecom下面是广告,users下面是用户统计和crash分析等。reader就是该软件的工程主体代码部分。由于采用了混淆,故有些文件名称无法猜出。整体上看,软件的工程不是特别大,按照Android的一贯分层模式来划分包的。

4 去广告

终于来到我的目的地,去广告。这里吐血大放送,一个技巧。如何快速定位一个apk的界面。作为新人,我刚进公司要废很大劲找到对应的代码,最长达1个小时(我司工程项目较大,已经分包)。这里我提供两个简单的方法。

1 命令行形式

使用adb 命令行,需要简单配置下。 将adb调试下apk,进入想要查找的应用程序界面,然后cmd中输入adb shell。最后输入,以下的几个都可以: a. 查看当前resume的是哪个activity: dumpsys activity | grep mResumedActivity b.resume的Activity dumpsys activity | grep mFocusedActivity c. 焦点view adb shell dumpsys window windows | grep -E 'mCurrentFocus'

Paste_Image.png

2 快速查找法

找到对应的关键词,找能代表该界面的关键词,这个点是逆向去广告,去支付的很常用方法。本文软件界面,除去广告提示词外,还有就是点击小说的中间位置时的工具栏里面的关键字。一个直接在android studio中查找(eclipse类似),另外一个是上篇提到的反编译工具中查找。

Paste_Image.png

3正式进入去广告的activity---ActNovel

恩,这里顺便说一下,貌似开发人员命名很不规范,至少让我们这种不知道源码的阅读起来不方便,很严肃的事hao吗?

点击java源码的那个图标,进入jd 查看源码。

Paste_Image.png

这里叨叨下,使用jadx的查看源码,大家感受下。

Paste_Image.png

查找关键函数

看jadx上的截图,程序猿大哥这次写的很明白呀。恩,有人一定会问,那万一遇到不能猜出来的怎么办呢?很简单,使用本文提到的快速定位法,比如,本文想去掉这个页面广告,点击×,看弹出的窗口提示文字,快速反定位到函数。当然本文去广告的点很多,jadx上的是addAdsView()从整体上。还有其他地方可以去广告的点。看下源代码:

    private void addAdsView() {
        if (com.esbook.reader.a.a.E != 0 && !this.isClosed) {
            this.isAdShowing = true;
            this.adContainer.removeAllViews();
            if (this.easouAdUtils == null) {
                this.easouAdUtils = new bo(getApplicationContext(), this, this.adContainer, com.esbook.reader.a.a.L, com.esbook.reader.a.a.K, MSG_LOAD_NEXT_CHAPTER);
                this.easouAdUtils.a(new ca(this));
                this.easouAdUtils.a(new cb(this));
            } else {
                this.easouAdUtils.a(this.adContainer, this.easouAdUtils.b());
            }
            if (this.ad_coverview == null) {
                this.ad_coverview = new View(getApplicationContext());
                this.ad_coverview.setBackgroundColor(getResources().getColor(R.color.transparent_ad));
            }
            ViewGroup viewGroup = (ViewGroup) this.ad_coverview.getParent();
            if (viewGroup != null) {
                viewGroup.removeAllViews();
            }
            this.adContainer.addView(this.ad_coverview, new LayoutParams(-1, -1));
            if (com.esbook.reader.a.a.j == MSG_LOAD_PRE_CHAPTER || com.esbook.reader.a.a.j == MSG_CHANGE_SOURCE || com.esbook.reader.a.a.j == ERROR) {
                showAdCover(true);
            } else {
                showAdCover(false);
            }
        }
    }

想去广告点很多呀, (1)从一开始就return,不添加。 (2)还有就是:

if (com.esbook.reader.a.a.j == MSG_LOAD_PRE_CHAPTER || com.esbook.reader.a.a.j == MSG_CHANGE_SOURCE || com.esbook.reader.a.a.j == ERROR) {
                showAdCover(true);
            } else {
                showAdCover(false);
            }

都showAdCover(false) (3) showAdCover函数里面不显示广告也可以。 ok,来找到smali源代码。

Paste_Image.png

进入对应函数:

.method private addAdsView()V
    .locals 9

    const/4 v8, -0x1

    const/4 v7, 0x1

    sget v0, Lcom/esbook/reader/a/a;->E:I

    if-eqz v0, :cond_0

    iget-boolean v0, p0, Lcom/esbook/reader/activity/ActNovel;->isClosed:Z

    if-eqz v0, :cond_1

    :cond_0
    :goto_0
    return-void

    :cond_1
    iput-boolean v7, p0, Lcom/esbook/reader/activity/ActNovel;->isAdShowing:Z

    iget-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->adContainer:Landroid/widget/RelativeLayout;

    invoke-virtual {v0}, Landroid/widget/RelativeLayout;->removeAllViews()V

    iget-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->easouAdUtils:Lcom/esbook/reader/util/bo;

    if-nez v0, :cond_5

    new-instance v0, Lcom/esbook/reader/util/bo;

    invoke-virtual {p0}, Lcom/esbook/reader/activity/ActNovel;->getApplicationContext()Landroid/content/Context;

    move-result-object v1

    iget-object v3, p0, Lcom/esbook/reader/activity/ActNovel;->adContainer:Landroid/widget/RelativeLayout;

    sget v4, Lcom/esbook/reader/a/a;->L:I

    sget v5, Lcom/esbook/reader/a/a;->K:I

    const/4 v6, 0x2

    move-object v2, p0

    invoke-direct/range {v0 .. v6}, Lcom/esbook/reader/util/bo;-><init>(Landroid/content/Context;Landroid/app/Activity;Landroid/widget/RelativeLayout;III)V

    iput-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->easouAdUtils:Lcom/esbook/reader/util/bo;

    iget-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->easouAdUtils:Lcom/esbook/reader/util/bo;

    new-instance v1, Lcom/esbook/reader/activity/ca;

    invoke-direct {v1, p0}, Lcom/esbook/reader/activity/ca;-><init>(Lcom/esbook/reader/activity/ActNovel;)V

    invoke-virtual {v0, v1}, Lcom/esbook/reader/util/bo;->a(Lcom/esbook/reader/util/bq;)V

    iget-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->easouAdUtils:Lcom/esbook/reader/util/bo;

    new-instance v1, Lcom/esbook/reader/activity/cb;

    invoke-direct {v1, p0}, Lcom/esbook/reader/activity/cb;-><init>(Lcom/esbook/reader/activity/ActNovel;)V

    invoke-virtual {v0, v1}, Lcom/esbook/reader/util/bo;->a(Lcom/esbook/reader/util/bs;)V

    :goto_1
    iget-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->ad_coverview:Landroid/view/View;

    if-nez v0, :cond_2

    new-instance v0, Landroid/view/View;

    invoke-virtual {p0}, Lcom/esbook/reader/activity/ActNovel;->getApplicationContext()Landroid/content/Context;

    move-result-object v1

    invoke-direct {v0, v1}, Landroid/view/View;-><init>(Landroid/content/Context;)V

    iput-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->ad_coverview:Landroid/view/View;

    iget-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->ad_coverview:Landroid/view/View;

    invoke-virtual {p0}, Lcom/esbook/reader/activity/ActNovel;->getResources()Landroid/content/res/Resources;

    move-result-object v1

    const v2, 0x7f090013

    invoke-virtual {v1, v2}, Landroid/content/res/Resources;->getColor(I)I

    move-result v1

    invoke-virtual {v0, v1}, Landroid/view/View;->setBackgroundColor(I)V

    :cond_2
    iget-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->ad_coverview:Landroid/view/View;

    invoke-virtual {v0}, Landroid/view/View;->getParent()Landroid/view/ViewParent;

    move-result-object v0

    check-cast v0, Landroid/view/ViewGroup;

    if-eqz v0, :cond_3

    invoke-virtual {v0}, Landroid/view/ViewGroup;->removeAllViews()V

    :cond_3
    iget-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->adContainer:Landroid/widget/RelativeLayout;

    iget-object v1, p0, Lcom/esbook/reader/activity/ActNovel;->ad_coverview:Landroid/view/View;

    new-instance v2, Landroid/widget/RelativeLayout$LayoutParams;

    invoke-direct {v2, v8, v8}, Landroid/widget/RelativeLayout$LayoutParams;-><init>(II)V

    invoke-virtual {v0, v1, v2}, Landroid/widget/RelativeLayout;->addView(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V

    sget v0, Lcom/esbook/reader/a/a;->j:I

    if-eq v0, v7, :cond_4

    sget v0, Lcom/esbook/reader/a/a;->j:I

    const/4 v1, 0x4

    if-eq v0, v1, :cond_4

    sget v0, Lcom/esbook/reader/a/a;->j:I

    const/4 v1, 0x7

    if-ne v0, v1, :cond_6

    :cond_4   
    invoke-direct {p0, v7}, Lcom/esbook/reader/activity/ActNovel;->showAdCover(Z)V

    goto :goto_0

    :cond_5
    iget-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->easouAdUtils:Lcom/esbook/reader/util/bo;

    iget-object v1, p0, Lcom/esbook/reader/activity/ActNovel;->adContainer:Landroid/widget/RelativeLayout;

    iget-object v2, p0, Lcom/esbook/reader/activity/ActNovel;->easouAdUtils:Lcom/esbook/reader/util/bo;

    invoke-virtual {v2}, Lcom/esbook/reader/util/bo;->b()I

    move-result v2

    invoke-virtual {v0, v1, v2}, Lcom/esbook/reader/util/bo;->a(Landroid/widget/RelativeLayout;I)V

    goto :goto_1

    :cond_6
    const/4 v0, 0x0

    invoke-direct {p0, v0}, Lcom/esbook/reader/activity/ActNovel;->showAdCover(Z)V

    goto/16 :goto_0
.end method

关键点如下:

sget v0, Lcom/esbook/reader/a/a;->E:I

    if-eqz v0, :cond_0

    iget-boolean v0, p0, Lcom/esbook/reader/activity/ActNovel;->isClosed:Z

    if-eqz v0, :cond_1

    :cond_0
 if-eq v0, v1, :cond_4

    sget v0, Lcom/esbook/reader/a/a;->j:I

    const/4 v1, 0x7

    if-ne v0, v1, :cond_6

    :cond_4   
    invoke-direct {p0, v7}, Lcom/esbook/reader/activity/ActNovel;->showAdCover(Z)V

    goto :goto_0

    :cond_5
    iget-object v0, p0, Lcom/esbook/reader/activity/ActNovel;->easouAdUtils:Lcom/esbook/reader/util/bo;

    iget-object v1, p0, Lcom/esbook/reader/activity/ActNovel;->adContainer:Landroid/widget/RelativeLayout;

    iget-object v2, p0, Lcom/esbook/reader/activity/ActNovel;->easouAdUtils:Lcom/esbook/reader/util/bo;

    invoke-virtual {v2}, Lcom/esbook/reader/util/bo;->b()I

    move-result v2

    invoke-virtual {v0, v1, v2}, Lcom/esbook/reader/util/bo;->a(Landroid/widget/RelativeLayout;I)V

    goto :goto_1

    :cond_6
    const/4 v0, 0x0

    invoke-direct {p0, v0}, Lcom/esbook/reader/activity/ActNovel;->showAdCover(Z)V

    goto/16 :goto_0

对着源代码,还是很容易阅读。 怎么去,简单的nop掉呗,恩,这里挖了个坑等大家。整个过程结束了,码字挺辛苦的,各位看官有收获点个赞呗!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 添加Intent.FLAG_ACTIVITY_CLEAR_TOP 都做了些什么背景整体流程

    用户1127566
  • IntelliJ IDEA spring mvc +mybatis 环境搭建服务器(下)直接使用类来生成Mapper:

    用户1127566
  • ConstraintLayout 使用简介一 背景二 demo三 进一步升级打怪四 更多

    用户1127566
  • 配置GoldenGate同步DDL语句(

    在配置GoldenGate同步DDL语句(2)中我们针对多种DDL语句在GoldenGate环境中的同步进行了测试,但在默认情况下replicat在复制DDL语...

    py3study
  • 如何自行查找出SAP CRM产品主数据页面的assignment block基于的settype类型

    We know an assignment block in overview page is built based on settype or relati...

    Jerry Wang
  • how to know which settype an assignment block is built based on

    We know an assignment block in overview page is built based on settype or relati...

    Jerry Wang
  • iOS开发提升效率工具之InjectionIII

    随着项目越来越大,每次build的时间也是在变长。当只是修改一个UI上的小问题时,比如字体、颜色、frame就要重新build再次等待一段时间,这种开发效率是大...

    用户6094182
  • 深入解读Quartz的原理

    Quartz的原理不是很复杂,只要搞明白几个概念,然后知道如何去启动和关闭一个调度程序即可。

    技术从心
  • 使用QUuid生成唯一码

    Qt君
  • 数据结构 | 每日一练(34)

    ——老子

    闫小林

扫码关注云+社区

领取腾讯云代金券