Windows95 激活

早期的系统及软件激活大部分使用了离线激活技术,究其原因是因为当时的网络并不发达,许多软件都不具备离线激活的条件。故许多软件和系统厂商采用离线激活码的形式来验证软件的合法性。

离线密钥验证的原理其实非常简单,即对一整段输入的内容进行某种形式的计算和排列组合,最终得到一个合法的结果,程序即判定为激活完成。

以遭到破解的Windows95安装过程中的激活程序为例,其零售版激活程序要求输入长度为10位数字的激活码,格式为:

xxx-xxxxxxx

后来人们发现,000-0000000 和 000-1111111 等极为简单和重复的密码也能成功通过验证。经过对激活程序的反编译,有人成功破解出了 Windows95 激活程序的运行逻辑:

在零售版中,连字符前的三位数字采用黑名单制,即除了黑名单上列出的几种组合,其余任何内容均可通过测试,如下图:

黑名单给出的几种排列组合

余下的七位数字则会将各个数位的数字求和,并验证其与7的整除性。若Sum能被7整除(不留余数),程序即判定为序列号有效,验证通过。

以激活码000-1111111为例,前三位000未出现在黑名单中,验证通过。后七位1111111相加各数位相加之和等于7,可被数字7整除。到此为止,整个程序的流程验证完毕。

111-1111111通过验证的原理

除零售版外,OEM的激活码有所不同,但也被民间大神成功反编译:

与零售版相同,OEM版的激活码也由几个部分组成。其中前两个数字需满足为1-366之间的数字;第四、五位数字则为95-03之间的数字。中间由OEM作为OEM激活码的识别标志。下一段则为与零售版相同的mod7整除测试。最后五位数字不设限制,填写任意五位数字均可通过验证。

以下为 Windows 95 OEM 密钥测试程序

undefined2 __stdcall16far check_oem_key(char *key,int len)

{
  int key_length;
  int is_oem;
  int first_3_digits_int;
  int second_2_digits_int;
  undefined2 check_result;
  int i;
  int i_;
  char first_three_digits [4];
  char second_two_digits [3];
  char kc;
  
  key_length = LSTRLEN(key);
  if ((((key_length == 0x17) && (key[5] == '-')) && (key[9] == '-')) &&
     ((key[0x11] == '-' && (is_oem = check_oem_str(3,0x11704f9d,key + 6,len), is_oem == 0)))) {
                    /* Check first 5 digits, must be numeric */
    i = 0;
    do {
      kc = key[i];
      if (kc < '0') {
        return 0;
      }
      if ('9' < kc) {
        return 0;
      }
      i = i + 1;
    } while (i < 5);
                    /*  */
    copy_partial(3,key,len,first_three_digits);
    first_three_digits[3] = '\0';
    first_3_digits_int = atoi(first_three_digits);
    if ((first_3_digits_int != 0) &&
       (first_3_digits_int < 367
                    /* check if between 1 and 366 */)) {
      copy_partial(2,key + 3,len,second_two_digits);
      second_two_digits[2] = '\0';
      second_2_digits_int = atoi(second_two_digits);
      if (((second_2_digits_int < 3) || (94 < second_2_digits_int)) &&
         (((key[10] == '0' && ('0' < key[0x10])) && (key[0x10] < '8')))) {
        i_ = 0x12;
        while ((kc = key[i_], '/' < kc && (kc < ':'))) {
          i_ = i_ + 1;
          if (0x16 < i_) {
                    /* jump to part after oem- */
            check_result = mod7_check(key + 10,len);
            return check_result;
          }
        }
      }
    }
  }
  return 0;
}

代码源地址:https://gist.github.com/nezza/a25bee13f25a1733a4c7a1d3d1cf5882

文章部分插图来源:Youtube:stacksmashing

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