首页
社区
课程
招聘
[原创]riijj系列cm剖析(cm1)
发表于: 2009-4-10 21:37 5856

[原创]riijj系列cm剖析(cm1)

2009-4-10 21:37
5856

这是我的逆向分析处女作(希望能够完成riijj的整个系列, ).
写的不好的地方,还请大家多多包涵 .
没什么技术含量, 高手可以飘过,当然能够指点几句那是求之不得了.

目标:riijj系列 cm1.
断RegisterClassEx,由lpWNDCLASS 可以找打DialogFunc.
不废话了, 看反汇编
00401050 > .  817C24 08 110>cmp     dword ptr [esp+8], 111           ;  DialogFunc
00401058   .  75 74         jnz     short 004010CE                   ;  不是WM_COMMAND则跳走.
0040105A   .  8B4424 0C     mov     eax, dword ptr [esp+C]           ;  wParam
0040105E   .  66:3D EA03    cmp     ax, 3EA                          ;  消息来源是否注册按钮
00401062   .  75 42         jnz     short 004010A6
00401064   .  E8 C7010000   call    <KeyCall>                        ;  关键call
00401069   .  85C0          test    eax, eax
0040106B   .  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
0040106D   .  68 80504000   push    00405080                         ; |Title = "ncrackme"
00401072   .  75 1B         jnz     short 0040108F                   ; |
00401074   .  A1 B8564000   mov     eax, dword ptr [4056B8]          ; |
00401079   .  68 64504000   push    00405064                         ; |Text = "Registration successful."
0040107E   .  50            push    eax                              ; |hOwner => 0066035A ('Newbie smallsize crackme - v1',class='myWindowClass')
0040107F   .  FF15 C0404000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
00401085   .  E8 A6020000   call    <___setargv>
0040108A   .  33C0          xor     eax, eax
0040108C   .  C2 1000       retn    10
0040108F   >  8B0D B8564000 mov     ecx, dword ptr [4056B8]          ; |
00401095   .  68 50504000   push    00405050                         ; |Text = "Registration fail."
0040109A   .  51            push    ecx                              ; |hOwner => 0066035A ('Newbie smallsize crackme - v1',class='myWindowClass')
0040109B   .  FF15 C0404000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
004010A1   .  33C0          xor     eax, eax
004010A3   .  C2 1000       retn    10
004010A6   >  66:3D EB03    cmp     ax, 3EB

