首页
社区
课程
招聘
[原创]Happytown的第35个crackme分析+注册机
发表于: 2006-12-15 05:34 7730

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

2006-12-15 05:34
7730

【文章标题】: 【原创】Happytown的第35个crackme分析+注册机
【文章作者】: ylp1332
【作者邮箱】: [email]ylp1332@yahoo.com.cn[/email]
【作者主页】: n/a
【作者QQ号】: n/a
【软件名称】: CrackMe_0035.exe
【软件大小】: 220k
【下载地址】: 自己搜索下载
【加壳方式】: none
【保护方式】: md5,大数运算
【编写语言】: visual c++ 6
【使用工具】: peid,ida,ollydbg,vc6
【操作平台】: win32
【软件介绍】: 非商业软件
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  
  『分析过程』
  1、首先用PEiD 0.94检查,用visual c++ 6编译,没有加壳。
  
  2、用PEiD的插件Krypto ANAlyzer检查,发现有MD5算法和大数运算。
  
  3、用IDA载入,进行初步的静态分析。
  
  分析结论:
          使用了Miracl大数运算库;
          使用了标准的MD5算法;
          使用Windows API GetDlgItemTextA从控件中取得用户名、组织和注册码,
          用户名和组织名至少要2个字符长,注册码必须都是16进制字符,且不能为空。
  验证过程的反汇编代码如下:
  
  .text:00401110
  .text:00401110 ; =============== S U B R O U T I N E =======================================
  .text:00401110
  .text:00401110
  .text:00401110 ; int __cdecl OnCheck(HWND hDlg)
  .text:00401110 OnCheck         proc near               ; CODE XREF: DialogFunc+55p
  .text:00401110
  .text:00401110 var_2C4         = dword ptr -2C4h
  .text:00401110 md5_str_out     = dword ptr -2C0h
  .text:00401110 var_2BB         = dword ptr -2BBh
  .text:00401110 var_2B7         = dword ptr -2B7h
  .text:00401110 var_2B3         = word ptr -2B3h
  .text:00401110 var_2B1         = byte ptr -2B1h
  .text:00401110 md5_ctx         = dword ptr -2B0h
  .text:00401110 Serial          = dword ptr -258h
  .text:00401110 UserName        = byte ptr -190h
  .text:00401110 Group           = byte ptr -0C8h
  .text:00401110 hDlg            = dword ptr  4
  .text:00401110
  .text:00401110                 sub     esp, 2C4h
  .text:00401116                 push    ebx
  .text:00401117                 push    esi
  .text:00401118                 push    edi
  .text:00401119                 mov     ecx, 49
  .text:0040111E                 xor     eax, eax
  .text:00401120                 lea     edi, [esp+141h]
  .text:00401127                 mov     [esp+2D0h+UserName], 0
  .text:0040112F                 mov     [esp+2D0h+Group], 0
  .text:00401137                 rep stosd
  .text:00401139                 stosw
  .text:0040113B                 stosb
  .text:0040113C                 mov     ecx, 49
  .text:00401141                 xor     eax, eax
  .text:00401143                 lea     edi, [esp+209h]
  .text:0040114A                 mov     byte ptr [esp+2D0h+Serial], 0
  .text:0040114F                 rep stosd
  .text:00401151                 stosw
  .text:00401153                 stosb
  .text:00401154                 mov     ecx, 49
  .text:00401159                 xor     eax, eax
  .text:0040115B                 lea     edi, [esp+2D0h+Serial+1]
  .text:0040115F                 mov     byte ptr [esp+2D0h+md5_str_out], 0
  .text:00401164                 rep stosd
  .text:00401166                 stosw
  .text:00401168                 stosb
  .text:00401169                 xor     eax, eax        ; 使 eax = 0
  .text:0040116B                 mov     [esp+2D0h+md5_str_out+1], eax
  .text:0040116F                 mov     [esp+2D0h+var_2BB], eax
  .text:00401173                 mov     [esp+2D0h+var_2B7], eax
  .text:00401177                 mov     [esp+2D0h+var_2B3], ax
  .text:0040117C                 push    eax
  .text:0040117D                 push    300h
  .text:00401182                 mov     [esp+2D8h+var_2B1], al
  .text:00401186                 call    _mirsys         ; mirsys(300h,0h)
  .text:0040118B                 mov     esi, [esp+2D8h+hDlg]
  .text:00401192                 mov     edi, ds:GetDlgItemTextA
  .text:00401198                 add     esp, 8
  .text:0040119B                 lea     ecx, [esp+2D0h+UserName]
  .text:004011A2                 mov     ebx, eax
  .text:004011A4                 push    0C9h            ; nMaxCount
  .text:004011A9                 push    ecx             ; lpString
  .text:004011AA                 push    3EDh            ; nIDDlgItem
  .text:004011AF                 push    esi             ; hDlg
  .text:004011B0                 call    edi ; GetDlgItemTextA
  .text:004011B2                 cmp     eax, 2          ; 用户名不少于2个字符
  .text:004011B5                 jnb     short loc_4011C3
  .text:004011B7
  .text:004011B7 loc_4011B7:                             ; CODE XREF: OnCheck+135j
  .text:004011B7                 pop     edi
  .text:004011B8                 pop     esi
  .text:004011B9                 xor     eax, eax
  .text:004011BB                 pop     ebx
  .text:004011BC                 add     esp, 2C4h
  .text:004011C2                 retn
  .text:004011C3 ; ---------------------------------------------------------------------------
  .text:004011C3
  .text:004011C3 loc_4011C3:                             ; CODE XREF: OnCheck+A5j
  .text:004011C3                 lea     edx, [esp+2D0h+Group]
  .text:004011CA                 push    0C9h            ; nMaxCount
  .text:004011CF                 push    edx             ; lpString
  .text:004011D0                 push    3EEh            ; nIDDlgItem
  .text:004011D5                 push    esi             ; hDlg
  .text:004011D6                 call    edi ; GetDlgItemTextA
  .text:004011D8                 cmp     eax, 2          ; 组织名不少于2个字符
  .text:004011DB                 jnb     short loc_4011E9
  .text:004011DD                 pop     edi
  .text:004011DE                 pop     esi
  .text:004011DF                 xor     eax, eax
  .text:004011E1                 pop     ebx
  .text:004011E2                 add     esp, 2C4h
  .text:004011E8                 retn
  .text:004011E9 ; ---------------------------------------------------------------------------
  .text:004011E9
  .text:004011E9 loc_4011E9:                             ; CODE XREF: OnCheck+CBj
  .text:004011E9                 lea     eax, [esp+2D0h+Serial]
  .text:004011ED                 push    0C9h            ; nMaxCount
  .text:004011F2                 push    eax             ; lpString
  .text:004011F3                 push    3EFh            ; nIDDlgItem
  .text:004011F8                 push    esi             ; hDlg
  .text:004011F9                 call    edi ; GetDlgItemTextA
  .text:004011FB                 test    eax, eax        ; 注册码不能为空
  .text:004011FD                 jnz     short loc_401209
  .text:004011FF                 pop     edi
  .text:00401200                 pop     esi
  .text:00401201                 pop     ebx
  .text:00401202                 add     esp, 2C4h
  .text:00401208                 retn
  .text:00401209 ; ---------------------------------------------------------------------------
  .text:00401209
  .text:00401209 loc_401209:                             ; CODE XREF: OnCheck+EDj
  .text:00401209                 mov     al, byte ptr [esp+2D0h+Serial] ; 取注册码的第一个字符
  .text:0040120D                 test    al, al
  .text:0040120F                 jz      short loc_401253
  .text:00401211                 lea     esi, [esp+2D0h+Serial] ; 取注册码
  .text:00401215
  .text:00401215 loc_401215:                             ; CODE XREF: OnCheck+141j
  .text:00401215                 cmp     dword_414FDC, 1 ; 循环检查注册码的每一个字符看是否是16进制字符,否则退出
  .text:0040121C                 jle     short loc_401232
  .text:0040121E                 xor     ecx, ecx
  .text:00401220                 push    80h             ; int
  .text:00401225                 mov     cl, [esi]
  .text:00401227                 push    ecx             ; int
  .text:00401228                 call    __isctype
  .text:0040122D                 add     esp, 8
  .text:00401230                 jmp     short loc_401243
  .text:00401232 ; ---------------------------------------------------------------------------
  .text:00401232
  .text:00401232 loc_401232:                             ; CODE XREF: OnCheck+10Cj
  .text:00401232                 mov     eax, off_414DD0
  .text:00401237                 xor     edx, edx
  .text:00401239                 mov     dl, [esi]
  .text:0040123B                 mov     al, [eax+edx*2]
  .text:0040123E                 and     eax, 80h
  .text:00401243
  .text:00401243 loc_401243:                             ; CODE XREF: OnCheck+120j
  .text:00401243                 test    eax, eax
  .text:00401245                 jz      loc_4011B7
  .text:0040124B                 mov     al, [esi+1]
  .text:0040124E                 inc     esi
  .text:0040124F                 test    al, al
  .text:00401251                 jnz     short loc_401215
  .text:00401253
  .text:00401253 loc_401253:                             ; CODE XREF: OnCheck+FFj
  .text:00401253                 lea     ecx, [esp+2D0h+Group] ; 取组织名
  .text:0040125A                 push    ebp
  .text:0040125B                 push    ecx             ; char *
  .text:0040125C                 call    __strrev        ; 将组织名字符串逆转
  .text:00401261                 mov     edi, eax
  .text:00401263                 or      ecx, 0FFFFFFFFh
  .text:00401266                 xor     eax, eax
  .text:00401268                 lea     edx, [esp+2D8h+UserName] ; 取用户名
  .text:0040126F                 repne scasb
  .text:00401271                 not     ecx
  .text:00401273                 sub     edi, ecx
  .text:00401275                 mov     esi, edi
  .text:00401277                 mov     ebp, ecx
  .text:00401279                 mov     edi, edx
  .text:0040127B                 or      ecx, 0FFFFFFFFh
  .text:0040127E                 repne scasb
  .text:00401280                 mov     ecx, ebp
  .text:00401282                 dec     edi
  .text:00401283                 shr     ecx, 2
  .text:00401286                 rep movsd
  .text:00401288                 mov     ecx, ebp
  .text:0040128A                 lea     eax, [esp+2D8h+md5_ctx]
  .text:0040128E                 and     ecx, 3
  .text:00401291                 push    eax
  .text:00401292                 rep movsb               ; 用户名和组织名的逆连接起来
  .text:00401294                 call    _MD5_Init
  .text:00401299                 lea     edi, [esp+2DCh+UserName]
  .text:004012A0                 or      ecx, 0FFFFFFFFh
  .text:004012A3                 xor     eax, eax
  .text:004012A5                 lea     edx, [esp+2DCh+md5_ctx]
  .text:004012A9                 repne scasb
  .text:004012AB                 not     ecx
  .text:004012AD                 dec     ecx
  .text:004012AE                 push    ecx
  .text:004012AF                 lea     ecx, [esp+2E0h+UserName]
  .text:004012B6                 push    ecx
  .text:004012B7                 push    edx
  .text:004012B8                 call    _MD5_Update
  .text:004012BD                 lea     eax, [esp+2E8h+md5_ctx]
  .text:004012C1                 lea     ecx, [esp+2E8h+md5_str_out]
  .text:004012C5                 push    eax
  .text:004012C6                 push    ecx
  .text:004012C7                 call    _MD5_Final
  .text:004012CC                 push    0
  .text:004012CE                 mov     dword ptr [ebx+234h], 10h ; mip->IOBASE = 16;
  .text:004012D8                 call    _mirvar
  .text:004012DD                 push    0
  .text:004012DF                 mov     esi, eax
  .text:004012E1                 call    _mirvar
  .text:004012E6                 push    0
  .text:004012E8                 mov     edi, eax
  .text:004012EA                 call    _mirvar
  .text:004012EF                 push    0
  .text:004012F1                 mov     ebp, eax
  .text:004012F3                 call    _mirvar
  .text:004012F8                 push    offset a97944b587e4991 ; "97944B587E49910C2DFDD84BA062BC8917B3085"...
  .text:004012FD                 push    ebp
  .text:004012FE                 mov     ebx, eax
  .text:00401300                 call    _cinstr
  .text:00401305                 push    offset a10001   ; "10001"
  .text:0040130A                 push    edi
  .text:0040130B                 call    _cinstr
  .text:00401310                 lea     edx, [esp+310h+md5_str_out]
  .text:00401314                 push    ebx
  .text:00401315                 push    edx
  .text:00401316                 push    16
  .text:00401318                 call    _bytes_to_big
  .text:0040131D                 add     esp, 48h
  .text:00401320                 lea     eax, [esp+2D4h+Serial] ; 取用户输入的注册码,然后转化为大数,与计算出来的注册码比较
  .text:00401324                 push    eax
  .text:00401325                 push    esi
  .text:00401326                 call    _cinstr
  .text:0040132B                 push    esi
  .text:0040132C                 push    ebp
  .text:0040132D                 push    edi
  .text:0040132E                 push    esi
  .text:0040132F                 call    _powmod
  .text:00401334                 push    ebx
  .text:00401335                 push    esi
  .text:00401336                 call    _compare        ; 大数比较。相等则注册成功,否则失败
  .text:0040133B                 mov     [esp+2F4h+var_2C4], eax
  .text:0040133F                 push    esi
  .text:00401340                 call    _mirkill
  .text:00401345                 push    edi
  .text:00401346                 call    _mirkill
  .text:0040134B                 push    ebp
  .text:0040134C                 call    _mirkill
  .text:00401351                 push    ebx
  .text:00401352                 call    _mirkill
  .text:00401357                 add     esp, 30h
  .text:0040135A                 call    _mirexit
  .text:0040135F                 mov     ecx, [esp+2D4h+var_2C4]
  .text:00401363                 xor     eax, eax
  .text:00401365                 pop     ebp
  .text:00401366                 pop     edi
  .text:00401367                 test    ecx, ecx
  .text:00401369                 pop     esi
  .text:0040136A                 pop     ebx
  .text:0040136B                 setz    al
  .text:0040136E                 add     esp, 2C4h
  .text:00401374                 retn
  .text:00401374 OnCheck         endp
  .text:00401374
  
  
  注册码验证过程:
  1、将用户名字符串和组织名字符串的逆串连接起来,用标准MD5算法计算该字符串hash值,将该hash串转化为大数H。
  2、将注册码转化为大数S,进行模幂运算S^e mod p = C
  3、如果H = C,则注册成功。
  其中 e=10001h,p=97944B587E49910C2DFDD84BA062BC8917B3085FFAB61ABF930A8396CDE8B9E3h
  
  可以看出整个验证过程很简单。
  生成注册码的过程:
  1、将用户名字符串和组织名字符串的逆串连接起来,用标准MD5算法计算该字符串hash值,将该hash串转化为大数H。
  2、令 e*d mod p-1 = 1,则 d = e^-1 mod p-1。用扩展Euclid算法求得e关于模p-1的乘法逆元d,则有
  S = C^d mod p = H^d mod p
  3、将大数S转化为字符串,即为所求的注册码。
  
  
  以下是一组正确的注册码:
      name:  ylp1332
     group:  hahik
    serial:  52575D6C6D8A32B11FF6F8215B93DBC9AE89ACCFFECFCF89B6D442A484F54278
  
  
  以下是keygen的主要代码,不含md5算法实现。
  在visual c++ 6 with sp6 下编译通过。
  
  #include <stdio.h>
  #include <string.h>
  #include "miracl.h"
  #include "md5.h"
  
  #pragma comment ( lib, "miracl.lib" )
  
  #define MAXLEN 50
  
  int main(int argc, char **argv)
  {
          char usr_name[ MAXLEN ] = {0};
          char grp_name[ MAXLEN ] = {0};
          char ser_code[ MAXLEN ] = {0};
          char hash_out[ MAXLEN ] = {0};
  
          struct MD5Context md5_ctx;
          miracl *mip;
          big x,y,z,w;
          char buf[ MAXLEN ];
  
          // Your Name here, at least 2 chars !   
          strcpy( usr_name, "ylp1332" );
          // Your Group here, at least 2 chars !
          strcpy( grp_name, "hahik" );
  
          printf("    name:  %s\n", usr_name );
          printf("   group:  %s\n", grp_name );
  
          memset( buf, 0, MAXLEN );
          strcpy( buf, usr_name );
          strcat( buf, _strrev(grp_name) );
  
          MD5Init( &md5_ctx );
          MD5Update( &md5_ctx, buf, strlen(buf) );
          MD5Final( hash_out, &md5_ctx );
  
          mip = mirsys( 0x300, 0 );
          mip->IOBASE = 0x10;
  
          x  = mirvar( 0 );
          y  = mirvar( 0 );
          z  = mirvar( 0 );
          w  = mirvar( 0 );
  
          bytes_to_big( 16, hash_out, x );
          cinstr( y, "648A7A87920C9DE7244271CB87F0B5F980FCC19B58229E0F602AE3298E1EC5DD" );
          cinstr( z, "97944B587E49910C2DFDD84BA062BC8917B3085FFAB61ABF930A8396CDE8B9E3" );
          powmod( x, y, z, w );
          cotstr( w, ser_code );
  
          printf("  serial:  %s\n", ser_code );
  
          mirkill( x );
          mirkill( y );
          mirkill( z );
          mirkill( w );
  
          mirexit();
          return 0;
  }
  
  
--------------------------------------------------------------------------------
【经验总结】
  静态分析和动态调试相结合。
  大数运算要熟悉正逆向推导过程。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年12月15日 5:33:12


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

收藏
免费 7
支持
分享
最新回复 (5)
雪    币: 47147
活跃值: (20450)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
恭喜 ylp1332 有精华帖了 ,好文章
2006-12-15 09:50
0
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
3

楼主潜水很深的嘛
2006-12-15 11:00
0
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
4
恭喜恭喜
分析得很仔细,不错不错。
2006-12-15 11:52
0
雪    币: 461
活跃值: (93)
能力值: ( LV9,RANK:1170 )
在线值:
发帖
回帖
粉丝
5
恭喜 ylp1332 ,好文章!
2006-12-15 20:41
0
雪    币: 342
活跃值: (318)
能力值: ( LV12,RANK:740 )
在线值:
发帖
回帖
粉丝
6
学习了,我写过的Happytown的第29个crackme注册机也应该是这样的.
2006-12-15 23:43
0
游客
登录 | 注册 方可回帖
返回
//