首页
社区
课程
招聘
一个据说是新手级Crackme的分析
发表于: 2006-6-29 16:55 6472

一个据说是新手级Crackme的分析

2006-6-29 16:55
6472

下载地址:http://www.crackmes.de/users/starzboy/keygen_me_2/

使用工具:OllyDbg

前言:要考试了,没时间弄复杂的程序,看见这个比较“浅显易懂”,拿来小搞一把,
大概花不了半天时间吧。

解密:

这是一个基于控制台的程序,注册信息包含三方面内容:User_Name、User_ID以及
password。用OllyDbg载入,查找相关的字串,很快定位到如下代码处:

////////////////  以下是代码  ////////////////

004014D3  |.  C74424 04 CF0>mov     dword ptr [esp+4], 004400CF      ;  ASCII "Enter User-Name: "
004014DB  |.  C70424 C03344>mov     dword ptr [esp], 004433C0
004014E2  |.  E8 71AE0300   call    0043C358                         ;  printf
004014E7  |.  8D85 F8FEFFFF lea     eax, [ebp-108]                   ; |
004014ED  |.  890424        mov     [esp], eax                       ; |
004014F0  |.  E8 8BF40000   call    <jmp.&msvcrt.gets>               ; \gets
004014F5  |.  80BD F8FEFFFF>cmp     byte ptr [ebp-108], 0
004014FC  |.  0F84 A8010000 je      004016AA
00401502  |.  C74424 04 E10>mov     dword ptr [esp+4], 004400E1      ;  ASCII "Enter User-ID: "
0040150A  |.  C70424 C03344>mov     dword ptr [esp], 004433C0
00401511  |.  E8 42AE0300   call    0043C358                         ;  printf
00401516  |.  8D85 DCFEFFFF lea     eax, [ebp-124]
0040151C  |.  894424 04     mov     [esp+4], eax
00401520  |.  C70424 603444>mov     dword ptr [esp], 00443460
00401527  |.  E8 C4720200   call    004287F0                         ;  scanf("%ld",...)
0040152C  |.  C785 D8FEFFFF>mov     dword ptr [ebp-128], 0
00401536  |>  8D85 F8FEFFFF /lea     eax, [ebp-108]                  ; |
0040153C  |.  890424        |mov     [esp], eax                      ; |
0040153F  |.  E8 2CF40000   |call    <jmp.&msvcrt.strlen>            ; \strlen
00401544  |.  3B85 D8FEFFFF |cmp     eax, [ebp-128]                  ;  计数器
0040154A  |.  76 5B         |jbe     short 004015A7
0040154C  |.  8D45 F8       |lea     eax, [ebp-8]
0040154F  |.  0385 D8FEFFFF |add     eax, [ebp-128]
00401555  |.  2D 00010000   |sub     eax, 100
0040155A  |.  0FBE00        |movsx   eax, byte ptr [eax]             ;  依次取User_Name各字符
0040155D  |.  8985 F4FEFFFF |mov     [ebp-10C], eax
00401563  |.  8D85 F4FEFFFF |lea     eax, [ebp-10C]
00401569  |.  8100 656C2A03 |add     dword ptr [eax], 32A6C65
0040156F  |.  8B85 DCFEFFFF |mov     eax, [ebp-124]                  ;  UserID
00401575  |.  0FAF85 DCFEFF>|imul    eax, [ebp-124]
0040157C  |.  01C0          |add     eax, eax
0040157E  |.  0385 F4FEFFFF |add     eax, [ebp-10C]
00401584  |.  05 237AD602   |add     eax, 2D67A23
00401589  |.  8985 F4FEFFFF |mov     [ebp-10C], eax
0040158F  |.  8B95 F4FEFFFF |mov     edx, [ebp-10C]
00401595  |.  8D85 F0FEFFFF |lea     eax, [ebp-110]
0040159B  |.  0110          |add     [eax], edx                      ;  计算双字累加和
0040159D  |.  8D85 D8FEFFFF |lea     eax, [ebp-128]
004015A3  |.  FF00          |inc     dword ptr [eax]
004015A5  |.^ EB 8F         \jmp     short 00401536
004015A7  |>  C74424 04 F10>mov     dword ptr [esp+4], 004400F1      ;  ASCII "Enter Password: "
004015AF  |.  C70424 C03344>mov     dword ptr [esp], 004433C0
004015B6  |.  E8 9DAD0300   call    0043C358                         ;  printf
004015BB  |.  8D85 E8FEFFFF lea     eax, [ebp-118]
004015C1  |.  894424 04     mov     [esp+4], eax
004015C5  |.  C70424 603444>mov     dword ptr [esp], 00443460
004015CC  |.  E8 1F720200   call    004287F0                         ;  scanf("%ld",...)
004015D1  |.  C74424 04 CE0>mov     dword ptr [esp+4], 004400CE
004015D9  |.  C70424 C03344>mov     dword ptr [esp], 004433C0
004015E0  |.  E8 73AD0300   call    0043C358
004015E5  |.  C74424 04 28B>mov     dword ptr [esp+4], 0043B128
004015ED  |.  890424        mov     [esp], eax
004015F0  |.  E8 BB8C0200   call    0042A2B0
004015F5  |.  8B85 F0FEFFFF mov     eax, [ebp-110]
004015FB  |.  3B85 E8FEFFFF cmp     eax, [ebp-118]                   ;  相等则注册成功
00401601  |.  75 3A         jnz     short 0040163D
00401603  |.  C74424 04 020>mov     dword ptr [esp+4], 00440102      ;  ASCII "Access Granted !"
0040160B  |.  C70424 C03344>mov     dword ptr [esp], 004433C0
00401612  |.  E8 41AD0300   call    0043C358
00401617  |.  C74424 04 28B>mov     dword ptr [esp+4], 0043B128
0040161F  |.  890424        mov     [esp], eax
00401622  |.  E8 898C0200   call    0042A2B0
00401627  |.  C74424 04 140>mov     dword ptr [esp+4], 00440114      ;  ASCII "You did it Cracker...now make a keygen !"
0040162F  |.  C70424 C03344>mov     dword ptr [esp], 004433C0
00401636  |.  E8 1DAD0300   call    0043C358

