吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6343|回复: 5
收起左侧

[Android 原创] CrackMe-F1F2.apk 分析

[复制链接]
Sugus 发表于 2014-8-19 13:53
本帖最后由 淡然出尘 于 2015-2-3 18:43 编辑

请先看这两篇:http://www.52pojie.cn/thread-232658-1-1.html
http://www.52pojie.cn/thread-281850-1-1.html

大神们已经分析很完整了,只是第三个apk,也就是CrackMe-F1F2.apk尚没有注册机,虽然说算法有点...,所就连同分析一起写下来

好吧,言归正传,请看下面

首先反编译,然后查找uncorrect,找到LisenceCheck$1.smali中的onClick方法
0632859b-a6da-42ce-a398-94bacd4be13f.png
接下来就是分析该方法了

[Asm] 纯文本查看 复制代码
# virtual methods
.method public onClick(Landroid/view/View;)V
    .locals 10
    .param p1, "v"    # Landroid/view/View;
    .prologue
    const/4 v9, 0x0
    const-string v8, ""
    .line 53
    check-cast p1, Landroid/widget/Button;
    .end local p1    # "v":Landroid/view/View;
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    iget-object v6, v6, Lcom/mstar/test/LisenceCheck;->mbutton:Landroid/widget/Button;
    if-ne p1, v6, :cond_5
    .line 55
    new-instance v4, Ljava/lang/String;
    const-string v6, ""
    invoke-direct {v4, v8}, Ljava/lang/String;-><init>(Ljava/lang/String;)V
    .line 56
    .local v4, "s1":Ljava/lang/String;
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    iget-object v6, v6, Lcom/mstar/test/LisenceCheck;->meditun:Landroid/widget/EditText;
    invoke-virtual {v6}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
    move-result-object v6
    invoke-interface {v6}, Landroid/text/Editable;->toString()Ljava/lang/String;
    move-result-object v4
    #上面的代码是接收输入的用户名的值
    .line 57
    new-instance v5, Ljava/lang/String;
    const-string v6, ""
    invoke-direct {v5, v8}, Ljava/lang/String;-><init>(Ljava/lang/String;)V
    .line 58
    .local v5, "s2":Ljava/lang/String;
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    iget-object v6, v6, Lcom/mstar/test/LisenceCheck;->meditsn:Landroid/widget/EditText;
    invoke-virtual {v6}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
    move-result-object v6
    invoke-interface {v6}, Landroid/text/Editable;->toString()Ljava/lang/String;
    move-result-object v5
    #上面的代码是接收输入的序列号的值
    .line 60
    const/4 v1, 0x0
    .local v1, "i":I
    const/4 v2, 0x0
    .line 62
    .local v2, "k1":I
    const/4 v1, 0x0 #这里定义v1为0
    :goto_0
    invoke-virtual {v4}, Ljava/lang/String;->length()I
    move-result v6  #读取输入用户名的值(即v4的值)的长度,给到v6
    if-lt v1, v6, :cond_1   #如果v1小于v6,则跳转cond_1
    .line 69
    :cond_0
    xor-int/lit16 v2, v2, 0x5678    #v2与0x5678进行异或运算,然后将结果给到v2
    .line 72
    const/4 v3, 0x0
    .line 73
    .local v3, "k2":I
    const/4 v1, 0x0     #又重新给v1赋值为0
    :goto_1
    invoke-virtual {v5}, Ljava/lang/String;->length()I
    move-result v6  #去输入序列号的长度,给到v6
    if-lt v1, v6, :cond_3   #若v1小于v6,则跳转
    .line 78
    xor-int/lit16 v3, v3, 0x1234
    .line 80
    if-ne v2, v3, :cond_4
    .line 81
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    invoke-virtual {v6}, Lcom/mstar/test/LisenceCheck;->getApplicationContext()Landroid/content/Context;
    move-result-object v6
    const-string v7, "Lisence Correct\uff01"    #显示序列号正确咯
    invoke-static {v6, v7, v9}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    move-result-object v6
    invoke-virtual {v6}, Landroid/widget/Toast;->show()V
    .line 92
    .end local v1    # "i":I
    .end local v2    # "k1":I
    .end local v3    # "k2":I
    .end local v4    # "s1":Ljava/lang/String;
    .end local v5    # "s2":Ljava/lang/String;
    :goto_2
    return-void
    .line 64
    .restart local v1    # "i":I
    .restart local v2    # "k1":I
    .restart local v4    # "s1":Ljava/lang/String;
    .restart local v5    # "s2":Ljava/lang/String;
    :cond_1
    invoke-virtual {v4, v1}, Ljava/lang/String;->charAt(I)C 
    move-result v0  #读取v4的值的第v1位,给到v0(注意,这里给的是ASCII码)
                    #比如v4的第v1位为1,则v0的值为49
    .line 65
    .local v0, "ch":C
    const/16 v6, 0x41   #即十进制65
    if-lt v0, v6, :cond_0   #若v0小于v6,则跳转,若输入的用户名都为数字,很明显这样肯定要跳转
                            #若是输入的为字母或者是一些符号什么的,就不跳转,因为ASCII码65是A嘛
    .line 66
    const/16 v6, 0x5a   #即十进制90
    if-le v0, v6, :cond_2   #若v0小于v6,则跳转,这里v6为90,即是说,如果输入为大写字母,则跳转
    const/16 v6, 0x20
    sub-int v6, v0, v6
    int-to-char v0, v6  #这里又是将输入的小写字母转换成大写字母
    .line 67
    :cond_2
    add-int/2addr v2, v0    #将大写字母的ASCII码给到v2
    .line 62
    add-int/lit8 v1, v1, 0x1    #相当于 v1++
    goto :goto_0
    .line 74
    .end local v0    # "ch":C
    .restart local v3    # "k2":I
    :cond_3
    invoke-virtual {v5, v1}, Ljava/lang/String;->charAt(I)C 
    move-result v0  #去输入序列号(即v5的值)的第v1位,给到v0,这里同样是ASCII码
    .line 75
    .restart local v0    # "ch":C
    const/16 v6, 0x30
    sub-int v6, v0, v6
    int-to-char v0, v6  #v0减去48,然后将结果给到v0
    .line 76
    mul-int/lit8 v6, v3, 0xa    #v3乘以10,结果给到v6
    add-int v3, v6, v0  #将v6和v0的值相加,结果给到v3
    .line 73
    add-int/lit8 v1, v1, 0x1    #相对于v1++
    goto :goto_1
    .line 83
    .end local v0    # "ch":C
    :cond_4
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    invoke-virtual {v6}, Lcom/mstar/test/LisenceCheck;->getApplicationContext()Landroid/content/Context;
    move-result-object v6
    const-string v7, "Lisence Uncorrect\uff01"  #显示序列号错误咯
    invoke-static {v6, v7, v9}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    move-result-object v6
    invoke-virtual {v6}, Landroid/widget/Toast;->show()V
    goto :goto_2
    .line 88
    .end local v1    # "i":I
    .end local v2    # "k1":I
    .end local v3    # "k2":I
    .end local v4    # "s1":Ljava/lang/String;
    .end local v5    # "s2":Ljava/lang/String;
    :cond_5
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    iget-object v6, v6, Lcom/mstar/test/LisenceCheck;->meditun:Landroid/widget/EditText;
    const-string v7, ""
    invoke-virtual {v6, v8}, Landroid/widget/EditText;->setText(Ljava/lang/CharSequence;)V
    .line 89
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    iget-object v6, v6, Lcom/mstar/test/LisenceCheck;->meditsn:Landroid/widget/EditText;
    const-string v7, ""
    invoke-virtual {v6, v8}, Landroid/widget/EditText;->setText(Ljava/lang/CharSequence;)V
    goto :goto_2
