吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 46403|回复: 103
收起左侧

[Android 原创] 【Android】安卓手机下xx.apk JAVA破解之旅

    [复制链接]
元亨利之贞 发表于 2013-4-7 20:18
前言:
看到吾爱安卓方面的文章较少,发篇以前的文章 赚点cb 嘿嘿
这几天手机上装了个软件,用了没多久就收费了,颇为不爽,于是便想看看能否破解,便有了下文,

请注意该文章只为  技术交流,请不要进行非法破解。技术有限  难免有疏漏之处  还望海涵

软件描述:这个apk使用一定次数后就会扣掉积分 当积分少于0的时候 便不能使用,每次启动程序的时候便会提示积分为0,需要注册,
这说明程序在启动的时候就已经检测了积分,刚好可以利用这点
下载地址:
[AppleScript] 纯文本查看 复制代码
1
http://pan.baidu.com/share/link?shareid=64695&uk=201738998

220545luw4lo5abw14qwi4.png
1.环境配置
   首先请下载好最新的jdk,网络上到处都是,记得配置环境变量,网络都有
   其次下载工具(请注意使用的时候所有路径要是英文的)
[AppleScript] 纯文本查看 复制代码
1
http://code.google.com/p/gapktool/downloads/list
   以及签名工具: Auto-sign_aW.zip (9.82 KB, 下载次数: 215)
   另外附加一个网址 是翻译java的反汇编代码的,大家看不懂可以参考这个网站:
   http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html

2.开始反编译
(1)使用工具apktool1.4(现在有1.5了). 他在上面提供的工具的lib目录下,用前先将apk文件拷本到这个目录下,使用方法是,启动cmd,定位到该目录,然后键入命令:xxx.apk为你的apk
[AppleScript] 纯文本查看 复制代码
1
apktool d xxx.apk

然后就会在该目录下生成反编译的文件,包括资源,源代码(是java的反编译文件),我们将在这里修改源代码

(2)打开Gapktool.bat,选择你的apk,及其反编译输出的路径,注意不要中文,请将两个勾选上,点击开始反编译就会生成反编译文件,过不了多久就会提示保存,以及自动打开java decompiler
213345wwxps4psw06bp4wd.jpg
(3)需要注意到是java decompiler里面的源代码似乎被混淆了,很多变量或者函数词不达意,需要自己去猜
(4)在自己设置的输出目录中,除了包含反编译的代码外,还有其他资源,图片等,这里可以手动DIY或者汉化
        如在res\values下  包含strings.xml  这个文件包含软件菜单的文件,可以汉化  
             res\values下 的drawable包含图片资源 可以替换等等  大家可以自己挖掘
214424e8ruxlhz6rg6rh0k.jpg

3.代码的定位
我们的目的是为了破解,那么代码的文件在smali文件夹下,通过分析可以知道,com文件夹是程序主要的代码,net主要包括广告代码,android应该是安卓系统的库代码吧,在com文件夹加内包括许多smail的文件这些都是主程序的核心代码,但是命名都没有规则,你不知道他们是拿来干什么的
214833u61xososc2s0tys1.jpg
所幸的是 部分文件还是可以猜出来的 ,比如activity_register.smali,An_QimenActivity.smali这些一看就知道是与注册相关的文件
(1)既然如此,我们就在Java Decompiler中查看下activity_register.java,代码很明显:
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.nfbazi.qimen;
 
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.nfbazi.qimen.a.a;
 
public class activity_register extends Activity
{
a a = new a(this);
private SharedPreferences b;
 
protected void onCreate(Bundle paramBundle)
{
super.onCreate(paramBundle);
setContentView(2130903043);
EditText localEditText1 = (EditText)findViewById(2131165228);
EditText localEditText2 = (EditText)findViewById(2131165230);
localEditText1.setText(a.o);
localEditText2.setFocusable(true);
localEditText2.setFocusableInTouchMode(true);
Button localButton1 = (Button)findViewById(2131165232);
Button localButton2 = (Button)findViewById(2131165233);
localButton1.setOnClickListener(new bp(this));
localButton2.setOnClickListener(new bo(this));
TextView localTextView = (TextView)findViewById(2131165231);
if (a.q) //如果对象a.q字段不为0
{
localTextView.setTextColor(-16776961); //那么设置文字颜色
localTextView.setText("您已经注册了本程序。"); //设置文本
localEditText2.setText("************"); //设置文本
localEditText2.setEnabled(false); // 将填写注册码的文本框变灰 因为已经注册了
}
}
}

