这个是我刚做逆向时做的的一个项目,拿出来与大家分享一下,希望能对于刚开始从事逆向的新手有些帮助,还请大牛多多指点。
微信5.01打飞机破解 [url=]1[/url].准备用到的软件和工具 (1)ApkToolkit2.1 (2)jd-gui (3) Smali2Java GUI (4) We_Chat_v5_01.apk (http://app.cnmo.com/android/195481/) 2.反编译微信apk 这个apk是不能用apktoolkit直接反编译,需要手动进行。首先在ApkToolkit的根目录里的Bin文件里,打开cmd命令窗口 [url=][/url] 其中 java -jar apktool.jar 是用Java命令以jar文件来启动apktool d -r是指要反编译解压apk文件 后面的那个是要反编译的apk 002是存放反编译出来的文件 在002\assets\preload里的那个带shoot的jar就是要修改的文件 直接用RAR压缩软件解压后即可以得到 classes.dex 用apktool反编译这个classes.dex 这时就会有一个classes文件夹出现,这里包含的都是smali文件,可以用记事本直接修改,但这不方面阅读,接下来还需要把classes.dex反编译成jar,照着上面方法,使用apktool把apk转换成jar 用jd-gui就可以打开这个classes_dex2jar.jar 3.分析代码找到关键点 (1)修改子弹为双发 使用jd-gui可以很容易在这个actor文件夹下找到可疑点 现在知道了要怎么改,就需要在相对应的Player.smali文件中去修改,smali文件和java语法不一样,需要自己多多摸索总结 可以按关键字来搜索,这里拿NORMAL来找 把NORMAL改为DOUBLE后保存 改了这些还不够,这里的意思是:游戏一开始,飞机使用的子弹类型就是由原来的单发变成了双发,但游戏过程中,程序会不断检测子弹状态,如果不是处于双发BUFF状态时,还会把它重新改回单发的 在下面PlayerActor里可以明显看出程序怎么样来检测飞机子弹类型的 这里连函数名都是check,不就是检测的意思啊,这里有一个if判断 System.currentTimeMillis() 就是获取当前时间 this.player.getStartBulletDouble() 就是你吃到子弹双的时间 this.player.getShootDoubleTime() 就是子弹双持续的时间 连起来就是:如果(当前时间--你吃到子弹双的时间) 大于 子弹双持续的时间 就把子弹状态调为子弹单发的 这里需要达到的目的就是不让他执行if里的这一句: this.player.setBulletType(Player.BulletType.NORMAL) 从字面上也可以看出这是要把子弹改回单发的,这简单的方法(改动最小的)就是把NORMAL改成DOUBLE,当然你可以让if里的条件不成立,也是可以达到目的 修改smali文件方法同上 (2)修改每释放一个炸弹,炸弹数会增加一个 炸弹的源代码在jd-jui里面是显示不出来的 所有在这里要用Smali2Java GUI打开 经过代码的分析查找找到了炸弹减少的的位置。 public final void Nu() { if(mBombNumber < 0x3) { mBombNumber = (mBombNumber + 0x1); } } 这一段是对吃到的炸弹进行判断,当炸弹数小于等于3个是,吃到炸弹后才会加1,当炸弹数为3个时,在吃到炸弹则不会在添加炸弹数。 public final void Nv() { if(mBombNumber > 0) { mBombNumber = (mBombNumber - 0x1); } } 这一段代码为释放炸弹时减少的炸弹数,当吃到的炸弹数大于0时,释放炸弹才会减1。 对应的smali里面为 修改每释放一个炸弹,炸弹数会增加一个只需修改Nv里面的减少的数量即可,既把Nv里面的-0x1改为0x1,这样修改的话可以实现释放炸弹后不会减1个反而会增加1个。但只改这一个地方是不行的,还需修改 一出代码才能实现本次修改。 经过对代码的查找跟踪分析Java代码如下: 这段代码是对炸弹的属性和状态做出了一个判断,该段代码中的MO为吃到炸弹数量,MU为炸弹的爆炸信号。如果只在Nv里修改-1为1是不行了,在这个还会对吃到的炸弹进行一个判断,如果吃的炸弹数量大于1时才会往下执行MU的爆炸代码。 下面为smali代码: invoke-static {}, Lcom/tencent/mm/plugin/shoot/a/h;->MO()Lcom/tencent/mm/plugin/shoot/a/h; move-result-object v0 iget v0, v0, Lcom/tencent/mm/plugin/shoot/a/h;->mBombNumber:I .line 603 if-lez v0, :cond_4e invoke-static {}, Lcom/tencent/mm/plugin/shoot/a/a;->MD()Lcom/tencent/mm/plugin/shoot/a/a; move-result-object v1 invoke-virtual {v1, v0}, Lcom/tencent/mm/plugin/shoot/a/a;->gP(I)Z move-result v0 if-eqz v0, :cond_4e 此处是对吃到的炸弹数是否大于0的一个判断 .line 604 invoke-static {}, Lcom/tencent/mm/plugin/shoot/a/h;->MO()Lcom/tencent/mm/plugin/shoot/a/h; move-result-object v0 iget-object v0, v0, Lcom/tencent/mm/plugin/shoot/a/h;->cKm:Lcom/tencent/mm/plugin/shoot/a/j; sget-object v1, Lcom/tencent/mm/plugin/shoot/a/j;->cKF:Lcom/tencent/mm/plugin/shoot/a/j; if-ne v0, v1, :cond_4e .line 605 invoke-static {}, Lcom/tencent/mm/plugin/shoot/a/h;->MO()Lcom/tencent/mm/plugin/shoot/a/h; move-result-object v0 iget-object v0, v0, Lcom/tencent/mm/plugin/shoot/a/h;->cKv:Lcom/tencent/mm/plugin/shoot/a/l; .line 606 invoke-static {}, Lcom/tencent/mm/plugin/shoot/a/h;->MO()Lcom/tencent/mm/plugin/shoot/a/h; move-result-object v0 invoke-direct {v0}, Lcom/tencent/mm/plugin/shoot/a/h;->MU()V 明白了这些就好修改了,不管上面判断的是大于0还是小于0,判断完之后都会执行爆炸的代码。 修改如下: 即把下面这段代码前面加上:cond_4e即可。 .line 606 invoke-static {}, Lcom/tencent/mm/plugin/shoot/a/h;->MO()Lcom/tencent/mm/plugin/shoot/a/h; move-result-object v0 invoke-direct {v0}, Lcom/tencent/mm/plugin/shoot/a/h;->MU()V 当然直接修改MO的值也是可以的,把MO这个条件直接删除,在炸弹爆炸时就不会对吃到炸弹的数量进行判断了,就算炸弹数为0时,一样也是可以放出炸弹的,首先是要先吃到一个炸弹,不然直接双击屏幕释放炸弹程序会崩溃的。 (3)修改游戏总分结算 经过对代码的分析追踪查找,找到了下面的分数结算代码。 所对应的smali代码如下: .method public final declared-synchronized a(Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;)V .registers 4 .parameter .prologue .line 87 monitor-enter p0 :try_start_1 sget-object v0, Lcom/tencent/mm/plugin/shoot/a/e;->cJS:[I invoke-virtual {p1}, Lcom/tencent/mm/plugin/shoot/actor/GameSprite$Type;->ordinal()I move-result v1 aget v0, v0, v1 :try_end_9 .catchall {:try_start_1 .. :try_end_9} :catchall_1c packed-switch v0, :pswitch_data_4a .line 105 :goto_c monitor-exit p0 return-void .line 89 :pswitch_e :try_start_e iget v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJI:I sget v1, Lcom/tencent/mm/plugin/shoot/actor/EnemyAircaft;->SCORE:I add-int/2addr v0, v1 iput v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJI:I .line 90 iget v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJC:I add-int/lit8 v0, v0, 0x1 iput v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJC:I :try_end_1b .catchall {:try_start_e .. :try_end_1b} :catchall_1c goto :goto_c .line 87 :catchall_1c move-exception v0 monitor-exit p0 throw v0 .line 93 :pswitch_1f :try_start_1f iget v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJI:I sget v1, Lcom/tencent/mm/plugin/shoot/actor/EnemyMiddleAircaft;->SCORE:I add-int/2addr v0, v1 iput v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJI:I .line 94 iget v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJD:I add-int/lit8 v0, v0, 0x1 iput v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJD:I goto :goto_c .line 97 :pswitch_2d iget v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJI:I sget v1, Lcom/tencent/mm/plugin/shoot/actor/EnemyLargeAircaft;->SCORE:I add-int/2addr v0, v1 iput v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJI:I .line 98 iget v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJE:I add-int/lit8 v0, v0, 0x1 iput v0, p0, Lcom/tencent/mm/plugin/shoot/a/d;->cJE:I goto :goto_c 我们知道一个小飞机的分数是1000,一个中型飞机的分数是6000,一个大型飞机的分数是60000,小飞机里面的0x1就是1*1000,中型飞机里面的0x1就是1*6000,大型飞机里面的0x1就是1*30000。分析完这些之后也就明白了游戏中的几种飞机是怎么样加分的了。其中此段代码中的cJC,cJD,cJE分别代表这小飞机的总分,中飞机的总分,大飞机的总分。 如果想要修改飞机的分数就可以从0x1开始下手了。就拿小飞机来说,如果把0x1改为0xa时计算最后1个小飞机的总分就变成了10*1000了。 (4)修改飞机为多条命 试用jd-jui飞机的生命代码很容易就可以找到了 找到飞机生命的初始化就可以进行修改了,把初始化的值为改为几飞机就会有几条命,在这里先改为5条明。 对应的smali代码如下: 在smali里面修改0x1为0x5这样飞机也就有了5条命,但只修改初始化值是没有效果的,因为程序中判断飞机不在战斗状态时候是不显示的,所以还需要对飞机的状态进行修改。 通过查找找打看下面的一段代码: 这段代码是所有游戏对象基类里面的碰撞处理代码,当生命值小于1 就移除该对象,如果生命值大于1则更改属性为HITING ,不过飞机如果遇到这个状态肯定不行的,因为撞击时候是不能继续飞行了,所以在这个要把HITING修改为FLIGTHING。 smali代码如下: 4.把修改好文件打包回apk 首先使用apktool重建dex文件,把那个classes文件拖入apktool指定的目录,点重建dex 接下来就是把修改好classes.dex替换掉原来的文件 可以用RAR文件直接打开原来jar,拖入既可替换 最后就是要对这个jar进行签名,apktool是不能对jar文件进行签名的 在签名前要把原来的签名给删除了,用解压打开jar,然后删除META-INF里的3个文件,META-INF文件夹不要删除 接下来使用Apktool签名,虽然失败了,但是可以看到它签名使用的的命令 java -jar "D:\Tool\ApkToolkit\Bin\signapk.jar" "D:\Tool\ApkToolkit\Bin\testkey.x509.pem" "D:\Tool\ApkToolkit\Bin\testkey.pk8" "D:\Tool\ApkToolkit\Bin\002\assets\preload\com.tencent.mm.plugin.shoot.520f0383473ecc2e70994b78a6a12318.jar" "D:\Tool\ApkToolkit\Bin\002\assets\preload"com.tencent.mm.plugin.shoot.520f0383473ecc2e70994b78a6a12318.S.apk" 这里只需要把最后那个apk改为jar即可 这样使用就可以成功为jar打上签名 然后使用apktool重建整个微信apk即可保证飞机大战插件和微信apk的签名统一
|