whypro 发表于 2010-4-22 22:11:06

【分享】各类应用密码学CrackMe,慢慢的会补全。

为了方便大家研究应用密码学,这久抽时间写了应用密码学的CrackMe,由于时间比较少,还没有把所有类型的写出,不过我会陆续增加全面的。破文有时间会每个CrackMe给出一篇,并且跟在破文分析的后面会发布每个CrackMe的源码,每个CrackMe的注册机我尽量用汇编来完成,方便与CrackMe本身源码区分。

Hash类CrackMe:
(说明:Hash类验证过程并没有做成不可逆,采用的是明码比较,大家分析时尽量分析算法实现)
CRC32算法 ==>
Adler32算法 ==>
MD2算法 ==>
MD4算法 ==>
MD5算法 ==>
SHA算法 ==>
RIPEMD算法 ==>
GOST算法 ==>
TIGER算法 ==>
HAVAL算法 ==>
对称类CrackMe:
3Way算法 ==>
AES算法 ==>
Blowfish算法 ==>
Twofish算法 ==>
Cast128算法 ==>
Cast256算法 ==>
DES算法 ==>
3DES算法 ==>
DESX算法 ==>
NewDes算法 ==>
DiaMond II算法 ==>
DiaMond II Lite算法 ==>
FROG算法 ==>
Ice算法 ==>
Thinice算法 ==>
Ice2算法 ==>
IDEA算法 ==>
Mars算法 ==>
Misty1算法 ==>
Q128算法 ==>
RC2算法 ==>
RC4算法 ==>
RC5算法 ==>
RC6算法 ==>
SAFERK40算法 ==>
SAFERK64算法 ==>
SAFERK128算法 ==>
SAFERSK40算法 ==>
SAFERSK64算法 ==>
SAFERSK128算法 ==>
Sapphire2算法 ==>
SCOP算法 ==>
Serpent算法 ==>
Shark算法 ==>
Skipjack算法 ==>
Square算法 ==>
TEA算法 ==>
TEAN算法 ==>

公开密钥类CrackMe:
RSA512算法 ==>
RSA1024算法 ==>
RSA2048算法 ==>
RSA4096算法 ==>

其它算法类CrackMe:
BASE64算法 ==>
XOR256Block算法 ==>
XOR256Stream算法 ==>
谢谢收集,随时保持更新,谢谢作者:windrand (转自看雪)

[ 本帖最后由 whypro 于 2010-5-6 15:24 编辑 ]

lgjxj 发表于 2010-4-22 22:28:16

精神上支持一下

whypro 发表于 2010-4-22 22:36:18

【文章标题】: Adler32CrackMe破文
【文章作者】: dttom
【作者邮箱】: dttom2006@126.com
【下载地址】: http://bbs.pediy.com/attachment.php?attachmentid=6637&d=1183881215
【保护方式】: 无
【使用工具】: ollydbg,IDA,peid
【软件介绍】: adler32算法的crackme
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
春节在家休息没事,看了看windrand发布密码学系列crackme,看了一下只有crc32的破文,出于兴趣我也来试试adler32算法crackme的破解。首先在网上查了一下adler32算法,查到RFC1950文档有adler32算法,大概看了一下C代码,下面开始查看crackMe程序。peid 检查为delphi编译,ollydbg打开F9,输入用户名,注册码,bp GetDlgItemTextA 下断,下面见代码:
.....
0040886E   > \68 FF000000   push    0FF                              ; /Count = FF (255.); Case 3EA of switch 00408854
00408873   .68 AC924000   push    004092AC                         ; |Buffer = Adler32C.004092AC
00408878   .68 F2030000   push    3F2                              ; |ControlID = 3F2 (1010.)
0040887D   .8B45 08       mov   eax, dword ptr          ; |
00408880   .50            push    eax                              ; |hWnd
00408881   .E8 B6BEFFFF   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA下断后在这个函数里,即在系统函数领空
00408886   .8D45 B4       lea   eax, dword ptr           ;Alt+F9来到这里
00408889   .BA AC924000   mov   edx, 004092AC                  ;ASCII "dttom"
0040888E   .B9 FF000000   mov   ecx, 0FF
00408893   .E8 C0AFFFFF   call    00403858
00408898   .837D B4 00    cmp   dword ptr , 0
0040889C   .75 1C         jnz   short 004088BA
0040889E   .6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004088A0   .68 DC8A4000   push    00408ADC                         ; |Title = ""D7,"",A2,"",B2,"崽崾?
004088A5   .68 E88A4000   push    00408AE8                         ; |Text = "用",BB,"??,B2,"",BB,"能为空请输入?,A1,""
004088AA   .8B45 08       mov   eax, dword ptr          ; |
004088AD   .50            push    eax                              ; |hOwner
004088AE   .E8 C1BEFFFF   call    <jmp.&user32.MessageBoxA>      ; \MessageBoxA
004088B3   .33DB          xor   ebx, ebx
004088B5   .E9 A2010000   jmp   00408A5C
004088BA   >68 FF000000   push    0FF                              ; /Count = FF (255.)
004088BF   .68 AC934000   push    004093AC                         ; |Buffer = Adler32C.004093AC
004088C4   .68 F3030000   push    3F3                              ; |ControlID = 3F3 (1011.)
004088C9   .8B45 08       mov   eax, dword ptr          ; |
004088CC   .50            push    eax                              ; |hWnd
004088CD   .E8 6ABEFFFF   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA
004088D2   .8D45 B0       lea   eax, dword ptr
004088D5   .BA AC934000   mov   edx, 004093AC                  ;ASCII "55556666"
004088DA   .B9 FF000000   mov   ecx, 0FF
004088DF   .E8 74AFFFFF   call    00403858                         ;计算假注册码长度
004088E4   .837D B0 00    cmp   dword ptr , 0            ;检测假注册码是否为空
004088E8   .75 1C         jnz   short 00408906
004088EA   .6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004088EC   .68 DC8A4000   push    00408ADC                         ; |Title = ""D7,"",A2,"",B2,"崽崾?
004088F1   .68 008B4000   push    00408B00                         ; |Text = ""D7,"",A2,"",B2,"崧?,B2,"",BB,"能为空请输入?,A1,""
004088F6   .8B45 08       mov   eax, dword ptr          ; |
004088F9   .50            push    eax                              ; |hOwner
004088FA   .E8 75BEFFFF   call    <jmp.&user32.MessageBoxA>      ; \MessageBoxA
004088FF   .33DB          xor   ebx, ebx
00408901   .E9 56010000   jmp   00408A5C
00408906   >33C0          xor   eax, eax
00408908   .55            push    ebp
00408909   .68 88894000   push    00408988
0040890E   .64:FF30       push    dword ptr fs:
00408911   .64:8920       mov   dword ptr fs:, esp
00408914   .8D45 A8       lea   eax, dword ptr
00408917   .BA AC924000   mov   edx, 004092AC                  ;ASCII "dttom"
0040891C   .B9 FF000000   mov   ecx, 0FF
00408921   .E8 32AFFFFF   call    00403858
00408926   .8B45 A8       mov   eax, dword ptr
00408929   .8D55 AC       lea   edx, dword ptr
0040892C   .E8 EBFCFFFF   call    0040861C                         ;F8后出现注册码,我们用F7跟进分析之
00408931   .8B45 AC       mov   eax, dword ptr
00408934   .50            push    eax
00408935   .8D45 A4       lea   eax, dword ptr
00408938   .BA AC934000   mov   edx, 004093AC                  ;ASCII "55556666"
0040893D   .B9 FF000000   mov   ecx, 0FF
00408942   .E8 11AFFFFF   call    00403858
00408947   .8B55 A4       mov   edx, dword ptr
0040894A   .58            pop   eax
0040894B   .E8 80B0FFFF   call    004039D0                         ;真假注册码比较函数
00408950   .75 17         jnz   short 00408969
00408952   .6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00408954   .68 DC8A4000   push    00408ADC                         ; |Title = ""D7,"",A2,"",B2,"崽崾?
00408959   .68 188B4000   push    00408B18                         ; |Text = "恭?,B2,"您?,AC,"",D7,"",A2,"",B2,"崧胝?",B7,"?,A1,""
0040895E   .8B45 08       mov   eax, dword ptr          ; |
00408961   .50            push    eax                              ; |hOwner
00408962   .E8 0DBEFFFF   call    <jmp.&user32.MessageBoxA>      ; \MessageBoxA
......

F7跟进40892C后,来到下面一段,下面要过两次子函数调用,省略了一些准备过程代码见下面的代码:
......
0040869A   .8BD3          mov   edx, ebx
0040869C   .E8 03FBFFFF   call    004081A4                         ;注册算法子函数,F7跟进
004086A1   .8B55 F8       mov   edx, dword ptr
004086A4   .8B45 F4       mov   eax, dword ptr
004086A7   .E8 8CCEFFFF   call    00405538                         ;对真注册码进行检查计算F7跟进(见最下面)
004086AC   .8BD6          mov   edx, esi

......

004081C0|.8BCE          mov   ecx, esi
004081C2|.8BD3          mov   edx, ebx
004081C4|.E8 23FFFFFF   call    004080EC                        ;第二个子函数F7跟进
......

00408114|.8BC7          mov   eax, edi
00408116|.E8 F9FEFFFF   call    00408014                        ;Adler32算法核心F7跟进
........

