吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3932|回复: 10
收起左侧

[原创] 160 个 CrackMe 之 153 - The_q.1 的注册算法分析和注册机实现

[复制链接]
solly 发表于 2019-7-17 11:22
本帖最后由 solly 于 2019-7-19 14:54 编辑

160 个 CrackMe 之 153 - The_q.1 是一个 Delphi 编译的 CrackMe 程序,文件信息如下,没有加壳:
00.png

既然是 Delphi 程序,直接先用 DeDeDark 打开看看,寻找事件入口:
02.png
可以看到到,有一个 Edit1Change 事件就是我们需要的事件,其入口地址为 0x00425F64,我们直接在 OD 中跳转到这个地址下断即可:
05.png
用 OD 载入并下好断点,F9 直接运行 CrackMe,显示界面如下图:
10.png


因为是 change 事件,我们先不要手动录入注册码。可以在记事本(notepad.exe)中录好,并复制,然后再到 CrackMe 中粘贴,这样可以一次性输入多个字符而只中断一次。如下图,我们输入的注册码:
11.png

我们前面已经在 0x00425F64 下了断点,程序就会断在这个位置,整个事件的代码如下:
[Asm] 纯文本查看 复制代码
00425F64  /.  55            push    ebp
00425F65  |.  8BEC          mov     ebp, esp
00425F67  |.  83C4 E8       add     esp, -18
00425F6A  |.  53            push    ebx
00425F6B  |.  56            push    esi
00425F6C  |.  57            push    edi
00425F6D  |.  33C9          xor     ecx, ecx
00425F6F  |.  894D F8       mov     dword ptr [ebp-8], ecx           ;  regCode
00425F72  |.  894D F4       mov     dword ptr [ebp-C], ecx           ;  temp1
00425F75  |.  894D F0       mov     dword ptr [ebp-10], ecx          ;  temp2
00425F78  |.  8945 FC       mov     dword ptr [ebp-4], eax           ;  Sender,文本控件对象(0x02331C9C)
00425F7B  |.  33C0          xor     eax, eax
00425F7D  |.  55            push    ebp
00425F7E  |.  68 8D614200   push    0042618D                         ;  try
00425F83  |.  64:FF30       push    dword ptr fs:[eax]
00425F86  |.  64:8920       mov     dword ptr fs:[eax], esp
00425F89  |.  C645 EB 00    mov     byte ptr [ebp-15], 0             ;  设置为失败标志
00425F8D  |.  8D55 F8       lea     edx, dword ptr [ebp-8]           ;  edx == buffer ===> regCode
00425F90  |.  8B45 FC       mov     eax, dword ptr [ebp-4]
00425F93  |.  8B80 EC010000 mov     eax, dword ptr [eax+1EC]
00425F99  |.  E8 AAF3FEFF   call    00415348                         ;  Control.GetText()
00425F9E  |.  8B45 F8       mov     eax, dword ptr [ebp-8]           ;  eax ===> regCode
00425FA1  |.  E8 CAD5FDFF   call    00403570                         ;  eax == strlen(regCode)
00425FA6  |.  8BD0          mov     edx, eax                         ;  edx == eax == strlen(regCode)
00425FA8  |.  8D45 F4       lea     eax, dword ptr [ebp-C]           ;  [ebp-c] ===> temp1
00425FAB  |.  E8 94D8FDFF   call    00403844                         ;  SetLength(temp1, (strlen(regCode))
00425FB0  |.  8B45 F8       mov     eax, dword ptr [ebp-8]           ;  eax ===> regCode
00425FB3  |.  E8 B8D5FDFF   call    00403570                         ;  eax == strlen(regCode)
00425FB8  |.  8BD0          mov     edx, eax                         ;  edx == eax == strlen(regCode)
00425FBA  |.  8D45 F0       lea     eax, dword ptr [ebp-10]          ;  [ebp-10] ===> temp2
00425FBD  |.  E8 82D8FDFF   call    00403844                         ;  SetLength(temp2, strlen(regCode))
00425FC2  |.  8B45 F8       mov     eax, dword ptr [ebp-8]           ;  eax ===> regCode
00425FC5  |.  E8 A6D5FDFF   call    00403570                         ;  strlen()
00425FCA  |.  83F8 08       cmp     eax, 8                           ;  strlen(regCode)>=8 ???
00425FCD  |.  7D 0D         jge     short 00425FDC
00425FCF  |.  8D45 F4       lea     eax, dword ptr [ebp-C]           ;  temp1
00425FD2  |.  BA 08000000   mov     edx, 8
00425FD7  |.  E8 68D8FDFF   call    00403844                         ;  SetLength(temp1, 8)
00425FDC  |>  C645 EF 01    mov     byte ptr [ebp-11], 1             ;  int x = 1
00425FE0  |.  C645 EE 01    mov     byte ptr [ebp-12], 1             ;  int k = 1
00425FE4  |.  8B45 F8       mov     eax, dword ptr [ebp-8]           ;  eax ===> regCode
00425FE7  |.  E8 84D5FDFF   call    00403570                         ;  strlen()
00425FEC  |.  84C0          test    al, al
00425FEE  |.  76 64         jbe     short 00426054                   ;  strlen(regCode) <= 0 ???
00425FF0  |.  8845 EA       mov     byte ptr [ebp-16], al            ;  int n = [ebp-16] == strlen(regCode)
00425FF3  |.  B3 01         mov     bl, 1                            ;  int i = 1;
00425FF5  |>  33C0          /xor     eax, eax
00425FF7  |.  8AC3          |mov     al, bl                          ;  i
00425FF9  |.  8B55 F8       |mov     edx, dword ptr [ebp-8]          ;  edx ===> regCode
00425FFC  |.  8A4402 FF     |mov     al, byte ptr [edx+eax-1]        ;  al = regCode[i-1]
00426000  |.  25 FF000000   |and     eax, 0FF
00426005  |.  0FA305 407842>|bt      dword ptr [427840], eax         ;  位测试和设置指令, bt 0x00000000, (eax % 32)
0042600C  |.  73 21         |jnb     short 0042602F                  ;  不低于跳转, al为偶数不跳转(即 ASCII 码为偶数),al为奇数则跳转
0042600E  |.  8D45 F4       |lea     eax, dword ptr [ebp-C]          ;  temp1
00426011  |.  E8 2AD7FDFF   |call    00403740                        ;  eax ===> temp1, 奇
00426016  |.  33D2          |xor     edx, edx
00426018  |.  8A55 EF       |mov     dl, byte ptr [ebp-11]           ;  dl == x
0042601B  |.  33C9          |xor     ecx, ecx
0042601D  |.  8ACB          |mov     cl, bl                          ;  cl == i
0042601F  |.  8B75 F8       |mov     esi, dword ptr [ebp-8]          ;  esi ===> regCode
00426022  |.  8A4C0E FF     |mov     cl, byte ptr [esi+ecx-1]        ;  cl = regCode[i-1], i= 4
00426026  |.  884C10 FF     |mov     byte ptr [eax+edx-1], cl        ;  temp1[x-1] == regCode[i-1]
0042602A  |.  FE45 EF       |inc     byte ptr [ebp-11]               ;  x++
0042602D  |.  EB 1F         |jmp     short 0042604E
0042602F  |>  8D45 F0       |lea     eax, dword ptr [ebp-10]         ;  [eax] ===> temp2
00426032  |.  E8 09D7FDFF   |call    00403740                        ;  eax ===> temp2,偶
00426037  |.  33D2          |xor     edx, edx
00426039  |.  8A55 EE       |mov     dl, byte ptr [ebp-12]           ;  k, [ebp-12] 初始化为 1
0042603C  |.  33C9          |xor     ecx, ecx                        ;  int j = 0
0042603E  |.  8ACB          |mov     cl, bl                          ;  j=i
00426040  |.  8B75 F8       |mov     esi, dword ptr [ebp-8]          ;  esi ===> regCode
00426043  |.  8A4C0E FF     |mov     cl, byte ptr [esi+ecx-1]        ;  cl = regCode[j-1]
00426047  |.  884C10 FF     |mov     byte ptr [eax+edx-1], cl        ;  temp1[k-1] == regCode[j-1], temp1== "bb7"
0042604B  |.  FE45 EE       |inc     byte ptr [ebp-12]               ;  k++
0042604E  |>  43            |inc     ebx                             ;  i++
0042604F  |.  FE4D EA       |dec     byte ptr [ebp-16]               ;  n--, n == strlen(regCode)
00426052  |.^ 75 A1         \jnz     short 00425FF5
00426054  |>  33FF          xor     edi, edi                         ;  int xorSum = 0
00426056  |.  33D2          xor     edx, edx
00426058  |.  8A55 EE       mov     dl, byte ptr [ebp-12]            ;  dl == stelen(temp1) + 1
0042605B  |.  4A            dec     edx
0042605C  |.  8D45 F0       lea     eax, dword ptr [ebp-10]          ;  eax ===> temp1, 奇
0042605F  |.  E8 E0D7FDFF   call    00403844                         ;  SetLength(), 写入字符串的长度值,成为 delphi格式字符串
00426064  |.  8A45 EE       mov     al, byte ptr [ebp-12]            ;  k = strlen(temp1) + 1
00426067  |.  48            dec     eax
00426068  |.  84C0          test    al, al
0042606A  |.  76 1A         jbe     short 00426086
0042606C  |.  8845 EA       mov     byte ptr [ebp-16], al            ;  n = strlen(temp1) - 1, 奇
0042606F  |.  B3 01         mov     bl, 1                            ;  int i = 1
00426071  |>  33C0          /xor     eax, eax
00426073  |.  8AC3          |mov     al, bl                          ;  i
00426075  |.  8B55 F0       |mov     edx, dword ptr [ebp-10]         ;  edx ===> temp1, 奇
00426078  |.  0FB64402 FF   |movzx   eax, byte ptr [edx+eax-1]
0042607D  |.  66:33F8       |xor     di, ax                          ;  xorSum = xorSum ^ temp1[i-1]
00426080  |.  43            |inc     ebx                             ;  i++
00426081  |.  FE4D EA       |dec     byte ptr [ebp-16]               ;  n--
00426084  |.^ 75 EB         \jnz     short 00426071
00426086  |>  8A45 EF       mov     al, byte ptr [ebp-11]            ;  j = strlen(temp2)+1, 偶
00426089  |.  F6D0          not     al                               ;  al == -6
0042608B  |.  3C 08         cmp     al, 8
0042608D  |.  76 1F         jbe     short 004260AE
0042608F  |.  8A5D EF       mov     bl, byte ptr [ebp-11]            ;  j
00426092  |.  80FB 08       cmp     bl, 8
00426095  |.  77 17         ja      short 004260AE                   ;  j>8
00426097  |>  8D45 F4       /lea     eax, dword ptr [ebp-C]          ;  [eax] ===> temp2, 偶
0042609A  |.  E8 A1D6FDFF   |call    00403740                        ;  eax ===> temp2
0042609F  |.  33D2          |xor     edx, edx
004260A1  |.  8AD3          |mov     dl, bl                          ;  x
004260A3  |.  C64410 FF 30  |mov     byte ptr [eax+edx-1], 30        ;  temp2 padding "0"
004260A8  |.  43            |inc     ebx
004260A9  |.  80FB 09       |cmp     bl, 9
004260AC  |.^ 75 E9         \jnz     short 00426097
004260AE  |>  8D45 F4       lea     eax, dword ptr [ebp-C]           ;  [eax] ===> temp2
004260B1  |.  BA 08000000   mov     edx, 8
004260B6  |.  E8 89D7FDFF   call    00403844                         ;  eax ===> SetLength(temp2, 8)
004260BB  |.  8D45 F8       lea     eax, dword ptr [ebp-8]           ;  [eax] ===> regCode
004260BE  |.  BA 04000000   mov     edx, 4
004260C3  |.  E8 7CD7FDFF   call    00403844                         ;  eax ===> SetLength(regCode, 4)
004260C8  |.  B3 01         mov     bl, 1                            ;  int i=1
004260CA  |>  8D45 F8       /lea     eax, dword ptr [ebp-8]          ;  regCode, 开始循环取temp2前4位
004260CD  |.  E8 6ED6FDFF   |call    00403740                        ;  eax ===> temp0
004260D2  |.  8BF3          |mov     esi, ebx                        ;  i
004260D4  |.  81E6 FF000000 |and     esi, 0FF
004260DA  |.  8B55 F4       |mov     edx, dword ptr [ebp-C]          ;  edx ===> temp2
004260DD  |.  8A5432 FF     |mov     dl, byte ptr [edx+esi-1]        ;  dl = temp2[i-1]
004260E1  |.  885430 FF     |mov     byte ptr [eax+esi-1], dl        ;  regCode == "0068"
004260E5  |.  43            |inc     ebx
004260E6  |.  80FB 05       |cmp     bl, 5
004260E9  |.^ 75 DF         \jnz     short 004260CA
004260EB  |.  8B45 F8       mov     eax, dword ptr [ebp-8]           ;  eax ===> temp2_0-3
004260EE  |.  E8 B5FFFDFF   call    004060A8                         ;  eax == StrToInt("6662") == 0x1A06
004260F3  |.  66:8945 EC    mov     word ptr [ebp-14], ax
004260F7  |.  B3 01         mov     bl, 1
004260F9  |>  8D45 F8       /lea     eax, dword ptr [ebp-8]          ;  regCode, 开始循环取 temp2 后4位
004260FC  |.  E8 3FD6FDFF   |call    00403740                        ;  eax ===> temp0
00426101  |.  8BF3          |mov     esi, ebx
00426103  |.  81E6 FF000000 |and     esi, 0FF
00426109  |.  8B55 F4       |mov     edx, dword ptr [ebp-C]
0042610C  |.  8A5432 03     |mov     dl, byte ptr [edx+esi+3]
00426110  |.  885430 FF     |mov     byte ptr [eax+esi-1], dl
00426114  |.  43            |inc     ebx
00426115  |.  80FB 05       |cmp     bl, 5
00426118  |.^ 75 DF         \jnz     short 004260F9
0042611A  |.  8B45 F8       mov     eax, dword ptr [ebp-8]           ;  eax ===> temp2_4-7
0042611D  |.  E8 86FFFDFF   call    004060A8                         ;  eax == StrToInt("4680") == 0x1248
00426122  |.  8BC8          mov     ecx, eax
00426124  |.  66:85FF       test    di, di                           ;  xorSum 不能为 0
00426127  |.  74 1B         je      short 00426144
00426129  |.  66:8B45 EC    mov     ax, word ptr [ebp-14]            ;  前4位 0x44
0042612D  |.  66:33C1       xor     ax, cx                           ;  前4位 xor 后4位
00426130  |.  0FB7C0        movzx   eax, ax
00426133  |.  0FB7D7        movzx   edx, di
00426136  |.  8BCA          mov     ecx, edx
00426138  |.  99            cdq
00426139  |.  F7F9          idiv    ecx                              ;  (前4位 xor 后4位) mod (xorSum(regCode前3位))
0042613B  |.  83FA 0D       cmp     edx, 0D                          ;  余数为 0x0D, 13
0042613E  |.  75 04         jnz     short 00426144
00426140  |.  C645 EB 01    mov     byte ptr [ebp-15], 1             ;  设置为成功标志
00426144  |>  807D EB 00    cmp     byte ptr [ebp-15], 0
00426148  |.  74 15         je      short 0042615F                   ; 0 - 失败,1 - 成功
0042614A  |.  8B45 FC       mov     eax, dword ptr [ebp-4]
0042614D  |.  8B80 F4010000 mov     eax, dword ptr [eax+1F4]
00426153  |.  BA A4614200   mov     edx, 004261A4                    ;  ASCII "R-E-G-I-S-T-E-R-E-D !!"
00426158  |.  E8 1BF2FEFF   call    00415378                         ;  Control.SetText()
0042615D  |.  EB 13         jmp     short 00426172
0042615F  |>  8B45 FC       mov     eax, dword ptr [ebp-4]
00426162  |.  8B80 F4010000 mov     eax, dword ptr [eax+1F4]
00426168  |.  BA C4614200   mov     edx, 004261C4                    ;  ASCII "NOT Registered !"
0042616D  |.  E8 06F2FEFF   call    00415378                         ;  Control.SetText()
00426172  |>  33C0          xor     eax, eax
00426174  |.  5A            pop     edx
00426175  |.  59            pop     ecx
00426176  |.  59            pop     ecx
00426177  |.  64:8910       mov     dword ptr fs:[eax], edx
0042617A  |.  68 94614200   push    00426194
0042617F  |>  8D45 F0       lea     eax, dword ptr [ebp-10]
00426182  |.  BA 03000000   mov     edx, 3
00426187  |.  E8 8CD1FDFF   call    00403318
0042618C  \.  C3            retn
0042618D   .^ E9 4ECCFDFF   jmp     00402DE0                         ;  catch
00426192   .^ EB EB         jmp     short 0042617F
00426194   .  5F            pop     edi
00426195   .  5E            pop     esi
00426196   .  5B            pop     ebx
00426197   .  8BE5          mov     esp, ebp
00426199   .  5D            pop     ebp
0042619A   .  C3            retn

上面的代码中,我在每行代码后基本都有说明,不过可能流程不清晰,下面的图,更能説明问题:
20.png
CrackMe 首先将我们输入的序列号进行字符分组,分组原则就是序列号中每个字符的 ASCII 码值,按码值的奇偶性,分成两组字符串:str1 和 str2。
str1 所含字符的ascii 码值都是奇数的数字或其它非数字字符,str2 所含字符的 ascii 码值均为偶数的数字字符。
str1 的长度无限制,最少为1个字符。str2 最少要8个数字字符,如果不够,在后面补“0”字符,如果有多,则8个以后的字符用不到。
接下来就是运算,str1 中的每个字符依次进行 xor 运算,结果为 r1。如下所示,str1 的长度为 n:
r1 = str1[0] xor str1[1] xor str1[2] xor str1[3] xor str1[4] xor ...... xor str1[n-1];
str2 则将8个字符,分成两组,前4个一组形成32bits整数 n1,后4个一组形成另一个32bits整数 n2,然后两个整数进行 xor 运算,形成结果 r2。如下所示:
n1 = StrToInt(str2[0]str2[1]str2[2]str2[3]),
n2 = StrToInt(str2[4]str2[5]str2[6]str2[7])


r2 = n1 xor n2;


最后,r1 和 r2 要满足以下条件:
r2 mod r1 == 0x0D

从上面分析可以看,r1 通过 xor 运算得到,最简单的情况是 r1 只由一个字符运算得到,即 str1 只有一个字符:

r1 = 0x00 xor str1[0];
我们的注册机就是按这个原则来进行注册码算码的,注册机的源码如下,使用 Dev-C++调试通过:
[C++] 纯文本查看 复制代码
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

int main(int argc, char** argv) {

        ///RAND_MAX = 47; // 0~46
        srand((unsigned)time(NULL)); //// 初始化随机数

        srand((unsigned)rand() * rand()); //// 初始化随机数

        printf("Keygen for The.q.1, please wait...\n");

        long o = 0x20;
        for(long k=0; k<100; k++) {  //// 最多测试100次 
                /// 生成两个由偶数数字组成的4位数字 
                long n1 = 0;
                long n2 = 0;
                for(int i=0; i<3; i++) {
                        n1 = n1 * 10 + ((long)(4 * rand() / (RAND_MAX + 1))) * 2;
                        n2 = n2 * 10 + ((long)(3 * rand() / (RAND_MAX + 1))) * 2;
                }
                /// 增加成功机率
                n1 += 8000;
                n2 += 6000;
        
                long n = n2 xor n1;
                
                //// 生成 1 位除数,1位奇数即可,跳过xor操作 
                for (long i=33; i<126; i+=2) { /// 可见字符 (0x21~0x7D)
                        if((n % i) == 13) {
                                o = i; /// 成功 
                                //printf("o = %d\n", i);
                                break;
                        }
                }

                /// U08220640, k82446222, S82626242, G80406
                if(o != 0x20) {
                        printf("Serial: %c%04u%04u\n", o, n1, n2);
                        break;                
                }
                
                //sleep(5);
        }
        
        if(o == 0x20) {
                printf("Serial Not Found, please run again!\n");
        }
        
        return 0;
}

上面注释中 U08220640, k82446222, S82626242, G80406,都是计算出来的可用注册码。

下面对注册码规则进一步説明:
1、如果计算出来的注册码后面是‘0’,可以不用输入这些‘0’,如 G80406000,只要输入 G80406 即可,其余的 CrackMe 自己会补上。
2、由于两个相同的字符 xor 后结果为0,不会影响下一次 xor 运算,所以在 str1 中,可以成对(或成双,2,4,6,8....)地插入非数字字符或者奇数数字(1,3,5,7,9),并且位置不限,如上面 G80406,可以输入 ggG80406,G80g4g06
, gGg80g4g06gkkg 等等,都是有效的。



分析完毕!!!


补充:
前面的注册机,首先确定n1,n2,形成 r2,然后测试 r1(即 str1),如果反过来考虑。我们先确定 r1(即 str1),然后强制设置 n2 = 0000,就是不考虑 n2 了,这样就可以根据条件算出 r2,就得到 n1 了,因为 n1 = r2 了。
新的注册机代码如下:
[C++] 纯文本查看 复制代码
/**
 * 方式 2
***/ 
long getSN2() {
//        for(int i=33; i<127; i++) {
//                printf("%c", i);    /// 生成 base 字符串,手动删除其中的0,2,4,6,8,放到后的base数组变量中。
//        }        
//        printf("\n");
        ///
        srand((unsigned)time(NULL)); //// 初始化随机数

        srand((unsigned)rand() * rand()); //// 初始化随机数

        printf("Keygen for The.q.1, please wait...\n");

        char base[] = "!\"#$%&'()*+,-./13579:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
        long n = strlen(base);
        
        //// 测试次数
        long n1 = 0; 
        for (int k=0; k<100; k++) {
                int i = ((int)(n * rand() / (RAND_MAX + 1)));

                long o = (long)base[i];    //// 确定 str1
        
                //计算n1 
                n1 = 1;
                long j = 0;
                while(n1<8888) {
                        j++;
                        n1 = o * j + 13;    //// 计算 n1
                        
                        //// 下面测试n1是否全由偶数数字组成
                        long m = n1 % 2; 
                        if(m == 1) {
                                continue;
                        }
                        m = (n1/10) % 2;
                        if(m == 1) {
                                continue;
                        }
                        m = (n1/100) % 2;
                        if(m == 1) {
                                continue;
                        }
                        m == (n1/1000) % 2;
                        if(m == 0) {
                                break;     /// 成功找到 n1 
                        }
                }
                
                if(n1 <= 8888) {
                        //long n2 = 0;
                        printf("Serial: %c%04d\n", o, n1);
                        break;
                }
        }

        if(n1>8888) {
                printf("Serial Not Found, please run again!\n");
        }
        
        return 0;
}


补充2:
如果对方式2进一步简化,设置 j==1,这样,r2 = o + 13 了。当计算的 r2 (或 n1)只有两位数时,就能满足条件了。
方式3如下:
[C++] 纯文本查看 复制代码
/**
 * 方式 3
***/
long getSN3() {
//        for(int i=33; i<87; i++) {  ///控制 i+13<100
//                int x = i + 13;  /// 计算r2, (j==1)
//                long m = x % 2; 
//                if(m == 1) {
//                        continue;
//                }
//                m = (x/10) % 2;
//                if(m == 0) {
//                        printf("%c", i);  //// 生成下面的 base 字符串 
//                }
//        }
//        printf("\n");

        char base[] = "!#/1357CEGIK";
        //long i = (unsigned)time(NULL) % 12; ////随机在12个序列号中选一个 
        for(long i=0; i<12; i++) //// 生成全部 12 个简单注册码 
        { 
                long o = (long)base[i];    //// r1+13<100
                ///
                printf("%c%04d\n", o, o+13);
        }
        
        return 0;
}


这样得到12个简单的注册码:
[HTML] 纯文本查看 复制代码
!0046
#0048
/0060
10062
30064
50066
70068
C0080
E0082
G0084
I0086
K0088



补充3:
前面是生成“计算简单”的注册码,基本按规则可口算得到。下面考虑一下最短的注册码,因为 CrackMe 会自己补0,我们可以考虑当r2 (或n1)为整百或整千时最简短。修改后的方式4如下:
[C++] 纯文本查看 复制代码
/**
 * 方式 4,控制输入的位数最少 
***/
long getSN4() {
	char base[] = "!\"#$%&'()*+,-./13579:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
	long n = strlen(base);
	 
	for(int r=2000; r<8800; r+=200) {  ///控制 r2 去除尾0后只有1~2位 
		for(int i=0; i<n; i++) {
			long x = (r - 13) % base[i];
			if(x==0) {
				long r2 = r/100;
		    	long m = r2 % 2; 
		    	if(m == 1) {
					continue;
				}
				m = (r2/10) % 2;
				if(m == 0) {
					printf("%c%d\n", base[i], r2);
				}
			}
		}
	}

	return 0;
}



运行后,输出如下:
[HTML] 纯文本查看 复制代码
Q22
M24
542
O42
)44
k44
!46
180