////KeyCall
00401262  |> \A1 BC564000   mov     eax, dword ptr [4056BC]          ;  Dialog句柄.
00401267  |.  8D5424 28     lea     edx, dword ptr [esp+28]          ;  存放注册号缓冲区
0040126B  |.  6A 10         push    10
0040126D  |.  52            push    edx
0040126E  |.  68 E9030000   push    3E9                              ;  注册号Edit控件的ID
00401273  |.  50            push    eax
00401274  |.  FFD6          call    esi
00401276  |.  0FBE4424 08   movsx   eax, byte ptr [esp+8]            ;  name[0]
0040127B  |.  0FBE4C24 09   movsx   ecx, byte ptr [esp+9]            ;  name[1]
00401280  |.  99            cdq
00401281  |.  F7F9          idiv    ecx                              ;  eax为商,edx为余数
00401283  |.  8BCA          mov     ecx, edx                         ;  ecx = 余数.
00401285  |.  83C8 FF       or      eax, FFFFFFFF
00401288  |.  0FBE5424 0A   movsx   edx, byte ptr [esp+A]            ;  name[2]
0040128D  |.  0FAFCA        imul    ecx, edx
00401290  |.  41            inc     ecx                              ;  除数.
00401291  |.  33D2          xor     edx, edx
00401293  |.  F7F1          div     ecx
00401295  |.  50            push    eax                              ;  商作为种子
00401296 >|.  E8 A5000000   call    <_srand>                         ;  刚开始这里是被inline进来的srand最后发现是srand
0040129B  |.  83C4 04       add     esp, 4
0040129E  |.  33F6          xor     esi, esi
004012A0  |>  E8 A5000000   /call    <_rand>                         ;  这里先来个15次rand. 目的是变换种子
004012A5  |.  99            |cdq
004012A6  |.  B9 1A000000   |mov     ecx, 1A
004012AB  |.  F7F9          |idiv    ecx
004012AD  |.  80C2 41       |add     dl, 41
004012B0  |.  885434 18     |mov     byte ptr [esp+esi+18], dl
004012B4  |.  46            |inc     esi
004012B5  |.  83FE 0F       |cmp     esi, 0F
004012B8  |.^ 72 E6         \jb      short 004012A0
004012BA  |.  57            push    edi                              ;  保护现场.
004012BB  |.  8D7C24 0C     lea     edi, dword ptr [esp+C]
004012BF  |.  83C9 FF       or      ecx, FFFFFFFF
004012C2  |.  33C0          xor     eax, eax
004012C4  |.  33F6          xor     esi, esi
004012C6  |.  F2:AE         repne   scas byte ptr es:[edi]
004012C8  |.  F7D1          not     ecx
004012CA  |.  49            dec     ecx                              ;  求用户名的长度.,
004012CB  |.  74 59         je      short 00401326
004012CD  |>  8A4434 0C     /mov     al, byte ptr [esp+esi+C]        ;  name[i]
004012D1  |.  C0F8 05       |sar     al, 5
004012D4  |.  0FBEC0        |movsx   eax, al                         ;  eax = name[i] << 5
004012D7  |.  8D1480        |lea     edx, dword ptr [eax+eax*4]
004012DA  |.  8D04D0        |lea     eax, dword ptr [eax+edx*8]
004012DD  |.  8D0440        |lea     eax, dword ptr [eax+eax*2]      ;  eax *= 41*3
004012E0  |.  85C0          |test    eax, eax
004012E2  |.  7E 0A         |jle     short 004012EE                  ;  这里其实永远不会跳,因为上面乘法永不会溢出.
004012E4  |.  8BF8          |mov     edi, eax                        ;  上面的eax作为一个计数器.
004012E6  |>  E8 5F000000   |/call    <_rand>                        ;  调用rand 这么多次,目的变化种子.
004012EB  |.  4F            ||dec     edi
004012EC  |.^ 75 F8         |\jnz     short 004012E6
004012EE  |>  E8 57000000   |call    <_rand>                         ;  再来调用一次.
004012F3  |.  99            |cdq                                     ;  edx = 0
004012F4  |.  B9 1A000000   |mov     ecx, 1A
004012F9  |.  8D7C24 0C     |lea     edi, dword ptr [esp+C]          ;  用户名地址,这里代码穿插着,这句是为后面求长度服务的.
004012FD  |.  F7F9          |idiv    ecx
004012FF  |.  0FBE4C34 2C   |movsx   ecx, byte ptr [esp+esi+2C]      ;  OK,这里是就是注册号.取首字节.
00401304  |.  80C2 41       |add     dl, 41
00401307  |.  0FBEC2        |movsx   eax, dl                         ;  eax = eax%0x1A +'A'
0040130A  |.  2BC1          |sub     eax, ecx                        ;  这里关键. 要让ecx = eax
0040130C  |.  885434 1C     |mov     byte ptr [esp+esi+1C], dl       ;  这个写入跟上面那个循环的写入是一样的,混淆视听的.
00401310  |.  99            |cdq                                     ;  这里要看上面的减法定. edx = 0 或-1
00401311  |.  33C2          |xor     eax, edx                        ;  这句结合上面一句就是eax = |eax|
00401313  |.  83C9 FF       |or      ecx, FFFFFFFF
00401316  |.  2BC2          |sub     eax, edx                        ;  这句看edx情况定.
00401318  |.  03D8          |add     ebx, eax                        ;  每次的eax累加到ebx.
0040131A  |.  33C0          |xor     eax, eax
0040131C  |.  46            |inc     esi
0040131D  |.  F2:AE         |repne   scas byte ptr es:[edi]
0040131F  |.  F7D1          |not     ecx
00401321  |.  49            |dec     ecx                             ;  用户名长度.
00401322  |.  3BF1          |cmp     esi, ecx
00401324  |.^ 72 A7         \jb      short 004012CD
00401326  |>  5F            pop     edi                              ;  恢复这个寄存器.
00401327  |.  8BC3          mov     eax, ebx                         ;  看了这里就知道为什么上面那句减法的结果一定要为零
00401329  |.  5E            pop     esi
0040132A  |.  5B            pop     ebx
0040132B  |.  83C4 30       add     esp, 30
0040132E  \.  C3            retn
0040132F      90            nop