那么我们只要简单的 把if(a.q)去掉就不就可以了?

(2)我们打开activity_register.smali  观察代码:拉到最后,代码比较长 我们不关心别的
[AppleScript] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
.class public Lcom/nfbazi/qimen/activity_register;
.super Landroid/app/Activity;
 
 
# instance fields
.field a:Lcom/nfbazi/qimen/a/a;
 
.field private b:Landroid/content/SharedPreferences;
 
 
# direct methods
.method public constructor <init>()V
.locals 1
 
invoke-direct {p0}, Landroid/app/Activity;-><init>()V
 
new-instance v0, Lcom/nfbazi/qimen/a/a;
 
invoke-direct {v0, p0}, Lcom/nfbazi/qimen/a/a;-><init>(Landroid/content/Context;)V
 
iput-object v0, p0, Lcom/nfbazi/qimen/activity_register;->a:Lcom/nfbazi/qimen/a/a;
 
return-void
.end method
 
.method static synthetic a(Lcom/nfbazi/qimen/activity_register;)Landroid/content/SharedPreferences;
.locals 1
 
iget-object v0, p0, Lcom/nfbazi/qimen/activity_register;->b:Landroid/content/SharedPreferences;
 
return-object v0
.end method
 
.method static synthetic a(Lcom/nfbazi/qimen/activity_register;Landroid/content/SharedPreferences;)V
.locals 0
 
iput-object p1, p0, Lcom/nfbazi/qimen/activity_register;->b:Landroid/content/SharedPreferences;
 
return-void
.end method
 
 
# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
.locals 4
 
const/4 v3, 0x1
 
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
 
const v0, 0x7f030003
 
invoke-virtual {p0, v0}, Lcom/nfbazi/qimen/activity_register;->setContentView(I)V
 
const v0, 0x7f07002c
 
invoke-virtual {p0, v0}, Lcom/nfbazi/qimen/activity_register;->findViewById(I)Landroid/view/View;
 
move-result-object v0
 
check-cast v0, Landroid/widget/EditText;
 
const v1, 0x7f07002e
 
invoke-virtual {p0, v1}, Lcom/nfbazi/qimen/activity_register;->findViewById(I)Landroid/view/View;
 
move-result-object v1
 
check-cast v1, Landroid/widget/EditText;
 
sget-object v2, Lcom/nfbazi/qimen/a/a;->o:Ljava/lang/String;
 
invoke-virtual {v0, v2}, Landroid/widget/EditText;->setText(Ljava/lang/CharSequence;)V
 
invoke-virtual {v1, v3}, Landroid/widget/EditText;->setFocusable(Z)V
 
invoke-virtual {v1, v3}, Landroid/widget/EditText;->setFocusableInTouchMode(Z)V
 
const v0, 0x7f070030
 
invoke-virtual {p0, v0}, Lcom/nfbazi/qimen/activity_register;->findViewById(I)Landroid/view/View;
 
move-result-object v0
 
check-cast v0, Landroid/widget/Button;
 
const v2, 0x7f070031
 
invoke-virtual {p0, v2}, Lcom/nfbazi/qimen/activity_register;->findViewById(I)Landroid/view/View;
 
move-result-object v2
 
check-cast v2, Landroid/widget/Button;
 
new-instance v3, Lcom/nfbazi/qimen/bp;
 
invoke-direct {v3, p0}, Lcom/nfbazi/qimen/bp;-><init>(Lcom/nfbazi/qimen/activity_register;)V
 
invoke-virtual {v0, v3}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V
 
new-instance v0, Lcom/nfbazi/qimen/bo;
 
invoke-direct {v0, p0}, Lcom/nfbazi/qimen/bo;-><init>(Lcom/nfbazi/qimen/activity_register;)V
 
