android版微信打飞机无敌补丁分析及其制作方法

本文出自:http://www.creturn.com/android版微信打飞机无敌补丁分析及其制作方法/

原创作品,转载请注明来源及其作者信息,负责后果自负!

最近微信5.0版本发布后增加了游戏中心,并且自带一款打飞机游戏,ios版本刚发布1天就被crack掉,并且除了一个无敌补丁,奈何手里没ios设备也没法测试.自己玩了下,感觉游戏真没多少技术含量,不过微信的优势很明显,集成了好友数据,所以结果就是最近天天听到那些家伙喊着”打飞机” ~。~

不过对于游戏一点都不感冒的我看到好友那么高的分数再对比下自己,额真有点那个啥。所以对于技术控来说去拼命玩那个玩意就有点浪费生命了,所以本着hack for fun 的思想就试试看看能crack掉不.

首先分析下游戏

游戏对象:

飞机,子弹,炸弹,敌机
实现方法就有多种成为无敌的方法:

1.让飞机无敌,也就是不死

2.让子弹威力变大,并且不消失,这样一个子弹就可以打多个敌机

3.给自己添加”大量”炸弹,这样也就无敌了

4.让敌机碰到自己无效,这样就相当于隐形模式了,同样无敌了

5.给自己多加几条名,这样既可以达到无敌的方式又可以死掉(方便提交分数)不然死都死不掉。

代码分析:

刚开始看到这个游戏以为用的是html5+js写的,不过解包后看到里面的东西就傻眼了,不过依然有方法.

1.下载 5.0 android的版本的微信,修改后缀名为zip然后解压,如图:


2.在解压的目录中找到assset目录然后打开里面的preload目录,如图:


可以看到这个目录放了一些jar包,猜测微信采用插件机制来实现功能模块的扩展,其中以”com.tencent.mm.plugin.shoot”开头的jar包,从名字中可以猜测到它就是我们的目标

这里要说后面需要用到的两款软件:

1.apktool :用来把apk或者jar包反编译成android的java虚拟机的机器码,方便修改代码逻辑

下载地址: https://code.google.com/p/android-apktool/

2.dex2jar :用来把dex文件反编译jar

下载地址: http://pan.baidu.com/share/link?shareid=2401317361&uk=2317334154

3.auto-sign: 用来对apk进行签名的

下载地址: http://pan.baidu.com/share/link?shareid=2387101337&uk=2317334154

4.jd-gui: 用来查看编译过的class java代码

下载地址: http://java.decompiler.free.fr/?q=jdgui
工具齐全后就开始对代码动刀

用dex2jar把com.tencent.mm.plugin.shoot开头的那个文件处理下,会得到以dex2jar.jar结尾的文件用jd-gui打开这个文件,我们就能看到编译出来的文件,不过腾讯的同学对代码进行了混淆处理所以里面有很多a,b,c,d,e这样的文件,不过很不幸的是腾讯的家伙估计太粗心了,把游戏对象和功能代码没做混淆,混淆的反而是gdx游戏框架的代码,如图:

在actor这个包里面明显能看出来各个类的作用,不知道腾讯的同学是妹子想多了还是不给发奖金了,核心部分不做混淆处理…

上面分析的时候说过无敌模式的几种方式,我这里采用最后一种给自己多加几条命这样也能死掉~~  不然分数都提交不了就没有意义了,看看Player类中的构造函数(或者叫做初始化函数也行):

1 public Player()
2  {
3  setLiftCount(1);
4  setType(GameSprite.Type.HERO);
5  setState(GameSprite.State.FLIGTHING);
6  setSpeedVelocity(new ag(0.0F, 0.0F));
7  getBounds().height = HEIGHT;
8  getBounds().width = WIDTH;
9  this.mShootDelay = (4.0F * h.Ml().MC().Mi().cEP);
10  this.mShootDoubleTime = h.Ml().MC().Mi().cEQ;
11  }

明显能够看出来setLiftCount() 这个方法是用来初始化生命值的,如果把这里改大点,不就实现了我们的多条命了。

用apktool工具对 com.tencent.mm.plugin.shoot开头的这个包进行反编译,命令如下:

1 apktool d 文件名

后面的d参数是反编译,如果换成b就是再次编译回去。

解包后文件如下图所示:

其中smali目录就是反编译后的代码,里面的文件以 smali结尾,文件位置和包位置保持一致如下图:

用任意一款文本编辑器打开Player.smali文件,我们可以看到里面的代码,如下图:

仔细看有点像汇编,不过它却不是网上可以找到smali语法帮助,我们在这个文件中找到初始化方法,constructor <init>()看着是不是很眼熟:

1 .method public constructor <init>()V
2  .locals 2
3  
4 .prologue
5  const/4 v1, 0x0
6  
7 .line 46
8  invoke-direct {p0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;-><init>()V
9  
10 .line 32
11  sget-object v0, Lcom/tencent/mm/plugin/shoot/actor/Player$BulletType;->NORMAL:Lcom/tencent/mm/plugin/shoot/actor/Player$BulletType;
12  
13 iput-object v0, p0, Lcom/tencent/mm/plugin/shoot/actor/Player;->mBulleType:Lcom/tencent/mm/plugin/shoot/actor/Player$BulletType;
14  
15 .line 47
16  const/4 v0, 0x1
17  
18 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/Player;->setLiftCount(I)V
19  
20 .line 48
21  sget-object v0, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;->HERO:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
22  
23 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/Player;->setType(Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;)V
24  
25 .line 49
26  sget-object v0, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;->FLIGTHING:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;
27  
28 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/Player;->setState(Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;)V
29  
30 .line 50
31  new-instance v0, Lcom/badlogic/gdx/math/ag;
32  
33 invoke-direct {v0, v1, v1}, Lcom/badlogic/gdx/math/ag;-><init>(FF)V
34  
35 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/Player;->setSpeedVelocity(Lcom/badlogic/gdx/math/ag;)V
36  
37 .line 52
38  invoke-virtual {p0}, Lcom/tencent/mm/plugin/shoot/actor/Player;->getBounds()Lcom/badlogic/gdx/math/af;
39  
40 move-result-object v0
41  
42 sget v1, Lcom/tencent/mm/plugin/shoot/actor/Player;->HEIGHT:F
43  
44 iput v1, v0, Lcom/badlogic/gdx/math/af;->height:F
45  
46 .line 53
47  invoke-virtual {p0}, Lcom/tencent/mm/plugin/shoot/actor/Player;->getBounds()Lcom/badlogic/gdx/math/af;
48  
49 move-result-object v0
50  
51 sget v1, Lcom/tencent/mm/plugin/shoot/actor/Player;->WIDTH:F
52  
53 iput v1, v0, Lcom/badlogic/gdx/math/af;->width:F
54  
55 .line 55
56  invoke-static {}, Lcom/tencent/mm/plugin/shoot/a/h;->Ml()Lcom/tencent/mm/plugin/shoot/a/h;
57  
58 move-result-object v0
59  
60 invoke-virtual {v0}, Lcom/tencent/mm/plugin/shoot/a/h;->MC()Lcom/tencent/mm/plugin/shoot/a/d;
61  
62 move-result-object v0
63  
64 invoke-virtual {v0}, Lcom/tencent/mm/plugin/shoot/a/d;->Mi()Lcom/tencent/mm/plugin/shoot/a/b;
65  
66 move-result-object v0
67  
68 iget v0, v0, Lcom/tencent/mm/plugin/shoot/a/b;->cEP:F
69  
70 const/high16 v1, 0x4080
71  
72 mul-float/2addr v0, v1
73  
74 iput v0, p0, Lcom/tencent/mm/plugin/shoot/actor/Player;->mShootDelay:F
75  
76 .line 59
77  invoke-static {}, Lcom/tencent/mm/plugin/shoot/a/h;->Ml()Lcom/tencent/mm/plugin/shoot/a/h;
78  
79 move-result-object v0
80  
81 invoke-virtual {v0}, Lcom/tencent/mm/plugin/shoot/a/h;->MC()Lcom/tencent/mm/plugin/shoot/a/d;
82  
83 move-result-object v0
84  
85 invoke-virtual {v0}, Lcom/tencent/mm/plugin/shoot/a/d;->Mi()Lcom/tencent/mm/plugin/shoot/a/b;
86  
87 move-result-object v0
88  
89 iget v0, v0, Lcom/tencent/mm/plugin/shoot/a/b;->cEQ:I
90  
91 int-to-long v0, v0
92  
93 iput-wide v0, p0, Lcom/tencent/mm/plugin/shoot/actor/Player;->mShootDoubleTime:J
94  
95 .line 60
96  return-void
97 .end method

根据smali语法修改如下代码:

1 .line 47
2 const/4 v0, 0x1
3  
4 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/Player;->setLiftCount(I)V

改为:

1 .line 47
2 const/4 v0, 0x7  # 注意这里修改成7
3  
4 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/Player;->setLiftCount(I)V
修改的地方把默认的1改成了7,也就是说有7条命了。不过别高兴太早,如果这样改了,是没有效果的。因为程序中判断飞机不在战斗状态时候
是不显示的,所以还需要修改一处代码,先看看原来的java代码GameSprite.smali:
1 public void hit(boolean paramBoolean)
2  {
3 this.liftCount = (-1 this.liftCount);
4 if (this.liftCount <= 0)
5 {
6 if (paramBoolean)
7 {
8 setState(GameSprite.State.DEAD);
9 setSpeedVelocity(this.speedZero);
10 return;
11 }
12 if ((getType() == GameSprite.Type.ENEMY_AIRCAFT) || (getType() == GameSprite.Type.ENEMY_LARGE_AIRCAFT) || (getType() == GameSprite.Type.ENEMY_MIDDLE) || (getType() == GameSprite.Type.PROPS_BOMB) || (getType() == GameSprite.Type.PROPS_DOUBLE))
13 h.Ml().MD().c(getType());
14 while (true)
15 {
16 setState(GameSprite.State.EXPLODING);
17 break;
18 if (getType() == GameSprite.Type.HERO)
19 h.Ml().MD().MT();
20 }
21 }
22 setState(GameSprite.State.HITING);
23  }
这段代码是所有游戏对象基类里面的碰撞处理代码,当生命值小于1 就移除该对象,如果生命值大于1则更改属性为HITING ,不过飞机如果遇到这
个状态肯定不行的,撞机了还能继续飞?所以这里需要判断下如果是飞机,那么就要修改它的状态为:FLIGTHING
所以如果按照java代码修改的代码会和下面的代码一样:
1 public void hit(boolean paramBoolean)
2 {
3 this.liftCount = (-1 this.liftCount);
4 if (this.liftCount <= 0)
5 {
6 if (paramBoolean)
7 {
8 setState(GameSprite.State.DEAD);
9 setSpeedVelocity(this.speedZero);
10 return;
11 }
12 if ((getType() == GameSprite.Type.ENEMY_AIRCAFT) || (getType() == GameSprite.Type.ENEMY_LARGE_AIRCAFT) || (getType() == GameSprite.Type.ENEMY_MIDDLE) || (getType() == GameSprite.Type.PROPS_BOMB) || (getType() == GameSprite.Type.PROPS_DOUBLE))
13 h.Ml().MD().c(getType());
14 while (true)
15 {
16 setState(GameSprite.State.EXPLODING);
17 break;
18 if (getType() == GameSprite.Type.HERO)
19 h.Ml().MD().MT();
20 }
21 }
22  
23 //在这里添加我们的代码
24  
25 if(getType==GameSprite.Type.HERO)
26  
27 {
28  
29 setState(GameSprite.State.FLIGTHING);
30  
31 else {
32 setState(GameSprite.State.HITING);
33  
34 }
35 }
java 代码我们知道怎么修改了,那么smali里面的代码同样根据这个逻辑处理下即可,当然这块稍微有点难度,得看下语法手册再来修改,
修改的代码如下所示:
1 .method public hit(Z)V
2  .locals 2
3  .parameter
4  
5 .prologue
6  .line 45
7  iget v0, p0, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->liftCount:I
8  
9 add-int/lit8 v0, v0, -0x1
10  
11 iput v0, p0, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->liftCount:I
12  
13 .line 46
14  iget v0, p0, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->liftCount:I
15  
16 if-gtz v0, :cond_4
17  
18 .line 47
19  if-eqz p1, :cond_0
20  
21 .line 48
22  sget-object v0, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;->DEAD:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;
23  
24 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->setState(Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;)V
25  
26 .line 57
27  :goto_0
28  iget-object v0, p0, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->speedZero:Lcom/badlogic/gdx/math/ag;
29  
30 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->setSpeedVelocity(Lcom/badlogic/gdx/math/ag;)V
31  
32 .line 61
33  :goto_1
34  return-void
35  
36 .line 50
37  :cond_0
38  invoke-virtual {p0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->getType()Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
39  
40 move-result-object v0
41  
42 sget-object v1, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;->ENEMY_AIRCAFT:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
43  
44 if-eq v0, v1, :cond_1
45  
46 invoke-virtual {p0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->getType()Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
47  
48 move-result-object v0
49  
50 sget-object v1, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;->ENEMY_LARGE_AIRCAFT:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
51  
52 if-eq v0, v1, :cond_1
53  
54 invoke-virtual {p0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->getType()Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
55  
56 move-result-object v0
57  
58 sget-object v1, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;->ENEMY_MIDDLE:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
59  
60 if-eq v0, v1, :cond_1
61  
62 invoke-virtual {p0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->getType()Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
63  
64 move-result-object v0
65  
66 sget-object v1, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;->PROPS_BOMB:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
67  
68 if-eq v0, v1, :cond_1
69  
70 invoke-virtual {p0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->getType()Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
71  
72 move-result-object v0
73  
74 sget-object v1, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;->PROPS_DOUBLE:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
75  
76 if-ne v0, v1, :cond_3
77  
78 .line 51
79  :cond_1
80  invoke-static {}, Lcom/tencent/mm/plugin/shoot/a/h;->Ml()Lcom/tencent/mm/plugin/shoot/a/h;
81  
82 move-result-object v0
83  
84 invoke-virtual {v0}, Lcom/tencent/mm/plugin/shoot/a/h;->MD()Lcom/tencent/mm/plugin/shoot/a/l;
85  
86 move-result-object v0
87  
88 invoke-virtual {p0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->getType()Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
89  
90 move-result-object v1
91  
92 invoke-virtual {v0, v1}, Lcom/tencent/mm/plugin/shoot/a/l;->c(Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;)V
93  
94 .line 55
95  :cond_2
96  :goto_2
97  sget-object v0, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;->EXPLODING:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;
98  
99 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->setState(Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;)V
100  
101 goto :goto_0
102  
103 .line 52
104  :cond_3
105  invoke-virtual {p0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->getType()Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
106  
107 move-result-object v0
108  
109 sget-object v1, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;->HERO:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
110  
111 if-ne v0, v1, :cond_2
112  
113 .line 53
114  invoke-static {}, Lcom/tencent/mm/plugin/shoot/a/h;->Ml()Lcom/tencent/mm/plugin/shoot/a/h;
115  
116 move-result-object v0
117  
118 invoke-virtual {v0}, Lcom/tencent/mm/plugin/shoot/a/h;->MD()Lcom/tencent/mm/plugin/shoot/a/l;
119  
120 move-result-object v0
121  
122 invoke-virtual {v0}, Lcom/tencent/mm/plugin/shoot/a/l;->MT()V
123  
124 goto :goto_2
125  
126 ###注意这里是我家的代码
127  
128 invoke-virtual {p0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->getType()Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
129  
130 move-result-object v0
131  
132 sget-object v1, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;->HERO:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;
133  
134 if-ne v0, v1, :cond_11
135  
136 ###本段结束
137  
138 .line 59
139  :cond_4
140  sget-object v0, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;->HITING:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;
141  
142 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->setState(Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;)V
143  
144 ###注意这里是我家的代码
145  :cond_11
146  sget-object v0, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;->FLIGTHING:Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;
147  
148 invoke-virtual {p0, v0}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite;->setState(Lcom/tencent/mm/plugin/shoot/actor/GameSprite$State;)V
149  
150 ###本段结束
151  
152 goto :goto_1
153 .end method

同理,需要给自己飞机多增加一些炸弹或者双子弹等都可以在palyer初始化的时候调用相应的方法,根据添加的方法写出对应的smali代码就能实现上面分析的无敌模式的多种情况 接下来我们需要进行打包,修改完代码后,用如下命令打包

1 apk b 解包的包文件夹名称

这里需要注意的是,打包后必须进行签名,不然只对微信的apk包做签名处理是不起作用的。 签名命令如下:

1 # 注意 update.zip 是需要签名的文件 update_signed.zip 是签名后的文件
2 java -jar signapk.jar testkey.x509.pem testkey.pk8 update.zip update_signed.zip

签名后把微信的apk安装包重命名为zip结尾,然后用压缩工具打开,替换里面相应的com.tencent.mm.plugin.shoot.XXXXXX
替换后对微信安装包重新签名即可,注意用adb安装程序的话不管什么结尾的文件名都行,要是copy到内存卡中进行安装必须改成apk不然识别不了。
这里提供一个改好的apk安装包,下载地址:http://pan.baidu.com/share/link?shareid=1113420314&uk=2317334154
注意:修改别人的软件是不合法的,所以这里提供的修改版本安装包我可没说是自己改的或许是从网上找的,大家懂得就行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值