平安全息萬年曆1.0.4演算法分析

看雪資料發表於2000-12-02

平安全息萬年曆(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.");
  }
}

相關文章