invoke-virtual {v2, v0}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V
 
const v0, 0x7f07002f
 
invoke-virtual {p0, v0}, Lcom/nfbazi/qimen/activity_register;->findViewById(I)Landroid/view/View;
 
move-result-object v0
 
check-cast v0, Landroid/widget/TextView;
 
sget-boolean v2, Lcom/nfbazi/qimen/a/a;->q:Z
 
if-eqz v2, :cond_0 //这里的if-eqz 就是说 如果v2变量等于0的平方那么就跳...,我们将他删除掉
 
const v2, -0xffff01 //定义常量v2
 
invoke-virtual {v0, v2}, Landroid/widget/TextView;->setTextColor(I)V //调用方法设置颜色,参数为v0和v2,那么v2应该是颜色信息
 
const-string v2, "\u60a8\u5df2\u7ecf\u6ce8\u518c\u4e86\u672c\u7a0b\u5e8f\u3002" //定义字串也就是该程序已经注册
 
invoke-virtual {v0, v2}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
 
const-string v0, "************" //将文本框设置为********** 之后再设置为灰色
 
invoke-virtual {v1, v0}, Landroid/widget/EditText;->setText(Ljava/lang/CharSequence;)V
 
const/4 v0, 0x0
 
invoke-virtual {v1, v0}, Landroid/widget/EditText;->setEnabled(Z)V
 
:cond_0
return-void
[/backcolor].end method


所以完整的代码是:
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
上面部分一样 从这里开始
const v2, -0xffff01
 
invoke-virtual {v0, v2}, Landroid/widget/TextView;->setTextColor(I)V
 
const-string v2, "\u60a8\u5df2\u7ecf\u6ce8\u518c\u4e86\u672c\u7a0b\u5e8f\u3002"
 
invoke-virtual {v0, v2}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
 
const-string v0, "************"
 
invoke-virtual {v1, v0}, Landroid/widget/EditText;->setText(Ljava/lang/CharSequence;)V
 
const/4 v0, 0x0
 
invoke-virtual {v1, v0}, Landroid/widget/EditText;->setEnabled(Z)V
 
:cond_0
return-void
.end method


事实上  经过以上修改之后,只是在注册窗口上显示注册了  而积分依旧是0  代码还需要定位  这里只是为了好看 如图:
22281443zz23nq4zponoau.jpg

(2)那么既然这个文件没用  我们就看另一个An_QimenActivity.java这个文件,通过搜索“积分”我们可以看到这样的代码:
[AppleScript] 纯文本查看 复制代码
1
2
3
4
5
6
7
public String d()
{
com.nfbazi.qimen.a.a.a = c();
if (com.nfbazi.qimen.a.a.a < 5);
for (String str = "剩余积分:" + Integer.toString(com.nfbazi.qimen.a.a.a) + " 分。 您的积分不足。" + 10 + "次试用期过后,如果没有注册,还想继续免费使用软件,可点击程序主页面右下角的“获取积分”," + "通过下载安装应用,免费获取一定积分。" + "您也可以付费注册本软件,无需通过积分方式使用。点击程序主页面左下角“菜单”里的帮助,查看如何注册。" + "注册后,不会再有积分事项显示。"; ; str = "剩余积分:" + Integer.toString(com.nfbazi.qimen.a.a.a) + " 分。 每次点击“时家奇门”会“日家奇门”,会消费积分 " + 5 + " 分。")
return str;
}

明显是注册的....通过判断对象a.a.a是否小于5,也就是积分是否小于5来进行提示,那么a.a.a的值是通过他上面的c()方法来得到的,我们现在在这个文件中搜索c()代码;
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
public int c()
{
try
{
int i2 = YoumiPointsManager.queryPoints(this);
i1 = i2;
return i1; //返回的i1就是我们的积分,而i1是通过调用YoumiPointsManager.queryPoints(this)得到的,我们没必要深究这个方法的实现,只要修改返回的值就得到积分了
}
catch (Exception localException)
{
while (true)
int i1 = 0;
}
}

我们那么打开An_QimenActivity.smali定位到c()方法(方法名是一样的,只是汇编代码不一样) 代码如下:
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
.method public c()I
.locals 1
 
