吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 22761|回复: 43
收起左侧

[Android 原创] 再战开放式注册算法:手机通话短信定位大师注册算法还原

  [复制链接]
taintitly 发表于 2014-8-7 17:12
本帖最后由 taintitly 于 2014-8-8 08:44 编辑

这个帖子的软件,最近失业在家,闲来无事,拿来练手。
大家如果有兴趣,可以自己拿来练练手,编译,还原算法,写注册机。
这个软件集合了反编译,dex2jar,算法还原等几个很值得研究的地方。
如果你只是想简单的用爆破解决问题,可以跳过这篇文章了。
爆破就像抢劫,没有一点技术含量。
本篇文章也是给大家一个写注册算法的启发。

本篇只限于探讨算法还原,不涉及第三方反编译和dex转jar的讨论,谢谢

老规矩,反编译进入smali,找到判别注册与否的函数isreg


.method public staticisReg(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
   .locals 27
   .param p0, "arg0"    #Ljava/lang/String;   //邮箱(大写)
   .param p1, "arg1"    #Ljava/lang/String;   //手机imei最后8
   .param p2, "arg2"    #Ljava/lang/String;   //输入的注册码注册码

   .prologue
   .line 451
   const-string v23, ""

   move-object/from16 v0, v23

   move-object/from16 v1, p0

   invoke-virtual {v0, v1},Ljava/lang/String;->equals(Ljava/lang/Object;)Z

   move-result v23

   if-nez v23, :cond_0

   if-nez p0, :cond_1

    .line452
   :cond_0
   const/16 v23, 0x0

   .line 492
   :goto_0
return v23 //判别邮箱是否为空,如果是则返回false
还原为java代码:
if(("".equals(paramString1)) || (paramString1 == null))
return false

   .line 454
   :cond_1
   const-string v23, ""

   move-object/from16 v0, v23

   move-object/from16 v1, p1

   invoke-virtual {v0, v1},Ljava/lang/String;->equals(Ljava/lang/Object;)Z

   move-result v23

   if-nez v23, :cond_2

   if-nez p1, :cond_3

   .line 455
   :cond_2
   const/16 v23, 0x0

goto :goto_0  //判别机器码是否为空,如果是则返回false
还原为java代码:
if(("".equals(paramString2)) || (paramString2 == null))
      return false

   .line 457
   :cond_3
   const-string v23, ""

   move-object/from16 v0, v23

   move-object/from16 v1, p2

   invoke-virtual {v0, v1},Ljava/lang/String;->equals(Ljava/lang/Object;)Z

   move-result v23

   if-nez v23, :cond_4

   if-nez p2, :cond_5

   .line 458
   :cond_4
   const/16 v23, 0x0

goto :goto_0 //判别输入的注册码是否为空,是则返回false
还原为java代码:
if(("".equals(paramString3)) || (paramString3 == null))
      return false

   .line 461
   :cond_5
   :try_start_0
   invoke-virtual/range {p2 .. p2}, Ljava/lang/String;->length()I

move-result v10//计算输入的注册码的字符长度,推入i
还原为java代码:
int i =paramString3.length()

   .line 462
   .local v10, "l":I
   const/16 v23, 0x0

   const/16 v24, 0x1

    move-object/from16 v0, p2

   move/from16 v1, v23

   move/from16 v2, v24

   invoke-virtual {v0, v1, v2},Ljava/lang/String;->substring(II)Ljava/lang/String;

   move-result-object v23

   invoke-static/range {v23 .. v23},Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I

move-result v8  //将注册码的第一位数值推入j
还原为java代码:
int j =Integer.parseInt(paramString3.substring(0, 1))

   .line 463
   .local v8, "i":I
   add-int/lit8 v23, v10, -0x1

   move-object/from16 v0, p2

   move/from16 v1, v23

   invoke-virtual {v0, v1},Ljava/lang/String;->substring(I)Ljava/lang/String;

   move-result-object v23

   invoke-static/range {v23 .. v23},Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I

move-result v9 //将注册码最后一位数值推入k
还原为java代码:
int k =Integer.parseInt(paramString3.substring(i - 1))

   .line 465
   .local v9, "j":I
   const/16 v23, 0x0

   add-int/lit8 v24, v8, 0x1

   move-object/from16 v0, p2

   move/from16 v1, v23

   move/from16 v2, v24

   invoke-virtual {v0, v1, v2},Ljava/lang/String;->substring(II)Ljava/lang/String;

move-result-objectv13//

还原为java代码:
String str1 =paramString3.substring(0, j + 1)

   .line 466
   .local v13, "q":Ljava/lang/String;
   add-int/lit8 v23, v8, 0x1

   add-int/lit8 v24, v10, -0x1

   move-object/from16 v0, p2

   move/from16 v1, v23

   move/from16 v2, v24

   invoke-virtual {v0, v1, v2},Ljava/lang/String;->substring(II)Ljava/lang/String;

move-result-objectv14

还原为java代码:
String str2 = paramString3.substring(j + 1,i - 1)

   .line 468
   .local v14, "r":Ljava/lang/String;
   new-instance v23, Ljava/lang/StringBuilder;

   const/16 v24, 0x0

   move/from16 v0, v24

   invoke-virtual {v14, v0, v9},Ljava/lang/String;->substring(II)Ljava/lang/String;

   move-result-object v24

   invoke-static/range {v24 .. v24},Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

   move-result-object v24

   invoke-direct/range {v23 .. v24},Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

   add-int/lit8 v24, v9, 0x1

   move/from16 v0, v24

   invoke-virtual {v14, v0},Ljava/lang/String;->substring(I)Ljava/lang/String;

   move-result-object v24

   invoke-virtual/range {v23 .. v24},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

   move-result-object v23

   invoke-virtual/range {v23 .. v23},Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

   move-result-object v15

   .line 469
   .local v15, "s":Ljava/lang/String;
   const/16 v23, 0x10

   move/from16 v0, v23

   invoke-static {v15, v0},Ljava/lang/Long;->parseLong(Ljava/lang/String;I)J

move-result-widev21

还原为java代码:
long l1 =Long.parseLong(str2.substring(0, k) + str2.substring(k + 1), 16)

   .line 470
   .local v21, "y":J
   add-int/lit8 v23, v9, 0x1

   move/from16 v0, v23

   invoke-virtual {v14, v9, v0},Ljava/lang/String;->substring(II)Ljava/lang/String;

   move-result-object v23

   invoke-static/range {v23 .. v23},Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I

move-result v20

还原为java代码:
int m =Integer.parseInt(str2.substring(k, k + 1))

   .line 472
   .local v20, "x":I
   invoke-static {}, Ljava/lang/System;->currentTimeMillis()J

move-result-widev3

还原为java代码:
long l2 =System.currentTimeMillis()

   .line 474
   .local v3, "c":J
   new-instance v23, Ljava/lang/StringBuilder;

   invoke-static/range {p0 .. p0},Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

   move-result-object v24

   invoke-direct/range {v23 .. v24},Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

   const-string v24, "0o"

    invoke-virtual/range {v23 .. v24},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

   move-result-object v23

   move-object/from16 v0, v23

   move/from16 v1, v20

   invoke-virtual {v0, v1},Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

   move-result-object v23

   invoke-virtual/range {v23 .. v23},Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

   move-result-object v23

   invoke-static/range {v23 .. v23},Lcn/malasi/service/OtherOperatorService;->MD5(Ljava/lang/String;)Ljava/lang/String;

move-result-objectv6
还原为java代码:
String str3 =MD5(paramString1 + "0o" + m)

   .local v6, "g":Ljava/lang/String;
   new-instance v23, Ljava/lang/StringBuilder;

   invoke-static/range {p1 .. p1},Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

   move-result-object v24

   invoke-direct/range {v23 .. v24},Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

   const-string v24, "0o"

   invoke-virtual/range {v23 .. v24},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

   move-result-object v23

   move-object/from16 v0, v23

   move/from16 v1, v20

   invoke-virtual {v0, v1},Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

   move-result-object v23

   invoke-virtual/range {v23 .. v23},Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

   move-result-object v23

   invoke-static/range {v23 .. v23},Lcn/malasi/service/OtherOperatorService;->MD5(Ljava/lang/String;)Ljava/lang/String;

move-result-objectv7

还原为java代码:
String str4 =MD5(paramString2 + "0o" + m)

   .line 475
   .local v7, "h":Ljava/lang/String;
   new-instance v23, Ljava/lang/StringBuilder;

   invoke-static {v8}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;

   move-result-object v24

   invoke-direct/range {v23 .. v24},Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

   add-int v24, v8, v9

   move/from16 v0, v24

   invoke-virtual {v6, v9, v0},Ljava/lang/String;->substring(II)Ljava/lang/String;

   move-result-object v24

   invoke-virtual/range {v23 .. v24},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

   move-result-object v23

   invoke-virtual/range {v23 .. v23},Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-objectv11

还原为java代码:
String str5 = j+ str3.substring(k, j + k)

   .local v11, "m":Ljava/lang/String;
   new-instance v23, Ljava/lang/StringBuilder;

   invoke-static {v8}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;

   move-result-object v24

   invoke-direct/range {v23 .. v24},Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

   add-int v24, v8, v9

   move/from16 v0, v24

   invoke-virtual {v7, v9, v0}, Ljava/lang/String;->substring(II)Ljava/lang/String;

   move-result-object v24

   invoke-virtual/range {v23 .. v24},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

   move-result-object v23

   invoke-virtual/range {v23 .. v23},Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-objectv12

还原为java代码:
String str6 = j+ str4.substring(k, j + k)

   .line 477
   .local v12, "n":Ljava/lang/String;
   invoke-virtual {v11, v13},Ljava/lang/String;->equals(Ljava/lang/Object;)Z

   move-result v23

   if-nez v23, :cond_6

   invoke-virtual {v12, v13},Ljava/lang/String;->equals(Ljava/lang/Object;)Z
:try_end_0

   .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

   move-result v23

if-eqz v23,:cond_9

还原为java代码:
!str5.equals(str1))
      {
        boolean bool = str6.equals(str1);
        if (!bool);
      }

   .line 479
   :cond_6
   const/16 v23, 0x9

   move/from16 v0, v20

   move/from16 v1, v23

   if-ne v0, v1, :cond_7

   .line 480
   const/16 v23, 0x1

   goto/16 :goto_0

   .line 482
   :cond_7
   if-nez v20, :cond_8

   const/16 v20, 0xc

   .line 483
   :cond_8
   sub-long v16, v3, v21

   .local v16, "te":J
   const-wide v23, 0x9a7ec800L

   move/from16 v0, v20

   int-to-long v0, v0

   move-wide/from16 v25, v0

   mul-long v18, v23, v25

   .line 484
   .local v18, "tt":J
   const-wide/16 v23, 0x0

   cmp-long v23, v16, v23

   if-lez v23, :cond_9

   cmp-long v23, v16, v18

   if-gez v23, :cond_9

   .line 485
   const/16 v23, 0x1

