首页
社区
课程
招聘
[原创]Happytown的第18个crackme分析+注册机
发表于: 2006-12-5 21:47 5264

[原创]Happytown的第18个crackme分析+注册机

2006-12-5 21:47
5264

【文章标题】: Happytown的第18个crackme分析+注册机
【文章作者】: kaien
【作者邮箱】: kkaien@hotmail.com
【软件名称】: CrackMe_0018.exe
【加壳方式】: 无壳
【使用工具】: OllyDbg,VC(写注册机用)
【操作平台】: winxp

本文分两部分,前半部分是算法分析;后半部分是注册机。
其实,本文的前半部分在我的另一个帖子里已经发表过了。
但是我们的happytown发话了,不写出注册机誓不罢休!- -
无奈之下,只好献丑了!
时间仓促,水平有限,错误之处在所难免,还望各位大大们手下留情 ^_^

算法部分代码如下,很简单,看我注释:

0040117E   |.  68 C9000000        push 0C9                                         ; /Count = C9 (201.)
00401183   |.  50                 push eax                                         ; |Buffer
00401184   |.  68 E8030000        push 3E8                                         ; |ControlID = 3E8 (1000.)
00401189   |.  57                 push edi                                         ; |hWnd
0040118A   |.  FFD5               call ebp                                         ; \GetDlgItemTextA
0040118C   |.  8BF0               mov esi,eax
0040118E   |.  83FE 04            cmp esi,4                                        ;  用户名长度>=4
00401191   |.  0F8C CA000000      jl CrackMe_.00401261
00401197   |.  8BCE               mov ecx,esi
00401199   |.  81E1 01000080      and ecx,80000001
0040119F   |.  79 05              jns short CrackMe_.004011A6
004011A1   |.  49                 dec ecx
004011A2   |.  83C9 FE            or ecx,FFFFFFFE
004011A5   |.  41                 inc ecx
004011A6   |>  0F85 B5000000      jnz CrackMe_.00401261                            ;  用户名长度必须为偶数,否则就跳了
004011AC   |.  8D9424 D8000000    lea edx,dword ptr ss:[esp+D8]
004011B3   |.  56                 push esi
004011B4   |.  52                 push edx
004011B5   |.  E8 B6000000        call CrackMe_.00401270                           ;  小写转大写
004011BA   |.  83C4 08            add esp,8
004011BD   |.  85C0               test eax,eax
004011BF   |.  0F84 9C000000      je CrackMe_.00401261
004011C5   |.  8D4424 10          lea eax,dword ptr ss:[esp+10]
004011C9   |.  68 C9000000        push 0C9
004011CE   |.  50                 push eax
004011CF   |.  68 E9030000        push 3E9
004011D4   |.  57                 push edi
004011D5   |.  FFD5               call ebp
004011D7   |.  3BC6               cmp eax,esi
004011D9   |.  0F85 82000000      jnz CrackMe_.00401261
004011DF   |.  8D4C24 10          lea ecx,dword ptr ss:[esp+10]
004011E3   |.  50                 push eax
004011E4   |.  51                 push ecx
004011E5   |.  E8 86000000        call CrackMe_.00401270
004011EA   |.  83C4 08            add esp,8
004011ED   |.  85C0               test eax,eax
004011EF   |.  74 70              je short CrackMe_.00401261
004011F1   |.  8BC6               mov eax,esi
004011F3   |.  33FF               xor edi,edi
004011F5   |.  99                 cdq
004011F6   |.  2BC2               sub eax,edx
004011F8   |.  8BE8               mov ebp,eax
004011FA   |.  D1FD               sar ebp,1
004011FC   |.  3BEB               cmp ebp,ebx
004011FE   |.  7E 51              jle short CrackMe_.00401251
00401200   |>  8A4C7C 11          /mov cl,byte ptr ss:[esp+edi*2+11]               ;  取密码第二位
00401204   |.  8A447C 10          |mov al,byte ptr ss:[esp+edi*2+10]               ;  取密码第一位
00401208   |.  80E9 41            |sub cl,41                                       ;  cl= 第二位-41
0040120B   |.  2C 41              |sub al,41                                       ;  al= 第一位-41
0040120D   |.  0FBEF1             |movsx esi,cl                                    ;  esi=cl
00401210   |.  0FBEC8             |movsx ecx,al                                    ;  ecx=al
00401213   |.  BB 1A000000        |mov ebx,1A                                      ;  ebx=1A
00401218   |.  8D14C9             |lea edx,dword ptr ds:[ecx+ecx*8]                ;  edx=ecx*9=(密码第一位-41)*9
0040121B   |.  8D0472             |lea eax,dword ptr ds:[edx+esi*2]                ;  eax=(密码第一位-41)*9 + (密码第二位-41)*2
0040121E   |.  99                 |cdq                                             ;  求余数
0040121F   |.  F7FB               |idiv ebx                                        ;  eax=eax/ebx=eax/1A 且余数给edx
00401221   |.  0FBE847C D8000000  |movsx eax,byte ptr ss:[esp+edi*2+D8]            ;  eax=用户名第一位
00401229   |.  83E8 41            |sub eax,41                                      ;  eax=eax-41
0040122C   |.  3BD0               |cmp edx,eax                                     ;  比较eax和余数edx
0040122E       75 31              jnz short CrackMe_.00401261
00401230   |.  8D0476             |lea eax,dword ptr ds:[esi+esi*2]                ;  eax=esi*3=cl*3=(密码第二位-41)*3
00401233   |.  8D0C81             |lea ecx,dword ptr ds:[ecx+eax*4]                ;  ecx = ecx+eax*4 = al+eax*4 = (密码第一位-41)+(密码第二位-41)*0C
00401236   |.  03C1               |add eax,ecx                                     ;  eax=eax+ecx= (密码第一位-41)+(密码第二位-41)*0F
00401238   |.  8BCB               |mov ecx,ebx                                     ;  ecx=ebx=1A
0040123A   |.  99                 |cdq
0040123B   |.  F7F9               |idiv ecx                                        ;  eax=eax/1A 余数edx
0040123D   |.  0FBE847C D9000000  |movsx eax,byte ptr ss:[esp+edi*2+D9]            ;  eax=取用户名第二位
00401245   |.  83E8 41            |sub eax,41                                      ;  eax=用户名第二位-41
00401248   |.  3BD0               |cmp edx,eax                                     ;  比较eax和余数edx
0040124A   |.  75 15              |jnz short CrackMe_.00401261
0040124C   |.  47                 |inc edi                                         ;  edi++
0040124D   |.  3BFD               |cmp edi,ebp                                     ;  一组一组的来,每组两个字符,所以共(用户名长度/2)组
0040124F   |.^ 7C AF              \jl short CrackMe_.00401200
00401251   |>  5F                 pop edi
00401252   |.  5E                 pop esi
00401253   |.  5D                 pop ebp
00401254   |.  B8 01000000        mov eax,1
00401259   |.  5B                 pop ebx
0040125A   |.  81C4 90010000      add esp,190
00401260   |.  C3                 retn
00401261   |>  5F                 pop edi
00401262   |.  5E                 pop esi
00401263   |.  5D                 pop ebp
00401264   |.  33C0               xor eax,eax
00401266   |.  5B                 pop ebx
00401267   |.  81C4 90010000      add esp,190
0040126D   \.  C3                 retn

