新人刚接触android逆向,请多多包涵!注意:本文仅用于移动安全的研究,勿用于非法用途,由此带来的后果与本文作者无关。如果感觉好用,请支持正版,毕竟软件作者也是不容易的。
接上篇,柳暗花明之注册机制系统分析
-----------------------------------------------
二 注册机制系统分析
-----------------------------------------------
在上篇中,讲解的注册机制的初步分析,但是当软件重启后,会失效,也就是说该apk会有重启验证。
在分析重启验证之前,我们首先来分析下,下图中的注册机制的实现。
首先看下付款的实现,如下:
[Java] 纯文本查看 复制代码 public void onClick(DialogInterface arg4, int arg5) {
m.a(this.a).startActivity(new Intent("android.intent.action.VIEW", Uri.parse("https://me.alipay.com/fengyun2108")));
}
看到没,比较简单,就是支付宝支付的界面,所以这部分不是关键。
再来到授权看看
[Java] 纯文本查看 复制代码 public void onClick(DialogInterface arg6, int arg7) {
new q(m.a(this.a), null).start();
AboutActivity.a(m.a(this.a), ProgressDialog.show(m.a(this.a), "提示", "授权中,请稍后...", true));
AboutActivity.a(m.a(this.a)).setCancelable(false);
}
在授权处理中,新建了一个多线程类q,跟进如下所示
[Java] 纯文本查看 复制代码 public void run() {
super.run();
Message v0 = AboutActivity.e(this.a).obtainMessage();
v0.what = AboutActivity.f(this.a).a();
AboutActivity.e(this.a).sendMessage(v0);
}
看到没,此处利用异步回调机制发送了消息,那我们看下消息的what是什么,跟进bf类的a()方法,如下:
[Java] 纯文本查看 复制代码 public int a() {
String v0 = this.a.getSystemService("phone").getDeviceId();
Log.d("tt", "IMEI=" + v0);
try {
URL v1 = new URL(this.b);
v1.openConnection().connect();
InputStream v1_1 = v1.openStream();
BufferedReader v2 = new BufferedReader(new InputStreamReader(v1_1));
do {
String v3 = v2.readLine();
if(v3 == null) {
goto label_19;
}
}
while(!v3.equals(v0));
v1_1.close();
int v0_2 = 0;
return v0_2;
label_19:
v1_1.close();
return 1;
}
catch(Exception v0_1) {
Log.d("tt", v0_1.getMessage());
return 2;
}
}
可以清楚的看到,该软件是如何授权的,流程为:
首先获得机器码->然后连接服务器获取数据->将服务器获得的数据与机器码对比,如果相等返回0,否则返回1。
然后我们再看下,异步回调的实现过程。来到f类的handleMessage(Message arg5)方法中,如下:
[Java] 纯文本查看 复制代码 public void handleMessage(Message arg5) {
DialogInterface$OnClickListener v3 = null;
AboutActivity.a(this.a).dismiss();
if(arg5.what == 0) {
Log.d("tt", "Authorization success!");
if(AboutActivity.c(this.a) != null) {
AboutActivity.c(this.a).h(true);
new ce().a(this.a, AboutActivity.c(this.a));
AboutActivity.d(this.a);
new AlertDialog$Builder(this.a).setTitle("授权成功").setMessage("恭喜,授权成功!请重新启动应用。").setPositiveButton(
"好的", v3).show();
}
}
else if(arg5.what == 1) {
Log.d("tt", "Authorization failed!");
new AlertDialog$Builder(this.a).setTitle("授权失败").setMessage("请确认:\n1.您已付款成功,并按提示正确填写“付款说明”!\n2.付款成功后需要一段时间(一般为一个工作日),才能授权成功,请耐心等待。")
.setPositiveButton("好的", v3).show();
}
else if(arg5.what == 2) {
Log.d("tt", "Authorization has exception!");
new AlertDialog$Builder(this.a).setTitle("授权失败").setMessage("请检查网络!").setPositiveButton(
"好的", v3).show();
}
}
来到这,我想大家应该明白了吧,作者就是利用在异步回调中,进行注册授权的。
下面来看下,软件重启验证的实现过程
找到类MainActivityFree(主活动)的oncreate方法,如下:
[Java] 纯文本查看 复制代码 public void onCreate(Bundle arg3) {
super.onCreate(arg3);
Log.d("tt", "onCreate");
this.getWindow().setSoftInputMode(3);
this.requestWindowFeature(1);
this.R = s.a(((Activity)this));
if(this.R.n()) {
Intent v0 = new Intent();
v0.setClass(((Context)this), WelcomeActivity.class);
this.startActivityForResult(v0, 1001);
}
this.a();
this.b();
this.c();
AppConnect.getInstance(((Context)this));
if(this.R.o()) {
new bf(((Activity)this)).b();
}
}
从该方法可知,同样利用S类的a()方法,获取config.xml的内容,如下:
[Java] 纯文本查看 复制代码 this.R = s.a(((Activity)this));
最后,如果config.xml文件获得中的payVersion标签为true,则会new一个bf类,并调用其b()方法,来到该方法:
[Java] 纯文本查看 复制代码 public void b() {
new bh(this, null).start();
}
继续跟进bh类如下:
[Java] 纯文本查看 复制代码 public void run() {
Log.d("tt", "VerificateLicense...");
super.run();
Message v0 = bf.b(this.a).obtainMessage();
v0.what = this.a.a();
bf.b(this.a).sendMessage(v0);
}
其中 this.a.a();同样为上面讲解的bf类的 public int a()方法,即在此访问服务器进行重启验证,是否非法。
流程如下所示:
APK重启->再次连接服务器验证(防止非法授权)->根据返回结果,在异步回调中,进行处理,如果正常授权,则不变,
否则,提示非法授权用户,并修改config.xml中的payVersion标签为false。
上面便是整个异步回调实现软件注册的详细过程。在了解了注册机制后,破解也就变的特别简单了。
-----------------------------------------------
三 APK破解之道
-----------------------------------------------
根据上面的分析,最佳的破解点在于bf类的 public int a()方法中。
利用apktool反编译后,打开bf.smali文件,找到a()方法,修改如下:
其中,第一处和第二处修改,主要是为了获得服务器的访问网址和参数。
然后打包,签名,点击授权,并在cmd中输入adb logcat -s SN:V
运行效果如下:
然后打开LOG出的网址看看
看到没,全是授权的设备号,也算是一次意外的发现吧。
|