goto/16 :goto_0


还原为java代码:
{
        if (m == 9)
          return true;
        if (m == 0)
          m = 12;
        long l3 = l2 - l1;
        long l4 = 2592000000L * m;
        if ((l3 > 0L) && (l3 <l4))
          return true;
      }

   .line 489
   .end local v3    # "c":J
   .end local v6    #"g":Ljava/lang/String;
   .end local v7    #"h":Ljava/lang/String;
   .end local v8    # "i":I
   .end local v9    # "j":I
   .end local v10    #"l":I
   .end local v11    #"m":Ljava/lang/String;
   .end local v12    # "n":Ljava/lang/String;
   .end local v13    #"q":Ljava/lang/String;
   .end local v14    #"r":Ljava/lang/String;
   .end local v15    #"s":Ljava/lang/String;
   .end local v16    #"te":J
   .end local v18    #"tt":J
   .end local v20    #"x":I
   .end local v21    #"y":J
   :catch_0
   move-exception v5

   .line 490
   .local v5, "e":Ljava/lang/Exception;
   invoke-virtual {v5}, Ljava/lang/Exception;->printStackTrace()V

   .line 492
   .end local v5    #"e":Ljava/lang/Exception;
    :cond_9
   const/16 v23, 0x0

goto/16 :goto_0
还原为java代码:
    catch (Exception localException)
    {
      localException.printStackTrace();
    }
    return false;

