首页
社区
课程
招聘
[旧帖] [分享]CrackMe 2007专辑学习笔记 0.00雪花
发表于: 2010-7-21 19:12 2232

[旧帖] [分享]CrackMe 2007专辑学习笔记 0.00雪花

2010-7-21 19:12
2232
最近下载了CrackMe2007专辑,打算先从CrackMe入手学习,所以开一个帖子用来记录自己的学习过程和心得,这个版块多数都是初学者,希望大家以交流为目的,非交流的问题就不要回复了,省的以后自己在翻看时要多爬好多层楼。

做了一段时间cm的练习,发现自己现在看MASM写的程序反汇编后的代码很顺手,而看那些VB MFC等就很费劲了,里面的call一层套一层,看的很晕。好在现在一直都是先自己做几遍实在过不去在看教程,也争取每一个都能写出注册机代码了,虽然自己的编程水平很差。其实我写的那些注释只是对自己而言的,可能有的地方我不熟悉反复看了几遍才懂就多写了些,有些地方很容易看明白就没怎么写注释,估计后面的练习注释写的会越来越少了。。                 2010-7-30

[课程]Linux pwn 探索篇!

收藏
免费 0
支持
分享
最新回复 (27)
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
由于空闲时间也不是很多,不一定天天更新,只是当自己将一个crackme完全从头到尾做完后就来更新一下,也大致看了下,crackme2007专辑中有些是有壳的,所以目前只做那些没有加壳的,尽量要求自己先自己做一遍,当不明白的时候在结合教程来做,等完全分析清楚算法后,自己再独立写出注册机来,说到编程方面我也是个菜鸟,可能写出来的代码一点都不符合规范,但我目前的目标是能实现功能就行了。先贴一个前几天做的一个练习。

CrackMe 2007   序列号->逍遥风->ACG TRIAL 分析

下载地址大家自己找。