:try_start_0 //异常代码
//得到积分
invoke-static {p0}, Lnet/youmi/android/appoffers/YoumiPointsManager;->queryPoints(Landroid/content/Context;)I
:try_end_0 //异常结束
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
 
move-result v0 //将积分赋给v0返回,,我们可以在这行代码上面修改v0的值 这样不管他返回多少 都会被我们覆盖 我们可以这样修改const/4 v3,0xxxx xxx为你需要的积分
 
:goto_0
return v0
 
:catch_0 //处理异常部分
move-exception v0
 
const/4 v0, 0x0
 
goto :goto_0
.end method


修改后的代码是:其他都一样 这里只显示c()
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
.method public c()I
.locals 1
 
:try_start_0
invoke-static {p0}, Lnet/youmi/android/appoffers/YoumiPointsManager;->queryPoints(Landroid/content/Context;)I
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
const/4 v0,0x5  //关键一句
move-result v0
 
:goto_0
return v0
 
:catch_0
move-exception v0
 
const/4 v0, 0x0
 
goto :goto_0
.end method


这样我们就破解完成了.....

4. apk的打包和签名
(1)同样使用apktool1.4,命令格式为:
[AppleScript] 纯文本查看 复制代码
1
apktool b xxxx

其中xxx为你的文件夹,如果环境配置没错,代码修改的也没错,那么将顺利编译,编译成功的文件在你的apk目录下的dist文件夹,将他拷贝出来,这时候还不能安装,因为没有签名

    (2)打开签名工具auto-sign,将刚才生成的apk文件拷贝到这里,并且其改名为update.zip,然后运行sign.bat批处理,会自动生成一个update_signed.zip文件,这个文件就是签名后的文件,可以修改为xx.apk进行安装了

如图  这样的破解后的样子,每次点击起局都会固定返回5积分,至于你问我为什么不修改多点积分,我也想,每次修改为其他值就编译报错,估计是设计到安卓编程的设计,或者寄存器吧这个还有待研究...............另外提供的练手压缩包内的注册部分 我就没该了 留给大家练手吧,把积分搞定了等于免费了,其实还可以搞其他的,如去广告,修改资源等等
094443bl88ohv8uo83ubum.jpg


破解到这里就基本完成了,可以看到手机软件写的比较简单,我们修改一个return就ok了,随着安卓平台的普及,相信未来安卓平台的趋势将会愈发重要


五:遗留的一些问题
其实这个破解不是真正意义上的破解,我只是修改了积分,还是再研究下达到程序的注册,去广告等。
另外程序在修改积分的时候 我发现除了修改为0x5以外  其他的值都会奔溃,不知道为什么
希望有高手可以解答下







免费评分

参与人数 7热心值 +7 收起 理由
吾爱破解1990 + 1 我很赞同!
szs6008 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
这只猪 + 1 啊啊啊啊!不小心手贱点到了反对。。。不好.
youdeath + 1 新手的福音。好东东。今天也是第一次评分,.
qq1129209565 + 1 我很赞同!
781732825 + 1 我很赞同!
okman110 + 1 这样的帖子 居然没人加热心和分 没天理啊!

查看全部评分

本帖被以下淘专辑推荐:

  • · 教程|主题: 122, 订阅: 88

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Rocfly 发表于 2014-7-12 16:54








                       我是为了来涨姿势的
头像被屏蔽
xiawei1203 发表于 2013-4-7 20:23
zxxz2002 发表于 2013-4-7 20:24
q2533714 发表于 2013-4-7 20:24
哈哈哈 学习了 谢谢分享
kuwo911 发表于 2013-4-7 20:28
强力教程    非常精彩
furedelu 发表于 2013-4-7 20:33
前来学习学习
qq7156792 发表于 2013-4-7 20:34
一种破解思路,很不错的说,谢谢分享
jerry828 发表于 2013-4-7 20:40
学习了!
Apocalypse 发表于 2013-4-7 20:51
值得分享 不过有些数据加密就比较困难
niucaidi 发表于 2013-4-7 20:55
虽然我看不懂!  但是我果断要顶!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-3 21:14

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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