发新帖

新人帖拿出来与大家分享一下

[复制链接]
4666 1
这个是我刚做逆向时做的的一个项目,拿出来与大家分享一下,希望能对于刚开始从事逆向的新手有些帮助,还请大牛多多指点。

微信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的签名统一


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

举报 使用道具

回复

精彩评论1

美的随想    发表于 2015-9-29 21:53:24 | 显示全部楼层
感谢楼主分享

举报 使用道具

回复 支持 反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表