• 标 题:mIRC v5.81版注册码算法分析和注册机编写
  • 作 者:chn-boy
  • 时 间:2000-12-11 13:04:35
  • 链 接:http://bbs.pediy.com

mIRC v5.81版注册码算法分析和注册机编写

软件名称:mIRC v5.81
下载网址:http://soft.hn.cninfo.net/
调试工具:SoftICE 4.05
调试平台:Win2K、W32dsm89

    作者:chn-boy
    日期:2000-12-11

    先用W32dsm89进行静态分析,查找字符串“”,然后上下察看,发现在地址0049D875处有点问题,记下这个地址。下回在mIRC领空时
下中断:bpx 0049D875,从新再进行注册,程序拦断在0049D875处:

:0049D861 E8D89B0800              Call 0052743E
:0049D866 68D33B5400              push 00543BD3
:0049D86B 68EC375400              push 005437EC
:0049D870 E850FBFFFF              call 0049D3C5  <-- 注册码的计算Call,跟踪进去详细看看。程序运行到此,d *esp和d esp->4
                                                      你可以看到你输入的Name和Code。
:0049D875 85C0                    test eax, eax  <-- 第一次拦断在此,如果EAX=1,则注册成功
:0049D877 0F84B0000000            je 0049D92D
:0049D87D BED41F5300              mov esi, 00531FD4
:0049D882 BFEC375400              mov edi, 005437EC
:0049D887 33C0                    xor eax, eax


将0049D870处的Call 0049D3C5代码取出片断如下:
:0049D41D 68044B5500              push 00554B04 <-- 你输入的Code
:0049D422 68004A5500              push 00554A00 <-- 你输入的Name
:0049D427 E8A6FEFFFF              call 0049D2D2 <-- 将你输入的Code和Name分别进行运算,然后进行比较,如果相等,则EAX=1。
:0049D42C 85C0                    test eax, eax
:0049D42E 7407                    je 0049D437
:0049D430 B801000000              mov eax, 00000001  <-- 将 EAX 置 1,也是注册成功的标志
:0049D435 EB74                    jmp 0049D4AB     

将0049D427处的Call 0049D2D2代码取出片断如下:
:0049D2F3 6A2D                    push 0000002D  <-- 字符'-'
:0049D2F5 56                      push esi      <-- Code字符串的offset
:0049D2F6 E841B00700              call 0051833C  <-- 得出Code字符串中'-'的位置,值返回到EAX中
:0049D2FB 83C408                  add esp, 00000008
:0049D2FE 8BD8                    mov ebx, eax
:0049D300 85DB                    test ebx, ebx
:0049D302 7507                    jne 0049D30B
:0049D304 33C0                    xor eax, eax
:0049D306 E9B1000000              jmp 0049D3BC
:0049D30B C60300                  mov byte ptr [ebx], 00  <-- 将Code字符串中的'-'字符置为0x00
:0049D30E 56                      push esi                <-- Code字符串的offset
:0049D30F E848440800              call 0052175C          <-- 算出第一部分的值,比如:'781', 最后得到0x030D=781
                                                          <-- 将值返回到EAX中
:0049D314 59                      pop ecx
:0049D315 8945FC                  mov dword ptr [ebp-04], eax
:0049D318 C6032D                  mov byte ptr [ebx], 2D  <-- 将以前转换的'-'恢复
:0049D31B 43                      inc ebx               
:0049D31C 803B00                  cmp byte ptr [ebx], 00  |
:0049D31F 7507                    jne 0049D328            |看看第二部分是否存在,若否,则跳到注册不成功的地方
:0049D321 33C0                    xor eax, eax            |
:0049D323 E994000000              jmp 0049D3BC            |

:0049D328 53                      push ebx
:0049D329 E82E440800              call 0052175C          <-- 得到第二部分的值
:0049D32E 59                      pop ecx
:0049D32F 8945F8                  mov dword ptr [ebp-08], eax
:0049D332 FF7508                  push [ebp+08]
:0049D335 E8A2B00700              call 005183DC
:0049D33A 59                      pop ecx
:0049D33B 8945F4                  mov dword ptr [ebp-0C], eax
:0049D33E 33C0                    xor eax, eax
:0049D340 33DB                    xor ebx, ebx
:0049D342 BA03000000              mov edx, 00000003
:0049D347 8B4D08                  mov ecx, dword ptr [ebp+08]    <-- 将Name字符串的长度值给ECX
:0049D34A 83C103                  add ecx, 00000003              <-- Name从第3+1=4个字符开始处理
:0049D34D 3B55F4                  cmp edx, dword ptr [ebp-0C]
:0049D350 7D1C                    jge 0049D36E                  <-- 如果Name长度少于等于3,则注册不成功