从上面结果还可以看出,180 后面的0可以去掉,只输入 18 即可,这一个应该是最简单的注册码了!!!

免费评分

参与人数 4威望 +2 吾爱币 +12 热心值 +4 收起 理由
Hmily + 2 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
13324420405 + 1 + 1 用心讨论,共获提升!
天空藍 + 1 + 1 用心讨论,共获提升!
朱朱你堕落了 + 3 + 1 牛B!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

yycoolrich 发表于 2019-7-17 11:53
和高人还有很大的差距!!!!
社会峰哥 发表于 2019-7-17 12:24
hxp.china.sh 发表于 2019-7-17 12:46
有没有VB的教程呀,以前的方法不管用         
伽古拉 发表于 2019-7-17 13:19
好的 谢谢楼主的无私分享
wxjerry 发表于 2019-7-17 14:15
谢谢楼主的无私分享!
天空藍 发表于 2019-7-17 14:48
社会峰哥 发表于 2019-7-17 12:24
数学不好怎么办  不会算啊

这只是代码逻辑算法而已,不会算可以用计算器(软体工程型)。有错请指正。
夜夜思念 发表于 2019-7-17 19:58
学习了,感谢分享~
 楼主| solly 发表于 2019-7-19 14:41
天空藍 发表于 2019-7-17 14:48
这只是代码逻辑算法而已,不会算可以用计算器(软体工程型)。有错请指正。

不是计算器,还是要先理解怎么算的,怎么算还是要有点数学逻辑滴,计算器只是验算你的理解。
天空藍 发表于 2019-7-19 16:47
solly 发表于 2019-7-19 14:41
不是计算器,还是要先理解怎么算的,怎么算还是要有点数学逻辑滴,计算器只是验算你的理解。

我的意思是说这个数学比例占得少,主要是代码逻辑问题,这些主要是靠调试来弄懂代码逻辑,而不是靠数学,靠数学的会是一堆数学符号。 xor像我就不晓得如何算,指令逻辑不懂,只要将指令和数字放入计算机运算,答案就出来了,接下来就是靠调试弄懂代码原理。有错在帮忙指正。thank
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-22 14:16

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表