.end method



看了头晕吧?肯定头晕,现在把片段再整理下,整理的好一些:

Java代码整段还原如下:

public static boolean isReg(String paramString1, String paramString2,String paramString3)
  {
   if (("".equals(paramString1)) || (paramString1 == null))
     return false; //判别邮箱是否为空
   if (("".equals(paramString2)) || (paramString2 == null))
     return false; //判别机器码是否为空
   if (("".equals(paramString3)) || (paramString3 == null))
     return false; //判别注册码是否为空
   try
    {
     int i = paramString3.length(); //i=注册码长度
     int j = Integer.parseInt(paramString3.substring(0, 1));//j=注册码首位
     int k = Integer.parseInt(paramString3.substring(i - 1));//k=注册码末位
     String str1 = paramString3.substring(0, j + 1);//str1=注册码第一位到第j+1
     String str2 = paramString3.substring(j + 1, i - 1);//str2=注册码第j+2位到第i-1
      long l1 = Long.parseLong(str2.substring(0, k)+ str2.substring(k + 1), 16);
     int m = Integer.parseInt(str2.substring(k, k + 1));//m=str2k+1
     long l2 = System.currentTimeMillis();
     String str3 = MD5(paramString1 + "0o" + m);//str3=邮箱地址+0o+m字符串MD5加密
     String str4 = MD5(paramString2 + "0o" + m); //str4=机器码+0o+m字符串MD5加密
     String str5 = j + str3.substring(k, j + k);//str5=注册码首位字符+str3K+1位到j+k
     String str6 = j + str4.substring(k, j + k); //str6=注册码首位字符+str3K+1位到j+k
     if (!str5.equals(str1)) //判别:如果str1=str5 注册成功(邮箱)
     {
       boolean bool = str6.equals(str1); //判别:如果str1=str6 注册成功(机器码)
       if (!bool);
     }
     else
     {
       if (m == 9)
         return true;
       if (m == 0)
         m = 12;
       long l3 = l2 - l1;
       long l4 = 2592000000L * m;
       if ((l3 > 0L) && (l3 < l4))
         return true;
     }
    }
   catch (Exception localException)
    {
     localException.printStackTrace();
    }
   return false;
  }



