taintitly 发表于 2014-8-7 17:12

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

本帖最后由 taintitly 于 2014-8-8 08:44 编辑

http://www.52pojie.cn/thread-255540-1-1.html这个帖子的软件,最近失业在家,闲来无事,拿来练手。大家如果有兴趣,可以自己拿来练练手,编译,还原算法,写注册机。这个软件集合了反编译,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_0return 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=str2第k+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=注册码首位字符+str3第K+1位到j+k位   String str6 = j + str4.substring(k, j + k); //str6=注册码首位字符+str3第K+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位               所以说,这是一个开放性的注册码,一个邮箱或者机器码能有很多个注册码。但是,如果我们限定住一个或者两个条件。因为j和k这两个最主要的参数是注册码的第一位和最后一位。那么,注册码的判别就没有那么复杂了。为了让注册码看起来不那么容易被拆解分析,我先将j和k设定成一个固定的数值。写出来的注册机有时候运算一个注册码也是需要1-3分钟时间。囧。不过好歹还是可以用了。


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

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

大侠牛逼啊
页: [1] 2 3 4 5
查看完整版本: 再战开放式注册算法:手机通话短信定位大师注册算法还原