.end method


本人小菜,写个注册机都写了半天
注册机:
[Java] 纯文本查看 复制代码
import java.util.*; 
class User{
        public int calc1(String X){
                int v2 = 0;
                if(X.length() != 0){
                        for(int i = 0;i<X.length();i++){
                                char c1 = X.charAt(i);
                                if(c1<65){
                                        break;
                                }else if(c1>90){
                                        v2 = v2 + (c1 - 0x20);
                                }
                        }
                }
                v2 = v2 ^0x5678;
                return v2;
        }
}
class Lisence{
        public int calc2(String Y){
                int v3 = 0;
                if(Y.length() != 0){
                        for(int i = 0;i<Y.length();i++){
                                char c2 = Y.charAt(i);
                                String str1 = String.valueOf(c2);
                                int i1 = Integer.valueOf(str1).intValue();
                                int i2 = v3 * 10;
                                v3 = i1 + i2;
                        }
                }
                v3 = v3 ^ 0x1234;
                return v3;
        }
}
class Test{
        public static void main(String[] args) {
                User user = new User();
                Lisence lisence = new Lisence();

                Scanner s = new Scanner(System.in);
                String str = null;
                System.out.print("请输入用户名:");
                str = s.next();
                int i1 = Integer.valueOf(user.calc1(str)).intValue();
                   int j = 0;
                while(true){
                        String ss = "" + j;
                        if(i1 == lisence.calc2(ss)){
                                System.out.println("序列号:" + ss);
                                break;
                        }
                        j++;
                }
        }
}


QQ截图20140819134131.png
QQ截图20140819134105.png

分析至此,如有错误,请各位大神指出。
欢迎各位交流,大神快来教我吧

免费评分

参与人数 1热心值 +1 收起 理由
小试锋芒 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.

查看全部评分

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

 楼主| Sugus 发表于 2014-8-19 13:55
沙发肯定是我的
weew 发表于 2014-8-19 15:37
924410377 发表于 2014-8-19 21:15 来自手机
taintitly 发表于 2014-8-19 22:44

F1、F2函数

//F1函数部分,s1为输入的用户名


1  int i = 0,k1 = 0;;
2  char ch;
3  for (i = 0; i<s1.length();i++)
4  {
5  ch = s1.charAt(i);
6  if (ch < 'A') break;
7  if (ch > 'Z') ch -= 32;
8  k1 = k1 + ch;
9  }
10 k1 = k1 ^ 0x5678;

//F2函数部分,s2为输入的序列号


1 int k2 = 0;
2 for (i = 0;i < s2.length(); i++)
3 {
4     ch = s2.charAt(i);
5     ch –= 48;
6     k2 = k2 * 10 + ch;
7 }
8 k2 = k2 ^ 0x1234;

原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就是对应用户名的正确的序列号。

注册机的核心代码



1  int i = 0;
2  int k3 = 0;
3  char ch;
4  for (i = 0; i < s1.length(); i++)
5  {
6      ch = s1.charAt(i);
7      if (ch < 'A') break;
8      if (ch > 'Z')
9      ch -= 32;
10     k3 = k3 + ch;
11 }
12 k3 = k3 ^ 0x5678 ^ 0x1234;
//s1为用户名,k3为根据s1算出来的正确的序列号,单独写一个注册机,然后通过注册机计算

免费评分

参与人数 1热心值 +1 收起 理由
Sugus + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.

查看全部评分

Kzgtkc 发表于 2014-12-29 23:11
3个都全了,,谢谢
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-24 13:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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