00408014/$53            PUSH EBX
00408015|.56            PUSH ESI
00408016|.50            PUSH EAX
00408017|.31DB          XOR EBX,EBX                              ;置s2=0;
00408019|.66:8B58 02    MOV BX,WORD PTR DS:
0040801D|.8120 FFFF0000 AND DWORD PTR DS:,0FFFF             ;adler & 0xffff;
00408023|.8B00          MOV EAX,DWORD PTR DS:               ;置adler初值1,s1中间结果存在EAX
00408025|.89D6          MOV ESI,EDX
00408027|.09C9          OR ECX,ECX
00408029|.74 25         JE SHORT Adler32C.00408050
0040802B|>0FB616      /MOVZX EDX,BYTE PTR DS:
0040802E|.01D0          |ADD EAX,EDX
00408030|.3D F1FF0000   |CMP EAX,0FFF1                            ;65521=0x0fff1
00408035|.7C 05         |JL SHORT Adler32C.0040803C
00408037|.2D F1FF0000   |SUB EAX,0FFF1
0040803C|>01C3          |ADD EBX,EAX
0040803E|.81FB F1FF0000 |CMP EBX,0FFF1
00408044|.7C 06         |JL SHORT Adler32C.0040804C
00408046|.81EB F1FF0000 |SUB EBX,0FFF1
0040804C|>46            |INC ESI
0040804D|.49            |DEC ECX
0040804E|.^ 75 DB         \JNZ SHORT Adler32C.0040802B
00408050|>C1E3 10       SHL EBX,10                              ;(s2 << 16)
00408053|.01C3          ADD EBX,EAX                               ;+ s1
00408055|.58            POP EAX
00408056|.8918          MOV DWORD PTR DS:,EBX
00408058|.5E            POP ESI
00408059|.5B            POP EBX
0040805A\.C3            RETN
......

00405538/$53            push    ebx
00405539|.56            push    esi
0040553A|.57            push    edi
0040553B|.8BFA          mov   edi, edx
0040553D|.8BF0          mov   esi, eax
0040553F|.8BC6          mov   eax, esi
00405541|.E8 3EE3FFFF   call    00403884                        ;计算真注册码长度
00405546|.8BD8          mov   ebx, eax
00405548|.8BC7          mov   eax, edi
0040554A|.8BD3          mov   edx, ebx
0040554C|.E8 7FE5FFFF   call    00403AD0
00405551|.8BD6          mov   edx, esi
00405553|.8B37          mov   esi, dword ptr
00405555|.85DB          test    ebx, ebx
00405557|.74 15         je      short 0040556E
00405559|>8A02          /mov   al, byte ptr              ;比较注册码每个字节,若大于0x61小于0x7A,则减0x20
0040555B|.3C 61         |cmp   al, 61
0040555D|.72 06         |jb      short 00405565
0040555F|.3C 7A         |cmp   al, 7A
00405561|.77 02         |ja      short 00405565
00405563|.2C 20         |sub   al, 20
00405565|>8806          |mov   byte ptr , al
00405567|.42            |inc   edx
00405568|.46            |inc   esi
00405569|.4B            |dec   ebx
0040556A|.85DB          |test    ebx, ebx
0040556C|.^ 75 EB         \jnz   short 00405559
0040556E|>5F            pop   edi
0040556F|.5E            pop   esi
00405570|.5B            pop   ebx
00405571\.C3            retn
.....
   
核心算法汇编代码大概对应如下的C代码:
#define BASE 65521
unsigned long update_adler32(unsigned long adler,
         unsigned char *buf, int len)
      {
          unsigned long s1 = adler & 0xffff;
          unsigned long s2 = (adler >> 16) & 0xffff;
          int n;

          for (n = 0; n < len; n++) {
            s1 = (s1 + buf) % BASE;
            s2 = (s2 + s1)   % BASE;
          }
          return (s2 << 16) + s1;
      }
   
注册算法分析出来,下面写出注册代码,这一块我的基础比较差,写的不完善,算是抛砖引玉吧

#include <stdio.h>
#include <string>

#define BASE 65521 /* largest prime smaller than 65536 */

unsigned long update_adler32(unsigned long adler,unsigned char *buf, int len)
{
    unsigned long s1 = adler & 0xffff;
    unsigned long s2 = (adler >> 16) & 0xffff;
    int n;

    for (n = 0; n < len; n++) {
      s1 = (s1 + buf) % BASE;
      s2 = (s2 + s1)   % BASE;
    }
    return (s2 << 16) + s1;
}

unsigned long adler32(unsigned char *buf, int len)
{
    return update_adler32(1L, buf, len);
}

void main()
{
    unsigned long Tmp=0;
    int len;
    unsigned char *str;
    str = (unsigned char *) malloc(512);
      
    printf("请输入用户名:");
    scanf("%s",str);
   
          len=strlen((const char*)str);
   
    Tmp=adler32(str,len);
    printf("\n注册码:%p \n",Tmp);

}

--------------------------------------------------------------------------------
【经验总结】 最好先了解算法原理,再跟踪,这样难度就小多了。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2008年02月21日 下午 01:51:01

[ 本帖最后由 whypro 于 2010-4-25 14:28 编辑 ]

whypro 发表于 2010-4-23 06:21:42

CRC32算法 ==>CRC32CrackMe:

CRC(CyclicRedundancyCheck,直译:循环冗余校验)技术是一项很成熟的技术,在众多领域有广泛的应用,在数据存储和通信传输应用中处处都可以看到它的身影。最常用的CRC校验形式有CRC-16,CRC-32两种形式,采用CRC-16校验,可以保证在1014 位码元中只含有一位未被检测出的错误,采用CRC-32校验的出错概率比CRC-16还低105 倍。CRC的主要特点就是:检错能力极强,开销很小,易于实现。从性能和开销上综合考虑,其远远优于奇偶校验及算术和校验等方式。因此,很多软件在加密保护时都将CRC技术应用其中。

--------------------------------------------------------------------------------

【注册验证部分代码】

00401282   .68 00010000   PUSH 100                                 ; /Count = 100 (256.)
00401287   .51            PUSH ECX                                 ; |Buffer
00401288   .68 E8030000   PUSH 3E8                                 ; |ControlID = 3E8 (1000.)
0040128D   .56            PUSH ESI                                 ; |hWnd
0040128E   .FFD3          CALL EBX                                 ; \GetDlgItemTextA
00401290   .8DBC24 0C0100>LEA EDI,DWORD PTR SS:             ;用户名地址送EDI(根据字符串参考在这里下断)00401297   .83C9 FF       OR ECX,FFFFFFFF
0040129A   .33C0          XOR EAX,EAX
0040129C   .F2:AE         REPNE SCAS BYTE PTR ES:
0040129E   .F7D1          NOT ECX
004012A0   .49            DEC ECX
004012A1   .83F9 01       CMP ECX,1                                  ;用户名位数与1比较
004012A4   .73 1F         JNB SHORT CRC32Cra.004012C5                ;大于等于1则跳
004012A6   .6A 40         PUSH 40                                    ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004012A8   .68 8C604000   PUSH CRC32Cra.0040608C                     ; |注册提示
004012AD   .68 74604000   PUSH CRC32Cra.00406074                     ; |用户名不能为空请输入!
004012B2   .56            PUSH ESI                                 ; |hOwner
004012B3   .FF15 A8504000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>]; \MessageBoxA
004012B9   .5F            POP EDI
004012BA   .5E            POP ESI
004012BB   .33C0          XOR EAX,EAX
004012BD   .5B            POP EBX
004012BE   .81C4 00030000 ADD ESP,300
004012C4   .C3            RET
004012C5   >8D5424 0C   LEA EDX,DWORD PTR SS:
004012C9   .68 00010000   PUSH 100
004012CE   .52            PUSH EDX
004012CF   .68 07040000   PUSH 407
004012D4   .56            PUSH ESI
004012D5   .FFD3          CALL EBX
004012D7   .8D7C24 0C   LEA EDI,DWORD PTR SS:               ;试验码地址送EDI
004012DB   .83C9 FF       OR ECX,FFFFFFFF
004012DE   .33C0          XOR EAX,EAX
004012E0   .F2:AE         REPNE SCAS BYTE PTR ES:
004012E2   .F7D1          NOT ECX
004012E4   .49            DEC ECX
004012E5   .83F9 01       CMP ECX,1                                  ;试验码位数与1比较
004012E8   .73 1F         JNB SHORT CRC32Cra.00401309                ;大于等于1则跳
004012EA   .6A 40         PUSH 40                                    ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004012EC   .68 8C604000   PUSH CRC32Cra.0040608C                     ; |注册提示
004012F1   .68 5C604000   PUSH CRC32Cra.0040605C                     ; |注册码不能为空请输入!
004012F6   .56            PUSH ESI                                 ; |hOwner
004012F7   .FF15 A8504000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>]; \MessageBoxA
004012FD   .5F            POP EDI
004012FE   .5E            POP ESI
004012FF   .33C0          XOR EAX,EAX
00401301   .5B            POP EBX
00401302   .81C4 00030000 ADD ESP,300
00401308   .C3            RET
00401309   >8D8424 0C0200>LEA EAX,DWORD PTR SS:
00401310   .8D8C24 0C0100>LEA ECX,DWORD PTR SS:             ;用户名地址
00401317   .50            PUSH EAX
00401318   .51            PUSH ECX
00401319   .E8 F2FDFFFF   CALL CRC32Cra.00401110                     ;算法Call,F7跟进去
0040131E   .8D9424 140200>LEA EDX,DWORD PTR SS:             ;算法Call计算得到的值
00401325   .8D4424 14   LEA EAX,DWORD PTR SS:            ;试验码
00401329   .52            PUSH EDX                                 ;注册码地址入栈
0040132A   .50            PUSH EAX                                 ;试验码地址入栈
0040132B   .E8 D0FCFFFF   CALL CRC32Cra.00401000                     ;比较真假注册码Call,F7跟进00401330   .83C4 10       ADD ESP,10
00401333   .83F8 01       CMP EAX,1                                  ;EAX=0与0比较
00401336   .6A 40         PUSH 40                                    ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401338   .68 8C604000   PUSH CRC32Cra.0040608C                     ; |注册提示
0040133D   .75 18         JNZ SHORT CRC32Cra.00401357                ; |不相等则跳向死亡(关健跳)
0040133F   .68 48604000   PUSH CRC32Cra.00406048                     ; |恭喜你,注册码正确!
00401344   .56            PUSH ESI                                 ; |hOwner
00401345   .FF15 A8504000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>]; \MessageBoxA
0040134B   .5F            POP EDI
0040134C   .5E            POP ESI
0040134D   .33C0          XOR EAX,EAX
0040134F   .5B            POP EBX
00401350   .81C4 00030000 ADD ESP,300
00401356   .C3            RET
00401357   >68 30604000   PUSH CRC32Cra.00406030                     ; |注册码错误,继续加油!
0040135C   .56            PUSH ESI                                 ; |hOwner
0040135D   .FF15 A8504000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>]; \MessageBoxA
00401363   .5F            POP EDI
00401364   .5E            POP ESI
00401365   .33C0          XOR EAX,EAX
00401367   .5B            POP EBX
00401368   .81C4 00030000 ADD ESP,300
0040136E   .C3            RET