总结一下算法:

1。用户名和密码都必须是大小写字母(大写还是小写无关紧要)

2。用户名和密码的位数必须相同且为偶数,位数不能小于4。

算法关键是:

用户名的第一位-41H = [(密码第一位-41H)*9H + (密码第二位-41H)*2H] % 1AH

用户名的第二位-41H = [(密码第一位-41H)+(密码第二位-41H)*0FH] % 1AH

解上面这个方程组就行。(% 就是C里面的取余数运算)
后面的用户名和密码的3、4位;5、6位等等,都可以同样的方法算出。

我们可以看到,如果知道密码的两位来确定用户名比较好计算。因为,连续两位密码可以分别唯一的计算出两位用户名来。

=====================================================================

下面是一个简单的注册机,C写的。
这个注册机将会根据给定的长度随机生成用户名和注册码。
鉴于大小写不是关键,所以我一律按大写算了。大家不要介意

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

void main()
{
        char code1,code2,name1,name2;
        int length;
        char code[256],name[256];

        //自己给定密码和用户名长度,两个的长度必须相等且为偶数。
        //密码长度=用户名的长度=length*2
        //length必须>=2
           //如密码长度为10,即length=5
        length=5;

        //构造随机变量
        srand((unsigned)time(NULL));       
        for(int i=1;i<=length;i++)
        {
        //随机生成注册码
        //code1和2为ASCII的65-90之间的大写字母,即A-Z。取小写字母也无妨
                code1=int(((float(rand())/RAND_MAX)*26)+65);
                code2=int(((float(rand())/RAND_MAX)*26)+65);
                name1=((((code1-0x41)*9)+((code2-0x41)*2))%0x1A)+0x41;
                name2=(((code1-0x41)+((code2-0x41)*0xF))%0x1A)+0x41;
                code[i*2-2]=code1;
                code[i*2-1]=code2;
                name[i*2-2]=name1;
                name[i*2-1]=name2;
        }
        code[i*2-2]='\0';
        name[i*2-2]='\0';
        printf("用户名:\t%s\n",name);
        printf("密码:\t%s\n",code);

}

====================================================================
几个随机生成的结果(已验证):

长度4的
用户名: STWY
密码:   IZQE

长度6的
用户名: ESKUXI
密码:   ISCWXZ

长度8的
用户名: EFDDHCNO
密码:   IFNIZVVD

长度10的
用户名: OTDMXGOYTM
密码:   OJHJHTCYJV

长度20的
用户名: DGFDZNMXNYSOTFTFVLXU
密码:   LRXQVWKNXHUKFAFALAPJ

长度60的
用户名: UVMAQYKJKZHIHDENVGREQISINPMNXIRJEGMRVUTZPOEYCYEQYURSBEXEOPVL
密码:   INIWMGSPQLVNHYUDXLNPOKYSDGIJXZBEQIOVFBJIFLEKUCSMUAVFLDRNIXLA

长度100的
用户名: UVUAKPYIECREINMGMLKBBMQFSSBMAOEYVKLZVLUGPCDQWKDXPUIDZBWFORSVQPJTGVEVOMOJJRMEYVMEBLLLQNENMZFVPMLASKIV
密码:   INWCOHCQKWNPOTEOSDGRXBQBAWXBIQEKDXVCLASUNBNVIORQBDMPDMUZYDYFSFPCQJGBKOMFZWOICDOIPYNMCZUDATLSPFDFOYAR

这是本人在看雪的第三篇破文,希望大家喜欢。


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (2)
雪    币: 538
活跃值: (460)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
2
强啊楼住,学习了!!
2006-12-6 15:02
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
不错啊.我还跟不出算法了。慢慢学了。
2006-12-10 00:47
0
游客
登录 | 注册 方可回帖
返回
//