:0049D352 0FB631                  movzx esi, byte ptr [ecx]            |
:0049D355 0FAF3485341F5300        imul esi, dword ptr [4*eax+00531F34]  |
:0049D35D 03DE                    add ebx, esi                          |
:0049D35F 40                      inc eax                              |从Name的第4个字符开始,分别用值*对应
:0049D360 83F826                  cmp eax, 00000026 (Name长度要少于0x29)|的一个固定字符串(算法分析中给出),
:0049D363 7E02                    jle 0049D367                          |并求和,将和总值给EBX,用d 0053F34你
:0049D365 33C0                    xor eax, eax                          |可以看到这个固定的字符串。
:0049D367 42                      inc edx                              |
:0049D368 41                      inc ecx                              |
:0049D369 3B55F4                  cmp edx, dword ptr [ebp-0C]          |
:0049D36C 7CE4                    jl 0049D352                          |
:0049D36E 3B5DFC                  cmp ebx, dword ptr [ebp-04]          <-- 比较EBX和前面算出的那个第一部分是否相等
:0049D371 7404                    je 0049D377
:0049D373 33C0                    xor eax, eax                          <-- 不等,则注册不成功
:0049D375 EB45                    jmp 0049D3BC
:0049D377 33C0                    xor eax, eax
:0049D379 33DB                    xor ebx, ebx
:0049D37B BA03000000              mov edx, 00000003
:0049D380 8B4D08                  mov ecx, dword ptr [ebp+08]
:0049D383 83C103                  add ecx, 00000003
:0049D386 3B55F4                  cmp edx, dword ptr [ebp-0C]
:0049D389 7D23                    jge 0049D3AE
:0049D38B 0FB631                  movzx esi, byte ptr [ecx]            |
:0049D38E 0FB679FF                movzx edi, byte ptr [ecx-01]          |
:0049D392 0FAFF7                  imul esi, edi                        |
:0049D395 0FAF3485341F5300        imul esi, dword ptr [4*eax+00531F34]  |
:0049D39D 03DE                    add ebx, esi                          |从Name的第4个字符开始,分别用值*前一个字符
:0049D39F 40                      inc eax                              |得值*固定字符串对应值,求和后将值存放到EBX
:0049D3A0 83F826                  cmp eax, 00000026                    |
:0049D3A3 7E02                    jle 0049D3A7                          |
:0049D3A5 33C0                    xor eax, eax                          |
:0049D3A7 42                      inc edx                              |
:0049D3A8 41                      inc ecx                              |
:0049D3A9 3B55F4                  cmp edx, dword ptr [ebp-0C]          |
:0049D3AC 7CDD                    jl 0049D38B                          |
:0049D3AE 3B5DF8                  cmp ebx, dword ptr [ebp-08]          <-- 比较EBX和前面算出的那个第二部分是否相等
:0049D3B1 7404                    je 0049D3B7
:0049D3B3 33C0                    xor eax, eax                          <-- 不等,则注册不成功
:0049D3B5 EB05                    jmp 0049D3BC
:0049D3B7 B801000000              mov eax, 00000001                    <-- 置EAX=1,注册成功的标志
:0049D3BC 5F                      pop edi
:0049D3BD 5E                      pop esi
:0049D3BE 5B                      pop ebx
:0049D3BF 8BE5                    mov esp, ebp
:0049D3C1 5D                      pop ebp
:0049D3C2 C20800                  ret 0008


【算法分析】
    这个注册码算法很简单,形式就是:假定Name(简称N)和Code(简称C),令N'=Fn1(N), N''=Fn2(N), C'=Fc1(C), C''=Fc2(C),
如果能让C'=N' && C''=N''那么注册成功。
    根据前面分析,固定字符串为0B 06 11 0C 0C 0E 05 0C 10 0A 0B 06 0E 0E 04 0B 06 0E 0E 04 0B 09 0C 0B 0A 08 0A 0A ...
        N'=Fn1(N)的定义为:从Name第4个字符开始,分别用值*这个固定的字符串,求出总和。
        N''=Fn2(N)的定义为:从Name第4个字符开始,分别用值*前一个字符值*这个固定的字符串,求出总和。

    下面关键问题是得到C', C'',由上面的分析可以知道C'=N'=Fn1(N),C''=N''=Fn2(N),那么:
        C=Fc1逆(C') + '-' + Fc2逆(C'') = Fc1逆(Fn1(N)) + '-' + Fc2逆(Fn2(N))
这个C是很好根据N来得到的。

    详细的注册机请看下文。

  • 标 题:mIRC v5.81版注册机编写 (Turbo C 2.0)
  • 作 者:chn-boy
  • 时 间:2000-12-11 13:11:13

mIRC v5.81版注册机编写

软件名称:mIRC v5.81
下载网址:http://soft.hn.cninfo.net/
编程工具:Turbo C 2.0

    作者:chn-boy
    日期:2000-12-11



#include <stdio.h>
#include <ctype.h>

unsigned char s_str[] = { 0x0B,0x06,0x11,0x0C,0x0C,0x0E,0x05,0x0C,0x10,
              0x0A,0x0B,0x06,0x0E,0x0E,0x04,0x0B,0x06,0x0E,
              0x0E,0x04,0x0B,0x09,0x0C,0x0B,0x0A,0x08,0x0A,
              0x0A };
unsigned char *pstr,name_str[31],code_str[22],buffer_str[22];
unsigned long sum1,sum2;
int k = 3;

void main()
{
    printf("\nPlease Enter your NAME: ");
    scanf("%s",name_str);
    if(strlen(name_str) > 3) {
        pstr = name_str;
        sum1 = 0;
        sum2 = 0;
        k = 3;
        while(*(pstr+k) != '\0') {
            sum1 += (unsigned long)(*(pstr+k)) * (unsigned long)(s_str[k-3]);
            sum2 += (unsigned long)(*(pstr+k)) * (unsigned long)(*(pstr+k-1)) * (unsigned long)(s_str[k-3]);
            k++;
        }
        ultoa(sum1, code_str, 10);
        k = strlen(code_str);
        code_str[k] = 0x2D;
        code_str[k + 1] = '\0';

        ultoa(sum2, buffer_str, 10);
        strcat(code_str,buffer_str);

        printf("\nYour Code is: %s", code_str);
    } else {
        printf("\nMust be 4 or more char......");
    }
}

    另外,为了Name可以输入汉字的需要,用VC++ 6.0编写了一个32位的Windows程序,大小20K,如果谁需要,可以和我联系。*_^