全文的Bao均为暴,由于Bao力这个词存在,所以不让发布,只有这样改着---⊙﹏⊙b汗
这一节要解密的apk要求输入用户名和序列号,如果匹配则通过Toast显示一个Lisence Correct! 否则 则显示 Lisence Uncorrect!
启动界面
错误的用户名和序列号
和前面的apk不同的是,这个apk要求输入用户名和序列号,且采用了前文的第三种序列号保护验证模式,即采用了:
F1(用户名) = F2(序列号)
通常来说,若F1、F2其一可逆转。找出正确序列号的方法就是要找出这么一种F1或F2的逆变换。若F1或F2函数比较简单,找出逆变换写出注册机是可行的,这也是很多cracker追求的解密方式,且此方法不破坏原apk的完整性。但有些时候,为了追求迅速解密软件的序列号保护,很多人会选择使用Bao破解。Bao力破解的着手点在最终的比较代码上。不管采用哪种序列号的保护验证模式,最后必然会存在这么一种类似的比较的方式。以伪代码贴出:
if A 等于 B
{
//验证正确
//do something
}
else
{
//验证失败
//do something
}
Bao力破解的要点在于修改判断语句的条件。把“等于”改成“不等于”,或者是把“不等于”改成“等于”。那么此时,随便输入错误的用户名和序列号,就能进入到“验证正确”的板块去,从而成功的注册软件。
在汇编语言中,Bao力破解也是类似的原理。
je或jz //相等则跳(机器码是74或84)
jne或jnz //不相等则跳(机器码是75或85)
常见的修改就是把对比部分的机器码中74改成75或者84改成85,在反编译的smali文件中,也是类似的。
符号 |
smali语法 |
Bao力破解修改 |
== |
if-eq |
if-eq改成if-ne |
!= |
if-ne |
if-ne 改成 if-eq |
equals |
if-eqz |
if-eqz改成 if-nez |
!equals |
if-nez |
if-nez 改成if-eqz |
//若不相等,则跳转到cond_4,此处就是密文的比较
.line 80
if-ne v2, v3, :cond_4
..
//cond_4处,使用Toast显示Lisence Uncorrect!
:cond_4
..
const-string v7, "Lisence Uncorrect/uff01"
…
invoke-virtual {v6}, Landroid/widget/Toast;->show()V
我们就是把上面的
if-ne v2, v3, :cond_4
修改成
if-eq v2, v3, :cond_4
至此该apk序列号Bao力破解的核心步骤就完成了。
使用adb push到虚拟机中进行测试,随便在用户名和序列号输入框中输入任意的非正确组合,均能显示“Lisence Correct!”。如下图:
阅读F1和F2函数的smali代码就不再重复了,这仅仅需要的是耐心,因为反编译出来的smali代码多跳转也多,相对比较难读,不过比汇编还是容易读懂一些。下面列举此apk使用的两个F1,F2函数的JAVA代码。完成其一函数大的逆转来帮助我们完成这个apk的注册机。
//F1函数部分,s1为输入的用户名
//F2函数部分,s2为输入的序列号
原apk就是这样,若k1==k2,那么验证成功,否则验证失败。
可以看出 F2函数的循环部分,仅仅是把序列号s2从字符串转换为整型,存于k2中,此处的k2我们成为k2[序列号]。最后做异或运算,从而得出密文,覆盖于k2中,此处的k2成为k2[密文]。在异或运算中,若存在
c = a xor b (对应到F2函数中的最后一步,即 k2[密文] = k2[序列号] xor 0x1234)
则a=c xor b (对应着k2[序列号] = k2[密文] xor 0x1234)
也就是说通过 密文 xor 0x1234 就能得到序列号
在F1函数的结果也就是密文。所以,注册机的写法也就出来了:把F1的结果 xor 0x1234就是对应用户名的正确的序列号。
//s1为用户名,k3为根据s1算出来的正确的序列号,单独写一个注册机,然后通过注册机计算”Ethan”的序列号,正确序列号为17724,验证通过。
正确的用户名和序列号
原apk放于共享资源中,需要的请自行前往下载。