////////////////  以上是代码  ////////////////

不知道为什么,OllyDbg在加载这种控制台程序时似乎无法保留上次的断点。如果对C
语言的几个标准库函数有些印象的话,应该不难看出过程43C358相当于printf,而过
程4287F0则相当于scanf。生成注册码部分的算法完全包含在从401536到4015A5的循
环中,在4015FB处只是将输入的Password同程序中算出来的进行比较。唯一要注意的
是User_ID和Password都只能输入十进制数值。关于这一点,我曾经尝试过在User_ID
中输入字符串,结果在40156F处的[ebp-124]中出现的内容就是一个奇怪的堆栈地址,
当时就纳闷了:程序在不同的环境下分配到的堆栈段地址也可能不一样,如果以这个
作为注册算法的一个运算数,就意味着注册算法在每次运行时都不一样,哪里还有通
用的注册机可言?后来无意中输入了一个比较小的纯数值,发现上述[ebp-124]中就
是这个数值,于是明白这个地方原本是只能输数值的。再测试一下可知:象
2147483647以及-1这样的数值都可以输,但2147483648却不能输,否则又变成22xxxx
之类的堆栈地址了,相当于scanf带"%ld"格式符的情况。实际上,注意到取用户名的
时候用的函数是gets,而User_ID和password都是用scanf,大致也能明白一些了吧。

  将401536到4015A5这段代码翻译成伪代码形式就是:

  N = strlen(User_Name)
    c = 0
    i = 1
循环:当i <= N
    a = User_Name第i个字符的ASCII码
  a = a + 32A6C65h
    b = User_ID
    b = b * b
    b = b + b
    b = b + a
    b = b + 2D67A23h
    c = c + b
    i = i + 1
循环尾
    return c――password

  将此算法再优化一番,把与循环无关的运算都提出来。其中可以手算:
   32A6C65h + 2D67A23h = 600E688h
则可以得到:

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

long int liPasswordValue(char *szUserName, long int liUserIDValue)
{
        long int loc_liMagicAdditive = (liUserIDValue * liUserIDValue << 1) + 0x600E688;
        long int loc_liDwordCheckSum = 0;
        int      loc_N               = strlen(szUserName);

        for(int i = 0; i < loc_N; i++)
     {
                loc_liDwordCheckSum = loc_liDwordCheckSum + (long int)szUserName[i] + loc_liMagicAdditive;
        }

        return loc_liDwordCheckSum;
}

/* 主函数中可如下调用 */
int main(int argc, char *argv[])
{
        char     szUserName[80];
      long int liUserIDValue;

        printf("请输入用户名:");
        gets(szUserName);
        printf("\n请输入用户ID:");
        scanf("%ld", &liUserIDValue);
        printf("\n你的密码已生成:%ld\n", liPasswordValue(szUserName, liUserIDValue));

}


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
对我有些帮助!谢谢!
2006-6-30 14:03
0
雪    币: 253
活跃值: (25)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
3
对我等菜鸟实在是帮助大
2006-7-2 13:55
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
学习学习。。
2006-7-4 22:55
0
雪    币: 132
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
没的下载啊
2006-8-29 09:55
0
雪    币: 338
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
莱鸟先学习了!
2006-8-29 23:43
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
看来新手也不容易啊,楼主多搞了半天,我们新手就要。。。
2006-9-6 16:51
0
游客
登录 | 注册 方可回帖
返回
//