0040127D   .  BF 06214000   MOV EDI,crcme1.00402106
00401282   .  33DB          XOR EBX,EBX                  ;  上面函数取注册码,之后将放用户名的地址送入EDI
00401284   .  33C0          XOR EAX,EAX
00401286   >  8A1F          MOV BL,BYTE PTR DS:[EDI]     ;  取用户名的每一位的ascii
00401288   .  80FB 20       CMP BL,20                    ;  格式判断,如果ascii吗小于20则是非打印字符,就跳走
0040128B   .  0F82 95000000 JB crcme1.00401326
00401291   .  03C3          ADD EAX,EBX                  ;  累加用户名的每一位ascii码
00401293   .  47            INC EDI                      ;  指向下一位用户名的字符
00401294   .  803F 00       CMP BYTE PTR DS:[EDI],0      ;  是否到用户名最后一位,是否是0
00401297   .^ 75 ED         JNZ SHORT crcme1.00401286
00401299   .  C1C0 03       ROL EAX,3                    ;  用户名ascii码之和循环左移3位,相当于乘以8
0040129C   .  35 A5150500   XOR EAX,515A5                ;  再和0x515A5异或,后压栈保存
004012A1   .  50            PUSH EAX
004012A2   .  33C0          XOR EAX,EAX
004012A4   .  33DB          XOR EBX,EBX
004012A6   .  33FF          XOR EDI,EDI
004012A8   .  BE 2E214000   MOV ESI,crcme1.0040212E      ;  注册码送入ESI
004012AD   >  B8 0A000000   MOV EAX,0A                   ;  EAX赋值0A,结合后面看是作为乘数
004012B2   .  8A1E          MOV BL,BYTE PTR DS:[ESI]     ;  循环取注册吗的每一位
004012B4   .  85DB          TEST EBX,EBX                 ;  此处是判断是否循环判断完了,是则跳出循环
004012B6   .  74 15         JE SHORT crcme1.004012CD     ;  因为在后面并没有判断结束循环的语句,而常用的ECX也没有减一的操作
004012B8   .  80FB 30       CMP BL,30                    ;  判断注册码是否是数字,分别判断是否小于0和大宇9,是则非数字
004012BB   .  72 69         JB SHORT crcme1.00401326
004012BD   .  80FB 39       CMP BL,39
004012C0   .  7F 64         JG SHORT crcme1.00401326
004012C2   .  83EB 30       SUB EBX,30                   ;  注册码的ASCII码减0x30,得出的值就是十进制的数字值
004012C5   .  0FAFF8        IMUL EDI,EAX
004012C8   .  03FB          ADD EDI,EBX                  ;  edi=edi*0A+十进制的注册码值,edi初值是0
004012CA   .  46            INC ESI
004012CB   .^ EB E0         JMP SHORT crcme1.004012AD
004012CD   >  81F7 CA870000 XOR EDI,87CA                 ;  注册码循环计算出的值和0x87CA异或
004012D3   .  8BDF          MOV EBX,EDI
004012D5   .  58            POP EAX                      ;  出栈的值是之前用户名循环计算出的值
004012D6   .  03C3          ADD EAX,EBX                  ;  将用户名和注册码循环计算出的结果相加
004012D8   .  35 E7970700   XOR EAX,797E7
004012DD   .  85C0          TEST EAX,EAX
004012DF      75 45         JNZ SHORT crcme1.00401326
004012E1   .  6A 00         PUSH 0                       ; /Style = MB_OK|MB_APPLMODAL
004012E3   .  68 1B204000   PUSH crcme1.0040201B         ; |-=ACG=- T h e   B e s t -=ACG=-
004012E8   .  68 77204000   PUSH crcme1.00402077         ; |Text = "Yeah You Did It!!!
Czyli nareszczie ci si?uda硂
Teraz mo縠sz przy彻czy?si?do ACG"
004012ED   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]    ; |hOwner
004012F0   .  E8 5D010000   CALL <JMP.&USER32.MessageBox>; \MessageBoxA
其中这段循环的作用是把字符转换为数字,比如输入136608,经执行这段循环后就变成数字的136608,只不过调试时看到的是16进制。
004012AD   > /B8 0A000000   MOV EAX,0A                   ;  EAX赋值0A,结合后面看是作为乘数
004012B2   . |8A1E          MOV BL,BYTE PTR DS:[ESI]     ;  循环取注册吗的每一位
004012B4   . |85DB          TEST EBX,EBX                 ;  此处是判断是否循环判断完了,是则跳出循环如果取到的是0则表明已经到字符处的末尾
004012B6   . |74 15         JE SHORT crcme1.004012CD     ;  因为在后面并没有判断结束循环的语句,而常用的ECX也没有减一的操作
004012B8   . |80FB 30       CMP BL,30                    ;  判断注册码是否是数字,分别判断是否小于0和大宇9,是则非数字
004012BB   . |72 69         JB SHORT crcme1.00401326
004012BD   . |80FB 39       CMP BL,39
004012C0   . |7F 64         JG SHORT crcme1.00401326
004012C2   . |83EB 30       SUB EBX,30                   ;  注册码的ASCII码减0x30,得出的值就是十进制的数字值
004012C5   . |0FAFF8        IMUL EDI,EAX
004012C8   . |03FB          ADD EDI,EBX                  ;  edi=edi*0A+十进制的注册码值,edi初值是0
004012CA   . |46            INC ESI
004012CB   .^\EB E0         JMP SHORT crcme1.004012AD
比如136608,,这样计算就得出数字的136608,第0位是1,第一位是3,第二位是6。。。。。
((((((0*10+1)*10+3)*10+6)*10+6)*10+0)*10+8=136608
这段也是想了好久才搞明白的。还有上面的那句TEST EBX,EBX,如果取得的是字符最后一个空字符则表明已经取完,就跳出循环。
改程序在开始还有一个验证KEY文件的过程,只是如果没有找到就直接进入程序,如果找到的话就弹出一个提示框,key文件名是:ACG.key
内容必须是12个字符,“ACG The Best”
00401012  |.  68 6B234000   PUSH crcme1.0040236B                     ; |ACG.key
00401017  |.  E8 84040000   CALL <JMP.&KERNEL32.CreateFileA>         ; \CreateFileA
0040101C  |.  83F8 FF       CMP EAX,-1
0040101F  |.  0F84 59010000 JE crcme1.0040117E
00401025  |.  A3 73234000   MOV DWORD PTR DS:[402373],EAX
0040102A  |.  6A 00         PUSH 0                                   ; /pFileSizeHigh = NULL
0040102C  |.  FF35 73234000 PUSH DWORD PTR DS:[402373]               ; |hFile = NULL
00401032  |.  E8 51040000   CALL <JMP.&KERNEL32.GetFileSize>         ; \GetFileSize
00401037  |.  83F8 0C       CMP EAX,0C
0040103A  |.  0F85 3E010000 JNZ crcme1.0040117E
00401040  |.  6A 0C         PUSH 0C                                  ; /MemSize = C (12.)
00401042  |.  6A 00         PUSH 0                                   ; |Flags = GMEM_FIXED
00401044  |.  E8 39040000   CALL <JMP.&KERNEL32.GlobalAlloc>         ; \GlobalAlloc
00401049  |.  A3 7B234000   MOV DWORD PTR DS:[40237B],EAX
0040104E  |.  6A 00         PUSH 0                                   ; /pOverlapped = NULL
00401050  |.  68 77234000   PUSH crcme1.00402377                     ; |pBytesRead = crcme1.00402377
00401055  |.  6A 0C         PUSH 0C                                  ; |BytesToRead = C (12.)
00401057  |.  FF35 7B234000 PUSH DWORD PTR DS:[40237B]               ; |Buffer = NULL
0040105D  |.  FF35 73234000 PUSH DWORD PTR DS:[402373]               ; |hFile = NULL
00401063  |.  E8 14040000   CALL <JMP.&KERNEL32.ReadFile>            ; \ReadFile
00401068  |.  8B3D 7B234000 MOV EDI,DWORD PTR DS:[40237B]
0040106E  |.  33DB          XOR EBX,EBX
00401070  |.  8A1F          MOV BL,BYTE PTR DS:[EDI]
00401072  |.  80F3 1B       XOR BL,1B
00401075  |.  C1C3 02       ROL EBX,2
00401078  |.  81F3 68010000 XOR EBX,168
0040107E  |.  85DB          TEST EBX,EBX
00401080  |.  0F85 F8000000 JNZ crcme1.0040117E
循环取出文件的内容,依次判断是否是那12个字符,过程是:取出的字符和1B异或,在左移2位,相当于*4。然后和一个值判断是否相等,
比如上面的判断值168,逆过来就是(0X168/4) XOR 1B = 41,其ASCII值为A。

算法:用户名的每位ASCII码累加,累加和*8再和0X515A5异或得到一个值A
        输入的注册码要是数字,将其转为数值后和0X87CA异或得到值B
        将A+B得到C,C再和0X797E7异或后是否是0来判断注册码是否正确。
所以逆推:C=0X797E7,B=0X797E7-A,
        注册码=(0X797E7-A)XOR 0X87CA
  C语言实现注册过程如下:
        int main(void)
{
        char sn[20]={"pediy"};
        int i;
        int sum=0;
        for (i=0;i<20;i++)
        {
                sum=sum+sn[i];   //求用户名的ascii吗累加
        }
        sum=sum*8;          //累加和*8
        sum=sum ^ 0X515A5;  //在和这个值异或
        sum=(0x797E7-sum)^0x87CA;   //计算出注册码。
        printf("%d\n",sum);
        getchar();
        return 0;
}
2010-7-21 19:15
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢分享谢谢分享
2010-7-22 00:34
0
雪    币: 499
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
支持分享
2010-7-22 06:33
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢分享。。。。
2010-7-22 07:28
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
CrackMe 2007->序列号->逍遥分->Splish CrackMe 分析和注册机

这个比较简单,刚开始先做简单的比较好,这个的注册码不是唯一的,组合很多。
查找字符串后找到关键断点,分析如下:共分成2部分

0040135D  |> \6A 20         PUSH 20                                  ; /字符串长度
0040135F  |.  68 15324000   PUSH CrackMe0.00403215                   ; |字符存放的地址
00401364  |.  FF35 90344000 PUSH DWORD PTR DS:[403490]               ; |hWnd = 0009029A (class='Edit',parent=0007024A)
0040136A  |.  E8 BB030000   CALL <JMP.&USER32.GetWindowTextA>        ; \取文本框字符
0040136F  |.  8D05 53134000 LEA EAX,DWORD PTR DS:[401353]            ;  将【401353】的内容送EAX,从字符串看应该是要找的
00401375  |.  8D1D 15324000 LEA EBX,DWORD PTR DS:[403215]            ;  将刚才输入的机器号送EBX
0040137B  |>  8038 00       /CMP BYTE PTR DS:[EAX],0
0040137E  |.  74 0C         |JE SHORT CrackMe0.0040138C              ;  依次取出每一位,按位比较是否相等,不等就跳走
00401380  |.  8A08          |MOV CL,BYTE PTR DS:[EAX]                ;  重新输入改采记下的那个字符串"HardCoded",提示成功
00401382  |.  8A13          |MOV DL,BYTE PTR DS:[EBX]
00401384  |.  38D1          |CMP CL,DL
00401386  |.  75 4A         |JNZ SHORT CrackMe0.004013D2             ;  此处为爆破点。
00401388  |.  40            |INC EAX
00401389  |.  43            |INC EBX
0040138A  |.^ EB EF         \JMP SHORT CrackMe0.0040137B
0040138C  |>  EB 2F         JMP SHORT CrackMe0.004013BD
0040138E  |.  43 6F 6E 67 7>ASCII "Congratulations,"
0040139E  |.  20 79 6F 75 2>ASCII " you got the har"
004013AE  |.  64 20 63 6F 6>ASCII "d coded serial",0
004013BD  |>  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
004013BF  |.  68 0A304000   PUSH CrackMe0.0040300A                   ; |Splish, Splash
004013C4  |.  68 8E134000   PUSH CrackMe0.0040138E                   ; |Congratulations, you got the hard coded serial
004013C9  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
004013CB  |.  E8 78030000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
004013D0  |.  EB 13         JMP SHORT CrackMe0.004013E5
004013D2  |>  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
004013D4  |.  68 0A304000   PUSH CrackMe0.0040300A                   ; |Splish, Splash
004013D9  |.  68 67304000   PUSH CrackMe0.00403067                   ; |Sorry, please try again.
004013DE  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
004013E0  |.  E8 63030000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
004013E5  |>  61            POPAD

第一部分结果:输入“HardCoded”后成功。
第二部分具体分析如下:
同样根据字符串找点关键断点:
004015E4  /$  55            PUSH EBP
004015E5  |.  8BEC          MOV EBP,ESP
004015E7  |.  6A 20         PUSH 20                                  ; /Count = 20 (32.)
004015E9  |.  68 42324000   PUSH CrackMe0.00403242                   ; |【403242】存放取得的注册码
004015EE  |.  FF75 0C       PUSH DWORD PTR SS:[EBP+C]                ; |hWnd
004015F1  |.  E8 34010000   CALL <JMP.&USER32.GetWindowTextA>        ; \GetWindowTextA
004015F6  |.  85C0          TEST EAX,EAX
004015F8  |.  0F84 95000000 JE CrackMe0.00401693
004015FE  |.  A3 67344000   MOV DWORD PTR DS:[403467],EAX            ;  将注册码的长度送【403467】
00401603  |.  6A 0B         PUSH 0B                                  ; /Count = B (11.)
00401605  |.  68 36324000   PUSH CrackMe0.00403236                   ; |【403236】存放取得的注册名
0040160A  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
0040160D  |.  E8 18010000   CALL <JMP.&USER32.GetWindowTextA>        ; \GetWindowTextA
00401612  |.  85C0          TEST EAX,EAX
00401614  |.  74 68         JE SHORT CrackMe0.0040167E
00401616  |.  A3 63344000   MOV DWORD PTR DS:[403463],EAX            ;  注册名长度送【403463】
0040161B  |.  33C9          XOR ECX,ECX
0040161D  |.  33DB          XOR EBX,EBX
0040161F  |.  33D2          XOR EDX,EDX                              ;  寄存器置0
00401621  |.  8D35 36324000 LEA ESI,DWORD PTR DS:[403236]            ;  取注册名存放地址
00401627  |.  8D3D 58324000 LEA EDI,DWORD PTR DS:[403258]
0040162D  |.  B9 0A000000   MOV ECX,0A                               ;  ECX赋初值0x0A
00401632  |>  0FBE041E      /MOVSX EAX,BYTE PTR DS:[ESI+EBX]         ;  循环取出注册名的每一位字符送EAX
00401636  |.  99            |CDQ
00401637  |.  F7F9          |IDIV ECX                                ;  除0x0A
00401639  |.  33D3          |XOR EDX,EBX                             ;  余数和EBX异或,EBX初始值为0,下次循环后就会变化
0040163B  |.  83C2 02       |ADD EDX,2                               ;  异或后的值在+2
0040163E  |.  80FA 0A       |CMP DL,0A                               ;  判断DL是否小于A,小于则将edx送【403258】地址
00401641  |.  7C 03         |JL SHORT CrackMe0.00401646              ;  不小于A则先将DL减去A在送【403258】
00401643  |.  80EA 0A       |SUB DL,0A
00401646  |>  88141F        |MOV BYTE PTR DS:[EDI+EBX],DL            ;  EBX是循环计数值,从0开始累加
00401649  |.  43            |INC EBX
0040164A  |.  3B1D 63344000 |CMP EBX,DWORD PTR DS:[403463]           ;  循环结束标志判断,当注册名取完后则推出循环
00401650  |.^ 75 E0         \JNZ SHORT CrackMe0.00401632
00401652  |.  33C9          XOR ECX,ECX
00401654  |.  33DB          XOR EBX,EBX
00401656  |.  33D2          XOR EDX,EDX                              ;  寄存器置零
00401658  |.  8D35 42324000 LEA ESI,DWORD PTR DS:[403242]            ;  取注册码
0040165E  |.  8D3D 4D324000 LEA EDI,DWORD PTR DS:[40324D]
00401664  |.  B9 0A000000   MOV ECX,0A                               ;  赋初值0A
00401669  |>  0FBE041E      /MOVSX EAX,BYTE PTR DS:[ESI+EBX]         ;  取出注册码的每一位
0040166D  |.  99            |CDQ
0040166E  |.  F7F9          |IDIV ECX                                ;  除0A
00401670  |.  88141F        |MOV BYTE PTR DS:[EDI+EBX],DL            ;  注册码ascii码除0x0A的余数
00401673  |.  43            |INC EBX
00401674  |.  3B1D 67344000 |CMP EBX,DWORD PTR DS:[403467]
0040167A  |.^ 75 ED         \JNZ SHORT CrackMe0.00401669
0040167C  |.  EB 2A         JMP SHORT CrackMe0.004016A8
0040167E  |>  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
00401680  |.  68 0A304000   PUSH CrackMe0.0040300A                   ; |Splish, Splash
00401685  |.  68 A0304000   PUSH CrackMe0.004030A0                   ; |Please enter your name.
0040168A  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
0040168C  |.  E8 B7000000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
00401691  |.  EB 62         JMP SHORT CrackMe0.004016F5
00401693  |>  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
00401695  |.  68 0A304000   PUSH CrackMe0.0040300A                   ; |Splish, Splash
0040169A  |.  68 B8304000   PUSH CrackMe0.004030B8                   ; |Please enter your serial number.
0040169F  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
004016A1  |.  E8 A2000000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
004016A6  |.  EB 4D         JMP SHORT CrackMe0.004016F5
004016A8  |>  8D35 4D324000 LEA ESI,DWORD PTR DS:[40324D]            ;  注册码每位循环计算出的值
004016AE  |.  8D3D 58324000 LEA EDI,DWORD PTR DS:[403258]            ;  注册名每位循环计算出的值
004016B4  |.  33DB          XOR EBX,EBX
004016B6  |>  3B1D 63344000 /CMP EBX,DWORD PTR DS:[403463]           ;  循环结束判断语句,【403463】存放注册名长度,看来根据这个值来决定循环次数
004016BC  |.  74 0F         |JE SHORT CrackMe0.004016CD
004016BE  |.  0FBE041F      |MOVSX EAX,BYTE PTR DS:[EDI+EBX]         ;  分别比较每一位
004016C2  |.  0FBE0C1E      |MOVSX ECX,BYTE PTR DS:[ESI+EBX]
004016C6  |.  3BC1          |CMP EAX,ECX
004016C8  |.  75 18         |JNZ SHORT CrackMe0.004016E2             ;  不同则调到失败提示窗口
004016CA  |.  43            |INC EBX
004016CB  |.^ EB E9         \JMP SHORT CrackMe0.004016B6
004016CD  |>  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
004016CF  |.  68 0A304000   PUSH CrackMe0.0040300A                   ; |Splish, Splash
004016D4  |.  68 42304000   PUSH CrackMe0.00403042                   ; |Good job, now keygen it.
004016D9  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
004016DB  |.  E8 68000000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA

算法总结:
先根据输入的注册名计算出一个值,取注册名的每一位后的ASCII码除以A,余数和当前的循环计数值异或,异或后的值加2,在判断得出的值是否小于0xA,不小于的话要先减去0xA,将此值保存。此值记作A
循环取出注册码的每位ascii码除以0xA,将余数保存,此值记作B,  最后取注册名的长度,循环比较值A和值B的每一位是否相等,循环次数是注册名的长度,看来注册码长度不能小于注册名的长度,否则这部比较不会通过的。
注册机源码:

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

int main(void)
{
        char name[]={"pediy"};
        printf("注册名:%s\n",name);
        char sn[20];
        int i,namelen;
        namelen=strlen(name);
        for (i=0;i<namelen;i++)
        {
                name[i]=name[i]%0x0A;   //取余数
                name[i]=name[i]^i;     //余数和当前循环的i值异或
                name[i]=name[i]+0x02;   // 异或后的结果加+2
                if (name[i]>=0x0A)
                {
                        name[i]=name[i]-0x0A;//  如果上面得的值大于0xA,就减去0xA。
                }
        }
        printf("注册码:");
        for (i=0;i<namelen;i++)
        {
                sn[i]=0x7*0x0A+name[i];     //逆算处真码,此处是0x07是随便取的,这样算出的
                printf("%c",sn[i]);        //主要是字母,也可以用其他值,因为注册码不唯一。
        }                              //注册码后面可以是任何值都可以验证过,因为之比较与注册名相同的注册码,后面的不比较。

        printf("\n\n");
        getchar();
        return 0;
}
2010-7-22 13:23
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
这是这几天做的练习中的一个,直接从练习笔记中考过来的。。
这几天也想找个免费软件试试,结果脱壳不会,看来要一步一步的来,还是继续我的crackme。

CrackMe2007->序列号->逍遥风->Bad Sector CrackMe

00401139   $  6A 32         PUSH 32                                  ; /Count = 32 (50.)
0040113B   .  68 F3204000   PUSH Crackme1.004020F3                   ; |Buffer = Crackme1.004020F3
00401140   .  68 C8000000   PUSH 0C8                                 ; |ControlID = C8 (200.)
00401145   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
00401148   .  E8 DE000000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
0040114D   .  83F8 00       CMP EAX,0                                ;  判断用户名是否为空,空则跳走
00401150   .  0F84 99000000 JE Crackme1.004011EF
00401156   .  83F8 04       CMP EAX,4                                ;  判断用户名是否小于4,小则跳走
00401159   .  0F82 90000000 JB Crackme1.004011EF
0040115F   .  33C9          XOR ECX,ECX
00401161   .  33DB          XOR EBX,EBX
00401163   .  33F6          XOR ESI,ESI
00401165   .  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX             ;  【EBP-4】中存放用户名的长度
00401168   >  0FBE81 F32040>MOVSX EAX,BYTE PTR DS:[ECX+4020F3]       ;  取得用户名的一位字符
0040116F   .  83F8 20       CMP EAX,20                               ;  判断取出的字符是否是空格
00401172   .  74 07         JE SHORT Crackme1.0040117B
00401174   .  6BC0 04       IMUL EAX,EAX,4                           ;  取出的字符ASCII吗乘以4送入EAX
00401177   .  03D8          ADD EBX,EAX                              ;  在EBX中累加刚才的乘积
00401179   .  8BF3          MOV ESI,EBX                              ;  乘机保存到ESI
0040117B   >  41            INC ECX                                  ;  计数器累加
0040117C   .  3B4D FC       CMP ECX,DWORD PTR SS:[EBP-4]             ;  判断是否用户名取完了,
0040117F   .^ 75 E7         JNZ SHORT Crackme1.00401168              ;  没有到用户名末尾则继续,否则往下执行
00401181   .  83FE 00       CMP ESI,0                                ;  如果根据用户名计算出的结果是0则跳走
00401184   .  74 69         JE SHORT Crackme1.004011EF
00401186   .  BB 89476500   MOV EBX,654789                           ;  将0x654789送给EBX
0040118B   >  0FBE81 F22040>MOVSX EAX,BYTE PTR DS:[ECX+4020F2]       ;  从用户名的最后一位开始取字符
00401192   .  4B            DEC EBX                                  ;  刚才送的那个值减一
00401193   .  6BC3 02       IMUL EAX,EBX,2                           ;  减一后的值乘以2送入EAX
00401196   .  03D8          ADD EBX,EAX                              ;  EAX和EBX相加;也就是(654789-1)*2+(654789-1)
00401198   .  4B            DEC EBX                                  ;  上面计算的结果减一
00401199   .  49            DEC ECX                                  ;  计数器减一
0040119A   .^ 75 EF         JNZ SHORT Crackme1.0040118B
0040119C   .  56            PUSH ESI                                 ; /<%lu>
0040119D   .  53            PUSH EBX                                 ; |<%lX>
0040119E   .  68 C7204000   PUSH Crackme1.004020C7                   ; |BS-%lX-%lu
004011A3   .  68 BB214000   PUSH Crackme1.004021BB                   ; |s = Crackme1.004021BB
004011A8   .  E8 6C000000   CALL <JMP.&USER32.wsprintfA>             ; \wsprintfA

算法:用户名至少4位,分别根据用户名顺序和倒叙计算出一个值,在计算下就是注册码,具体看上面的注释和下面的注册机源码。。
顺序计算是将每位的ascii码累加;倒叙是现在ebx附一个初值,之后减一,在和顺序时计算的值*2等计算,然后按格式输出即可。
一组正确的注册码:pediy    BS-6022E527-2156
#include <stdio.h>
int main(void)
{
        //这个crackme的注册码格式:BS-6022E527-2156,用户名不能低于4位。
        char name[20]={"abcdef"};
        int sn1;   //从第一个字符开始依次取用户名中的每个字符乘以4的累加值放于此。
        int sn2;   //从最后一个字符倒叙取用户名,循环计算结果存放处。
        int i;
        int ebx,esi,eax;
        ebx=0;
        esi=0;
        eax=0;
        sn1=0;
        sn2=0;
        for (i=0;i<20;i++)
        {
                sn2=sn2+name[i]*4;   
        }
       
        esi=sn1;
        ebx=0x654789;
        for (i=19;i>=0;i--)
        {
                if (name[i]>0x0)  //若是字符为空则不进入循环累计。
                {
                ebx=ebx-1;
                eax=ebx*2;
                ebx=ebx+eax;
                ebx--;
                }
        }
        sn1=ebx;
        printf("用户名:%s\n",name);
        printf("注册码:BS-%lX-%lu\n",sn1,sn2);
        getchar();
        return 0;
}
2010-7-28 19:17
0
雪    币: 1140
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
不错,想到就做,慢慢就熟练了!
2010-7-28 22:11
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
CrackMe 2007->序列号->逍遥风->Trsh—CrackMe 分析和注册机

重要的是先自己做几遍,实在不行再看教程。

004010D3   .  6A 50         PUSH 50                                  ; /Count = 50 (80.)
004010D5   .  68 B0344000   PUSH tsrh-cra.004034B0                   ; |Buffer = tsrh-cra.004034B0
004010DA   .  68 DE000000   PUSH 0DE                                 ; |ControlID = DE (222.)
004010DF   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
004010E2   .  E8 43020000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
004010E7   .  83F8 05       CMP EAX,5                                ;  取注册名并判断长度是否大于等于5位,否则跳走
004010EA   .  7D 26         JGE SHORT tsrh-cra.00401112
004010EC   .  B8 66354000   MOV EAX,tsrh-cra.00403566
004010F1   .  E8 05020000   CALL tsrh-cra.004012FB
004010F6   .  6A 40         PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004010F8   .  68 52354000   PUSH tsrh-cra.00403552                   ; |Title = "TSRh CrackMe *Easy*"
004010FD   .  68 00304000   PUSH tsrh-cra.00403000                   ; |Text = "Kill this Nag!!!"
00401102   .  6A 00         PUSH 0                                   ; |hOwner = NULL
00401104   .  E8 27020000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
00401109   .  33C0          XOR EAX,EAX
0040110B   .  5E            POP ESI
0040110C   .  5F            POP EDI
0040110D   .  5B            POP EBX
0040110E   .  C9            LEAVE
0040110F   .  C2 1000       RETN 10
00401112   >  E8 DC000000   CALL tsrh-cra.004011F3                   ;  关键call,跟进,格式化字符串:trsh-“7D3+注册名长度的十进制”
00401117   .  6A 50         PUSH 50                                  ; /Count = 50 (80.)
00401119   .  68 90314000   PUSH tsrh-cra.00403190                   ; |Buffer = tsrh-cra.00403190
0040111E   .  68 4D010000   PUSH 14D                                 ; |ControlID = 14D (333.)
00401123   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
00401126   .  E8 FF010000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
0040112B   .  A1 90314000   MOV EAX,DWORD PTR DS:[403190]            ;  取注册码字符,存放于【403190】处并赋值给eax
00401130   .  3D 74737268   CMP EAX,68727374                         ;  比较注册码的前4个字符是否是:0x68727374
00401135   .  75 23         JNZ SHORT tsrh-cra.0040115A
00401137   .  05 20320000   ADD EAX,3220                             ;  EAX赋值+0x3220,注册码前4为字符值加3220
0040113C   .  50            PUSH EAX
0040113D   .  33C0          XOR EAX,EAX
0040113F   .  E8 EA000000   CALL tsrh-cra.0040122E                   ;  关键call,跟进
00401144   .  58            POP EAX
00401145   .  85C0          TEST EAX,EAX
00401147   .  74 11         JE SHORT tsrh-cra.0040115A
00401149   .  33C2          XOR EAX,EDX
0040114B   .  8BD0          MOV EDX,EAX
0040114D   .  8BF0          MOV ESI,EAX
0040114F   .  33C0          XOR EAX,EAX
00401151   .  E8 31010000   CALL tsrh-cra.00401287                   ;  比较结果
00401156   .  84C0          TEST AL,AL
00401158   .  75 1F         JNZ SHORT tsrh-cra.00401179              ;  此处跳走就完蛋
0040115A   >  B8 85354000   MOV EAX,tsrh-cra.00403585
0040115F   .  E8 97010000   CALL tsrh-cra.004012FB


关键call根进
0040122E  /$  56            PUSH ESI
0040122F  |.  68 20334000   PUSH tsrh-cra.00403320                   ; /String = "tsrh-2008-CZYXY"
00401234  |.  E8 1B010000   CALL <JMP.&KERNEL32.lstrlenA>            ; \lstrlenA
00401239  |.  8B3D 14354000 MOV EDI,DWORD PTR DS:[403514]            ;  【403514】存放的是注册名的长度,取出送EDI
0040123F  |.  BE 01000000   MOV ESI,1
00401244  |.  8BC8          MOV ECX,EAX                              ;  EAX是取得的格式字符“tsrh-2008-”的长度,送ECX
00401246  |>  B8 B0344000   MOV EAX,tsrh-cra.004034B0                ;  ASCII "pediy"
0040124B  |.  0FB64406 FF   MOVZX EAX,BYTE PTR DS:[ESI+EAX-1]        ;  依次取出注册名的每位字符
00401250  |.  04 0C         ADD AL,0C                                ;  和0x0C相加
00401252  |.  0FB6D0        MOVZX EDX,AL                             ;  相加后的值送EDX
00401255  |.  83EA 11       SUB EDX,11                               ;  相加后的值减0X11
00401258  |.  03D0          ADD EDX,EAX
0040125A  |.  2BD1          SUB EDX,ECX
0040125C  |.  33C2          XOR EAX,EDX
0040125E  |.  50            PUSH EAX                                 ; /<%X>
0040125F  |.  68 18354000   PUSH tsrh-cra.00403518                   ; |Format = "%X"
00401264  |.  8D81 20334000 LEA EAX,DWORD PTR DS:[ECX+403320]        ; |
0040126A  |.  50            PUSH EAX                                 ; |s
0040126B  |.  E8 A8000000   CALL <JMP.&USER32.wsprintfA>             ; \wsprintfA
00401270  |.  83C4 0C       ADD ESP,0C
00401273  |.  68 20334000   PUSH tsrh-cra.00403320                   ; /String = "tsrh-2008-CZYXY"
00401278  |.  E8 D7000000   CALL <JMP.&KERNEL32.lstrlenA>            ; \lstrlenA
0040127D  |.  8BC8          MOV ECX,EAX
0040127F  |.  46            INC ESI
00401280  |.  4F            DEC EDI
00401281  |.^ 75 C3         JNZ SHORT tsrh-cra.00401246
00401283  |.  33C0          XOR EAX,EAX
00401285  |.  5E            POP ESI
00401286  \.  C3            RETN
00401287  /$  53            PUSH EBX
00401288  |.  BE 01000000   MOV ESI,1                                ;  ESI赋给值1
0040128D  |>  B8 B0344000   /MOV EAX,tsrh-cra.004034B0               ;  ASCII "pediy"
00401292  |.  0FB64406 FF   |MOVZX EAX,BYTE PTR DS:[ESI+EAX-1]
00401297  |.  85C0          |TEST EAX,EAX                            ;  判断是否取完注册码,取完则跳出循环
00401299  |.  74 34         |JE SHORT tsrh-cra.004012CF
0040129B  |.  40            |INC EAX                                 ;  注册名每位先加1
0040129C  |.  BA 20334000   |MOV EDX,tsrh-cra.00403320               ;  ASCII "tsrh-2008-CZYXY"
004012A1  |.  0FB65416 0B   |MOVZX EDX,BYTE PTR DS:[ESI+EDX+B]
004012A6  |.  33C2          |XOR EAX,EDX
004012A8  |>  83F8 41       |/CMP EAX,41                             ;  小于“A”则加0x8
004012AB  |.  7D 05         ||JGE SHORT tsrh-cra.004012B2
004012AD  |.  83C0 08       ||ADD EAX,8
004012B0  |.^ EB F6         |\JMP SHORT tsrh-cra.004012A8
004012B2  |>  83F8 5A       |/CMP EAX,5A                             ;  大于0x5A则减0x3
004012B5  |.  7E 05         ||JLE SHORT tsrh-cra.004012BC
004012B7  |.  83E8 03       ||SUB EAX,3
004012BA  |.^ EB F6         |\JMP SHORT tsrh-cra.004012B2
004012BC  |>  83C6 09       |ADD ESI,9
004012BF  |.  BB 20334000   |MOV EBX,tsrh-cra.00403320               ;  ASCII "tsrh-2008-CZYXY"
004012C4  |.  89041E        |MOV DWORD PTR DS:[ESI+EBX],EAX
004012C7  |.  83EE 08       |SUB ESI,8
004012CA  |.  83FE 10       |CMP ESI,10
004012CD  |.^ 75 BE         \JNZ SHORT tsrh-cra.0040128D
004012CF  |>  33C0          XOR EAX,EAX
004012D1  |.  5B            POP EBX
004012D2  |.  E8 01000000   CALL tsrh-cra.004012D8
004012D7  \.  C3            RETN

算法:用户名必须大于=5,其他具体看注册机源码

注册机:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h>
#include <ctype.h>
//初步试了下好像用户名输入的是数字计算出来的不对,
//所以下面的最好输入字母且不能低于5位。。
//注册码的第二部分是0x7D3+用户名的长度,第一部分必须是“tsrh-”
int main(void) 
{
	char name[]={"pediy"};
	int i;
	
	int namelen;
	char temp[20];  //存放一个中间计算过程
	char temp2[20];//存放注册码的第三部分
	printf("注册名:%s\n",name);

	for (i=0;i<20;i++)
	{
		temp[i]='\0';	temp2[i]='\0';
	}
	
	namelen=strlen(name);
	for (i=0;i<namelen;i++)
	{
	//	printf("%lX",(((name[i]+0x0C)*2-0x11)-0x0A-i)^(name[i]+0x0C));  //计算注册码中间的一个call,在根据这个结果计算真正的注册码
		int a;
		a=(((name[i]+0x0C)*2-0x11)-0x0A-i)^(name[i]+0x0C);
		if (i==1)
		{
			itoa(a,temp,16);
		}
	}

	if (islower(temp[0]))
	{
		temp[0]-=32;
	}

	for (i=0;i<namelen;i++)
	{
		name[i]++;
		if (i==0)
		{
			name[i]=name[i]^temp[0];
		}
		else
		{
			name[i]=name[i]^0x00;
		}
		while (name[i]<0x41)
		{
			name[i]+=0x8;
		}
		while (name[i]>0x5A)
		{
			name[i]-=3;
		}
		temp2[i]=name[i];
	}
	printf("\n\n");
	printf("注册码:tsrh-");
	printf("%d-",0x7D3+namelen);
	printf("%s",temp2);

	printf("\n\n");
	getchar();
	return 0; 
}




2010-7-29 13:14
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
CrackMe 2007->序列号->逍遥风->Salazan’s KeyGenMe#001 分析

查找字符串,很容易找到断点,输入注册名:pediy,注册码:12345678901234567890123456789
0045618C  |.  64:FF30       PUSH DWORD PTR FS:[EAX]
0045618F  |.  64:8920       MOV DWORD PTR FS:[EAX],ESP
00456192  |.  8D55 FC       LEA EDX,DWORD PTR SS:[EBP-4]
00456195  |.  8B83 F8020000 MOV EAX,DWORD PTR DS:[EBX+2F8]
0045619B  |.  E8 90CDFDFF   CALL SalazanK.00432F30                   ;  取输入的注册名,结果在【EBP-4】
004561A0  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
004561A3  |.  E8 58E3FAFF   CALL SalazanK.00404500
004561A8  |.  83F8 03       CMP EAX,3                                ;  判断注册名长度是否小于3,小则跳走
004561AB  |.  7C 1B         JL SHORT SalazanK.004561C8
004561AD  |.  8D55 F8       LEA EDX,DWORD PTR SS:[EBP-8]
004561B0  |.  8B83 FC020000 MOV EAX,DWORD PTR DS:[EBX+2FC]
004561B6  |.  E8 75CDFDFF   CALL SalazanK.00432F30                   ;  取输入的注册码,放于【EBP-8】中
004561BB  |.  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]
004561BE  |.  E8 3DE3FAFF   CALL SalazanK.00404500
004561C3  |.  83F8 03       CMP EAX,3                                ;  判断是否大于等于3,如果小于3则提示错误
004561C6  |.  7D 0C         JGE SHORT SalazanK.004561D4
004561C8  |>  B8 58624500   MOV EAX,SalazanK.00456258                ;  Min. 3 char in name/serial!
004561CD  |.  E8 3E6BFDFF   CALL SalazanK.0042CD10
004561D2  |.  EB 53         JMP SHORT SalazanK.00456227
004561D4  |>  8D55 F4       LEA EDX,DWORD PTR SS:[EBP-C]
004561D7  |.  8B83 FC020000 MOV EAX,DWORD PTR DS:[EBX+2FC]
004561DD  |.  E8 4ECDFDFF   CALL SalazanK.00432F30                   ;  取输入的注册码
004561E2  |.  8B45 F4       MOV EAX,DWORD PTR SS:[EBP-C]
004561E5  |.  E8 2EFBFFFF   CALL SalazanK.00455D18                   ;  关键call要跟进
004561EA  |.  84C0          TEST AL,AL
004561EC      74 1F         JE SHORT SalazanK.0045620D               ;  此处改成JNE既可以爆破
004561EE  |.  8B83 00030000 MOV EAX,DWORD PTR DS:[EBX+300]
004561F4  |.  8B80 08020000 MOV EAX,DWORD PTR DS:[EAX+208]
004561FA  |.  33D2          XOR EDX,EDX
004561FC  |.  E8 73EDFFFF   CALL SalazanK.00454F74
00456201  |.  BA 7C624500   MOV EDX,SalazanK.0045627C                ;  Congr! You are real cracker!

