creantan 发表于 2009-2-3 22:24

Zapline 转载CM(第7天) 算法分析

【文章标题】: ZAPLINE (CM--第七天)算法分析
【文章作者】: creantan
【作者邮箱】: creantan@126.com
【作者主页】: www.crack-me.com
【下载地址】: http://bbs.52pojie.cn/thread-18399-1-1.html
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
PEID查壳->ASPack 2.x (without poly) -> Alexey Solodovnikov
脱之
瞎输一个假码试运行,点Check没反应。。。。
下断bp GetDlgItemTextA...
断下返回
找到关键点
第一部分:
00401528|.68 00010000   push    100                              ; /Count = 100 (256.)
0040152D|.8D85 00FFFFFF lea   eax, dword ptr          ; |
00401533|.50            push    eax                              ; |Buffer
00401534|.6A 65         push    65                               ; |ControlID = 65 (101.)
00401536|.FF75 08       push    dword ptr                 ; |hWnd = 001C0B98 ('TheBigMan's CrackMe #6',class='#32770')
00401539|.E8 FA010000   call    <jmp.&USER32.GetDlgItemTextA>    ; \GetDlgItemTextA
0040153E|.89C3          mov   ebx, eax                         ;取用户名,eax保存用户名长度
00401540|.09DB          or      ebx, ebx
00401542|.75 04         jnz   short 00401548                   ;判断用户名是否为空
00401544|.31C0          xor   eax, eax
00401546|.EB 50         jmp   short 00401598
00401548|>BF BC020000   mov   edi, 2BC
0040154D|.BE 30000000   mov   esi, 30
00401552|.B8 48000000   mov   eax, 48
00401557|.99            cdq
00401558|.F7FB          idiv    ebx
0040155A|.29C6          sub   esi, eax
0040155C|.8D34B6      lea   esi, dword ptr
0040155F|.29F7          sub   edi, esi
00401561|.6BFF 6B       imul    edi, edi, 6B
00401564|.81EF 6CCF0000 sub   edi, 0CF6C
0040156A|.81FF 00230000 cmp   edi, 2300                        ;checkLen = (0x2BC - (0x30 - 0x48 / nameLen) * 5) * 0x6B - 0x0CF6C;
00401570|.7F 08         jg      short 0040157A                   ;用户名长度检验
00401572|.81FF 90010000 cmp   edi, 190
00401578|.7D 04         jge   short 0040157E
0040157A|>31C0          xor   eax, eax
0040157C|.EB 1A         jmp   short 00401598
0040157E|>8D85 00FFFFFF lea   eax, dword ptr
00401584|.50            push    eax                              ;用户名
00401585|.53            push    ebx                              ;用户名长度
00401586|.FF75 08       push    dword ptr
00401589|.E8 77FDFFFF   call    00401305                         ;关键CALL
F7进入算法第二部分:
0040139E|.68 00010000   push    100                              ; /Count = 100 (256.)
004013A3|.8D85 E1FCFFFF lea   eax, dword ptr          ; |
004013A9|.50            push    eax                              ; |Buffer
004013AA|.6A 66         push    66                               ; |ControlID = 66 (102.)
004013AC|.FF75 08       push    dword ptr                 ; |hWnd
004013AF|.E8 84030000   call    <jmp.&USER32.GetDlgItemTextA>    ; \GetDlgItemTextA
004013B4|.09C0          or      eax, eax
004013B6|.0F84 48010000 je      00401504                         ;判断假码是否为空
004013BC|.B8 CF110000   mov   eax, 11CF
004013C1|.0FB68D E1FCFF>movzx   ecx, byte ptr           ;假码第一个字符
004013C8|.99            cdq
004013C9|.F7F9          idiv    ecx
004013CB|.83FA 17       cmp   edx, 17                        ;模7余数与0x17比较
004013CE|.74 07         je      short 004013D7                   ;不等则不成功
004013D0|.31C0          xor   eax, eax                         ;可以计算下,不过后面有提示
004013D2|.E9 2D010000   jmp   00401504
004013D7|>31DB          xor   ebx, ebx
004013D9|.EB 0B         jmp   short 004013E6
004013DB|>8B45 10       /mov   eax, dword ptr          ;//////////////////////////
004013DE|.0FBE0418      |movsx   eax, byte ptr
004013E2|.0145 FC       |add   dword ptr , eax          ;取用户名ASCII码总和
004013E5|.43            |inc   ebx
004013E6|>3B5D 0C      cmp   ebx, dword ptr
004013E9|.^ 7C F0         \jl      short 004013DB                  ;//////////////////////////
004013EB|.31DB          xor   ebx, ebx                         ;ebx为计数器先清零
004013ED|.E9 83000000   jmp   00401475
004013F2|>8B55 10       /mov   edx, dword ptr          ;用户名地址
004013F5|.0FBE3C1A      |movsx   edi, byte ptr          ;逐个取用户名字符
004013F9|.8B75 FC       |mov   esi, dword ptr           ;用户名ASCII码总和
004013FC|.89D9          |mov   ecx, ebx
004013FE|.C1E1 02       |shl   ecx, 2
00401401|.89DA          |mov   edx, ebx
00401403|.42            |inc   edx
00401404|.29D1          |sub   ecx, edx
00401406|.0FB68C0D E1FE>|movzx   ecx, byte ptr
0040140E|.89FA          |mov   edx, edi
00401410|.31CA          |xor   edx, ecx
00401412|.89F1          |mov   ecx, esi
00401414|.0FAFCB      |imul    ecx, ebx
00401417|.29F1          |sub   ecx, esi
00401419|.89CE          |mov   esi, ecx
0040141B|.83F6 FF       |xor   esi, FFFFFFFF
0040141E|.8DB432 4D0100>|lea   esi, dword ptr     ;edx+0x34b+0x14d
00401425|.8B4D 0C       |mov   ecx, dword ptr           ;用户名长度
00401428|.89DA          |mov   edx, ebx
0040142A|.83C2 03       |add   edx, 3
0040142D|.0FAFCA      |imul    ecx, edx
00401430|.0FAFCF      |imul    ecx, edi
00401433|.89F0          |mov   eax, esi
00401435|.01C8          |add   eax, ecx
00401437|.B9 0A000000   |mov   ecx, 0A
0040143C|.31D2          |xor   edx, edx                         ;一堆加减乘除
0040143E|.F7F1          |div   ecx
00401440|.83C2 30       |add   edx, 30
00401443|.88941D FCFEFF>|mov   byte ptr , dl
0040144A|.0FB6BC1D FCFE>|movzx   edi, byte ptr
00401452|.81F7 ACAD0000 |xor   edi, 0ADAC
00401458|.89DE          |mov   esi, ebx
0040145A|.83C6 02       |add   esi, 2
0040145D|.89F8          |mov   eax, edi
0040145F|.0FAFC6      |imul    eax, esi
00401462|.B9 0A000000   |mov   ecx, 0A
00401467|.99            |cdq
00401468|.F7F9          |idiv    ecx
0040146A|.83C2 30       |add   edx, 30
0040146D|.88941D FCFEFF>|mov   byte ptr , dl      ;运算结果保存
00401474|.43            |inc   ebx
00401475|>3B5D 0C      cmp   ebx, dword ptr           ;ebx与用户名长度比较,用户名长度就是循环次数
00401478|.^ 0F8C 74FFFFFF \jl      004013F2
0040147E|.8D85 FCFEFFFF lea   eax, dword ptr          ;结果地址给EAX
00401484|.50            push    eax
00401485|.6A 54         push    54                               ;0X54 = 'T'
00401487|.8D85 DCFBFFFF lea   eax, dword ptr
0040148D|.50            push    eax                              ; |Format
0040148E|.8D85 E1FBFFFF lea   eax, dword ptr          ; |
00401494|.50            push    eax                              ; |s
00401495|.E8 CE020000   call    <jmp.&USER32.wsprintfA>          ; \wsprintfA
0040149A|.8B7D 0C       mov   edi, dword ptr          ;格式化与‘T’连接
0040149D|.89F8          mov   eax, edi
0040149F|.0FAF45 FC   imul    eax, dword ptr          ;用户名ASCII长度和
004014A3|.B9 64000000   mov   ecx, 64
004014A8|.99            cdq
004014A9|.F7F9          idiv    ecx
004014AB|.89D7          mov   edi, edx
004014AD|.83C7 30       add   edi, 30
004014B0|.57            push    edi                              ;(nameSum * nameLen) % 0x64 + 0x30
004014B1|.8DBD E1FBFFFF lea   edi, dword ptr
004014B7|.57            push    edi
004014B8|.8DBD D6FBFFFF lea   edi, dword ptr          ;(ASCII "%s-%d")这种形式格式化
004014BE|.57            push    edi                              ; |Format
004014BF|.8DBD E1FDFFFF lea   edi, dword ptr          ; |
004014C5|.57            push    edi                              ; |s
004014C6|.E8 9D020000   call    <jmp.&USER32.wsprintfA>          ; \wsprintfA
004014CB|.83C4 20       add   esp, 20
004014CE|.8D8D E1FDFFFF lea   ecx, dword ptr
004014D4|.83C8 FF       or      eax, FFFFFFFF
004014D7|>40            /inc   eax
004014D8|.803C01 00   |cmp   byte ptr , 0
004014DC|.^ 75 F9         \jnz   short 004014D7                  ;计算格式化后的字符串长度
004014DE|.50            push    eax                              ;长度
004014DF|.8D85 E1FCFFFF lea   eax, dword ptr
004014E5|.50            push    eax                              ;假码
004014E6|.8D85 E1FDFFFF lea   eax, dword ptr
004014EC|.50            push    eax                              ;得到的字符串
004014ED|.E8 D0FDFFFF   call    004012C2                         ;关键CALL
F7进入算法第三部分:
004012CB|.31F6          xor   esi, esi                         ;esi计数
004012CD|.46            inc   esi                              ;esi初始为1
004012CE|.EB 29         jmp   short 004012F9
004012D0|>8B55 08       /mov   edx, dword ptr           ;得到的字符串
004012D3|.0FBE3C32      |movsx   edi, byte ptr          ;取第二位字符part
004012D7|.89F8          |mov   eax, edi
004012D9|.83F0 20       |xor   eax, 20                         ;eax ^= 0x20
004012DC|.B9 0A000000   |mov   ecx, 0A                         ;ecx = 0x0A
004012E1|.99            |cdq
004012E2|.F7F9          |idiv    ecx
004012E4|.89D7          |mov   edi, edx                        ;edx = eax % ecx;edi=edx
004012E6|.83C7 30       |add   edi, 30                         ;edi += 0x30
004012E9|.8B55 0C       |mov   edx, dword ptr
004012EC|.0FBE1432      |movsx   edx, byte ptr          ;取假码对应位置的字符
004012F0|.39D7          |cmp   edi, edx                        ;与假码对应位字符比较
004012F2|.74 04         |je      short 004012F8
004012F4|.31C0          |xor   eax, eax                        ;不等EAX置0然后return
004012F6|.EB 08         |jmp   short 00401300
004012F8|>46            |inc   esi
004012F9|>39DE         cmp   esi, ebx
004012FB|.^ 7C D3         \jl      short 004012D0
好了,算法到这结束了。。。

注册机
        int nameLen,nameSum = 0;
        char name;
        const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWSYZ";
        int i,checkLen;
        printf("请输入用户名:");
        scanf("%s",name);
        nameLen = strlen(name);
        checkLen = (0x2BC - (0x30 - 0x48 / nameLen) * 5) * 0x6B - 0x0CF6C;
        if(checkLen <= 0x2300)
        {
                if(checkLen >= 0x190)
                {
                        for(i = 0 ; i<nameLen ; i++)
                        {
                                nameSum += (int)name;
                        }
                        int esi = 0,edi = 0,ecx = 0,eax = 0;
                        byte edx = 0;
                        char serial,part;
                        for( i = 0 ; i < nameLen ; i++)
                        {
                                edi = (int)name;
                                esi = nameSum;
                                ecx = i;
                                ecx = ecx << 2;
                                edx = i;
                                edx++;
                                ecx -= edx;
                                if(ecx < 0)
                                {
                                        ecx = 0;
                                }
                                else
                                {
                                        ecx = table;
                                }
                                edx = edi;
                                edx ^= ecx;
                                ecx = esi;
                                ecx *= i;
                                ecx -= esi;
                                esi = ecx;
                                esi ^=0xffffffff;
                                esi = edx + esi +0x14D;
                                ecx = nameLen;
                                edx = i;
                                edx += 3;
                                ecx *= edx;
                                ecx *= edi;
                                eax = esi;
                                eax += ecx;
                                ecx = 0x0A;
                                edx = 0;
                                edx = eax % ecx;
                                edx += 0x30;
                                edi = edx;
                                edi ^= 0x0ADAC;
                                esi = i;
                                esi += 2;
                                eax = edi;
                                eax *= esi;
                                ecx = 0x0A;
                                edx = eax % ecx;
                                edx += 0x30;
                                part = edx;
                        }
                        part = '\0';
                        int p;
                        p = (nameSum * nameLen) % 0x64 + 0x30;
                        wsprintf(serial,"%c%s-%d",0x54,part,p);
                        for(i = 1 ;i<13 ;i++)
                        {
                                serial= ((serial ^ 0x20) % 0x0A) +0x30;
                        }
                        serial = '\0';
                        printf("\n注册码为:%s\n",serial);
                }
        }
        else
        {
                printf("用户名长度检验失败~!");
        }
--------------------------------------------------------------------------------
【经验总结】
就是一堆加减乘除。。。不用程序来我还真看不清。呵呵。

--------------------------------------------------------------------------------
【版权声明】: 本文原创于creantan, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年02月03日 22:11:58

zapline 发表于 2009-2-3 23:23

真的很强啊
                                  edx = edi;
                                  edx ^= ecx;
                                  ecx = esi;
                                  ecx *= i;
                                  ecx -= esi;
                                  esi = ecx;
                                  esi ^=0xffffffff;
                                  esi = edx + esi +0x14D;
                                  ecx = nameLen;
                                  edx = i;
                                  edx += 3;
                                  ecx *= edx;
                                  ecx *= edi;
                                  eax = esi;
                                  eax += ecx;
                                  ecx = 0x0A;
                                  edx = 0;
                                  edx = eax % ecx;
                                  edx += 0x30;
                                  edi = edx;
                                  edi ^= 0x0ADAC;
                                  esi = i;
                                  esi += 2;
                                  eax = edi;
                                  eax *= esi;
                                  ecx = 0x0A;
                                  edx = eax % ecx;
                                  edx += 0x30;
                                  part = edx;
这一段应该该可以提炼一下,可是试试F5

a2213572 发表于 2009-2-8 10:43

下載學習!
:lol

iy0507 发表于 2009-2-23 00:18

学习了~~好强的
一直算法分析不过关呵呵

aizai1 发表于 2009-3-12 21:36

这个有意思.

myh0st 发表于 2013-5-29 10:39

很好,很有帮助!
页: [1]
查看完整版本: Zapline 转载CM(第7天) 算法分析