OK, 思路我们已经很明确了, 就是使ebx为零. 即ebx = 0;             (1)
而ebx = eax_1 + eax_2 + …+  
而在add ebx,eax之前有这两句:
Eax_i = |eax_i| ;
sub eax_i, edx_i ; 这句对eax加零或加1.
所以eax_i >=0;                                                 (2)
这样根据(1),(2), 得 eax_i = 0.
哎, 好了不说了,相信大家早都明白了, 我却还在这里啰嗦,

附上垃圾注册机代码:

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

char name[16];
char regCode[16];

void rep_rand(int c)
{
        int i;
        for(i= 0;i<c;++i)
                rand();
}
void main()
{
        int i,j,len,seed;
        int count;
        char ch;
        printf("Enter the Reg name (len>=3):\n");
        scanf("%s",name);
        len = strlen(name);
        seed =(int) (0xFFFFFFFF / ((name[0] % name[1]) * name[2] +1)) ;
        srand(seed);
       
        rep_rand(15);

        for(i=0;i<len;++i)
        {
                count = name[i] >> 5;
                count += 5*count*8;
                count *= 3;

                rep_rand(count);
               
                ch = 'A' + rand()%0x1A;
               
                //generate key
                regCode[i] = ch;
        }

        printf("the reg code is :  %s \n",regCode);
        getch();
}

一组可用序号: jackozoo / YRJHVRYR .

谢谢看到这里的朋友, 第一次写这种文章比较啰嗦.


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (7)
雪    币: 10902
活跃值: (3288)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
2
看得出楼主比较认真细心,
针对该cm的破文可能有不少
楼主既然辛苦写了这么多
我希望该破文能尽可能多的体现它的意义和价值
希望尽可能让不懂cm破解的人能根据你的破文分析得到你所提供的结果.
个人觉得楼主如果有空还是有必要再补充一下.
“断RegisterClassEx,由lpWNDCLASS 可以找打DialogFunc.“
针对这个尽量详细点,也许很多人都会,但也有不少初学的朋友.
讲得详细,并不会罗嗦,如果对其他初学的朋友有帮助,定会赢得尊敬!

希望大家都能踊跃地将自己的思路,分析体会整理出来作为宝贵的经验与大家分享!
感谢楼主详细的分析文章!很不错!
大家有好的建议可以和我交流沟通!
2009-4-10 22:08
0
雪    币: 1450
活跃值: (35)
能力值: (RANK:680 )
在线值:
发帖
回帖
粉丝
3
恩, 谢谢netwind. 这篇文章是蛮久以前写的, 今天连上网就放上来了.

我希望可以把riijj的整个系列都分析一遍,每一个都弄出一个注册机来.(当然是在未看别人的分析的情况下).

在提高自己的同时也希望可以为初入门的人做点贡献.
2009-4-10 23:36
0
雪    币: 145
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
谢谢,长知识了,菜鸟飞过!
2009-4-12 12:26
0
雪    币: 261
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
CM软件在哪里?
2009-4-20 10:41
0
雪    币: 421
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
仔细看了下上面的个断点,感觉不错
以前从来没有注意过这个函数,学习学习
2009-4-28 15:15
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
LZ如果附上CM下载让我们初学者可以边学边操作就好了
2009-4-28 21:38
0
雪    币: 155
活跃值: (29)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
8
2009-5-3 11:23
0
游客
登录 | 注册 方可回帖
返回
//