关键call根进后分析:
00455DD1  |.  33D2          XOR EDX,EDX
00455DD3  |>  8B4D F4       /MOV ECX,DWORD PTR SS:[EBP-C]
00455DD6  |.  0FB64C11 FF   |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1]
00455DDB  |.  03D9          |ADD EBX,ECX
00455DDD  |.  42            |INC EDX
00455DDE  |.  48            |DEC EAX
00455DDF  |.^ 75 F2         \JNZ SHORT SalazanK.00455DD3             ;  注册码的1-5位的ascii码累加
00455DE1  |>  81FB 8D010000 CMP EBX,18D                              ;  累加和是否是0x18D
00455DE7  |.  75 04         JNZ SHORT SalazanK.00455DED
00455DE9  |.  C645 E3 01    MOV BYTE PTR SS:[EBP-1D],1               ;  【EBP-1D】置1
00455DED  |>  33DB          XOR EBX,EBX
00455DEF  |.  8B45 F0       MOV EAX,DWORD PTR SS:[EBP-10]
00455DF2  |.  E8 09E7FAFF   CALL SalazanK.00404500
00455DF7  |.  85C0          TEST EAX,EAX
00455DF9  |.  7C 11         JL SHORT SalazanK.00455E0C
00455DFB  |.  40            INC EAX
00455DFC  |.  33D2          XOR EDX,EDX
00455DFE  |>  8B4D F0       /MOV ECX,DWORD PTR SS:[EBP-10]
00455E01  |.  0FB64C11 FF   |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1]
00455E06  |.  03D9          |ADD EBX,ECX
00455E08  |.  42            |INC EDX
00455E09  |.  48            |DEC EAX
00455E0A  |.^ 75 F2         \JNZ SHORT SalazanK.00455DFE
00455E0C  |>  81FB 8C010000 CMP EBX,18C                              ;  7--11位的ascii码相加后是否等于0x18C
00455E12  |.  75 04         JNZ SHORT SalazanK.00455E18
00455E14  |.  C645 E2 01    MOV BYTE PTR SS:[EBP-1E],1               ;  【EBP-1E】置1
00455E18  |>  33DB          XOR EBX,EBX
00455E1A  |.  8B45 EC       MOV EAX,DWORD PTR SS:[EBP-14]
00455E1D  |.  E8 DEE6FAFF   CALL SalazanK.00404500
00455E22  |.  85C0          TEST EAX,EAX
00455E24  |.  7C 11         JL SHORT SalazanK.00455E37
00455E26  |.  40            INC EAX
00455E27  |.  33D2          XOR EDX,EDX
00455E29  |>  8B4D EC       /MOV ECX,DWORD PTR SS:[EBP-14]
00455E2C  |.  0FB64C11 FF   |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1]
00455E31  |.  03D9          |ADD EBX,ECX
00455E33  |.  42            |INC EDX
00455E34  |.  48            |DEC EAX
00455E35  |.^ 75 F2         \JNZ SHORT SalazanK.00455E29
00455E37  |>  81FB 90010000 CMP EBX,190                              ;  13--17位ascii码累加
00455E3D  |.  75 04         JNZ SHORT SalazanK.00455E43
00455E3F  |.  C645 E1 01    MOV BYTE PTR SS:[EBP-1F],1               ;  【EBP-1F】置1
00455E43  |>  33DB          XOR EBX,EBX
00455E45  |.  8B45 E8       MOV EAX,DWORD PTR SS:[EBP-18]
00455E48  |.  E8 B3E6FAFF   CALL SalazanK.00404500
00455E4D  |.  85C0          TEST EAX,EAX
00455E4F  |.  7C 11         JL SHORT SalazanK.00455E62
00455E51  |.  40            INC EAX
00455E52  |.  33D2          XOR EDX,EDX
00455E54  |>  8B4D E8       /MOV ECX,DWORD PTR SS:[EBP-18]
00455E57  |.  0FB64C11 FF   |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1]
00455E5C  |.  03D9          |ADD EBX,ECX
00455E5E  |.  42            |INC EDX
00455E5F  |.  48            |DEC EAX
00455E60  |.^ 75 F2         \JNZ SHORT SalazanK.00455E54
00455E62  |>  81FB 88010000 CMP EBX,188                              ;  19--23位ascii码累加
00455E68  |.  75 04         JNZ SHORT SalazanK.00455E6E
00455E6A  |.  C645 E0 01    MOV BYTE PTR SS:[EBP-20],1               ;  【EBP-20】置1
00455E6E  |>  33DB          XOR EBX,EBX
00455E70  |.  8B45 E4       MOV EAX,DWORD PTR SS:[EBP-1C]
00455E73  |.  E8 88E6FAFF   CALL SalazanK.00404500
00455E78  |.  85C0          TEST EAX,EAX
00455E7A  |.  7C 11         JL SHORT SalazanK.00455E8D
00455E7C  |.  40            INC EAX
00455E7D  |.  33D2          XOR EDX,EDX
00455E7F  |>  8B4D E4       /MOV ECX,DWORD PTR SS:[EBP-1C]
00455E82  |.  0FB64C11 FF   |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1]
00455E87  |.  03D9          |ADD EBX,ECX
00455E89  |.  42            |INC EDX
00455E8A  |.  48            |DEC EAX
00455E8B  |.^ 75 F2         \JNZ SHORT SalazanK.00455E7F
00455E8D  |>  81FB 86010000 CMP EBX,186                              ;  25--29位ascii码累加
00455E93  |.  75 04         JNZ SHORT SalazanK.00455E99
00455E95  |.  C645 DF 01    MOV BYTE PTR SS:[EBP-21],1               ;  【EBP-21】置1
00455E99  |>  8A45 E3       MOV AL,BYTE PTR SS:[EBP-1D]
00455E9C  |.  2245 E2       AND AL,BYTE PTR SS:[EBP-1E]
00455E9F  |.  74 18         JE SHORT SalazanK.00455EB9
00455EA1  |.  807D E1 00    CMP BYTE PTR SS:[EBP-1F],0
00455EA5  |.  74 12         JE SHORT SalazanK.00455EB9
00455EA7  |.  807D E0 00    CMP BYTE PTR SS:[EBP-20],0
00455EAB  |.  74 0C         JE SHORT SalazanK.00455EB9
00455EAD  |.  807D DF 00    CMP BYTE PTR SS:[EBP-21],0
00455EB1  |.  74 06         JE SHORT SalazanK.00455EB9
00455EB3  |.  C645 FB 01    MOV BYTE PTR SS:[EBP-5],1
00455EB7  |.  EB 04         JMP SHORT SalazanK.00455EBD
00455EB9  |>  C645 FB 00    MOV BYTE PTR SS:[EBP-5],0
00455EBD  |>  33C0          XOR EAX,EAX
00455EBF  |.  5A            POP EDX
00455EC0  |.  59            POP ECX
00455EC1  |.  59            POP ECX
00455EC2  |.  64:8910       MOV DWORD PTR FS:[EAX],EDX
00455EC5  |.  68 E75E4500   PUSH SalazanK.00455EE7
00455ECA  |>  8D45 E4       LEA EAX,DWORD PTR SS:[EBP-1C]
00455ECD  |.  BA 05000000   MOV EDX,5
00455ED2  |.  E8 95E3FAFF   CALL SalazanK.0040426C
00455ED7  |.  8D45 FC       LEA EAX,DWORD PTR SS:[EBP-4]
00455EDA  |.  E8 69E3FAFF   CALL SalazanK.00404248
00455EDF  \.  C3            RETN

