美文网首页做一款APP收集的知识程序员android成神之路
反编译一款小说阅读软件 android逆向(三)

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

作者: nothingwxq | 来源:发表于2016-05-15 16:06 被阅读556次

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

    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掉呗,恩,这里挖了个坑等大家。整个过程结束了,码字挺辛苦的,各位看官有收获点个赞呗!

    相关文章

      网友评论

        本文标题:反编译一款小说阅读软件 android逆向(三)

        本文链接:https://www.haomeiwen.com/subject/yspvrttx.html