美文网首页
逆向破解Android版贪吃蛇

逆向破解Android版贪吃蛇

作者: andev009 | 来源:发表于2018-05-11 22:51 被阅读303次

    逆向就像破案,不断找线索,等最后破案了才发现原来如此简单。
    先说下破解目标,在无尽模式下让蛇不死。
    首先神器apktool反编译,顺利得到混淆后的代码和资源。


    1.png

    可以看到进行dex分包了。
    装APK跑一下,蛇碰撞死后,出现游戏结束对话框。在这步我们取得无尽模式的Activity是com.wepie.snake.app.activity.GameActivity,layout是activity_main.xml。布局如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">
        <com.wepie.snake.module.game.GameViewContainer android:layout_width="match_parent" android:layout_height="match_parent">
            <com.wepie.snake.lib.plugin.z android:id="@+id/main_snake_surface_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
            <com.wepie.snake.module.game.SpeedUpView android:id="@+id/main_speedup_bt" android:paddingLeft="80dp" android:paddingTop="80dp" android:paddingRight="40dp" android:paddingBottom="40dp" android:layout_width="200dp" android:layout_height="200dp" android:src="@drawable/shape_ffffff_corners_bl4_br4" android:scaleType="centerInside" android:layout_alignParentRight="true" android:layout_alignParentBottom="true"/>
        </com.wepie.snake.module.game.GameViewContainer>
        <com.wepie.snake.module.game.g android:id="@+id/main_snake_game_info_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
        <com.wepie.snake.module.game.RouletteView android:id="@+id/main_roulette_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentBottom="true"/>
    </RelativeLayout>
    

    有兴趣的可以研究下这些View,这里只谈破解分析结果。按正常逻辑,如果我们写代码,就是蛇死的时候,在布局里弹框。破解就是要找到蛇死的时机,然后hack掉。
    对布局文件分析后,得知com.wepie.snake.lib.plugin.z,这个类才是游戏真正的核心,很有迷惑性。
    z的定义如下:

    public class z extends GLSurfaceView {
    class c implements Renderer {
    public void onDrawFrame(GL10 gl10) {
                GLES20.glClear(16640);
                if (this.d.q && this.d.t.b.a) {
                    this.d.t.d();
                }
                if (this.a) {
                    this.d.q = false;
                    this.a = false;
                    b();
                }
                this.d.m.a();
                this.d.l.a();
                this.d.t.a(this.d.k);
                z zVar = this.d;
                zVar.f += this.d.t.c.c * ((float) this.d.t.b.d);
                zVar = this.d;
                zVar.g += this.d.t.c.d * ((float) this.d.t.b.d);
                com.wepie.snake.module.game.i.b.a(this.d.f * e.k, this.d.g * e.k, 20.0f, this.d.f * e.k, this.d.g * e.k, 0.0f, 0.0f, 1.0f, 0.0f);
                this.d.e.c();
                this.d.j.b();
                this.d.k.c();
                this.d.l.c();
                this.d.w.a(this.d.v);
                this.d.u.b(this.d.t);
                this.d.u.a(this.d.m, this.d.k);
                this.d.t.a();
                this.d.j.a(this.d.m);
                this.d.k.a();
                this.d.l.a(this.d.m);
                this.d.t.d.a(this.d.m);
                this.d.d.a(this.d.t);
                this.d.u.a(this.d.d);
                this.b++;
                if (this.b >= 60) {
                    this.b = 0;
                    this.d.p.a(this.d.v);
                }
            }
    }
    }
    

    代码被混淆过,考验耐心,细心和想象力的时候到了。
    熟悉GLSurfaceView的都知道,游戏循环逻辑在Renderer的onDrawFrame,猜想就是在这里面每次调用时检测蛇死了没。
    这里先说下一个误导,之前说蛇死了,弹框游戏结束,先找到弹框控件

    public class g extends FrameLayout {
        public GameRankView a;
        private Context b;
        private TextView c;
        private TextView d;
        private TextView e;
        private c f;
        private GameOverView g;
        private int h;
        private int i;
        private int j;
         public void a(boolean z, OffGameScoreInfo offGameScoreInfo) {
            b.a();
            this.g.setVisibility(0);//View.visible
            this.g.a(z, this.i, this.j, this.h);
            this.g.a(offGameScoreInfo);
            this.f.a();
        }
    
    }
    

    控件有a这个方法,里面正好有setVisibility(0),蛇死,调用这个a方法,看起来逻辑正确。于是去z (GLSurfaceView)里找哪里调用了g的a方法。找到下面几个地方

    this.d.u.a(this.d.m, this.d.k);//AiManager 
    this.d.j.a(this.d.m);//food
    this.d.l.a(this.d.m);//KillFactory
    this.d.t.d.a(this.d.m)//SnakeInfo
    

    上面的m就是g类。研究后发现四个方法没有想要的逻辑,四个方法作用后面注释了。
    仔细研究onDrawFrame里的方法,每次循环都在做什么?发现了这个方法

    this.d.d.a(this.d.t);
    

    第一个d是z,第二个d是com.wepie.snake.module.game.h.d,

    public class d {
     public void a(m mVar) {
            if (mVar.b.a) {
                this.k = mVar;
                i a = mVar.d.a();
                this.i = a.a;
                this.j = a.b;
                if (a()) {//重点
                    this.l = mVar.d.d + this.g;
                    int a2 = g.a(this.i, this.j);
                    this.t = 10000.0f;
                    this.u = 10000.0f;
                    e(a2);
                    a(a2);
                    b(a2);
                    if (a2 % 16 != 0) {
                        c(a2);
                    }
                    if ((a2 + 1) % 16 != 0) {
                        d(a2);
                    }
                    b();
                }
            }
        }
    
      private boolean a() {
            float f = this.k.d.d * 0.6f;
            if (this.i >= a + f && this.i <= c - f && this.j <= b - f && this.j >= f + d) {
                return true;
            }
            a(this.k, null);
            return false;
        }
    
    }
    

    这里做碰撞检测,如果a()为true,执行下面的代码,false呢?game over!
    好,找到这个位置,然后怎么修改?找到反编译后的smali代码,

    .line 61
    invoke-direct {p0}, Lcom/wepie/snake/module/game/h/d;->a()Z
    move-result v0
    

    我们想要的效果是是if(true),这样碰撞检测始终返回true,就不会死了,所以把smali代码这段判断直接删除。

    最后,回编译打包,跑跑看。


    2.png

    蛇撞墙后果然不会死了,但是蛇撞蛇还是会死,推测蛇撞蛇用了另外的碰撞检测。
    时间关系就不找了。

    当然最后只是删了两行代码而已,看起来很简单,过程其实没有那么容易,比如最后回编译打包,也许你会碰到问题,打不了包,仔细分析去解决吧。这里只是给个思路,仅供学习参考,勿做他用。
    这次分析纯粹是分析代码找重点,还有动态调试破解的方法,以后再来。

    相关文章

      网友评论

          本文标题:逆向破解Android版贪吃蛇

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