算法:注册码和用户名没有关系,注册码位数必须是29位,注册码的6 、12、18、24位可以是任意字符,其他的要分成5组,每组的ascii码累加和分别是:0x18D  0x18C  0x190   0x188  0x186  。下面注册机代码中先根据每组的和算出平均值,最后一位取累加和减去前四位的和,也就是每组都是前4位相同,最后一位不同而已。

[ATTACH]45996[/ATTACH]
 
这是关键call跟进后发现里面有好多call调用,执行到下面的循环累加过程时,查看堆栈的结果,应该是将29位注册码分成5部分,第一部分1—5位。第二部分:7-11位,第三部分:13-17位,第四部分:19—23位,第五部分:25-29位。29位中去掉了4位,每部分有5位。

注册机代码:这个只是个参考而已。。
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h>
#include <ctype.h>

int main(void) 
{  //注册名和计算没有关系,所以直接打印出注册码,
	//本来这个注册码组合就非常多,只是练习随便算出一个结果就行了。
	char sn[29];
	int i;
	//以下只是结果中的一种情况
	//前4位我取一样的值,第五位取判断累加和的值减去前4位的和。
	for (i=0;i<5;i++)   //第一组结果
	{
		sn[i]=0x18D/5;
		if (i==4)
		{
			sn[i]=0x18D-0x18D/5*4;//每组的第五位的值
		}
	}
	for (i=6;i<11;i++)   //第二组结果
	{
		sn[i]=0x18C/5;
		if (i==10)
		{
			sn[i]=0x18C-0x18C/5*4;//每组的第五位的值
		}
	}
	for (i=12;i<17;i++)   //第三组结果
	{
		sn[i]=0x190/5;
		if (i==16)
		{
			sn[i]=0x190-0x190/5*4;//每组的第五位的值
		}
	}
	for (i=18;i<23;i++)   //第四组结果
	{
		sn[i]=0x188/5;
		if (i==22)
		{
			sn[i]=0x188-0x188/5*4;//每组的第五位的值
		}
	}
	for (i=24;i<29;i++)   //第五组结果
	{
		sn[i]=0x186/5;
		if (i==28)
		{
			sn[i]=0x186-0x186/5*4;//每组的第五位的值
		}
	}
	 sn[5]='-'; sn[11]='-'; sn[17]='-'; sn[23]='-';

	for (i=0;i<29;i++)
	{
		printf("%c",sn[i]);
	}
		
	printf("\n\n");
	getchar();
	return 0; 
}


上传的附件:
2010-7-30 08:20
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
支持楼主!学习
2010-7-30 08:25
0
雪    币: 23
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
来学习的,需要研究一下
2010-7-30 09:00
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
CrackMe 2007->序列号->逍遥风->CZG CrackMe 分析

这个比较简单,但是当逆推计算公式时感觉很麻烦,后来就想直接照搬计算注册码的语句,之前看到论坛上有说明如何把汇编直接考到程序中,但当时也没仔细看,于是有了下面的代码,定义变量时用汇编中的各个寄存器和堆栈的名字,贴一个正确的注册码:pediy    3272156575

004015C5  |. /EB 09         JMP SHORT ECrackMe.004015D0
004015C7  |> |8B55 E0       /MOV EDX,DWORD PTR SS:[EBP-20]           ;  这个循环是计算注册码的关键代码
004015CA  |. |83C2 01       |ADD EDX,1
004015CD  |. |8955 E0       |MOV DWORD PTR SS:[EBP-20],EDX
004015D0  |> \8B45 E0        MOV EAX,DWORD PTR SS:[EBP-20]
004015D3  |.  3B45 E4       |CMP EAX,DWORD PTR SS:[EBP-1C]
004015D6  |.  7D 42         |JGE SHORT ECrackMe.0040161A
004015D8  |.  8B4D E0       |MOV ECX,DWORD PTR SS:[EBP-20]
004015DB  |.  51            |PUSH ECX                                ; /Arg1
004015DC  |.  8D4D EC       |LEA ECX,DWORD PTR SS:[EBP-14]           ; |
004015DF  |.  E8 1C030000   |CALL ECrackMe.00401900                  ; \这个call是依次循环取出输入注册名的每一位送到AL
004015E4  |.  0FBED0        |MOVSX EDX,AL
004015E7  |.  8B45 F0       |MOV EAX,DWORD PTR SS:[EBP-10]
004015EA  |.  03C2          |ADD EAX,EDX
004015EC  |.  8945 F0       |MOV DWORD PTR SS:[EBP-10],EAX
004015EF  |.  8B4D E0       |MOV ECX,DWORD PTR SS:[EBP-20]
004015F2  |.  C1E1 08       |SHL ECX,8
004015F5  |.  8B55 F0       |MOV EDX,DWORD PTR SS:[EBP-10]
004015F8  |.  33D1          |XOR EDX,ECX
004015FA  |.  8955 F0       |MOV DWORD PTR SS:[EBP-10],EDX
004015FD  |.  8B45 E0       |MOV EAX,DWORD PTR SS:[EBP-20]
00401600  |.  83C0 01       |ADD EAX,1
00401603  |.  8B4D E4       |MOV ECX,DWORD PTR SS:[EBP-1C]
00401606  |.  0FAF4D E0     |IMUL ECX,DWORD PTR SS:[EBP-20]
0040160A  |.  F7D1          |NOT ECX
0040160C  |.  0FAFC1        |IMUL EAX,ECX
0040160F  |.  8B55 F0       |MOV EDX,DWORD PTR SS:[EBP-10]
00401612  |.  0FAFD0        |IMUL EDX,EAX
00401615  |.  8955 F0       |MOV DWORD PTR SS:[EBP-10],EDX           ;  此时EDX中的值的10进制数就是正确的注册码。
00401618  |.^ EB AD         \JMP SHORT ECrackMe.004015C7             ;  后面的注册码比较函数就不在仔细跟了。
0040161A  |>  8B45 F0       MOV EAX,DWORD PTR SS:[EBP-10]
0040161D  |.  50            PUSH EAX                                 ;  下面这句是格式输出 %lu格式
0040161E  |.  68 54404000   PUSH ECrackMe.00404054                   ;  %lu
00401623  |.  8D4D DC       LEA ECX,DWORD PTR SS:[EBP-24]
00401626  |.  51            PUSH ECX
00401627  |.  E8 52070000   CALL <JMP.&MFC42.#2818>

这个比较简单,但是当逆推计算公式时感觉很麻烦,后来就想直接照搬计算注册码的语句,之前看到论坛上有说明如何把汇编直接考到程序中,但当时也没仔细看,于是有了下面的代码,定义变量时用汇编中的各个寄存器和堆栈的名字,这样可以把那个循环中的每一句都替换,最后输出edx的值,刚开始输出时用的是“%d”,结果发现是负数,后来跟踪了好久发现计算的都是对的,后来查看edx寄存器发现如果是有符号数的话就是输出的值,如果是无符号时就是正确的注册码了。后来改成printf("注册码:%lu\n",ebp10);后就正确了,  之前是printf("注册码:%lu\n",ebp10),真是疏忽呀。
贴一个正确的注册码:pediy    3272156575
#include <stdlib.h> 
#include <stdio.h> 
#include <string>
int main(void)
{
	char name[]={"pediy"};
	unsigned int ebp1c,ebp20,ebp10;
	unsigned int eax,ecx,edx,i;
	ebp20=0;
	ebp10=0x081276345;
	ebp1c=strlen(name);
	for (i=0;i<ebp1c;i++)
	{
		eax=name[i];//以下并不是汇编语句,只是定义的变量是汇编中的一些名字,
		edx=eax;  //具体的每一句是和上面的那个计算注册码循环中的代码一一对应。
		eax=ebp10;
		eax=eax+edx;
		ebp10=eax;
		ecx=ebp20;
		ecx=ecx*0x100;
		edx=ebp10;
		edx=edx^ecx;
		ebp10=edx;
		eax=ebp20;
		eax++;
		ecx=ebp1c;
		ecx=ecx*ebp20;
		ecx=~ecx;
		eax=eax*ecx;
		edx=ebp10;
		edx=edx*eax;
		ebp10=edx;
		ebp20++;

	}
	printf("注册名:%s\n",name);
	printf("注册码:%lu\n",ebp10);
	getchar();
	return 0;
}

2010-7-31 08:36
0
雪    币: 73
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
楼主不像是新手呀!
2010-7-31 09:09
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
CrackMe 2007->序列号->逍遥风->lnn1123 CrackMe0.11 算法分析

这个分析不是很难,可是后来在写注册机时怎么也没有写出来,后来又看了几遍论坛上的原帖,里面也没有这方面的分析,也没有给出一个注册码来,没办法,这次只能修改程序爆破了,,爆破的语句在下面分析中写出了。