【算法Call代码】
00401110/$83EC 0C       SUB ESP,0C                                 ;来到这里
00401113|.56            PUSH ESI
00401114|.57            PUSH EDI
00401115|.E8 B6FFFFFF   CALL CRC32Cra.004010D0                     ;动态生成码表Call,F7跟进0040111A|.8B7424 18   MOV ESI,DWORD PTR SS:            ;取用户名地址送ESI
0040111E|.83C9 FF       OR ECX,FFFFFFFF
00401121|.8BFE          MOV EDI,ESI
00401123|.33C0          XOR EAX,EAX
00401125|.83CA FF       OR EDX,FFFFFFFF
00401128|.F2:AE         REPNE SCAS BYTE PTR ES:
0040112A|.F7D1          NOT ECX
0040112C|.49            DEC ECX
0040112D|.85C9          TEST ECX,ECX                               ;测试用户名位数
0040112F|.7E 1F         JLE SHORT CRC32Cra.00401150                ;为0则跳
00401131|.53            PUSH EBX
00401132|>8BC2          /MOV EAX,EDX                               ;以下循环将进行一系列运算后根据EAX值取上面计算出码表中数据
00401134|.33DB          |XOR EBX,EBX
00401136|.8A1E          |MOV BL,BYTE PTR DS:                  ;依次取用户名
00401138|.25 FF000000   |AND EAX,0FF
0040113D|.33C3          |XOR EAX,EBX
0040113F|.C1EA 08       |SHR EDX,8
00401142|.8B0485 208540>|MOV EAX,DWORD PTR DS:       ;根据EAX的值取动态码表数组中的数据
00401149|.33D0          |XOR EDX,EAX                               ;EDX最后得到一个数值
0040114B|.46            |INC ESI
0040114C|.49            |DEC ECX
0040114D|.^ 75 E3         \JNZ SHORT CRC32Cra.00401132
0040114F|.5B            POP EBX
00401150|>33C9          XOR ECX,ECX
00401152|.8D4424 08   LEA EAX,DWORD PTR SS:
00401156|.894C24 09   MOV DWORD PTR SS:,ECX
0040115A|.6A 10         PUSH 10
0040115C|.F7D2          NOT EDX                                    ;这里对EDX取反
0040115E|.894C24 11   MOV DWORD PTR SS:,ECX
00401162|.50            PUSH EAX
00401163|.52            PUSH EDX
00401164|.C64424 14 00MOV BYTE PTR SS:,0
00401169|.884C24 1D   MOV BYTE PTR SS:,CL
0040116D|.E8 24380000   CALL CRC32Cra.00404996                  
00401172|.8D7C24 14   LEA EDI,DWORD PTR SS:
00401176|.83C9 FF       OR ECX,FFFFFFFF
00401179|.33C0          XOR EAX,EAX
0040117B|.83C4 0C       ADD ESP,0C
0040117E|.33F6          XOR ESI,ESI
00401180|.F2:AE         REPNE SCAS BYTE PTR ES:
00401182|.F7D1          NOT ECX
00401184|.49            DEC ECX                                    ;得到注册码个数
00401185|.74 25         JE SHORT CRC32Cra.004011AC               ;等于0则跳
00401187|>0FBE4C34 08   /MOVSX ECX,BYTE PTR SS:
0040118C|.51            |PUSH ECX
0040118D|.E8 4E020000   |CALL CRC32Cra.004013E0
00401192|.884434 0C   |MOV BYTE PTR SS:,AL
00401196|.83C4 04       |ADD ESP,4
00401199|.8D7C24 08   |LEA EDI,DWORD PTR SS:
0040119D|.83C9 FF       |OR ECX,FFFFFFFF
004011A0|.33C0          |XOR EAX,EAX
004011A2|.46            |INC ESI
004011A3|.F2:AE         |REPNE SCAS BYTE PTR ES:
004011A5|.F7D1          |NOT ECX
004011A7|.49            |DEC ECX
004011A8|.3BF1          |CMP ESI,ECX
004011AA|.^ 72 DB         \JB SHORT CRC32Cra.00401187                ;以上循环用于将注册码中小写字母转换为大写字母
004011AC|>8B4424 1C   MOV EAX,DWORD PTR SS:
004011B0|.8D5424 08   LEA EDX,DWORD PTR SS:
004011B4|.52            PUSH EDX                                 ; /String2
004011B5|.50            PUSH EAX                                 ; |String1
004011B6|.FF15 00504000 CALL DWORD PTR DS:[<&KERNEL32.lstrcpyA>]   ; \lstrcpyA
004011BC|.5F            POP EDI
004011BD|.5E            POP ESI
004011BE|.83C4 0C       ADD ESP,0C
004011C1\.C3            RET                                        ;这里结束

【动态生成码表Call】

004010D0/$56            PUSH ESI                                 ;这里开始
004010D1|.33D2          XOR EDX,EDX
004010D3|.B9 20854000   MOV ECX,CRC32Cra.00408520                  ;指向00408520内存地址(相当于指向一定义数组)
004010D8|>8BC2          /MOV EAX,EDX
004010DA|.BE 08000000   |MOV ESI,8                                 ;定义小循环次数
004010DF|>A8 01         |/TEST AL,1                              ;测试AL是否为奇数
004010E1|.74 09         ||JE SHORT CRC32Cra.004010EC               ;不是则跳
004010E3|.D1E8          ||SHR EAX,1                              ;右移1位
004010E5|.35 2083B8ED   ||XOR EAX,EDB88320                         ;与固定值EDB88320异或
004010EA|.EB 02         ||JMP SHORT CRC32Cra.004010EE
004010EC|>D1E8          ||SHR EAX,1                              ;右移1位
004010EE|>4E            ||DEC ESI
004010EF|.^ 75 EE         |\JNZ SHORT CRC32Cra.004010DF
004010F1|.8901          |MOV DWORD PTR DS:,EAX                ;将EAX值送入指定内存(数组)中
004010F3|.83C1 04       |ADD ECX,4                                 ;指向下一个数组单元地址
004010F6|.42            |INC EDX                                 ;EDX加1
004010F7|.81F9 20894000 |CMP ECX,CRC32Cra.00408920               ;与数组末地址比较(根据数组起始地址推算,该大循环次数为256次)
004010FD|.^ 7C D9         \JL SHORT CRC32Cra.004010D8                ;小于则跳
004010FF|.5E            POP ESI
00401100\.C3            RET                                        ;这里结束

