题目标题:可以用金币购买的key
题目描述:努力赚金币买key吧。
题目附件:Game.apk
下载附件后解压,在android手机或模拟器中安装apk:
要求有999个金币才能买key,但是因为余额只有99,所以买不了。
接下来就是反编译apk的时刻,首先下载dex2jar:
https://code.google.com/p/dex2jar/downloads/list
将Game.apk改名为Game.zip,然后用压缩软件解压。
把解压后的classes.dex文件放到dex2jar文件夹,执行命令:
sh d2j-dex2jar.sh classes.dex
执行后生成了classes_dex2jar.jar文件。
再下载JD-GUI,作用是查看jar文件反编译后的java代码:
http://java.decompiler.free.fr/?q=jdgui
用JD-GUI打开classes-dex2jar.jar,搜索关键字"价格只能数字",就转到了判断金币的代码处:
可见a.class的包名是syclover.jerryl3e.cuitinfosecgamelevel1,下面为验证金币的代码:
class a implements View.OnClickListener { a(MainActivity paramMainActivity) { } public void onClick(View paramView) { try { // 获取文本框输入的数字 int j = Integer.parseInt(MainActivity.a(this.a).getEditableText().toString()); i = j; // 如果输入的数字小于等于0或者大于99,就弹出提示 if ((i > 99) || (i == 0) || (i <= 0)) { MainActivity.a(this.a, "价格只能数字,而且要不能大于当前余额"); return; } } catch (Exception localException) { // 这里会跳出循环?好像反编译后的代码有问题。 while (true) int i = 0; // 向服务器提交加密后的金币 ProgressDialog localProgressDialog = ProgressDialog.show(paramView.getContext(), "", "正在购买……", true, true); h localh = new h(paramView.getContext(), localProgressDialog); String[] arrayOfString1 = { "price" }; String[] arrayOfString2 = new String[1]; arrayOfString2[0] = MainActivity.a(this.a, MainActivity.a(this.a).getEditableText().toString(), "JerryL3e"); String[] arrayOfString3 = { "flag", "key" }; localh.a("http://www.jerryl3e.com/cuitandroidgame/api.php"); localh.a(arrayOfString1); localh.b(arrayOfString2); localh.c(arrayOfString3); localh.start(); } } }
之前在windows下反编译出的java代码里有一些跳转语句,但是在mac反编译出来的却没有。
根据上面的判断条件,如果金币在1到99之间的话,就会转到下面的分支执行,用金币购买key时用了不少加密算法,好像先把金币用DES加密后再提交数据,验证成功后再用AES解密key。
由于游戏界面显示要输入999才能购买成功,所以最简单的方法就是修改上面的判断条件,但是在这里改是不行的,因为这个jar不能再编译成apk。
支持正反编译apk的只有apktool了,但是apktool反编译后的代码是smali代码,比较难懂。
虽然语法难懂,但是多看看帮助文档就懂了,那么下载apktool。
https://code.google.com/p/android-apktool/downloads/list
需要下载apktool1.5.2.tar.bz2 和 apktool-install-macosx-r05-ibot.tar.bz2,解压后和Game.apk放到一起,文件如下图所示:
用终端进入apktool的文件夹后用以下命令反编译apk:
./apktool d -f Game.apk game
执行后生成了一个名字为game的文件夹,以下是game目录的树状图。
. ├── AndroidManifest.xml ├── apktool.yml ├── res │ └── ...... └── smali ├── android │ └── ...... └── syclover └── jerryl3e └── cuitinfosecgamelevel1 ├── MainActivity.smali ├── a.smali ├── b.smali ├── c.smali ├── d.smali ├── e.smali ├── f.smali ├── g.smali ├── h.smali └── i.smali
根据包名syclover.jerryl3e.cuitinfosecgamelevel1找到a.smali,代码如下:
.method public onClick(Landroid/view/View;)V // ...... :goto_0 // 把16位(两字节)的0x63(99)放入v2寄存器 const/16 v2, 0x63 // 如果v0的值(用户输入的金币)大于v2,就跳到标签cond_0 if-gt v0, v2, :cond_0 // 如果v0的值等于0,就跳到标签cond_0 if-eqz v0, :cond_0 // 如果v0大于0就跳到cond_1,也就是购买key的地方 if-gtz v0, :cond_1 :cond_0 // 提示"价格只能数字,而且要不能大于当前余额" iget-object v0, p0, Lsyclover/jerryl3e/cuitinfosecgamelevel1/a;->a:Lsyclover/jerryl3e/cuitinfosecgamelevel1/MainActivity; const-string v1, "\u4ef7\u683c\u53ea\u80fd\u6570\u5b57\uff0c\u800c\u4e14\u8981\u4e0d\u80fd\u5927\u4e8e\u5f53\u524d\u4f59\u989d" invoke-static {v0, v1}, Lsyclover/jerryl3e/cuitinfosecgamelevel1/MainActivity;->a(Lsyclover/jerryl3e/cuitinfosecgamelevel1/MainActivity;Ljava/lang/String;)V :goto_1 // 返回,不执行下面的代码 return-void :catch_0 // 异常处理 move-exception v0 move v0, v1 goto :goto_0 :cond_1 // 购买key invoke-virtual {p1}, Landroid/view/View;->getContext()Landroid/content/Context; move-result-object v0 const-string v2, "" const-string v3, "\u6b63\u5728\u8d2d\u4e70\u2026\u2026" // ...... .end method
根据上面的判断条件,只要把0x63改成一个大于999的数值就行了,不妨改成:
const/16 v2, 0x6363
这样的话999既不大于0x6363,也不等于0,而且大于0,所以会跳到购买key的地方。
保存后回到apktool文件夹,执行以下命令把smali文件编译成apk:
./apktool b game
执行后在game目录下生成了一个dist目录,里面就是编译好的Game.apk。
但这个apk是不能安装到手机的,因为还没签名,所以要下载签名工具:
https://github.com/glitterballs/release-tools/tree/master/SignApk
把编译出来的Game.apk改名为Game.zip,放到SignApk目录里。
用终端进入SignApk目录,执行以下命令:
java -jar signapk.jar certificate.pem key.pk8 Game.zip Game_signed.zip
执行后生成了Game_signed.zip,再改名为Game_signed.apk就可以在手机安装了。
安装后输入999金币购买,于是购买成功了:
所以破解apk的一般流程是:
1、解压apk,获取里面的classes.dex。
2、用dex2jar把classes.dex反编译成jar。
3、用JD-GUI打开jar文件查看java代码,确定要修改代码的地方。
4、用apktool反编译apk,对照JD-GUI的java代码修改smali代码。
5、再把smali代码编译成apk。
6、给apk签名。
2013/12/06 09:53:52
“./apktool d -f Game.apk game”命令不受用- -.
2013/12/08 18:44:12
windows叫控制台,linux叫终端
2014/01/04 00:13:39
是不是要安装Java啊-. –
2014/01/05 16:14:56
是的
2013/12/23 01:59:18
那为何命令无效- -.
2013/10/20 17:18:56
网盘的外链不能用,修复下呗。
2013/10/06 23:04:02
第二步还必须在linux下才行?
2013/10/08 21:03:00
windows也可以
2013/08/15 22:23:47
我想要你啊。
2013/07/15 14:38:43
APKtool是一个神器,这个APP是用来练手的么?
2013/07/15 15:06:51
这个app是用来做教程的。
2013/06/17 14:34:43
妈妈再也不用担心安卓的收费应用了
2013/05/29 23:53:38
学习了
(没找到比较符合的表情,就用这个吧)