00401112   .  6A 28         PUSH 28                                  ; /Count = 28 (40.)
00401114   .  8D45 BC       LEA EAX,DWORD PTR SS:[EBP-44]            ; |
00401117   .  50            PUSH EAX                                 ; |Buffer
00401118   .  FF35 04304000 PUSH DWORD PTR DS:[403004]               ; |hWnd = NULL
0040111E   .  E8 5B010000   CALL <JMP.&user32.GetWindowTextA>        ; \GetWindowTextA
00401123   .  8D75 BC       LEA ESI,DWORD PTR SS:[EBP-44]            ;  【EBP-44】保存输入用户名
00401126   .  AC            LODS BYTE PTR DS:[ESI]
00401127   .  3C 00         CMP AL,0                                 ;  判断用户名是否是空,
00401129   .  75 11         JNZ SHORT Crack.0040113C
0040112B   .  FF35 04304000 PUSH DWORD PTR DS:[403004]               ; /hWnd = NULL
00401131   .  E8 60010000   CALL <JMP.&user32.SetFocus>              ; \SetFocus
00401136   .  33C0          XOR EAX,EAX
00401138   .  C9            LEAVE
00401139   .  C2 1000       RETN 10
0040113C   >  8D45 BC       LEA EAX,DWORD PTR SS:[EBP-44]            ;  用户名不是空到这里,将用户名送EAX
0040113F   .  50            PUSH EAX
00401140   .  E8 6F010000   CALL Crack.004012B4                      ;  关键call,根据用户名计算出一个值。返回在ECX中
00401145   .  8D45 BC       LEA EAX,DWORD PTR SS:[EBP-44]
00401148   .  50            PUSH EAX                                 ; /String
00401149   .  E8 60010000   CALL <JMP.&kernel32.lstrlenA>            ; \取输入用户名的长度
0040114E   .  8BF8          MOV EDI,EAX                              ;  用户名长度送EDI,用作循环次数
00401150   .  8BC8          MOV ECX,EAX                              ;  ECX也是用户名长度
00401152   .  BB 01000000   MOV EBX,1                                ;  EBX赋初值1
00401157   .  33D2          XOR EDX,EDX                              ;  EDX置零
00401159   .  EB 1C         JMP SHORT Crack.00401177
0040115B   >  4F            DEC EDI                                  ;  循环计数值减一。初值是用户名的长度
0040115C   .  36:0FB6542F B>MOVZX EDX,BYTE PTR SS:[EDI+EBP-44]       ;  从用户名的末位开始读字符
00401162   .  33D3          XOR EDX,EBX                              ;  于EBX异或
00401164   .  0FAFD3        IMUL EDX,EBX                             ;  再与EBX相乘
00401167   .  83C3 05       ADD EBX,5
0040116A   .  3115 24304000 XOR DWORD PTR DS:[403024],EDX
00401170   .  C105 24304000>ROL DWORD PTR DS:[403024],5              ;  和【403024】异或后再乘以0x20
00401177   >  0BFF          OR EDI,EDI                               ;  判断是否循环结束
00401179   .^ 75 E0         JNZ SHORT Crack.0040115B
0040117B   .  A1 24304000   MOV EAX,DWORD PTR DS:[403024]
00401180   .  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX             ;  将【403024】的值放入【EBP-4】中保存
00401183   .  33C0          XOR EAX,EAX
00401185   .  6A 28         PUSH 28                                  ; /Count = 28 (40.)
00401187   .  8D85 3CFFFFFF LEA EAX,DWORD PTR SS:[EBP-C4]            ; |
0040118D   .  50            PUSH EAX                                 ; |Buffer
0040118E   .  FF35 08304000 PUSH DWORD PTR DS:[403008]               ; |hWnd = NULL
00401194   .  E8 E5000000   CALL <JMP.&user32.GetWindowTextA>        ; \取输入的注册码
00401199   .  33C9          XOR ECX,ECX
0040119B   .  33DB          XOR EBX,EBX                              ;  ECX EBX置零
0040119D   >  36:0FB69429 3>MOVZX EDX,BYTE PTR SS:[ECX+EBP-C4]       ;  循环取出注册码的每一位
004011A6   .  03DA          ADD EBX,EDX
004011A8   .  6BDB 10       IMUL EBX,EBX,10                          ;  先累加后再乘以0x10
004011AB   .  41            INC ECX
004011AC   .  3BC8          CMP ECX,EAX                              ;  判断是否循环结束
004011AE   .^ 75 ED         JNZ SHORT Crack.0040119D
004011B0   .  3B5D FC       CMP EBX,DWORD PTR SS:[EBP-4]             ;  上面上次计算的结果比较是否相等,相等则成功。
004011B3   .  74 15         JE SHORT Crack.004011CA                          ;此处修改成JMP 后既可以爆破。
004011B5   .  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
004011B7   .  68 30304000   PUSH Crack.00403030                      ; |Crackme V 0.11
004011BC   .  68 54304000   PUSH Crack.00403054                      ; |NO,try again
004011C1   .  6A 00         PUSH 0                                   ; |hOwner = NULL
004011C3   .  E8 C2000000   CALL <JMP.&user32.MessageBoxA>           ; \MessageBoxA
004011C8   .  EB 32         JMP SHORT Crack.004011FC
004011CA   >  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
004011CC   .  68 30304000   PUSH Crack.00403030                      ; |Crackme V 0.11
004011D1   .  68 3F304000   PUSH Crack.0040303F                      ; |Register successful!
004011D6   .  6A 00         PUSH 0                                   ; |hOwner = NULL
004011D8   .  E8 AD000000   CALL <JMP.&user32.MessageBoxA>           ; \MessageBoxA


2010-7-31 16:04
0
雪    币: 897
活跃值: (30)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
路过。。。。。
2010-8-1 08:06
0
雪    币: 72
活跃值: (392)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
这个不错的,谢谢楼主分享。
2010-8-1 08:58
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
CrackMe 2007->序列号->逍遥风->moon’s KGme #1 分析和注册机


这个脱壳很顺利,之后查找字符串,到以下位置。这个cm很简单,分析如下。
00447EB0  |.  55            PUSH EBP
00447EB1  |.  68 A17F4400   PUSH 123.00447FA1
00447EB6  |.  64:FF30       PUSH DWORD PTR FS:[EAX]
00447EB9  |.  64:8920       MOV DWORD PTR FS:[EAX],ESP
00447EBC  |>  8D55 F0       /LEA EDX,DWORD PTR SS:[EBP-10]
00447EBF  |.  8B86 D0020000 |MOV EAX,DWORD PTR DS:[ESI+2D0]
00447EC5  |.  E8 36C2FDFF   |CALL 123.00424100                       ;  取输入的用户名放于【EBP-10】
00447ECA  |.  8B55 F0       |MOV EDX,DWORD PTR SS:[EBP-10]
00447ECD  |.  8D45 FC       |LEA EAX,DWORD PTR SS:[EBP-4]
00447ED0  |.  E8 EFBCFBFF   |CALL 123.00403BC4
00447ED5  |.  8B45 FC       |MOV EAX,DWORD PTR SS:[EBP-4]
00447ED8  |.  E8 DFBCFBFF   |CALL 123.00403BBC                       ;  取输入的用户名长度
00447EDD  |.  83F8 06       |CMP EAX,6                               ;  判断是否大于等于6位,小于6的话重复上面循环
00447EE0  |.^ 7C DA         \JL SHORT 123.00447EBC                   ;  将输入注册名复制后追加到原注册名后
00447EE2  |.  8D45 F8       LEA EAX,DWORD PTR SS:[EBP-8]
00447EE5  |.  BA B87F4400   MOV EDX,123.00447FB8                     ;  xxxxxx
00447EEA  |.  E8 E5BAFBFF   CALL 123.004039D4
00447EEF  |.  BB 01000000   MOV EBX,1
00447EF4  |>  8D45 F8       /LEA EAX,DWORD PTR SS:[EBP-8]
00447EF7  |.  E8 90BEFBFF   |CALL 123.00403D8C
00447EFC  |.  8B55 FC       |MOV EDX,DWORD PTR SS:[EBP-4]
00447EFF  |.  8A541A FF     |MOV DL,BYTE PTR DS:[EDX+EBX-1]          ;  依次取出注册名每一位,循环6次,所以只取前6位
00447F03  |.  80C2 05       |ADD DL,5                                ;  注册名每位字符加5
00447F06  |.  885418 FF     |MOV BYTE PTR DS:[EAX+EBX-1],DL          ;  保存到这个地址。用于后面比较
00447F0A  |.  43            |INC EBX
00447F0B  |.  83FB 07       |CMP EBX,7
00447F0E  |.^ 75 E4         \JNZ SHORT 123.00447EF4
00447F10  |.  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]
00447F13  |.  BA C87F4400   MOV EDX,123.00447FC8                     ;  Hey, u r realy good!\n\rSend ur solution to moon.86@gmx.de!
00447F18  |.  E8 B7BAFBFF   CALL 123.004039D4
00447F1D  |.  8D55 EC       LEA EDX,DWORD PTR SS:[EBP-14]
00447F20  |.  8B86 EC020000 MOV EAX,DWORD PTR DS:[ESI+2EC]
00447F26  |.  E8 F9C4FFFF   CALL 123.00444424
00447F2B  |.  8B55 EC       MOV EDX,DWORD PTR SS:[EBP-14]            ;  取输入的注册码
00447F2E  |.  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]             ;  取计算出的真码
00447F31  |.  E8 96BDFBFF   CALL 123.00403CCC                        ;  比较注册码函数
00447F36  |.  75 26         JNZ SHORT 123.00447F5E                   ;  此处是爆破位置。
00447F38  |.  6A 00         PUSH 0
00447F3A  |.  8B45 F4       MOV EAX,DWORD PTR SS:[EBP-C]
00447F3D  |.  E8 3EBEFBFF   CALL 123.00403D80
00447F42  |.  8BD0          MOV EDX,EAX
00447F44  |.  B9 04804400   MOV ECX,123.00448004                     ;  Yeah, u got it!

算法看代码中的注释。
[B]一组正确的注册码:pediy    ujin~u[/B]
#include <stdlib.h> 
#include <stdio.h> 
#include <string>
int main(void)
{	//注册名注意最好是数字和字母,且字母不能是小写z,否则
	//计算出的注册码可能不容易输入,因为注册码是根据注册名每位
	//的ascii码加5得到的,而小写z和其后面的ascii码+5后会大于128.
	//注册名会单独保存一个位置且是6位,如果注册名大于6位则计算时只取
	//前6位计算,如果不够6位,则赋值输入的注册名并和输入的注册名合并,直到》=6位后就进入计算过程。
	char Name[]={"pediy"};
	const int n=6;
	int i;
	char RegName[n];  
	int NameLen=strlen(Name);
	if (NameLen>=n)
	{
		for (i=0;i<6;i++)
			RegName[i]=Name[i];
	}
	else
	{	int j=0;
		for (i=0;i<6;i++)
		{	
			if (j>NameLen-1)
			{
				j=0;
			}
			RegName[i]=Name[j];
			j++;
		}
	}
	printf("注册名:%s\n",Name);
	printf("注册码:");
	for (i=0;i<6;i++)
	{
		RegName[i]=RegName[i]+0x5;
		printf("%c",RegName[i]);
	}
	getchar();
	return 0;
}



2010-8-1 10:33
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
CrackMe 2007->序列号->逍遥风->Prolixe-KeygenMe#1 分析和注册机

这个CM分析了下算法,虽然计算注册码的call很好确定,但是要跟进去里面的call还有不少,后来就反复的试了好多次,主要用猜测的方法,同时要注意查看内存和堆栈的变化,比如在进入一个call前肯定要传参数,有时也要传入返回值保存的地方,所以主要查看call前面的几个语句的地址,F8不过call后在查看堆栈后的变化来猜测该call的功能,后来分析出计算注册码的过程(这步并没有在call里面,可以直接看到),计算出后有小写字母的话就转换大些等这些操作就是通过执行call后的变化猜出来的。
注册码分3部分,首尾部分是固定的字符,中间的字符数和输入的用户名位数相同,具体看代码。
00407FAD  |.  50            PUSH EAX                                 ; |Buffer
00407FAE  |.  68 E8030000   PUSH 3E8                                 ; |ControlID = 3E8 (1000.)
00407FB3  |.  53            PUSH EBX                                 ; |hWnd
00407FB4  |.  E8 97C6FFFF   CALL <JMP.&user32.GetDlgItemTextA>       ; \取输入的用户名,存放在【EBP-104】
00407FB9  |.  6A 1E         PUSH 1E                                  ; /Count = 1E (30.)
00407FBB  |.  8D85 FCFDFFFF LEA EAX,DWORD PTR SS:[EBP-204]           ; |
00407FC1  |.  50            PUSH EAX                                 ; |Buffer
00407FC2  |.  68 E9030000   PUSH 3E9                                 ; |ControlID = 3E9 (1001.)
00407FC7  |.  53            PUSH EBX                                 ; |hWnd
00407FC8  |.  E8 83C6FFFF   CALL <JMP.&user32.GetDlgItemTextA>       ; \取输入的注册码,存放于【EBP-204】
00407FCD  |.  80BD FCFDFFFF>CMP BYTE PTR SS:[EBP-204],0              ;  注册码是否是空?空则提示错误
00407FD4  |.  75 17         JNZ SHORT Keygen去.00407FED
00407FD6  |.  6A 40         PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00407FD8  |.  68 0C814000   PUSH Keygen去.0040810C                    ; |Error
00407FDD  |.  68 14814000   PUSH Keygen去.00408114                    ; |Enter a Serial
00407FE2  |.  53            PUSH EBX                                 ; |hOwner
00407FE3  |.  E8 88C6FFFF   CALL <JMP.&user32.MessageBoxA>           ; \MessageBoxA
00407FE8  |.  E9 B9000000   JMP Keygen去.004080A6
00407FED  |>  80BD FCFEFFFF>CMP BYTE PTR SS:[EBP-104],0              ;  用户名是否为空?空则提示错误
00407FF4  |.  75 17         JNZ SHORT Keygen去.0040800D
00407FF6  |.  6A 40         PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00407FF8  |.  68 0C814000   PUSH Keygen去.0040810C                    ; |Error
00407FFD  |.  68 24814000   PUSH Keygen去.00408124                    ; |Enter a Name
00408002  |.  53            PUSH EBX                                 ; |hOwner
00408003  |.  E8 68C6FFFF   CALL <JMP.&user32.MessageBoxA>           ; \MessageBoxA
00408008  |.  E9 99000000   JMP Keygen去.004080A6
0040800D  |>  8D85 F8FDFFFF LEA EAX,DWORD PTR SS:[EBP-208]
00408013  |.  8D95 FCFEFFFF LEA EDX,DWORD PTR SS:[EBP-104]           ;  用户名送EAX
00408019  |.  B9 00010000   MOV ECX,100
0040801E  |.  E8 19B8FFFF   CALL Keygen去.0040383C
00408023  |.  8B85 F8FDFFFF MOV EAX,DWORD PTR SS:[EBP-208]
00408029  |.  8D55 FC       LEA EDX,DWORD PTR SS:[EBP-4]
0040802C  |.  E8 E3FDFFFF   CALL Keygen去.00407E14                    ;  关键call,计算出注册码
00408031  |.  8D85 F4FDFFFF LEA EAX,DWORD PTR SS:[EBP-20C]
00408037  |.  8D95 FCFDFFFF LEA EDX,DWORD PTR SS:[EBP-204]
0040803D  |.  B9 00010000   MOV ECX,100
00408042  |.  E8 F5B7FFFF   CALL Keygen去.0040383C
00408047  |.  8B95 F4FDFFFF MOV EDX,DWORD PTR SS:[EBP-20C]
0040804D  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00408050  |.  E8 EBB8FFFF   CALL Keygen去.00403940                    ;  比较注册码
00408055      75 2F         JNZ SHORT Keygen去.00408086               ;  修改此处可以爆破。

贴出一组正确的注册码:用户名:123    注册码:HZF-RQX-GFD
#include <stdlib.h> 
#include <stdio.h> 
#include <string>
int main(void)
{	
	char name[]={"123"};
	//感觉这个CM的算法有些问题,当输入一些字符,比如有些小写字母
	//计算出来的就不一定对,主要原因应该是计算的超出了ASCII的范围。
	//比如我用pediy做用户名,计算出来的就不能用。
	//注册码必须以“HZF-”开始,以"-GDF"结束,中间的字符是下面计算的结果。
	int namelen=strlen(name);
	int ebx,ecx,edx,edi,i;
	printf("注册名:%s\n",name);
	ebx=1;
	for (i=0;i<namelen;i++)
	{	
		edi=name[i];
		edx=edi;
		ecx=ebx+5;
		edx=edx^ecx;
		edx=edx+edi;
		edx=edx+0x0A;
		ebx=ebx+1;
		if (edx>=0x61 && edx<=0x7A)
		{
			edx=edx-0x20; //小写转换成大写,其他字符不变。
		}
		name[i]=edx;  //用name数组保存计算的结果。
	}
	printf("注册码:HZF-%s-GFD\n",name);

	getchar();
	return 0;
}



2010-8-2 19:22
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
CrackMe 2007->序列号->逍遥风->Olivers CrackMe 分析

