更新
填坑|南X周易程序超出试用的解决办法
(出处: 吾爱破解论坛)
1.缘起
前几天在咱们论坛发了一篇x奥周易系列软件逆向思路\更新了视频演示,反响还不错。然后正好找到了一款竞品,就是下面这位了。其实这篇文章从发完X奥就一直在酝酿了,但是技术不过关,一直没达到完美的欺骗效果。今天顺藤摸瓜就摸到了一个关键点,改一下就好。如果不想看思路的就直接看第6部分,如果想看思路的就往下翻翻,看完全文,不过思路挺长的,但是如果您像我一样,也是小白,看完还是有收获的。
2.软件介绍
八字、六爻、风水、奇门、姓名、择吉、合婚,多种平台上应用,不断完善!
3.软件列表(版本在支持系统里面有区分)
练手包下载地址在附件里
以下安卓手机软件都可免费试用30次。
当然,跟着我做完以后就没有使用限制了
批八字算命玄空风水综合排盘六爻断卦奇门适甲专业起名八字合婚择吉程序金口诀八字用神南方万年历家居风水六爻排盘八字排盘4.支持系统
V1.73,适用于安卓系统4.0版至安卓7.11版。
V1.81,适用于安卓8.0及以上版本。
5.逆向程序
MT管理器
6.害,我都不好意思写标题
方法很简单,MT进入安装包,DEX++编辑器打开classes.dex文件,打开An_xxxxxActivity,搜索add,第一个结果如下:
add-int/lit8 v0,v0,0x1
删除这一行,一路保存后编译、签名。
好了,破解完了。
说句题外话,兄弟们,看着玩意没用,这句add-int/lit8 v0,v0,0x1是我找出来的,不是你。就像我能按照小夜大佬交代的查找ChkNum来欺骗X奥系列软件一样。换成这个系列我又啥都不会了。所以你只看这句价值不大,想学点东西还得看下面的思路。
至于成品嘛,这么简单你还好意思要成品?
7逆向过程
以“八字排盘 V1.73”为例,首先安装原版软件点完试用的30次,从第31次开始,则无法正常排盘,会引导注册。如图
我们点击注册,然后会弹出注册页面
然后有以下几种情景:
- 点击“确定”,提示“您还没有输入注册码”
- 随便输入注册码,点击“确定”,提示“您输入的注册码不对”
- 点击“退出”,则返回软件主页面
好了,直接进到MT管理器里,打开apk文件,使用DEX编辑器++打开classes.dex
随便浏览一下类列表,有一个“activity_register”类。
然后点击搜索,搜索上面几个关键词。
比如搜索“注册”可以看到以下结果
我们点击“您已经注册了本程序”这一条,看到如下代码:
if-nez v1, :cond_96
sget-boolean v1, Lcom/nfbazi/PaiBazi/a/a;->f:Z
if-eqz v1, :cond_aa
:cond_96
const v1, -0xffff01
invoke-virtual {v0, v1}, Landroid/widget/TextView;->setTextColor(I)V
const-string v1, "您已经注册了本程序。"
invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
const-string v0, "************"
invoke-virtual {v6, v0}, Landroid/widget/EditText;->setText(Ljava/lang/CharSequence;)V
const/4 v0, 0x0
invoke-virtual {v6, v0}, Landroid/widget/EditText;->setEnabled(Z)V
:cond_aa
return-void
.end method
这里面有两条判断:
if-nez v1, :cond_96
if-eqz v1, :cond_aa
关于Smali语法的解读,我们可以参考这篇文章:
if-eq 如果等于
if-ne 如果不等于
if-lt 如果小于
if-le 如果小于等于
if-gt 如果大于
if-ge 如果大于等于
if-eqz 如果等于零
if-nez 如果不等于0
if-ltz 如果小于零
if-lez 如果小于等于零
if-gtz 如果大于零
if-gez 如果大于等于零
————————————————
版权声明:本文为CSDN博主「Ceryool」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:
我们现在知道了
if-nez v1, :cond_96 #如果v1不等于0,就执行cond_96的代码
if-eqz v1, :cond_aa #如果v1等于0,就执行cond_aa的代码
我们通过第一个代码块可以发现cond_96的代码就是包含"您已经注册了本程序。"的那一堆,cond_aa返回空,就是什么都不返回。
可以推断一下,未注册的情况下,v1应该是0,注册后,v1就不是0了,此时返回cond_96,也就是"您已经注册了本程序。"
那我们就欺骗一下,让未注册情况下,也能返回"您已经注册了本程序。"有两种途径可以实现此目的
- 修改if-nez v1, :cond_96为if-eqz v1, :cond_96
- 修改if-eqz v1, :cond_aa为if-eqz v1, :cond_96
修改之后,我们可以看到效果如图
但是经过测试之后我发现,这只是个美化效果,也就是说,我们只是更改了外观,并没有欺骗软件以达到注册的目的
好,接下来接着操作。
回到MT管理器,先反编译一下AndroidManifest.xml,这里是软件权限,我感觉给它联网权限不太好,那么删除android.permission.INTERNET就行了
......
下面是软件的Activity
看完之后,接着使用DEX编辑器++打开classes.dex,刚才咱们修改了activity_register,并且发现这里面并不是验证是否激活的关键所在。
然后看一眼An_PaiBaziActivity,毕竟这是主界面,信息会多一些。Smali可读性比较差,我们转化成Java代码,可是代码有很多,看哪?咱们在一开始测试过,试用次数没了之后,再使用就会跳转到软件续用界面,那我们就搜一搜什么条件下跳转,搜索我们在AndroidManifest.xml看到的RuanjianXuyong,然后我们发现就一处可以找到:
public void b() {
Intent intent = new Intent();
intent.setClass(this, RuanjianXuyong.class);
startActivity(intent);
}
这句代码是什么意思呢。因为我没学过Java。所以我也没看明白,不过我清楚,肯定就是从这里跳转到软件续用界面去了。
我们不想见到软件续用界面,因此就不能让它intent.setClass(this, RuanjianXuyong.class);
所以,我就兴致勃勃的在Smali代码中定位RuanjianXuyong
.method public b()V
.registers 3
new-instance v0, Landroid/content/Intent;
invoke-direct {v0}, Landroid/content/Intent;->()V
const-class v1, Lcom/nfbazi/PaiBazi/RuanjianXuyong;
invoke-virtual {v0, p0, v1}, Landroid/content/Intent;->setClass(Landroid/content/Context;Ljava/lang/Class;)Landroid/content/Intent;
invoke-virtual {p0, v0}, Lcom/nfbazi/PaiBazi/An_PaiBaziActivity;->startActivity(Landroid/content/Intent;)V
return-void
.end method
用我这脑子想,就是,我不想要哪一行就直接注释掉哪一行,于是我在 const-class v1, Lcom/nfbazi/PaiBazi/RuanjianXuyong;前面加了一个#,然后心满意足的转进Java看了一眼,注释错了,然后我返回Smali代码,又把 invoke-virtual {v0, p0, v1}, Landroid/content/Intent;->setClass(Landroid/content/Context;Ljava/lang/Class;)Landroid/content/Intent;注释掉了,结果还是不行。
我不禁陷入了深思!我为啥要注释掉它?因为我不想见到软件续用啊;那我想见到什么?肯定是排盘结果啊!那我直接把RuanjianXuyong替换成webshow不就行了吗?!我可真是个小机灵鬼,说干就干。
然后我就把这行代码改成了:
const-class v1, Lcom/nfbazi/PaiBazi/webshow;
一路保存,反编译,覆盖安装,排个八字
嘿嘿,剧本好像有点不一样,软件试用界面是没了,排盘界面也出来了,可是内容去哪了?玩呢?气得我脑瓜子嗡嗡的,算了,先不破了,看看这软件哪里还有验证的地方。。咋这么麻烦呢?
这还有一个显示命例,按钮,点进去一看就是个档案夹的功能,可以时不时的把保存的案例拿出来复盘。然后我随便点了一个,想要看看复原效果,结果又看到这个熟悉的面孔了:
事情进行到这里,我又要开始深思了
嗯~总的,我好像嗅到成功的味道了,突破点在试用次数上!试用期间功能不受限制,说干就干。成功我来了。
痛定思痛、细心研读An_PaiBaziActivity的Java代码(我能看懂?其实我就是看看我认识哪几个单词)
147行:如果我没猜错的话,trytimes就是试用次数吧,我真是个小机灵鬼
private void e() {
this.h = getSharedPreferences("trytimesxml", 0);
a.k = Integer.parseInt(this.a.b(this.h.getString("tms", this.a.a("65AB24201"))).substring(7, 9));
if (a.k < 32) {
a.k++;
}
this.h.edit().putString("tms", this.a.a("65AB242" + String.valueOf(h.e(a.k)))).commit();
a.d("trytimesxml");
a.a("trytimesxml.xml", "system.out");
}
看完之后,啊,这段代码就是。。嗯,,那啥的、、是吧。(球都没看懂)
不过,这段代码过于眼熟
if (a.k < 32) { /*如果a.k < 32,就执行a.k++*/
a.k++; /*a.k++ 就是 a.k = a.k + 1*/
} /*a.k = a.k + 1就是说a.k每次加1*/
我混迹吾爱数载,一看这货就是在计数,没猜错的话,应该是这样的:
if(使用次数 < 32) {
使用次数++;
}
/*“使用次数”在具体程序中会对应不一样的变量名,表示的都是使用次数的意思*/
然后我又开始我的脑洞了:
啊哈,直接把使用次数++;删掉不就行了,我真是个小机灵鬼。当然上面是java代码,咱不能修改,那咱就去改Smali代码,怎么定位呢?反正我看不懂这东西,翻也不见得能翻到,先去网上冲一会儿浪:
ARM常用指令
ADD 加指令
SUB 减指令
STR 把寄存器内容存到栈上
LDR 把栈上内容载入一个寄存器中
.W 是一个可选指令宽度说明符。不会影响为此指令的行为,它只是确保生成32位指令。
BL 执行函数调用,并把使lr指向调用者的下一条指令,即函数的返回地址
BLX 同上,但是在ARM和thumb指令集间切换
CMP 指令进行比较两个操作数的大小