【比较真假注册码Call】
00401000/$81EC 00020000 SUB ESP,200                              ;这里开始
00401006|.56            PUSH ESI
00401007|.57            PUSH EDI
00401008|.B9 3F000000   MOV ECX,3F
0040100D|.33C0          XOR EAX,EAX
0040100F|.8D7C24 09   LEA EDI,DWORD PTR SS:
00401013|.C64424 08 00MOV BYTE PTR SS:,0
00401018|.F3:AB         REP STOS DWORD PTR ES:
0040101A|.66:AB         STOS WORD PTR ES:
0040101C|.AA            STOS BYTE PTR ES:
0040101D|.B9 3F000000   MOV ECX,3F
00401022|.33C0          XOR EAX,EAX
00401024|.8DBC24 090100>LEA EDI,DWORD PTR SS:
0040102B|.C68424 080100>MOV BYTE PTR SS:,0
00401033|.F3:AB         REP STOS DWORD PTR ES:
00401035|.66:AB         STOS WORD PTR ES:
00401037|.8B35 00504000 MOV ESI,DWORD PTR DS:[<&KERNEL32.lstrcpyA>>;kernel32.lstrcpyA
0040103D|.8D4C24 08   LEA ECX,DWORD PTR SS:
00401041|.AA            STOS BYTE PTR ES:
00401042|.8B8424 0C0200>MOV EAX,DWORD PTR SS:
00401049|.50            PUSH EAX                                 ; /String2
0040104A|.51            PUSH ECX                                 ; |String1
0040104B|.FFD6          CALL ESI                                 ; \lstrcpyA
0040104D|.8B9424 100200>MOV EDX,DWORD PTR SS:
00401054|.8D8424 080100>LEA EAX,DWORD PTR SS:
0040105B|.52            PUSH EDX                                 ; /String2
0040105C|.50            PUSH EAX                                 ; |String1
0040105D|.FFD6          CALL ESI                                 ; \lstrcpyA
0040105F|.8DBC24 080100>LEA EDI,DWORD PTR SS:
00401066|.83C9 FF       OR ECX,FFFFFFFF
00401069|.33C0          XOR EAX,EAX
0040106B|.F2:AE         REPNE SCAS BYTE PTR ES:
0040106D|.F7D1          NOT ECX
0040106F|.49            DEC ECX                                    ;注册码位数(8位)
00401070|.8D7C24 08   LEA EDI,DWORD PTR SS:
00401074|.8BD1          MOV EDX,ECX                              ;注册码位数送EDX(EDX=8)
00401076|.83C9 FF       OR ECX,FFFFFFFF
00401079|.F2:AE         REPNE SCAS BYTE PTR ES:
0040107B|.F7D1          NOT ECX
0040107D|.49            DEC ECX
0040107E|.3BCA          CMP ECX,EDX                              ;试验码位数与注册码位数进行比较
00401080|.75 40         JNZ SHORT CRC32Cra.004010C2                ;不相等则跳
00401082|.8D7C24 08   LEA EDI,DWORD PTR SS:
00401086|.83C9 FF       OR ECX,FFFFFFFF
00401089|.33D2          XOR EDX,EDX
0040108B|.F2:AE         REPNE SCAS BYTE PTR ES:
0040108D|.F7D1          NOT ECX
0040108F|.49            DEC ECX
00401090|.74 22         JE SHORT CRC32Cra.004010B4
00401092|>8A4414 08   /MOV AL,BYTE PTR SS:
00401096|.8A8C14 080100>|MOV CL,BYTE PTR SS:
0040109D|.3AC1          |CMP AL,CL
0040109F|.75 21         |JNZ SHORT CRC32Cra.004010C2
004010A1|.8D7C24 08   |LEA EDI,DWORD PTR SS:
004010A5|.83C9 FF       |OR ECX,FFFFFFFF
004010A8|.33C0          |XOR EAX,EAX
004010AA|.42            |INC EDX
004010AB|.F2:AE         |REPNE SCAS BYTE PTR ES:
004010AD|.F7D1          |NOT ECX
004010AF|.49            |DEC ECX
004010B0|.3BD1          |CMP EDX,ECX
004010B2|.^ 72 DE         \JB SHORT CRC32Cra.00401092                ;以上循环用于试验码与注册码比较
004010B4|>5F            POP EDI
004010B5|.B8 01000000   MOV EAX,1
004010BA|.5E            POP ESI
004010BB|.81C4 00020000 ADD ESP,200
004010C1|.C3            RET
004010C2|>5F            POP EDI
004010C3|.33C0          XOR EAX,EAX
004010C5|.5E            POP ESI
004010C6|.81C4 00020000 ADD ESP,200
004010CC\.C3            RET                                        ;这里结束



--------------------------------------------------------------------------------

C语言注册机如下:(注:该注册机得出的注册码值中字母都是小写的,在实际中应全部为大写,数字则保持不变)
以下C语言代码在VC6.0编译器下调试通过

#include "stdio.h"
#include "string.h"

//自定义函数//

//向table写入码表值
void fun2(unsigned long int *bp1);


//根据用户名计算具体数值后查码表得到注册码
unsigned long int fun1(char nam,unsigned long int *bp1);

//主函数
void main()
{

unsigned long int a;
char name;//用户名
    unsigned long int table={0};//动态生成的数组码表
unsigned long int *p;
p=table;//指针指向动态码表table
printf("请输入用户名: ");
gets(name);
fun2(p);//调用fun2函数向table数组码表写入数据
a=fun1(name,p);//调用fun1函数得到注册码
    printf("\n");
printf("你的注册码是: ");

    printf("%x",a);
printf("\n");
}

//调用自定义函数

//向table写入码表值:该函数对应动态生成码表Call
void fun2(unsigned long int *bp1)
{
unsigned long int a,c,d,si;
unsigned long int *p;
p=bp1;

d=0;

for(c=0;c<256;c++)

{
    a=d;
    si=0x8;
    for(si=0x8;si!=0;si--)
    {
      if(a%2==1)
      {
      a=a>>0x1;
      a=a^0xedb88320;
      }
      else
      {
      a=a>>0x1;
      }
    }
    *(p+c)=a;
    d=d+1;
}
}

//根据用户名计算具体数值后查上述码表得到注册码:该函数对应算法Call代码中蓝色小循环代码
unsigned long int fun1(char nam,unsigned long int *bp1)

{
unsigned long int a,b,d;
int m,i;
unsigned long int *p;
p=bp1;
m=strlen(nam);
d=0xffffffff;
for(i=0;i<m;i++)
{
      a=d;
      b=0;
      b=nam;
      a=a&0xff;
      a=a^b;
      d=d>>0x8;
      a=*(p+a);
      d=d^a;
}
d=~d;
return d;
}

给出一个注册码:
用户名:tgfy
注册码:92FF30CB

作者:天高飞扬(转自看雪)

tianxj 发表于 2010-4-23 07:22:46

好像很久了,以前玩过其中的几个

whypro 发表于 2010-4-24 20:49:16

BASE64算法 ==>Base64CrackMe.rar

Base64算法将输入的字符串或一段数据编码成只含有{''A''-''Z'', ''a''-''z'', ''0''-''9'', ''+'', ''/''}这64个字符的串,''=''用于填充。其编码的方法是,将输入数据流每次取6 bit,用此6 bit的值(0-63)作为索引去查表,输出相应字符。这样,每3个字节将编码为4个字符(3×8 → 4×6);不满4个字符的以''=''填充。


00412AC2   > \68 FF000000   push    0FF                              ; /Count = FF (255.); Case 3EA of switch 00412AA8
00412AC7   .68 F0334100   push    004133F0                         ; |Buffer = 复件_Bas.004133F0
00412ACC   .68 F2030000   push    3F2                              ; |ControlID = 3F2 (1010.)
00412AD1   .8B45 08       mov   eax, dword ptr          ; |
00412AD4   .50            push    eax                              ; |hWnd
00412AD5   .E8 AE2CFFFF   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA
00412ADA   .8D45 B4       lea   eax, dword ptr
00412ADD   .BA F0334100   mov   edx, 004133F0                  ;ASCII "whypro"
00412AE2   .B9 FF000000   mov   ecx, 0FF
00412AE7   .E8 9810FFFF   call    00403B84
00412AEC   .837D B4 00    cmp   dword ptr , 0
00412AF0   .75 1C         jnz   short 00412B0E
00412AF2   .6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00412AF4   .68 282D4100   push    00412D28                         ; |注册提示
00412AF9   .68 342D4100   push    00412D34                         ; |用户名不能为空请输入!
00412AFE   .8B45 08       mov   eax, dword ptr          ; |
00412B01   .50            push    eax                              ; |hOwner
00412B02   .E8 B92CFFFF   call    <jmp.&user32.MessageBoxA>      ; \MessageBoxA
00412B07   .33DB          xor   ebx, ebx
00412B09   .E9 A2010000   jmp   00412CB0
00412B0E   >68 FF000000   push    0FF                              ; /Count = FF (255.)
00412B13   .68 F0344100   push    004134F0                         ; |Buffer = 复件_Bas.004134F0
00412B18   .68 F3030000   push    3F3                              ; |ControlID = 3F3 (1011.)
00412B1D   .8B45 08       mov   eax, dword ptr          ; |
00412B20   .50            push    eax                              ; |hWnd
00412B21   .E8 622CFFFF   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA
00412B26   .8D45 B0       lea   eax, dword ptr
00412B29   .BA F0344100   mov   edx, 004134F0                  ;ASCII "d2h5cHJv"
00412B2E   .B9 FF000000   mov   ecx, 0FF
00412B33   .E8 4C10FFFF   call    00403B84
00412B38   .837D B0 00    cmp   dword ptr , 0
00412B3C   .75 1C         jnz   short 00412B5A
00412B3E   .6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00412B40   .68 282D4100   push    00412D28                         ; |注册提示
00412B45   .68 4C2D4100   push    00412D4C                         ; |注册码不能为空请输入!
00412B4A   .8B45 08       mov   eax, dword ptr          ; |
00412B4D   .50            push    eax                              ; |hOwner
00412B4E   .E8 6D2CFFFF   call    <jmp.&user32.MessageBoxA>      ; \MessageBoxA
00412B53   .33DB          xor   ebx, ebx
00412B55   .E9 56010000   jmp   00412CB0
00412B5A   >33C0          xor   eax, eax
00412B5C   .55            push    ebp
00412B5D   .68 DC2B4100   push    00412BDC
00412B62   .64:FF30       push    dword ptr fs:
00412B65   .64:8920       mov   dword ptr fs:, esp
00412B68   .8D45 AC       lea   eax, dword ptr
00412B6B   .BA F0334100   mov   edx, 004133F0                  ;ASCII "whypro"<--用户名
00412B70   .B9 FF000000   mov   ecx, 0FF
00412B75   .E8 0A10FFFF   call    00403B84                         ;关键点1<-拷贝用户名
00412B7A   .8B45 AC       mov   eax, dword ptr
00412B7D   .50            push    eax
00412B7E   .8D45 A4       lea   eax, dword ptr
00412B81   .BA F0344100   mov   edx, 004134F0                  ;ASCII "d2h5cHJv"<--密码
00412B86   .B9 FF000000   mov   ecx, 0FF
00412B8B   .E8 F40FFFFF   call    00403B84                         ;关键点2<-拷贝密码
00412B90   .8B45 A4       mov   eax, dword ptr
00412B93   .8D55 A8       lea   edx, dword ptr
00412B96   .E8 E5F8FFFF   call    00412480                         ;关键点3
00412B9B   .8B55 A8       mov   edx, dword ptr
00412B9E   .58            pop   eax
00412B9F   .E8 5811FFFF   call    00403CFC                         ;最后的比较
00412BA4   .75 17         jnz   short 00412BBD
00412BA6   .6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00412BA8   .68 282D4100   push    00412D28                         ; |注册提示
00412BAD   .68 642D4100   push    00412D64                         ; |恭喜您,注册码正确!
00412BB2   .8B45 08       mov   eax, dword ptr          ; |
00412BB5   .50            push    eax                              ; |hOwner
00412BB6   .E8 052CFFFF   call    <jmp.&user32.MessageBoxA>      ; \MessageBoxA
00412BBB   .EB 15         jmp   short 00412BD2
00412BBD   >6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00412BBF   .68 282D4100   push    00412D28                         ; |注册提示
00412BC4   .68 7C2D4100   push    00412D7C                         ; |注册码错误,继续加油!
00412BC9   .8B45 08       mov   eax, dword ptr          ; |
00412BCC   .50            push    eax                              ; |hOwner
00412BCD   .E8 EE2BFFFF   call    <jmp.&user32.MessageBoxA>      ; \MessageBoxA

00412BD2   >33C0          xor   eax, eax
00412BD4   .5A            pop   edx
00412BD5   .59            pop   ecx
00412BD6   .59            pop   ecx
00412BD7   .64:8910       mov   dword ptr fs:, edx
00412BDA   .EB 39         jmp   short 00412C15
00412BDC   .^ E9 2F06FFFF   jmp   00403210



call    00412480                         ;关键点3
00412480/$53            push    ebx
00412481|.56            push    esi
00412482|.57            push    edi
00412483|.51            push    ecx
00412484|.891424      mov   dword ptr , edx
00412487|.8BF8          mov   edi, eax
00412489|.B2 01         mov   dl, 1
0041248B|.A1 70F44000   mov   eax, dword ptr ;TMemoryStream 的使用
00412490|.E8 9B09FFFF   call    00402E30
00412495|.8BF0          mov   esi, eax
00412497|.B2 01         mov   dl, 1
00412499|.A1 70F44000   mov   eax, dword ptr ;TMemoryStream 的使用
0041249E|.E8 8D09FFFF   call    00402E30
004124A3|.8BD8          mov   ebx, eax
004124A5|.8BC7          mov   eax, edi
004124A7|.E8 0417FFFF   call    00403BB0   ;返回密码多少位
004124AC|.50            push    eax
004124AD|.8BC7          mov   eax, edi
004124AF|.E8 EC18FFFF   call    00403DA0   ;是否有密码
004124B4|.8BD0          mov   edx, eax
004124B6|.8BC6          mov   eax, esi
004124B8|.59            pop   ecx
004124B9|.8B38          mov   edi, dword ptr
004124BB|.FF57 10       call    dword ptr                         ;数据移动
004124BE|.6A 00         push    0                              ; /Arg2 = 00000000
004124C0|.6A 00         push    0                              ; |Arg1 = 00000000
004124C2|.8BC6          mov   eax, esi                         ; |
004124C4|.E8 B7ECFFFF   call    00411180                         ; \复件_Bas.00411180
004124C9|.8BD3          mov   edx, ebx
004124CB|.8BC6          mov   eax, esi
004124CD|.E8 0AFEFFFF   call    004122DC                         ;核心算法
004124D2|.6A 00         push    0                              ; /Arg2 = 00000000
004124D4|.6A 00         push    0                              ; |Arg1 = 00000000
004124D6|.8BC3          mov   eax, ebx                         ; |
004124D8|.E8 A3ECFFFF   call    00411180                         ; \复件_Bas.00411180
004124DD|.8BC3          mov   eax, ebx
004124DF|.8B10          mov   edx, dword ptr
004124E1|.FF12          call    dword ptr
004124E3|.8BD0          mov   edx, eax
004124E5|.8B0424      mov   eax, dword ptr
004124E8|.E8 9319FFFF   call    00403E80
004124ED|.8BC3          mov   eax, ebx
004124EF|.8B10          mov   edx, dword ptr
004124F1|.FF12          call    dword ptr
004124F3|.50            push    eax
004124F4|.8B4424 04   mov   eax, dword ptr
004124F8|.E8 F318FFFF   call    00403DF0
004124FD|.8BD0          mov   edx, eax
004124FF|.8BC3          mov   eax, ebx
00412501|.59            pop   ecx
00412502|.8B38          mov   edi, dword ptr
00412504|.FF57 0C       call    dword ptr
00412507|.8BC6          mov   eax, esi
00412509|.E8 5209FFFF   call    00402E60
0041250E|.8BC3          mov   eax, ebx
00412510|.E8 4B09FFFF   call    00402E60
00412515|.5A            pop   edx
00412516|.5F            pop   edi
00412517|.5E            pop   esi
00412518|.5B            pop   ebx
00412519\.C3            retn
call    004122DC                         ;核心算法

004122DC/$53            push    ebx
004122DD|.56            push    esi
004122DE|.57            push    edi
004122DF|.81C4 58FFFFFF add   esp, -0A8
004122E5|.895424 04   mov   dword ptr , edx
004122E9|.890424      mov   dword ptr , eax
004122EC|.8D7424 0C   lea   esi, dword ptr
004122F0|>C64424 08 00/mov   byte ptr , 0
004122F5|.33DB          |xor   ebx, ebx
004122F7|.8BD6          |mov   edx, esi
004122F9|.B9 58000000   |mov   ecx, 58
004122FE|.8B0424      |mov   eax, dword ptr
00412301|.8B38          |mov   edi, dword ptr
00412303|.FF57 0C       |call    dword ptr
00412306|.884424 09   |mov   byte ptr , al
0041230A|.807C24 09 00|cmp   byte ptr , 0
0041230F|.0F84 3C010000 |je      00412451
00412315|.3A5C24 09   |cmp   bl, byte ptr
00412319|.0F83 10010000 |jnb   0041242F
0041231F|>33D2          |/xor   edx, edx                     ;字符在+与z之间
00412321|.8AD3          ||mov   dl, bl
00412323|.8A0416      ||mov   al, byte ptr
00412326|.3C 2B         ||cmp   al, 2B
00412328|.72 46         ||jb      short 00412370
0041232A|.3C 7A         ||cmp   al, 7A
0041232C|.77 42         ||ja      short 00412370
0041232E|.33C0          ||xor   eax, eax
00412330|.8AC3          ||mov   al, bl
00412332|.807C06 01 2B||cmp   byte ptr , 2B
00412337|.72 37         ||jb      short 00412370
00412339|.33C0          ||xor   eax, eax
0041233B|.8AC3          ||mov   al, bl
0041233D|.807C06 01 7A||cmp   byte ptr , 7A
00412342|.77 2C         ||ja      short 00412370
00412344|.33C0          ||xor   eax, eax
00412346|.8AC3          ||mov   al, bl
00412348|.807C06 02 2B||cmp   byte ptr , 2B
0041234D|.72 21         ||jb      short 00412370
0041234F|.33C0          ||xor   eax, eax
00412351|.8AC3          ||mov   al, bl
00412353|.807C06 02 7A||cmp   byte ptr , 7A
00412358|.77 16         ||ja      short 00412370
0041235A|.33C0          ||xor   eax, eax
0041235C|.8AC3          ||mov   al, bl
0041235E|.807C06 03 2B||cmp   byte ptr , 2B
00412363|.72 0B         ||jb      short 00412370
00412365|.33C0          ||xor   eax, eax
00412367|.8AC3          ||mov   al, bl
00412369|.807C06 03 7A||cmp   byte ptr , 7A
0041236E|.76 16         ||jbe   short 00412386
00412370|>B9 64244100   ||mov   ecx, 00412464                  ;invalid base64 character
00412375|.B2 01         ||mov   dl, 1
00412377|.A1 FC5B4000   ||mov   eax, dword ptr
0041237C|.E8 0F7AFFFF   ||call    00409D90
00412381|.E8 EE0FFFFF   ||call    00403374
00412386|>33C0          ||xor   eax, eax
00412388|.8A0416      ||mov   al, byte ptr
0041238B|.8A80 71334100 ||mov   al, byte ptr     ;密码表
00412391|.884424 0A   ||mov   byte ptr , al
00412395|.8BFB          ||mov   edi, ebx
00412397|.81E7 FF000000 ||and   edi, 0FF
0041239D|.33C0          ||xor   eax, eax
0041239F|.8A443E 01   ||mov   al, byte ptr
004123A3|.8A80 71334100 ||mov   al, byte ptr
004123A9|.33D2          ||xor   edx, edx
004123AB|.8A543E 02   ||mov   dl, byte ptr
004123AF|.8A92 71334100 ||mov   dl, byte ptr
004123B5|.885424 0B   ||mov   byte ptr , dl
004123B9|.8A5424 0A   ||mov   dl, byte ptr
004123BD|.C1E2 02       ||shl   edx, 2
004123C0|.33C9          ||xor   ecx, ecx
004123C2|.8AC8          ||mov   cl, al
004123C4|.C1E9 04       ||shr   ecx, 4
004123C7|.0AD1          ||or      dl, cl
004123C9|.33C9          ||xor   ecx, ecx
004123CB|.8A4C24 08   ||mov   cl, byte ptr       密码d2h5cHJv
004123CF|.88540C 64   ||mov   byte ptr , dl<- 算出第一位存起来,
      

{(ascii(d)=64->1D(查表)/4=74)or(ascii(2)=32->36(查表)/12=03)}=77->w



004123D3|.FE4424 08   ||inc   byte ptr
004123D7|.807C3E 02 3D||cmp   byte ptr , 3D       ;= 判断是否结束
004123DC|.74 44         ||je      short 00412422
004123DE|.C1E0 04       ||shl   eax, 4
004123E1|.33D2          ||xor   edx, edx
004123E3|.8A5424 0B   ||mov   dl, byte ptr
004123E7|.C1EA 02       ||shr   edx, 2
004123EA|.0AC2          ||or      al, dl
004123EC|.33D2          ||xor   edx, edx
004123EE|.8A5424 08   ||mov   dl, byte ptr
004123F2|.884414 64   ||mov   byte ptr , al      
004123F6|.FE4424 08   ||inc   byte ptr
004123FA|.807C3E 03 3D||cmp   byte ptr , 3D       ;=判断是否结束
004123FF|.74 21         ||je      short 00412422
00412401|.8A4424 0B   ||mov   al, byte ptr
00412405|.C1E0 06       ||shl   eax, 6
00412408|.33D2          ||xor   edx, edx
0041240A|.8A543E 03   ||mov   dl, byte ptr
0041240E|.0A82 71334100 ||or      al, byte ptr
00412414|.33D2          ||xor   edx, edx
00412416|.8A5424 08   ||mov   dl, byte ptr
0041241A|.884414 64   ||mov   byte ptr , al
0041241E|.FE4424 08   ||inc   byte ptr
00412422|>80C3 04       ||add   bl, 4
00412425|.3A5C24 09   ||cmp   bl, byte ptr
00412429|.^ 0F82 F0FEFFFF |\jb      0041231F
0041242F|>33C9          |xor   ecx, ecx
00412431|.8A4C24 08   |mov   cl, byte ptr
00412435|.8D5424 64   |lea   edx, dword ptr
00412439|.8B4424 04   |mov   eax, dword ptr
0041243D|.8B18          |mov   ebx, dword ptr
0041243F|.FF53 10       |call    dword ptr
00412442|.33C0          |xor   eax, eax
00412444|.8A4424 09   |mov   al, byte ptr
00412448|.83F8 58       |cmp   eax, 58
0041244B|.^ 0F83 9FFEFFFF \jnb   004122F0
00412451|>81C4 A8000000 add   esp, 0A8
00412457|.5F            pop   edi
00412458|.5E            pop   esi
00412459|.5B            pop   ebx
0041245A\.C3            retn

这个是密码表:[注册码第n位+413371]
00413365                                    E3 40 00 F4
00413375E3 40 00 00 01 00 01 00 01 01 00 00 01 01 00 00鉆........
0041338500 01 00 01 01 8B C0 DC EA 40 00 EC EA 40 00 FC..嬂荜@.礻@.
00413395EA 40 00 00 00 00 00 3E 7F 7F 7F 3F 34 35 36 37闌.....>?4567
004133A538 39 3A 3B 3C 3D 7F 7F 7F 7F 7F 7F 7F 00 01 0289:;<=.
004133B503 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12.. ..
004133C513 14 15 16 17 18 19 7F 7F 7F 7F 7F 7F 1A 1B 1C
004133D51D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C !"#$%&'()*+,
004133E52D 2E 2F 30 31 32 33 00 8D 40 00 77 68 79 70 72-./0123.岪.whypr
004133F56F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00o...............

算法源程序:

[ 本帖最后由 whypro 于 2010-4-25 10:32 编辑 ]

whypro 发表于 2010-4-24 21:11:20

RC2算法 ==>RC2CrackMe.rar
对称加密,是一种比较传统的加密方式,其加密运算、解密运算使用的是同样的密钥,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码(称为对称密码)。因此,通信双方都必须获得这把钥匙,并保持钥匙的秘密。
参考http://www.chem.leeds.ac.uk/ICAMS/people/jon/rc2.html

0041A554   .55            push    ebp
0041A555   .68 D9A54100   push    0041A5D9
0041A55A   .64:FF30       push    dword ptr fs:
0041A55D   .64:8920       mov   dword ptr fs:, esp
0041A560   .8D45 AC       lea   eax, dword ptr
0041A563   .BA 68B54100   mov   edx, 0041B568                  ;ASCII "why" <-用户名
0041A568   .B9 FF000000   mov   ecx, 0FF
0041A56D   .E8 2699FEFF   call    00403E98
0041A572   .8B45 AC       mov   eax, dword ptr
0041A575   .50            push    eax
0041A576   .8D45 A4       lea   eax, dword ptr
0041A579   .BA 68B64100   mov   edx, 0041B668                  ;ASCII "414243444546" <-密码
0041A57E   .B9 FF000000   mov   ecx, 0FF
0041A583   .E8 1099FEFF   call    00403E98
0041A588   .8B45 A4       mov   eax, dword ptr
0041A58B   .8D4D A8       lea   ecx, dword ptr
0041A58E   .BA 68A74100   mov   edx, 0041A768                  ;windrand
0041A593   .E8 6CF8FFFF   call    00419E04
0041A598   .8B55 A8       mov   edx, dword ptr
0041A59B   .58            pop   eax
0041A59C   .E8 939AFEFF   call    00404034                         <-关键点1
0041A5A1   .75 17         jnz   short 0041A5BA
0041A5A3   .6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0041A5A5   .68 24A74100   push    0041A724                         ; |注册提示
0041A5AA   .68 74A74100   push    0041A774                         ; |恭喜您,注册码正确!
0041A5AF   .8B45 08       mov   eax, dword ptr          ; |
0041A5B2   .50            push    eax                              ; |hOwner
0041A5B3   .E8 A0B5FEFF   call    <jmp.&user32.MessageBoxA>      ; \MessageBoxA
0041A5B8   .EB 15         jmp   short 0041A5CF

<-关键点1 代码如下:
00404034/$53            push ebx
00404035|.56            push esi
00404036|.57            push edi
00404037|.89C6          mov esi,eax   eax<---用户名
00404039|.89D7          mov edi,edxedx<----地址所存的密码
0040403B|.39D0          cmp eax,edx
0040403D|.0F84 8F000000 je 复件_RC2.004040D2
00404043|.85F6          test esi,esi
00404045|.74 68         je short 复件_RC2.004040AF
00404047|.85FF          test edi,edi
00404049|.74 6B         je short 复件_RC2.004040B6
0040404B|.8B46 FC       mov eax,dword ptr ds:   <---字符多少个
0040404E|.8B57 FC       mov edx,dword ptr ds:   <---字符多少个
00404051|.29D0          sub eax,edx
00404053|.77 02         ja short 复件_RC2.00404057
00404055|.01C2          add edx,eax
00404057|>52            push edx
00404058|.C1EA 02       shr edx,2
0040405B|.74 26         je short 复件_RC2.00404083
0040405D|>8B0E          /mov ecx,dword ptr ds:------------------------
0040405F|.8B1F          |mov ebx,dword ptr ds:                        |   <---循环比较注册码和用户名的ascii是否相等,eax=0,提示成功!
00404061|.39D9          |cmp ecx,ebx                                       |
00404063|.75 58         |jnz short 复件_RC2.004040BD                        |   
00404065|.4A            |dec edx                                           |
00404066|.74 15         |je short 复件_RC2.0040407D                         |
00404068|.8B4E 04       |mov ecx,dword ptr ds:                     |
0040406B|.8B5F 04       |mov ebx,dword ptr ds:                     |
0040406E|.39D9          |cmp ecx,ebx                                        |
00404070|.75 4B         |jnz short 复件_RC2.004040BD                         |
00404072|.83C6 08       |add esi,8                                          |
00404075|.83C7 08       |add edi,8                                          |
00404078|.4A            |dec edx                                           |
00404079|.^ 75 E2         \jnz short 复件_RC2.0040405D------------------------
0040407B|.EB 06         jmp short 复件_RC2.00404083
0040407D|>83C6 04       add esi,4
00404080|.83C7 04       add edi,4
00404083|>5A            pop edx
00404084|.83E2 03       and edx,3
00404087|.74 22         je short 复件_RC2.004040AB   跳
00404089|.8B0E          mov ecx,dword ptr ds:
0040408B|.8B1F          mov ebx,dword ptr ds:
0040408D|.38D9          cmp cl,bl
0040408F|.75 41         jnz short 复件_RC2.004040D2
00404091|.4A            dec edx
00404092|.74 17         je short 复件_RC2.004040AB
00404094|.38FD          cmp ch,bh
00404096|.75 3A         jnz short 复件_RC2.004040D2
00404098|.4A            dec edx
00404099|.74 10         je short 复件_RC2.004040AB
0040409B|.81E3 0000FF00 and ebx,0FF0000
004040A1|.81E1 0000FF00 and ecx,0FF0000
004040A7|.39D9          cmp ecx,ebx
004040A9|.75 27         jnz short 复件_RC2.004040D2
004040AB|>01C0          add eax,eax                     关键eax
004040AD|.EB 23         jmp short 复件_RC2.004040D2
004040AF|>8B57 FC       mov edx,dword ptr ds:
004040B2|.29D0          sub eax,edx
004040B4|.EB 1C         jmp short 复件_RC2.004040D2
004040B6|>8B46 FC       mov eax,dword ptr ds:
004040B9|.29D0          sub eax,edx
004040BB|.EB 15         jmp short 复件_RC2.004040D2
004040BD|>5A            pop edx
004040BE|.38D9          cmp cl,bl
004040C0|.75 10         jnz short 复件_RC2.004040D2
004040C2|.38FD          cmp ch,bh
004040C4|.75 0C         jnz short 复件_RC2.004040D2
004040C6|.C1E9 10       shr ecx,10
004040C9|.C1EB 10       shr ebx,10
004040CC|.38D9          cmp cl,bl
004040CE|.75 02         jnz short 复件_RC2.004040D2
004040D0|.38FD          cmp ch,bh
004040D2|>5F            pop edi            返回了
004040D3|.5E            pop esi
004040D4|.5B            pop ebx
004040D5\.C3            retn

RC2的源码:

[ 本帖最后由 whypro 于 2010-5-5 09:58 编辑 ]

whypro 发表于 2010-4-24 21:18:36

<wincrypt.h> 应用

Here is the basic steps to encrypt/decrypt data using Crypto APIs
这是一个使用微软Crypto APIs 加密解密数据的例子
http://www.vckbase.com/document/journal/vckbase27/images/Crypto2701.gif
Initiating the Cryptography Service Provider (CSP): CryptAcquireContext, CryptReleaseContext
The CryptAcquireContext function is used to obtain a handle to a particular key container within a particular CSP. This returned handle can then be used to make calls to the selected CSP.
【第一步】初始化CSP(专门提供加密等服务或者功能的一个构件或者服务):使用Crypto APIs :CryptAcquireContext, CryptReleaseContext

CryptAcquireContext 创建密钥容器,得到CSP句柄以备后面的函数调用。
At the end of encryption/decryption you can call the CryptReleaseContext function to release the handle returned from a call to CryptAcquireContext.
在结束加密解密使用后请调用CryptReleaseContext释放CSP句柄。

Hashing Data: CryptCreateHash, CryptHashData, CryptGetHashParam, and CryptDestroyHash
"hashing" or "hash," refers to the method or algorithm used to derive a numeric value from a piece of data. In our case we will derive a numeric value (Hash) from our password which will be used to encrypt/decrypt the data and then this Hash value will be used to generate session key which we will see in the next step.
【第二步】HASH算法的使用

BOOL WINAPI CryptCreateHash(
HCRYPTPROV hProv,        //CSP句柄
ALG_ID Algid,        //选择hash算法,比如CALG_MD5等
HCRYPTKEY hKey,        //HMAC 和MAC算法时有用
DWORD dwFlags,        //保留,传入0即可
HCRYPTHASH* phHash        //返回hash句柄
);

CryptDestroyHash(hHash);        //释放句柄

BOOL WINAPI CryptHashData(
HCRYPTHASH hHash,        //hash对象
BYTE* pbData,                //被hash的数据
DWORD dwDataLen,                //数据的长度
DWORD dwFlags                //微软的CSP这个值会被忽略
);

CryptGetHashParam(
   hHash,
   HP_HASHSIZE,         //取hash数据的大小
   pbHashSize,         //输出hash数据大小的缓冲区
   &dwHashLen,         //缓冲区大小
   0)



To get hash value from Password first create a hash object using CryptCreateHash then you can call CryptHashData to get hash value derived from your password.
CryptCreateHash API用来创建hash对象,然后再用CryptHashData来Hash数据,最后使用CryptGetHashParam来获取Hash的数据。

Generating Keys: CryptDeriveKey, CryptGenKey, CryptDestroyKey
These three functions are the ones used to generate handles to keys:
【第三步】
CryptDeriveKey(                           调用CryptDeriveKey获取对话密码
   hCryptProv,                              CSP句柄
   CALG_RC2,                               一个ALG_ID结构,用来指定对称密钥生成的算法
   hHash,                                    哈希对象
   CRYPT_EXPORTABLE,             指定生成密钥的类型,CRYPT_EXPORTABLE意味着这个程序生成的密钥可以被其它程序调用,而不是仅仅限于这个程序当中。(但是它不能用于非对称密码中)
   &hKey)

The CryptDeriveKey function is used to generate a key from a specified password. (指定类型密钥)

The CryptGenKey function is used to generate a key from random generated data. (随即密钥)

The CryptDestroyKey function is used to release the handle to the key object.

Encrypting and Decrypting Data: CryptEncrypt, CryptDecrypt
In this step you prepare Buffer for Plain text or Cipher text (Encrypted text) for CryptEncrypt/CryptDecrypt call and then you can call CryptEncrypt for encryption or CryptDecrypt for decryption.
【第四步】 你可以使用CryptEncrypt, CryptDecrypt这两个api来加密或解密你的数据了。
Cleanup : CryptDestroyKey, CryptDestroyHash, CryptReleaseContext
Once you are done with encryption/decryption you have to do cleanup of resources taken by Crypto Apis. Cleanup requires the following steps
- Destroy session key using CryptDestroyKey
- Destroy key exchange key handle using CryptDestroyKey
- Destroy hash object using CryptDestroyHash
- Release Context provider handle using CryptReleaseContext
【第五步】清除你所使用过的句柄。
密码算法参考http://msdn.microsoft.com/en-us/library/aa380252(v=VS.85).aspx

密码算法MD5 -> vc++版本

[ 本帖最后由 whypro 于 2010-5-6 15:24 编辑 ]

lgjxj 发表于 2010-4-24 22:01:04

兄弟太有毅力了,我完全搞不定

whypro 发表于 2010-4-25 14:28:51

前面学习了密钥容器的建立的一些知识,现在我们接下来自然是学习如何获取一个密钥,首先是获取一个session key,即对话密钥,是对称密钥。
这些学习笔记主要是从MSDN中的例子中,学习基本的Cryptography API的用法,了解一些用法的过程。欢迎大家多提宝贵意见。
下面依旧是从一个小程序开始。这个程序的学习任务有以下几个:
任务一:调用CryptAcquireContext,获取一个缺省CSP和缺省密钥容器的句柄
任务二:用CryptCreateHash去创建一个空的哈希对象
任务三:用CryptHashData.哈希密码
任务四:调用CryptDeriveKey获取一个对话密钥
任务五:销毁密码和哈希后的数据
任务六:释放CSP
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include <Wincrypt.h>

#define MY_ENCODING_TYPE(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(char *s);
void GetConsoleInput(char*, int);

void main()
{

HCRYPTPROV hCryptProv;                        定义CSP句柄
HCRYPTKEY hKey;                              定义密钥句柄
HCRYPTHASH hHash;                            定义一个HASH对象的句柄
CHAR szPassword = "";                     定义512大小的字符数组,用来保存密码
DWORD dwLength;                              保存密码长度
fprintf(stderr,"Enter a password to be used to create a key:");

GetConsoleInput(szPassword, 512);                  获取密码,这个是自己写的函数,目的是在屏幕上显示的是*。
printf("The password has been stored.\n");
dwLength = strlen(szPassword);


if(CryptAcquireContext(                   以下是获取一个缺省的PROV_RSA_FULLCSP 句柄
   &hCryptProv,
   NULL,
   NULL,
   PROV_RSA_FULL,
   0))
{
    printf("A context has been acquired. \n");
}
else
{
   MyHandleError("Error during CryptAcquireContext!");
}
//--------------------------------------------------------------------
if(CryptCreateHash(                                  调用CryptCreateHash创建一个HASH对象
   hCryptProv,                                     一个CSP句柄
   CALG_MD5,                                    确定哈希算法
   0,   对于非密钥算法,这个参数一定是0,如果是密钥算法,那么这个参数就是密钥
   0,                        保留参数,为0
   &hHash))                                        一个哈希对象的指针
{
    printf("An empty hash object has been created. \n");
}
else
{
    MyHandleError("Error during CryptCreateHash!");
}
//--------------------------------------------------------------------
if(CryptHashData(                                 调用CryptHashData哈希密码
   hHash,                                       哈希对象
   (BYTE *)szPassword,               指向缓冲区的地址
   dwLength,                                    密码长度
   0))
{
   printf("The password has been hashed. \n");
}
else
{
   MyHandleError("Error during CryptHashData!");
}
//--------------------------------------------------------------------
if(CryptDeriveKey(                           调用CryptDeriveKey获取对话密码
   hCryptProv,                              CSP句柄
   CALG_RC2,                               一个ALG_ID结构,用来指定对称密钥生成的算法
   hHash,                                    哈希对象
   CRYPT_EXPORTABLE,             指定生成密钥的类型,CRYPT_EXPORTABLE意味着这个程序生成的密钥可以被其它程序调用,而不是仅仅限于这个程序当中。但是它不能用于非对称密码中。
   &hKey))
{
    printf("The key has been derived. \n");
}
else
{
    MyHandleError("Error during CryptDeriveKey!");
}
if(hHash)                                           销毁哈希对象
{
   if(!(CryptDestroyHash(hHash)))
       MyHandleError("Error during CryptDestroyHash");
}

if(hKey)                                          销毁密钥句柄
{
    if(!(CryptDestroyKey(hKey)))
      MyHandleError("Error during CryptDestroyKey");
}

if(hCryptProv)                                       销毁CSP句柄
{
   if(!(CryptReleaseContext(hCryptProv, 0)))
       MyHandleError("Error during CryptReleaseContext");
}
printf("The program to derive a key completed without error. \n");
} // end main
void MyHandleError函数的实现省略,在上一篇中有
void GetConsoleInput(char* strInput,
         int   intMaxChars)
{
char ch;
char minChar = ' ';
minChar++;

ch = getch();
while (ch != '\r')
{
    if (ch == '\b' && strlen(strInput) > 0)
    {
      strInput   = '\0';
      printf("\b \b");
    }
    else if (ch >= minChar && strlen(strInput) < intMaxChars)
    {
      strInput = '\0';
      strInput   = ch;
      putch('*');
    }
    ch = getch();
}
putch('\n');
}

下面讲讲如何复制一个对话密钥,照例是从一个程序讲起,完成以下任务。获取一个CSP句柄,创建一个对话密钥,复制密钥。改变密钥生成过程,随机填充一个缓冲区,销毁密钥句柄,释放CSP句柄。
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(char *s);
void main()
{
//-------------------------------------------------------------------
// Declare and initialize variables.

HCRYPTPROV   hCryptProv;                         CSP句柄
HCRYPTKEY    hOriginalKey;               源密钥句柄
HCRYPTKEY    hDuplicateKey;               复制后的密钥句柄
DWORD      dwMode;                           
BYTE          pbData;

printf("This program creates a session key and duplicates \n");
printf("that key. Next, parameters are added to the original \n");
printf("key. Finally, both keys are destroyed. \n\n");

if(CryptAcquireContext(                            获取CSP句柄,前面叙述过了,这里就不叙述了
   &hCryptProv,
   NULL,
   NULL,
   PROV_RSA_FULL,
   0))
{   
    printf("CryptAcquireContext succeeded. \n");
}
else
{
    MyHandleError("Error during CryptAcquireContext!\n");
}
//-------------------------------------------------------------------
if (CryptGenKey(                                    生成一个CALG_RC4算法生成的密钥,保存在hOriginalKey中
   hCryptProv,
   CALG_RC4,                                    ALG_ID结构,指定生成这个密钥使用的算法
   0,
   &hOriginalKey))
{
   printf("Original session key is created. \n");
}
else
{
   MyHandleError("ERROR - CryptGenKey.");
}

if (CryptDuplicateKey(                              复制密钥
   hOriginalKey,                                  源密钥
   NULL,                                        保留参数,必须为NULL
   0,                                          保留参数,必须为0
   &hDuplicateKey))                               副本密钥
{
   printf("The session key has been duplicated. \n");
}
else
{
   MyHandleError("ERROR - CryptDuplicateKey");
}
给源密钥设置附加参数
dwMode = CRYPT_MODE_ECB;                        CRYPT_MODE_ECB是一个没有反馈的块加密模式
if(CryptSetKeyParam(
   hOriginalKey,
   KP_MODE,                   指定密钥的某种属性被改变,
KP_MODE意味着改变的是加密模式
(BYTE*)&dwMode,                  指向一个已经被初始化的缓冲区
   0))                                          
{
   printf("Key Parameters set. \n");
}
else
{
   MyHandleError("Error during CryptSetKeyParam.");
}
if(CryptGenRandom(                           随机填充一块缓冲区
   hCryptProv,                                  CSP句柄
   8,                        缓冲区大小
   pbData))                      缓冲区地址
{
   printf("Random sequence generated. \n");
}
else
{
   MyHandleError("Error during CryptGenRandom.");
}
if(CryptSetKeyParam(                           再次给密钥设置属性
   hOriginalKey,
   KP_IV,               KP_IV意味着,这个函数的第三个参数指向一个BYTE数组,数组大小为块大小/8。
   pbData,
   0))
{
   printf("Parameter set with random sequence as "
   "initialization vector. \n");
}
else
{
   MyHandleError("Error during CryptSetKeyParam.");
}
//-------------------------------------------------------------------

if (hOriginalKey)                                 以下依次销毁,释放源密钥句柄,副本句柄,CSP句柄,
    if (!CryptDestroyKey(hOriginalKey))
      MyHandleError("Failed CryptDestroyKey\n");

if (hDuplicateKey)
    if (!CryptDestroyKey(hDuplicateKey))
            MyHandleError("Failed CryptDestroyKey\n");

if(hCryptProv)
    if (!CryptReleaseContext(hCryptProv, 0))
      MyHandleError("Failed CryptReleaseContext\n");

printf("\nThe program ran to completion without error. \n");

} // End of main.
当我们已经生成了一个密钥,我们下面要做的是如何保存,导出,导入一个对话密钥。将一个密钥保存起来,导出,保存到硬盘上。这样,这个密钥就可以在其它应用程序上使用,而不会随着生成密钥程序的关闭而丢失了。
下面这段程序就是用来演示如何保存,导出一个对话密钥的。
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(char *s);

void main(void)
{
//--------------------------------------------------------------------
// Declare and initialize variables.

HCRYPTPROV hProv;       // CSP handle
HCRYPTKEY hSignKey;   // Signature key pair handle
HCRYPTKEY hXchgKey;   // Exchange key pair handle
HCRYPTKEY hKey;         // Session key handle
BYTE *pbKeyBlob;      // Pointer to a simple key BLOB
DWORD dwBlobLen;      // The length of the key BLOB

//--------------------------------------------------------------------
// Acquire a cryptographic provider context handle.

if(CryptAcquireContext(                           获取一个缺省容器的CSP句柄
   &hProv,
   NULL,
   NULL,
   PROV_RSA_FULL,
   0))
{
    printf("The CSP has been acquired. \n");
}
else
{
    MyHandleError("Error during CryptAcquireContext.");
}

if(CryptGetUserKey(                                    获取一个AT_SIGNATURE类型的密钥句柄
   hProv,
   AT_SIGNATURE,
   &hSignKey))
{
    printf("The signature key has been acquired. \n");
}
else
{
    MyHandleError("Error during CryptGetUserKey for signkey.");
}
//--------------------------------------------------------------------

if(CryptGetUserKey(                                    获取一个AT_KEYEXCHANGE,类型的密钥句柄,保存在hXchgKey中
   hProv,
   AT_KEYEXCHANGE,
   &hXchgKey))
{
    printf("The key exchange key has been acquired. \n");
}
else
{
    printf("Error during CryptGetUserKey exchange key.");
}
// Generate a session key.

if (CryptGenKey(                                  生成一个CRYPT_EXPORTABLE(可导出的),CALG_RC4(指定算法)的密钥,保存在hKey
    hProv,      
    CALG_RC4,      
    CRYPT_EXPORTABLE,
    &hKey))
{   
    printf("Original session key is created. \n");
}
else
{
   MyHandleError("ERROR -- CryptGenKey.");
}
if(CryptExportKey(                                 CryptExportKey导出一个密钥
   hKey,                                          将要导出的密钥的句柄
   hXchgKey,                   用户最终使用到的密钥的句柄
   SIMPLEBLOB,                              指定BLOB的类型,SIMPLEBLOB说明是 用来导出对话密钥的
   0,                                             指定密钥的附加属性
   NULL,                                       
   &dwBlobLen))                                  当时这个函数在这里的主要
                        目的是得到这个BLOB的长度
{
   printf("Size of the BLOB for the session key determined. \n");
}
else
{
   MyHandleError("Error computing BLOB length.");
}

if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    MyHandleError("Out of memory. \n");
}
if(CryptExportKey(                            这是这个函数才是真正的导出密钥
   hKey,
   hXchgKey,
   SIMPLEBLOB,
   0,
   pbKeyBlob,
   &dwBlobLen))
{
   printf("Contents have been written to the BLOB. \n");
}
else
{
    MyHandleError("Error during CryptExportKey.");
}
free(pbKeyBlob);                                  释放内存

// Destroy the session key.
if(hKey)
    CryptDestroyKey(hKey);

// Destroy the signature key handle.
if(hSignKey)
    CryptDestroyKey(hSignKey);

// Destroy the key exchange key handle.
if(hXchgKey)
   CryptDestroyKey(hXchgKey);

// Release the provider handle.
if(hProv)
   CryptReleaseContext(hProv, 0);
printf("The program ran to completion without error. \n");

}

[ 本帖最后由 whypro 于 2010-5-6 15:06 编辑 ]
页: [1] 2
查看完整版本: 【分享】各类应用密码学CrackMe,慢慢的会补全。