这个crackme分析起来不是很难,但就是很麻烦,中间对字符处理了不下5次。在注册码比较过程中采用的是明码,所以可以直接看到真正的注册码。由于编程水平不行,目前没有写出注册机,等以后再说。具体如下:
输入用户名:abcdef,注册码:123456          注册名必须大于等于6位。
第一步操作是将用户名倒序后得以字符串记作A;  此时为:fedcba
第二步操作是将用户名的N-1位字符分别取出,A的每一位分别转换成10进制,之后组成第二个字符串,用户名的第一位是a,A的第一个字符f的10进制是103,这样就组成a103,依次类推,最终得到字符B:a103b101c100d99e98,
第三步操作是字符串B的首位和末尾除外的字符进行一次重复操作,如B中“a”和“最后的8”不进行操作,得的结果是记作C:
103b101c100d99e9
110033bb110011cc110000dd9999ee99=C
第四步操作是将C 的每一位字符的ASCII码转换成10进制但是最后一位不进行操作。得到的结果记作:D即:
110033bb110011cc110000dd9999ee9
494948485151989849494848494999994949484848481001005757575710110157
第五步操作是从D的第三位开始取字符,并且每次间隔3位,知道D中的字符取到最后或者取得字符数达到0x30位。取出的字符记作:E
485199484949481
第六步操作是从D的第3位开始取字符,从E中取字符,将取出的2个字符分别转换成10进制的数字,然后求2个数相减的绝对值,之后用这个绝对值修改对应的E值,,D值每次循环都累加3,E的每次循环累加1。   直到将E中的每个值就修改完,此时得到的值就是真正的注册码。
001748175151013



00430CA2  |.  33DB          XOR EBX,EBX                              ;  EBX置零,用于下面的循环赋初值
00430CA4  |.  8D55 FC       LEA EDX,DWORD PTR SS:[EBP-4]
00430CA7  |.  8B86 DC010000 MOV EAX,DWORD PTR DS:[ESI+1DC]
00430CAD  |.  E8 669FFEFF   CALL <ocrackme.取字符文本>                    ;  取输入的用户名,存于ebp-4
00430CB2  |.  8D55 F8       LEA EDX,DWORD PTR SS:[EBP-8]
00430CB5  |.  8B86 E0010000 MOV EAX,DWORD PTR DS:[ESI+1E0]
00430CBB  |.  E8 589FFEFF   CALL <ocrackme.取字符文本>                    ;  取输入的注册码,存于ebp-8
00430CC0  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]             ;  用户名送EAX
00430CC3  |.  E8 702CFDFF   CALL <ocrackme.取字符串长度>                   ;  用户名长度
00430CC8  |.  83F8 06       CMP EAX,6                                ;  是否大于等于6位
00430CCB  |.  7D 0F         JGE SHORT ocrackme.00430CDC
00430CCD  |.  B8 F40E4300   MOV EAX,ocrackme.00430EF4                ;  Name must be at least 6 Characters long
00430CD2  |.  E8 65DEFFFF   CALL ocrackme.0042EB3C
00430CD7  |.  E9 E8010000   JMP ocrackme.00430EC4
00430CDC  |>  837D F8 00    CMP DWORD PTR SS:[EBP-8],0               ;  注册码是否是空。
00430CE0  |.  75 34         JNZ SHORT ocrackme.00430D16
00430CE2  |.  B8 240F4300   MOV EAX,ocrackme.00430F24                ;  Enter a Serial #
00430CE7  |.  E8 50DEFFFF   CALL ocrackme.0042EB3C
00430CEC  |.  E9 D3010000   JMP ocrackme.00430EC4
00430CF1  |>  8B45 FC       /MOV EAX,DWORD PTR SS:[EBP-4]            ;  取得输入的注册码
00430CF4  |.  E8 3F2CFDFF   |CALL <ocrackme.取字符串长度>                  ;  计算注册码长度,在返回值EAX中
00430CF9  |.  2BC3          |SUB EAX,EBX
00430CFB  |.  8B55 FC       |MOV EDX,DWORD PTR SS:[EBP-4]            ;  注册码送EDX
00430CFE  |.  8A5402 FF     |MOV DL,BYTE PTR DS:[EDX+EAX-1]          ;  从最后一位开始取注册码的每个字符
00430D02  |.  8D45 E4       |LEA EAX,DWORD PTR SS:[EBP-1C]
00430D05  |.  E8 562BFDFF   |CALL ocrackme.00403860
00430D0A  |.  8B55 E4       |MOV EDX,DWORD PTR SS:[EBP-1C]           ;  这个循环倒叙取出注册码并保存到一个位置。可由堆栈ebp-c中看出
00430D0D  |.  8D45 F4       |LEA EAX,DWORD PTR SS:[EBP-C]
00430D10  |.  E8 2B2CFDFF   |CALL ocrackme.00403940
00430D15  |.  43            |INC EBX
00430D16  |>  8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]            ;  输入的注册码送EAX
00430D19  |.  E8 1A2CFDFF   |CALL <ocrackme.取字符串长度>                  ;  取输入的注册码长度
00430D1E  |.  3BD8          |CMP EBX,EAX                             ;  是否已到注册码最后
00430D20  |.^ 7C CF         \JL SHORT ocrackme.00430CF1              ;  未到最后则继续循环
00430D22  |.  BB 01000000   MOV EBX,1
00430D27  |.  EB 36         JMP SHORT ocrackme.00430D5F
00430D29  |>  FF75 EC       /PUSH DWORD PTR SS:[EBP-14]              ;  这个循环是顺序取每个字符,并得到每个字符的十进制数
00430D2C  |.  8D45 E4       |LEA EAX,DWORD PTR SS:[EBP-1C]           ;  在ebp-14中存放,取得位数是字符长度减一
00430D2F  |.  8B55 FC       |MOV EDX,DWORD PTR SS:[EBP-4]
00430D32  |.  8A541A FF     |MOV DL,BYTE PTR DS:[EDX+EBX-1]
00430D36  |.  E8 252BFDFF   |CALL ocrackme.00403860
00430D3B  |.  FF75 E4       |PUSH DWORD PTR SS:[EBP-1C]
00430D3E  |.  8D55 E0       |LEA EDX,DWORD PTR SS:[EBP-20]
00430D41  |.  8B45 F4       |MOV EAX,DWORD PTR SS:[EBP-C]
00430D44  |.  0FB64418 FF   |MOVZX EAX,BYTE PTR DS:[EAX+EBX-1]
00430D49  |.  E8 2A5AFDFF   |CALL ocrackme.00406778
00430D4E  |.  FF75 E0       |PUSH DWORD PTR SS:[EBP-20]
00430D51  |.  8D45 EC       |LEA EAX,DWORD PTR SS:[EBP-14]
00430D54  |.  BA 03000000   |MOV EDX,3
00430D59  |.  E8 9A2CFDFF   |CALL ocrackme.004039F8
00430D5E  |.  43            |INC EBX
00430D5F  |>  8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00430D62  |.  E8 D12BFDFF   |CALL <ocrackme.取字符串长度>
00430D67  |.  3BD8          |CMP EBX,EAX
00430D69  |.^ 7C BE         \JL SHORT ocrackme.00430D29
00430D6B  |.  BB 01000000   MOV EBX,1
00430D70  |.  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]
00430D73  |.  E8 4429FDFF   CALL ocrackme.004036BC
00430D78  |.  EB 4D         JMP SHORT ocrackme.00430DC7
00430D7A  |>  8D45 DC       /LEA EAX,DWORD PTR SS:[EBP-24]
00430D7D  |.  8B55 EC       |MOV EDX,DWORD PTR SS:[EBP-14]           ;  这个循环是将上面ebp-14中的字符去掉首尾和最后一位后,
00430D80  |.  8A141A        |MOV DL,BYTE PTR DS:[EDX+EBX]            ;  每个字符在重复一遍,比如字符:a102b101,结果就是:110022bb1100
00430D83  |.  8850 01       |MOV BYTE PTR DS:[EAX+1],DL
00430D86  |.  C600 01       |MOV BYTE PTR DS:[EAX],1
00430D89  |.  8D55 DC       |LEA EDX,DWORD PTR SS:[EBP-24]
00430D8C  |.  8D45 D8       |LEA EAX,DWORD PTR SS:[EBP-28]
00430D8F  |.  E8 581AFDFF   |CALL ocrackme.004027EC
00430D94  |.  8D45 D4       |LEA EAX,DWORD PTR SS:[EBP-2C]
00430D97  |.  8B55 EC       |MOV EDX,DWORD PTR SS:[EBP-14]
00430D9A  |.  8A141A        |MOV DL,BYTE PTR DS:[EDX+EBX]
00430D9D  |.  8850 01       |MOV BYTE PTR DS:[EAX+1],DL
00430DA0  |.  C600 01       |MOV BYTE PTR DS:[EAX],1
00430DA3  |.  8D55 D4       |LEA EDX,DWORD PTR SS:[EBP-2C]
00430DA6  |.  8D45 D8       |LEA EAX,DWORD PTR SS:[EBP-28]
00430DA9  |.  B1 02         |MOV CL,2
00430DAB  |.  E8 0C1AFDFF   |CALL ocrackme.004027BC
00430DB0  |.  8D55 D8       |LEA EDX,DWORD PTR SS:[EBP-28]
00430DB3  |.  8D45 F0       |LEA EAX,DWORD PTR SS:[EBP-10]
00430DB6  |.  E8 212BFDFF   |CALL ocrackme.004038DC
00430DBB  |.  8D45 F4       |LEA EAX,DWORD PTR SS:[EBP-C]
00430DBE  |.  8B55 F0       |MOV EDX,DWORD PTR SS:[EBP-10]
00430DC1  |.  E8 7A2BFDFF   |CALL ocrackme.00403940
00430DC6  |.  43            |INC EBX
00430DC7  |>  8B45 EC        MOV EAX,DWORD PTR SS:[EBP-14]
00430DCA  |.  E8 692BFDFF   |CALL <ocrackme.取字符串长度>
00430DCF  |.  48            |DEC EAX
00430DD0  |.  3BD8          |CMP EBX,EAX
00430DD2  |.^ 7C A6         \JL SHORT ocrackme.00430D7A
00430DD4  |.  BB 01000000   MOV EBX,1
00430DD9  |.  8D45 EC       LEA EAX,DWORD PTR SS:[EBP-14]
00430DDC  |.  E8 DB28FDFF   CALL ocrackme.004036BC
00430DE1  |.  EB 1C         JMP SHORT ocrackme.00430DFF
00430DE3  |>  8D55 E4       /LEA EDX,DWORD PTR SS:[EBP-1C]           ;  这个循环是将上见的重复后的字符每位的ASCII码值转换为10进制保存,但最后一位不转换
00430DE6  |.  8B45 F4       |MOV EAX,DWORD PTR SS:[EBP-C]
00430DE9  |.  0FB64418 FF   |MOVZX EAX,BYTE PTR DS:[EAX+EBX-1]
00430DEE  |.  E8 8559FDFF   |CALL ocrackme.00406778
00430DF3  |.  8B55 E4       |MOV EDX,DWORD PTR SS:[EBP-1C]
00430DF6  |.  8D45 EC       |LEA EAX,DWORD PTR SS:[EBP-14]
00430DF9  |.  E8 422BFDFF   |CALL ocrackme.00403940
00430DFE  |.  43            |INC EBX
00430DFF  |>  8B45 F4        MOV EAX,DWORD PTR SS:[EBP-C]
00430E02  |.  E8 312BFDFF   |CALL <ocrackme.取字符串长度>
00430E07  |.  3BD8          |CMP EBX,EAX
00430E09  |.^ 7C D8         \JL SHORT ocrackme.00430DE3
00430E0B  |.  BB 03000000   MOV EBX,3
00430E10  |.  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]
00430E13  |.  E8 A428FDFF   CALL ocrackme.004036BC
00430E18  |.  83FB 30       CMP EBX,30
00430E1B  |.  7D 22         JGE SHORT ocrackme.00430E3F
00430E1D  |>  8D45 E4       /LEA EAX,DWORD PTR SS:[EBP-1C]
00430E20  |.  8B55 EC       |MOV EDX,DWORD PTR SS:[EBP-14]
00430E23  |.  8A541A FF     |MOV DL,BYTE PTR DS:[EDX+EBX-1]
00430E27  |.  E8 342AFDFF   |CALL ocrackme.00403860
00430E2C  |.  8B55 E4       |MOV EDX,DWORD PTR SS:[EBP-1C]
00430E2F  |.  8D45 F4       |LEA EAX,DWORD PTR SS:[EBP-C]
00430E32  |.  E8 092BFDFF   |CALL ocrackme.00403940
00430E37  |.  83C3 03       |ADD EBX,3
00430E3A  |.  83FB 30       |CMP EBX,30
00430E3D  |.^ 7C DE         \JL SHORT ocrackme.00430E1D
00430E3F  |>  BB 01000000   MOV EBX,1
00430E44  |.  EB 5B         JMP SHORT ocrackme.00430EA1
00430E46  |>  8B45 FC       /MOV EAX,DWORD PTR SS:[EBP-4]
00430E49  |.  E8 EA2AFDFF   |CALL <ocrackme.取字符串长度>
00430E4E  |.  03C3          |ADD EAX,EBX
00430E50  |.  8B55 EC       |MOV EDX,DWORD PTR SS:[EBP-14]
00430E53  |.  8A5402 FD     |MOV DL,BYTE PTR DS:[EDX+EAX-3]
00430E57  |.  8D45 E4       |LEA EAX,DWORD PTR SS:[EBP-1C]
00430E5A  |.  E8 012AFDFF   |CALL ocrackme.00403860                  ;  将DL从复制到一个地方
00430E5F  |.  8B45 E4       |MOV EAX,DWORD PTR SS:[EBP-1C]
00430E62  |.  E8 4159FDFF   |CALL ocrackme.004067A8                  ;  取得DL的十进制值,在eax
00430E67  |.  50            |PUSH EAX
00430E68  |.  8D45 E4       |LEA EAX,DWORD PTR SS:[EBP-1C]
00430E6B  |.  8B55 F4       |MOV EDX,DWORD PTR SS:[EBP-C]            ;  第五个字符串送EDX
00430E6E  |.  8A541A FF     |MOV DL,BYTE PTR DS:[EDX+EBX-1]          ;  依次取出每一位
00430E72  |.  E8 E929FDFF   |CALL ocrackme.00403860
00430E77  |.  8B45 E4       |MOV EAX,DWORD PTR SS:[EBP-1C]           ;  DL的值复制到其他地方
00430E7A  |.  E8 2959FDFF   |CALL ocrackme.004067A8                  ;  也转换成10进制
00430E7F  |.  5A            |POP EDX
00430E80  |.  2BC2          |SUB EAX,EDX
00430E82  |.  99            |CDQ
00430E83  |.  33C2          |XOR EAX,EDX
00430E85  |.  2BC2          |SUB EAX,EDX
00430E87  |.  8D55 E8       |LEA EDX,DWORD PTR SS:[EBP-18]
00430E8A  |.  E8 E958FDFF   |CALL ocrackme.00406778
00430E8F  |.  8D45 F4       |LEA EAX,DWORD PTR SS:[EBP-C]
00430E92  |.  E8 712CFDFF   |CALL ocrackme.00403B08
00430E97  |.  8B55 E8       |MOV EDX,DWORD PTR SS:[EBP-18]
00430E9A  |.  8A12          |MOV DL,BYTE PTR DS:[EDX]
00430E9C  |.  885418 FF     |MOV BYTE PTR DS:[EAX+EBX-1],DL
00430EA0  |.  43            |INC EBX
00430EA1  |>  8B45 F4        MOV EAX,DWORD PTR SS:[EBP-C]
00430EA4  |.  E8 8F2AFDFF   |CALL <ocrackme.取字符串长度>
00430EA9  |.  3BD8          |CMP EBX,EAX
00430EAB  |.^ 7E 99         \JLE SHORT ocrackme.00430E46
00430EAD  |.  8B45 F4       MOV EAX,DWORD PTR SS:[EBP-C]
00430EB0  |.  8B55 F8       MOV EDX,DWORD PTR SS:[EBP-8]
00430EB3  |.  E8 902BFDFF   CALL ocrackme.00403A48                   ;  真假注册码比较
00430EB8  |.  75 0A         JNZ SHORT ocrackme.00430EC4              ;  修改此处可以爆破
00430EBA  |.  B8 400F4300   MOV EAX,ocrackme.00430F40                ;  You Got It!!! :)
00430EBF  |.  E8 78DCFFFF   CALL ocrackme.0042EB3C