看完上面的内容你是不是万念聚灰了?注册码本身居然也作为一个运算参数参与了注册码的计算,而且是MD5运算。
再简化一下吧:
注册码=注册码第一位+MD5(邮箱/机器码+”0o”+(注册码第j+2位到第i-1位字符的第k+1位))的第K+1位到j+k                   
所以说,这是一个开放性的注册码,一个邮箱或者机器码能有很多个注册码。
但是,如果我们限定住一个或者两个条件。
因为jk这两个最主要的参数是注册码的第一位和最后一位。
那么,注册码的判别就没有那么复杂了。
为了让注册码看起来不那么容易被拆解分析,我先将jk设定成一个固定的数值。
写出来的注册机有时候运算一个注册码也是需要1-3分钟时间。囧。
不过好歹还是可以用了。

1.png    2.png


PS:我用vb完全按JAVA还原出来的算法写的注册机,跑了8小时没跑出一个能用的注册码来。更囧。
我已经把算法的源码给还原出来了,至于大家用什么方式自己去写注册机啥的,
就看大家自己了,我只会用vb6.0
此软件有后门,会泄露信息,莫用!!
用这个软件发布这篇文章,探讨开放性注册算法罢了。
如果你有需要软件,留下机器码,我送10枚。

免费评分

参与人数 6热心值 +6 收起 理由
gb1855988 + 1 我很赞同!
SinCon + 1 表层破解的还原,还不错。
B6B6B6 + 1 学习了!!!!
weidi1990125 + 1 我哦去写了不发注册机干嘛? 还送10号不是.
六道魔君 + 1 太高深了 新人表示看不懂 而且大牛也不需.
小试锋芒 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.

查看全部评分

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

 楼主| taintitly 发表于 2014-8-21 17:05
liye1320 发表于 2014-8-21 15:08
smali文件 不用转换成java吗?好难看清楚

不用 我看smali文件更习惯
a44270110 发表于 2014-8-7 17:20
arja 发表于 2014-8-7 17:44
悲伤还是快乐 发表于 2014-8-7 17:57
楼主辛苦了,谢谢分享,学习了。
小试锋芒 发表于 2014-8-8 09:12
期待更多更精彩的内容!
liye1320 发表于 2014-8-21 15:08
smali文件 不用转换成java吗?好难看清楚
教父头子 发表于 2014-8-31 22:17 来自手机
太专业,有点看不懂
q348114971 发表于 2014-9-1 21:51
楼主辛苦来。
小强!! 发表于 2014-9-5 14:45 来自手机
大侠  牛逼啊
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-25 01:04

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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