• 标 题:平安全息万年历1.0.4算法分析
  • 作 者:chn-boy
  • 时 间:2000-12-2 9:27:39
  • 链 接:http://bbs.pediy.com

平安全息万年历(1.0.4)的注册码算法

声明:供交流用,Money多多的朋友请向作者注册——支持国产软件嘛。(嘻嘻)

软件名称:  平安全息万年历 1.0.4
下载地址: http://www.newhua.com.cn
软件说明: 该软件可快捷地查阅公历、农历、干支(四柱)、生肖、五行、九星、黑黄道、
建、宿、星期、大小月、每日物候、24节气,公、农历节日,值日吉星、神
煞及方位、时辰,日、时宜、忌,人、事、时之间的“合、冲、刑、害”关系,
查询中国历代纪元,邮政编码,国内外长话区号,古代趣味解梦、杂占。有自
动闹钟功能,正点起闹、定时叫闹。可打印择吉日历。是天文、地理、历史、
建筑、《易》学、中医、理学、民俗、人文、古文明研究者的利器,也是广泛
农、工、商、学、医人士的最佳司时工具。
程序关联:  msvbvm50.dll
目标:        研究注册码算法,并用C写出注册机
调试工具: softice4.05、IceDump6.016
作者:        chn-boy
写作日期: 2000-12-2

该程序VB编写,调用MSVBVM50.DLL。首先运行该软件,在注册窗口中
填写好你的Virtual Code,如我填写的为:
Name: 66745923  ß 由软件自动给出,不用填写
Code: 32194876
CTRL+D启用SoftICE4.05,下中断bpx hmemcpy,F5
回到windows,点注册,程序被SoftICE拦截。Bd * ,然后就是按F12数下,
当到MSVBVM50领空时,用命令:

s 30:0 l -1 56,57,8B,7C,24,10,8B,74,24,0C,8B,4C,24,14,33,C0,F3,66,A7

来查找VB50的核心字符串比较代码段(其实也可以下中断bpx __vbastrcomp)
在找到的地址处下中断:bpx 30:xxxxxxxx,按F5就可以让程序中断至该处,然
后就是繁琐的跟踪,一大堆来回跳转的指令(想想现在头都发麻),详细的代码
这里不再给出,告诉大家两个比较有用的中断点:
1)bpx 76380632 do “d ebx->8”  ß 该中断为最后注册码比较处,ebx->8
处存放的是Virtual Code通过计算得到
的字符串,edx->8处存放的是Name
通过计算得到的字符串,如果两个字符
串相等,则注册成功。

2)bpx 7628bcd do “d ebp->8”  ß该中断点其实就是bpx rtcmidbstr的外延
rtcmidbstr函数的功能就是用以从一个Table表中得到一个数据,入口参数为:
esp+4为Table表的地址偏移,esp+8为从距表多大偏移处得到数据,ecx中存放
的是获得数据的字节数。

整个软件的算法是这样的:根据软件的编号(如我的是66745923)通过一
种算法,从表1中查出对应的值构成一个字符串;然后再根据你输入的Code通
过另一种算法,从表2中查出对应的值构成另一个字符串。最终比较两个字符串
是否相等,若是,则注册成功(嘿嘿,我的我已经知道了:8*2*7*6*,其中*代
表任意阿拉伯数字)

下面我来说说它的算法:
1)第一个字符串:取出Name中奇数位四个数字6 7 5 2,逐一查表,合并得到
第一个字符串。80 7F C4 6B 66 59 6A 70
2)第二个字符串:将Name中偶数位和Code中奇数位取出,合并在一起,根据
我所填写的,Name 取出 6 4 9 3 (66745923),Code中取
出3 1 4 7 (32194876),然后合写成 63 41 94 37,注意中
间的间隔,每两位都是一个10进制数,分别*2-1,比如第
一个10进制数63,63*2-1=125=0x7D。那么前面的那个函
数rtcmidbstr的*(esp+8)=0x7D,也就是说从表的第125个字
节处取出ecx个字符,然后把四组合并起来,得到第二个字
符串。

由上述可知,对于Code中偶数位的数字可以任意填写。爽吧?!

算法明了,下面的关键是Table表的问题了。  :)

表1 —— 用来算Name 的字符串的:(此表我已经预处理了,为了编程方便)
A2 9E —— 0            FA 89 —— 1            6A 70 —— 2
28 72 —— 3            1F 65 —— 4            66 59 —— 5
80 7F —— 6            C4 6B —— 7            C1 5F —— 8
2E 9B —— 9


表2,共198个字节