2010-8-3 11:14
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
CrackMe 2007->序列号->逍遥风->ThrawN的CrackMe 分析

输入注册名和注册码后无反应,后来发现不输入注册名时会提示字符要在2个字符以上,就查找这个字符串提示,来到关键断点处,注册名不能低于3个字符。

00444BFB  |.  8BF8          MOV EDI,EAX
00444BFD  |.  33C0          XOR EAX,EAX
00444BFF  |.  55            PUSH EBP
00444C00  |.  68 EB4C4400   PUSH UP8.00444CEB
00444C05  |.  64:FF30       PUSH DWORD PTR FS:[EAX]
00444C08  |.  64:8920       MOV DWORD PTR FS:[EAX],ESP
00444C0B  |.  8D55 FC       LEA EDX,DWORD PTR SS:[EBP-4]
00444C0E  |.  8B87 D0020000 MOV EAX,DWORD PTR DS:[EDI+2D0]
00444C14  |.  E8 87F1FDFF   CALL UP8.00423DA0                        ;  取输入的用户名,【EBP-4】
00444C19  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00444C1C  |.  E8 3FEFFBFF   CALL UP8.00403B60                        ;  取用户名长度
00444C21  |.  83F8 03       CMP EAX,3                                ;  判断用户名长度是否大于等于3
00444C24  |.  7D 15         JGE SHORT UP8.00444C3B
00444C26  |.  6A 00         PUSH 0                                   ; /Arg1 = 00000000
00444C28  |.  66:8B0D FC4C4>MOV CX,WORD PTR DS:[444CFC]              ; |
00444C2F  |.  B2 01         MOV DL,1                                 ; |
00444C31  |.  B8 084D4400   MOV EAX,UP8.00444D08                     ; |Name must be more than 2 characters!
00444C36  |.  E8 E5F9FFFF   CALL UP8.00444620                        ; \UP8.00444620
00444C3B  |>  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]             ;  用户名送EAX
00444C3E  |.  E8 1DEFFBFF   CALL UP8.00403B60                        ;  该call返回用户名长度
00444C43  |.  8BD8          MOV EBX,EAX
00444C45  |.  85DB          TEST EBX,EBX
00444C47  |.  7E 29         JLE SHORT UP8.00444C72
00444C49  |.  BE 01000000   MOV ESI,1                                ;  ESI赋初值1
00444C4E  |>  8D4D E8       /LEA ECX,DWORD PTR SS:[EBP-18]
00444C51  |.  8B45 FC       |MOV EAX,DWORD PTR SS:[EBP-4]            ;  用户名送EAX
00444C54  |.  0FB64430 FF   |MOVZX EAX,BYTE PTR DS:[EAX+ESI-1]       ;  取出用户名的每一位字符
00444C59  |.  BA 02000000   |MOV EDX,2                               ;  EDX赋值0x2
00444C5E  |.  E8 BD2EFCFF   |CALL UP8.00407B20                       ;  从堆栈中可知是该call会是EBP-18等于上面取得的字符ascii码
00444C63  |.  8B55 E8       |MOV EDX,DWORD PTR SS:[EBP-18]
00444C66  |.  8D45 F8       |LEA EAX,DWORD PTR SS:[EBP-8]
00444C69  |.  E8 FAEEFBFF   |CALL UP8.00403B68                       ;  将取出的每个字符的ASCII码合并
00444C6E  |.  46            |INC ESI
00444C6F  |.  4B            |DEC EBX
00444C70  |.^ 75 DC         \JNZ SHORT UP8.00444C4E
00444C72  |>  8D55 F0       LEA EDX,DWORD PTR SS:[EBP-10]
00444C75  |.  A1 48784400   MOV EAX,DWORD PTR DS:[447848]            ;  将【447848】的值送给EAX。
00444C7A  |.  E8 712EFCFF   CALL UP8.00407AF0                        ;  该call将EAX的值转换成有符号十进制表示%d
00444C7F  |.  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]
00444C82  |.  8B55 F8       MOV EDX,DWORD PTR SS:[EBP-8]
00444C85  |.  E8 EEECFBFF   CALL UP8.00403978                        ;  将根据用户名字符计算的结果存于ebp-C
00444C8A  |.  8D45 EC       LEA EAX,DWORD PTR SS:[EBP-14]
00444C8D  |.  8B4D F4       MOV ECX,DWORD PTR SS:[EBP-C]
00444C90  |.  8B55 F0       MOV EDX,DWORD PTR SS:[EBP-10]
00444C93  |.  E8 14EFFBFF   CALL UP8.00403BAC                        ;  将上面转换的十进制数和上面的结果按字符方式合并成一个
00444C98  |.  8D55 E4       LEA EDX,DWORD PTR SS:[EBP-1C]
00444C9B  |.  8B87 D4020000 MOV EAX,DWORD PTR DS:[EDI+2D4]
00444CA1  |.  E8 FAF0FDFF   CALL UP8.00423DA0                        ;  取出输入的假的注册码
00444CA6  |.  8B45 E4       MOV EAX,DWORD PTR SS:[EBP-1C]
00444CA9  |.  8B55 EC       MOV EDX,DWORD PTR SS:[EBP-14]
00444CAC  |.  E8 BFEFFBFF   CALL UP8.00403C70                        ;  比较真假注册码是否相同
00444CB1  |.  75 15         JNZ SHORT UP8.00444CC8                   ;  修改此处可以爆破
00444CB3  |.  6A 00         PUSH 0                                   ; /Arg1 = 00000000
00444CB5  |.  66:8B0D FC4C4>MOV CX,WORD PTR DS:[444CFC]              ; |
00444CBC  |.  B2 02         MOV DL,2                                 ; |
00444CBE  |.  B8 384D4400   MOV EAX,UP8.00444D38                     ; |Correct!
00444CC3  |.  E8 58F9FFFF   CALL UP8.00444620                        ; \UP8.00444620

上面【447848】的值计算方法是:先取C:盘的序列号,再乘以2,  得值A,将A转换成10进制,取其第四位的数字和A相乘,得值B,B再乘以3的值就是送入【447848】的值。
反汇编分析如下:
00444B18  |.  64:8920       MOV DWORD PTR FS:[EAX],ESP
00444B1B  |.  6A 00         PUSH 0                                   ; /pFileSystemNameSize = NULL
00444B1D  |.  6A 00         PUSH 0                                   ; |pFileSystemNameBuffer = NULL
00444B1F  |.  8D45 F0       LEA EAX,DWORD PTR SS:[EBP-10]            ; |
00444B22  |.  50            PUSH EAX                                 ; |pFileSystemFlags
00444B23  |.  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]             ; |
00444B26  |.  50            PUSH EAX                                 ; |pMaxFilenameLength
00444B27  |.  56            PUSH ESI                                 ; |pVolumeSerialNumber
00444B28  |.  68 00010000   PUSH 100                                 ; |MaxVolumeNameSize = 100 (256.)
00444B2D  |.  8D85 F0FEFFFF LEA EAX,DWORD PTR SS:[EBP-110]           ; |
00444B33  |.  50            PUSH EAX                                 ; |VolumeNameBuffer
00444B34  |.  68 E84B4400   PUSH UP8.00444BE8                        ; |c:\
00444B39  |.  E8 2A15FCFF   CALL <JMP.&KERNEL32.GetVolumeInformation>; \GetVolumeInformationA
00444B3E  |.  8B06          MOV EAX,DWORD PTR DS:[ESI]               ;  取的的c:\序列号送EAX
00444B40  |.  03C0          ADD EAX,EAX                              ;  序列号乘以2
00444B42  |.  8BF0          MOV ESI,EAX
00444B44  |.  8D95 ECFEFFFF LEA EDX,DWORD PTR SS:[EBP-114]
00444B4A  |.  8BC6          MOV EAX,ESI
00444B4C  |.  E8 9F2FFCFF   CALL UP8.00407AF0                        ;  将序列号转换成10进制表示。
00444B51  |.  8B95 ECFEFFFF MOV EDX,DWORD PTR SS:[EBP-114]           ;  EBP-114中就是转换成的10进制
00444B57  |.  8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
00444B5D  |.  E8 6EF2FDFF   CALL UP8.00423DD0                        ;  再将10进制数转换成字符串保存
00444B62  |.  8D55 F8       LEA EDX,DWORD PTR SS:[EBP-8]
00444B65  |.  8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
00444B6B  |.  E8 30F2FDFF   CALL UP8.00423DA0
00444B70  |.  8D45 FC       LEA EAX,DWORD PTR SS:[EBP-4]
00444B73  |.  8B55 F8       MOV EDX,DWORD PTR SS:[EBP-8]
00444B76  |.  8A52 03       MOV DL,BYTE PTR DS:[EDX+3]               ;  十进制数的第4位送DL,从0开始的话就是第三位
00444B79  |.  E8 0AEFFBFF   CALL UP8.00403A88
00444B7E  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00444B81  |.  E8 D62FFCFF   CALL UP8.00407B5C                        ;  取出并转换成数字,
00444B86  |.  F7EE          IMUL ESI                                 ;  将上面序列号乘以2后的值再乘以转换成10进制数的第四位。
00444B88  |.  8D0440        LEA EAX,DWORD PTR DS:[EAX+EAX*2]         ;  再乘以0x3
00444B8B  |.  A3 48784400   MOV DWORD PTR DS:[447848],EAX            ;  将结果送入【447848】,用于后面注册码的计算

贴出一组正确的注册码:用户名“pediy”,注册码是:“-1670752387065646979”
算法见注册机中注释
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
int sn();
int main(void)
{       
        //这个的算法也很简单,注册码是由2个字符串合并得到的,第一个字符串
        //是先求出c盘的序列号并*2,得值A,将A转换成10进制取第四位数字和A相乘后再乘以0x3所得的值按10进制输出。
        //第二部分是将输入的用户名的每个字符的ASCII码(16进制表示)转换成字符串
        //如用户名“pediy”,注册码是:“-1670752387065646979”
        char name[]={"pediy"};
       
        printf("注册名:%s\n",name);
        printf("注册码:%d",sn());  //输出根据序列号计算出的值。
       
        int namelen=strlen(name);
        int i;
        for (i=0;i<namelen;i++) //此处就不转换成字符串了,直接打印输出。
        {
                printf("%LX",name[i]);  //此处必须是“X”,因为小写的得到的注册码是错误的
        }
        printf("\n\n");
        getchar();
        return 0;
}

int sn()   //取硬盘序列号并计算出一个值
{
        char pathName[]={"c:\\"};
        char vName[255];
        char fName[255];
        unsigned long int Serial;
        GetVolumeInformation(pathName,vName,255,&Serial,0,0,fName,255);
        Serial=Serial*2;  //序列号*2
        char buffer[255];
        itoa(Serial,buffer,10);//转换成10进制
        char n=buffer[3]-0x30;        //取其第三位,得的值是该数字的ascii码-0x30
        Serial=Serial*n;        //和上面的数字相乘
        Serial=Serial*0x3;    //再乘以3
        return Serial;

}
2010-8-4 11:59
0
雪    币: 72
活跃值: (392)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
谢谢楼主分享。
2010-8-4 12:14
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
CrackMe 2007->序列号->逍遥风->DTC。CrackMe10 分析

查找字符串,来到以下地方,分析如下:脱壳用论坛上的软件脱的

0040119B   .  6A 33         PUSH 33                                  ; /Count = 33 (51.)
0040119D   .  68 2C624000   PUSH keygenme.0040622C                   ; |Buffer = keygenme.0040622C
004011A2   .  68 D1070000   PUSH 7D1                                 ; |ControlID = 7D1 (2001.)
004011A7   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
004011AA   .  E8 AF010000   CALL <JMP.&user32.GetDlgItemTextA>       ; \取输入的用户名
004011AF   .  6BC0 05       IMUL EAX,EAX,5                           ;  用户名长度*0x5;
004011B2   .  3D FA000000   CMP EAX,0FA                              ;  是否大于等于0x0FA
004011B7   .  0F87 89000000 JA keygenme.00401246                     ;  是否小于等于0x1E,即用户名长度大于5小于50;
004011BD   .  83F8 1E       CMP EAX,1E
004011C0   .  0F82 80000000 JB keygenme.00401246
004011C6   .  6A 00         PUSH 0                                   ; /IsSigned = FALSE
004011C8   .  6A 00         PUSH 0                                   ; |pSuccess = NULL
004011CA   .  68 D2070000   PUSH 7D2                                 ; |ControlID = 7D2 (2002.)
004011CF   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
004011D2   .  E8 81010000   CALL <JMP.&user32.GetDlgItemInt>         ; \GetDlgItemInt
004011D7   .  A3 5F624000   MOV DWORD PTR DS:[40625F],EAX            ;  取注册码输入框中的值,看来一定要输入数字
004011DC   .  68 2C624000   PUSH keygenme.0040622C
004011E1   .  E8 C2000000   CALL keygenme.004012A8                   ;  关键call跟进。
004011E6   .  803D 63624000>CMP BYTE PTR DS:[406263],1               ;  关键call中会对【406263】设置个标志,在这判断
004011ED   .  74 43         JE SHORT keygenme.00401232               ;  若为“1”就跳到失败处,否则成功。

关键算法call跟进后如下:

004012A8  /$  55            PUSH EBP
004012A9  |.  8BEC          MOV EBP,ESP
004012AB  |.  803D B4124000>CMP BYTE PTR DS:[4012B4],0CC
004012B2  |.  74 53         JE SHORT keygenme.00401307
004012B4  |.  33C0          XOR EAX,EAX
004012B6  |.  33C9          XOR ECX,ECX
004012B8  |.  803D D4124000>CMP BYTE PTR DS:[4012D4],0CC
004012BF  |.  74 46         JE SHORT keygenme.00401307
004012C1  |.  33D2          XOR EDX,EDX
004012C3  |.  8B55 08       MOV EDX,DWORD PTR SS:[EBP+8]             ;  EDX是输入的用户名
004012C6  |>  8A02          /MOV AL,BYTE PTR DS:[EDX]                ;  依次取出注册名的每一个字符送入AL
004012C8  |.  84C0          |TEST AL,AL                              ;  字符是否取完?
004012CA  |.  74 08         |JE SHORT keygenme.004012D4              ;  取完则跳出循环
004012CC  |.  03C8          |ADD ECX,EAX
004012CE  |.  C1C1 08       |ROL ECX,8
004012D1  |.  42            |INC EDX
004012D2  |.^ EB F2         \JMP SHORT keygenme.004012C6
004012D4  |>  83F1 02       XOR ECX,2
004012D7  |.  83E9 50       SUB ECX,50
004012DA  |.  81F1 37130000 XOR ECX,1337
004012E0  |.  56            PUSH ESI
004012E1  |.  66:8B35 79614>MOV SI,WORD PTR DS:[406179]
004012E8  |.  66:03CE       ADD CX,SI
004012EB  |.  803D FA124000>CMP BYTE PTR DS:[4012FA],0CC
004012F2  |.  74 13         JE SHORT keygenme.00401307
004012F4  |.  5E            POP ESI
004012F5  |.  A1 5F624000   MOV EAX,DWORD PTR DS:[40625F]          【40625f】存放的是先前取得的注册码,是一个16进制数字。
004012FA  |.  3BC1          CMP EAX,ECX
004012FC  |.  75 04         JNZ SHORT keygenme.00401302
004012FE  |.  33C0          XOR EAX,EAX
00401300  |.  EB 0E         JMP SHORT keygenme.00401310
00401302  |>  33C0          XOR EAX,EAX
00401304  |.  40            INC EAX
00401305  |.  EB 10         JMP SHORT keygenme.00401317
00401307  |>  C605 63624000>MOV BYTE PTR DS:[406263],1      
0040130E  |.  EB 07         JMP SHORT keygenme.00401317
00401310  |>  C605 63624000>MOV BYTE PTR DS:[406263],0
00401317  |>  C9            LEAVE
00401318  \.  C2 0400       RETN 4

算法:用户名长度大于5小于50位,注册码必须是数字,根据用户名计算出一个值,然后和输入的注册码比较,相等就在一个位置置0,不相等就置1,然后判断该位置的值。

做这个的时候要用到循环移位,但是c语言中的移位运算符并不是循环移位的,后来在网上搜到一个代码
假设移位的数字在ecx中:
if (ecx & 0x80000000)
        {
                ecx=ecx<<1;
                ecx=ecx | 0x01;
        }       
        else
                ecx=ecx<<1;
        }
一组正确的注册码:abcdef     1690755840

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

int main(void)
{       
        char name[]={"abcdef"};
        int i,j,namelen;
        unsigned long int ecx,eax;
        eax=0;
        ecx=0;
        namelen=strlen(name);
        for (i=0;i<namelen;i++)
        {
                eax=name[i];
                ecx=ecx+eax;
                for (j=0;j<8;j++)
                {
                        if (ecx & 0x80000000)  //循环左移一位运算,
                        {
                                ecx=ecx<<1;
                                ecx=ecx | 0x01;
                        }       
                        else
                                ecx=ecx<<1;
                }       
        }
        ecx=ecx^0x2;
        ecx=ecx-0x50;
        ecx=ecx^0x1337;
        ecx=ecx+0x07DA;

        printf("注册名:%s\n",name);
        printf("注册码:%d\n",ecx);
        printf("\n\n");
        getchar();
        return 0;
}
2010-8-5 17:37
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
CrackMe 2007->序列号->逍遥风->Rith—CrackMe1 分析
一组正确的注册码:ABCDEF   f6d2bh
不知这个cm有问题还是程序有问题,还是我分析的不彻底,有人知道的话请指出。计算出来的值如果超过0x7F的话就是错误的注册码,全部都小于0x7F时才正确,也就是超过了ascii表的范围显示出来的就不正确。注册名不能小于5位,注册码和注册名位数要相同,取出注册名的每一位和固定字串中的每一位后计算出一个值。

0040159A   .  56            PUSH ESI
0040159B   .  8BF1          MOV ESI,ECX
0040159D   .  57            PUSH EDI
0040159E   .  68 48304000   PUSH Rith_Cra.00403048                   ;  31415926535897932384
004015A3   .  8D4C24 14     LEA ECX,DWORD PTR SS:[ESP+14]
004015A7   .  897424 1C     MOV DWORD PTR SS:[ESP+1C],ESI
004015AB   .  E8 FA020000   CALL <JMP.&MFC42.#537>
004015B0   .  6A 01         PUSH 1
004015B2   .  8BCE          MOV ECX,ESI
004015B4   .  C74424 28 000>MOV DWORD PTR SS:[ESP+28],0
004015BC   .  E8 E3020000   CALL <JMP.&MFC42.#6334>
004015C1   .  8B7E 60       MOV EDI,DWORD PTR DS:[ESI+60]            ;  取得用户名,送EDI
004015C4   .  8B5F F8       MOV EBX,DWORD PTR DS:[EDI-8]             ;  用户名长度送EBX
004015C7   .  83FB 05       CMP EBX,5                                ;  EBX中用户名长度不能小于5
004015CA   .  7C 7E         JL SHORT Rith_Cra.0040164A
004015CC   .  8B46 64       MOV EAX,DWORD PTR DS:[ESI+64]            ;  注册码送EAX
004015CF   .  894424 14     MOV DWORD PTR SS:[ESP+14],EAX
004015D3   .  3958 F8       CMP DWORD PTR DS:[EAX-8],EBX             ;  比较用户名长度和注册码长度
004015D6   .  75 72         JNZ SHORT Rith_Cra.0040164A              ;  不等就跳走
004015D8   .  83FB 14       CMP EBX,14                               ;  用户名长度是否大于0x14,是否大于20位
004015DB   .  7F 6D         JG SHORT Rith_Cra.0040164A
004015DD   .  33C9          XOR ECX,ECX
004015DF   .  85DB          TEST EBX,EBX
004015E1   .  7E 54         JLE SHORT Rith_Cra.00401637
004015E3   .  8B7424 10     MOV ESI,DWORD PTR SS:[ESP+10]            ;  取字串“31415926535897932384”
004015E7   >  8A040F        MOV AL,BYTE PTR DS:[EDI+ECX]             ;  逐位取出用户名
004015EA   .  0FBE2C31      MOVSX EBP,BYTE PTR DS:[ECX+ESI]          ;  逐位取出刚才字串中的字符
004015EE   .  0FBEC0        MOVSX EAX,AL
004015F1   .  99            CDQ
004015F2   .  F7FD          IDIV EBP
004015F4   .  8BC2          MOV EAX,EDX                              ;  2个字符ascii码相除
004015F6   .  D1E0          SHL EAX,1                                ;  商值乘以0x2,左移一位相当于*2
004015F8   .  83F8 7B       CMP EAX,7B
004015FB   .  7E 03         JLE SHORT Rith_Cra.00401600
004015FD   .  83E8 1A       SUB EAX,1A                               ;  若大于0x7B,就减去0x1A
00401600   >  83F8 41       CMP EAX,41
00401603   .  7D 09         JGE SHORT Rith_Cra.0040160E
00401605   .  BA 82000000   MOV EDX,82                               ;  是否小于0x41,小的话就0x82-该值
0040160A   .  2BD0          SUB EDX,EAX
0040160C   .  8BC2          MOV EAX,EDX
0040160E   >  83F8 5B       CMP EAX,5B
00401611   .  7E 12         JLE SHORT Rith_Cra.00401625
00401613   .  83F8 61       CMP EAX,61                               ;  若<=0x5B 且 >=0x61  就跳到下面
00401616   .  7D 0D         JGE SHORT Rith_Cra.00401625
00401618   .  99            CDQ
00401619   .  BD 0A000000   MOV EBP,0A
0040161E   .  F7FD          IDIV EBP
00401620   .  83C2 30       ADD EDX,30
00401623   .  8BC2          MOV EAX,EDX
00401625   >  8B5424 14     MOV EDX,DWORD PTR SS:[ESP+14]
00401629   .  38040A        CMP BYTE PTR DS:[EDX+ECX],AL
0040162C   .  75 1C         JNZ SHORT Rith_Cra.0040164A
0040162E   .  41            INC ECX
0040162F   .  3BCB          CMP ECX,EBX
00401631   .^ 7C B4         JL SHORT Rith_Cra.004015E7
00401633   .  8B7424 18     MOV ESI,DWORD PTR SS:[ESP+18]
00401637   >  6A 00         PUSH 0
00401639   .  68 34304000   PUSH Rith_Cra.00403034                   ;  Congratulations!
0040163E   .  68 20304000   PUSH Rith_Cra.00403020                   ;  Well done cracker!

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

int main(void)
{       
        char name[]={"ABCDEF"};
//不知这个cm有问题还是程序有问题,计算出来的值如果超过0x7F的话就是错误
        //的注册码,全部都小于0x7F时才正确,也就是超过了ascii表的范围。
        //注册名不能小于5位,注册码和注册名位数要相同,取出注册名的每一位和
        //固定字串中的每一位后计算出一个值。
        printf("注册名:%s\n",name);
        printf("注册名:");
        char table[]={"31415926535897932384"};
        int i,j,namelen,tablelen;
         int eax,ebx,ecx,edx,ebp;
        namelen=strlen(name);
        tablelen=strlen(table);
        for (i=0;i<namelen;i++)
        {
                eax=name[i];
                ebp=table[i];
                edx=0;
       
                edx=eax % ebp;
                eax=edx;
                eax=eax*0x2;
                if (eax>0x7B)
                {
                        eax=eax-0x1A;
                }
                if (eax<0x41)
                {
                        eax=0x82-eax;
                }
                if (eax>0x5B )
                {
                        if (eax<0x61)
                        {
                                edx=0;
                                ebp=0x0A;
                                edx=eax % ebp;
                                edx=edx+0x30;
                        eax=edx;
                        }
                }
        printf("%c",eax);       
        }
               
        printf("\n\n");
        getchar();
        return 0;
}
2010-8-6 12:22
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
CrackMe 2007->序列号->逍遥风->CodeFantasy CrackMe 分析


OD载入程序,用“超级字符串查找”发现有注册成功的提示,下断点,跟踪如下:
00408DDC  |> \68 FF000000   PUSH 0FF                                 ; /Count = FF (255.); Case 3EA of switch 00408DBB
00408DE1  |.  68 9CA24000   PUSH CodeFant.0040A29C                   ; |Buffer = CodeFant.0040A29C
00408DE6  |.  68 F2030000   PUSH 3F2                                 ; |ControlID = 3F2 (1010.)
00408DEB  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]             ; |
00408DEE  |.  50            PUSH EAX                                 ; |hWnd
00408DEF  |.  E8 68B9FFFF   CALL <JMP.&user32.GetDlgItemTextA>       ; \取用户名
00408DF4  |.  8D45 B4       LEA EAX,DWORD PTR SS:[EBP-4C]
00408DF7  |.  BA 9CA24000   MOV EDX,CodeFant.0040A29C
00408DFC  |.  B9 FF000000   MOV ECX,0FF
00408E01  |.  E8 6AAAFFFF   CALL CodeFant.00403870
00408E06  |.  837D B4 00    CMP DWORD PTR SS:[EBP-4C],0              ;  用户名不为空
00408E0A  |.  0F84 9E000000 JE CodeFant.00408EAE
00408E10  |.  68 FF000000   PUSH 0FF                                 ; /Count = FF (255.)
00408E15  |.  68 9CA34000   PUSH CodeFant.0040A39C                   ; |Buffer = CodeFant.0040A39C
00408E1A  |.  68 F3030000   PUSH 3F3                                 ; |ControlID = 3F3 (1011.)
00408E1F  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]             ; |
00408E22  |.  50            PUSH EAX                                 ; |hWnd
00408E23  |.  E8 34B9FFFF   CALL <JMP.&user32.GetDlgItemTextA>       ; \取输入的注册码
00408E28  |.  8D45 AC       LEA EAX,DWORD PTR SS:[EBP-54]
00408E2B  |.  BA 9CA24000   MOV EDX,CodeFant.0040A29C
00408E30  |.  B9 FF000000   MOV ECX,0FF
00408E35  |.  E8 36AAFFFF   CALL CodeFant.00403870
00408E3A  |.  8B45 AC       MOV EAX,DWORD PTR SS:[EBP-54]
00408E3D  |.  8D55 B0       LEA EDX,DWORD PTR SS:[EBP-50]
00408E40  |.  E8 23FCFFFF   CALL CodeFant.00408A68                   ;  关键call,根据用户名计算一个值
00408E45  |.  8B45 B0       MOV EAX,DWORD PTR SS:[EBP-50]
00408E48  |.  50            PUSH EAX
00408E49  |.  8D45 A8       LEA EAX,DWORD PTR SS:[EBP-58]
00408E4C  |.  BA 9CA34000   MOV EDX,CodeFant.0040A39C
00408E51  |.  B9 FF000000   MOV ECX,0FF
00408E56  |.  E8 15AAFFFF   CALL CodeFant.00403870
00408E5B  |.  8B55 A8       MOV EDX,DWORD PTR SS:[EBP-58]
00408E5E  |.  58            POP EAX
00408E5F  |.  E8 84ABFFFF   CALL CodeFant.004039E8
00408E64  |.  75 48         JNZ SHORT CodeFant.00408EAE
00408E66  |.  6A 40         PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00408E68  |.  68 AC8F4000   PUSH CodeFant.00408FAC                   ; |注册提示
00408E6D  |.  68 B88F4000   PUSH CodeFant.00408FB8                   ; |恭喜您,注册码正确!
00408E72  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]             ; |
00408E75  |.  50            PUSH EAX                                 ; |hOwner
00408E76  |.  E8 19B9FFFF   CALL <JMP.&user32.MessageBoxA>           ; \MessageBoxA

注册码计算的关键call就不贴了,计算过程如下:分别取出用户名的每一位,其ascii码值+0xA,并转换成16进制表示,且16进制的字母用大写表示,把用户名的所有字符都转换完后就得到了注册码。如:pediy  对应的注册码:7A6F6E7383      p的ascii值0x70 加上0xA 得0x7A,以此类推,y的ascii码:0x79,加0xA后是0x83;
注册机:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{	
	char name[]={"pediy"};
	int i;
	int namelen=strlen(name);
	printf("注册名:%s\n",name);
	printf("注册码:");
	for (i=0;i<namelen;i++)
	{
		printf("%X",name[i]+0xA);
	}
	
	getchar();
	return 0;
}


2010-8-7 14:55
0
游客
登录 | 注册 方可回帖
返回
//