C4 6B FA 89 28 72 A2 9E-2E 9B 6A 70 C1 5F FA 89  .k..(r....jp._..
C4 6B C1 5F A2 9E 80 7F-C4 6B 80 7F 80 7F C4 6B  .k._....k...k
FA 89 2E 9B 28 72 28 72-66 59 28 72 C1 5F 28 72  ....(r(rfY(r._(r
FA 89 1F 65 6A 70 2E 9B-C4 6B A2 9E 28 72 FA 89  ...ejp...k..(r..
A2 9E C1 5F 1F 65 6A 70-6A 70 80 7F C1 5F 2E 9B  ..._.ejpjp.._..
28 72 C4 6B 66 59 C4 6B-80 7F 1F 65 28 72 C4 6B  (r.kfY.k..e(r.k
6A 70 FA 89 A2 9E 66 59-2E 9B FA 89 C4 6B FA 89  jp....fY.....k..
80 7F C4 6B C1 5F 28 72-C4 6B 6A 70 C1 5F 1F 65  ..k._(r.kjp._.e
2E 9B 66 59 66 59 80 7F-80 7F C4 6B 2E 9B FA 89  ..fYfY...k....
C4 6B 80 7F 66 59 A2 9E-1F 65 28 72 66 59 FA 89  .k.fY...e(rfY..
2E 9B 6A 70 6A 70 A2 9E-2E 9B 6A 70 66 59 C4 6B  ..jpjp....jpfY.k
A2 9E 1F 65 28 72 66 59-C1 5F FA 89 C1 5F FA 89  ...e(rfY._..._..
66 59 66 59 FA 89



要得到注册码,那么我们就需要根据Name得到字符串进行逆运算,从而得到Code的
四个奇数位的数字是什么?大家可以想想看。。其实也是蛮简单的。。
    注册机随后附上。

*_^        *_^        *_^

详细信息:

平安全息万年历1.0.4注册机

下面的是根据前述算法做出注册机,我试了一下,好用  :)
如果要源程序,可以和我联系。Tialon@126.com

#include <stdio.h>
#include <ctype.h>
#define STR_LEN 8

unsigned char Table1[] = { 0xA2,0x9E,0xFA,0x89,0x6A,0x70,0x28,0x72,0x1F,
              0x65,0x66,0x59,0x80,0x7F,0xC4,0x6B,0xC1,0x5F,
              0x2E,0x9B };

unsigned char Table2[] = { 0xC4,0x6B,0xFA,0x89,0x28,0x72,0xA2,0x9E,0x2E,
              0x9B,0x6A,0x70,0xC1,0x5F,0xFA,0x89,0xC4,0x6B,
              0xC1,0x5F,0xA2,0x9E,0x80,0x7F,0xC4,0x6B,0x80,
              0x7F,0x80,0x7F,0xC4,0x6B,0xFA,0x89,0x2E,0x9B,
              0x28,0x72,0x28,0x72,0x66,0x59,0x28,0x72,0xC1,
              0x5F,0x28,0x72,0xFA,0x89,0x1F,0x65,0x6A,0x70,
              0x2E,0x9B,0xC4,0x6B,0xA2,0x9E,0x28,0x72,0xFA,
              0x89,0xA2,0x9E,0xC1,0x5F,0x1F,0x65,0x6A,0x70,
              0x6A,0x70,0x80,0x7F,0xC1,0x5F,0x2E,0x9B,0x28,
              0x72,0xC4,0x6B,0x66,0x59,0xC4,0x6B,0x80,0x7F,
              0x1F,0x65,0x28,0x72,0xC4,0x6B,0x6A,0x70,0xFA,
              0x89,0xA2,0x9E,0x66,0x59,0x2E,0x9B,0xFA,0x89,
              0xC4,0x6B,0xFA,0x89,0x80,0x7F,0xC4,0x6B,0xC1,
              0x5F,0x28,0x72,0xC4,0x6B,0x6A,0x70,0xC1,0x5F,
              0x1F,0x65,0x2E,0x9B,0x66,0x59,0x66,0x59,0x80,
              0x7F,0x80,0x7F,0xC4,0x6B,0x2E,0x9B,0xFA,0x89,
              0xC4,0x6B,0x80,0x7F,0x66,0x59,0xA2,0x9E,0x1F,
              0x65,0x28,0x72,0x66,0x59,0xFA,0x89,0x2E,0x9B,
              0x6A,0x70,0x6A,0x70,0xA2,0x9E,0x2E,0x9B,0x6A,
              0x70,0x66,0x59,0xC4,0x6B,0xA2,0x9E,0x1F,0x65,
              0x28,0x72,0x66,0x59,0xC1,0x5F,0xFA,0x89,0xC1,
              0x5F,0xFA,0x89,0x66,0x59,0x66,0x59,0xFA,0x89,
              '\0' };

unsigned char buf_str[] = "**";
unsigned char Number_str[STR_LEN+1];
unsigned char Code_str[] = "0*0*0*0*";
char *pstr,*pt;
int pos=0,k=0;

void main() {
  printf("\nPlease Enter Number of your SoftWare: ");
  scanf("%s",Number_str);
  if(strlen(Number_str)>=STR_LEN){
    pstr = Number_str;
    pt = Table2;
    while(k<STR_LEN){
      buf_str[0] = Table1[(*(pstr+k)-0x30)*2];
      buf_str[1] = Table1[(*(pstr+k)-0x30)*2+1];
      pos = (*(pstr+k+1)-0x30)*10*2;
      Code_str[k] = ((int)strstr(pt+pos,buf_str)-(int)pt-pos)/2+1+0x30;
      k += 2;
    }
    printf("\nYour Code is: %s  [ * -- any digital ]",Code_str);
  }else {
    printf("Enter Number error.");
  }
}