首页
社区
课程
招聘
[原创]TMG Official Trial Keygenme #3分析
发表于: 2006-10-17 17:15 7282

[原创]TMG Official Trial Keygenme #3分析

2006-10-17 17:15
7282

【文章标题】: TMG Official Trial Keygenme #3分析
【文章作者】: HappyTown
【作者邮箱】: [email]wxr277@163.com[/email]
【作者主页】: www.pediy.com
【软件名称】: TMG Official Trial Keygenme #3
【下载地址】: 附件内
【加壳方式】: 无
【保护方式】: MD5 + ElGamal
【编写语言】: VC 5.0
【使用工具】: OD,DAMN_Hash,BigCalc
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  建议你在阅读该破文的同时对原程序进行调试,这样效果会更好。
  
  一、基本信息:
      1. PEiD查看,为VC 5编写,无壳;
      2. 用PEiD的KANAL插件查看,MD5 inside;
      3. 用IDA分析不出什么库的相关函数;
      4. 什么都不输入,弹出错误信息,这个可以帮助定位应该下断的地方。
  
  二、分析过程:
      1. OD载入后,下断;
      2. 查找文本字符串,根据"MIRACL error"我们发现的确使用了miracl库,这就需要手动定位库函数了,下面我会努力解释如何做到这一点;
      3. 输入注册信息:
  Username:happy
  Registration Code:1234567890ABCDEF2222222233333333 (为什么是32位的原因在下面)
  
  我把Registration Code分为sn_1和sn_2,各长16。
  
  00401000  /$>sub     esp, 1FC
  00401006  |.>push    ebx
  00401007  |.>push    ebp
  00401008  |.>push    esi
  00401009  |.>mov     esi, [<&USER32.SendDlgItem>;  USER32.SendDlgItemMessageA
  0040100F  |.>lea     eax, [esp+188]
  00401016  |.>push    edi
  00401017  |.>mov     edi, [esp+210]
  0040101E  |.>push    eax                        ; /lParam
  0040101F  |.>push    41                         ; |wParam = 41
  00401021  |.>push    0D                         ; |Message = WM_GETTEXT
  00401023  |.>push    3F1                        ; |ControlID = 3F1 (1009.)
  00401028  |.>push    edi                        ; |hWnd
  00401029  |.>call    esi                        ; \SendDlgItemMessageA
  0040102B  |.>cmp     eax, 5                     ;  name长度>=5
  0040102E  |.>mov     [esp+20], eax
  00401032  |.>jnb     short 00401052
  00401034  |.>push    10                         ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
  00401036  |.>push    0040A264                   ; |Title = "Error"
  0040103B  |.>push    0040A244                   ; |Text = "Length of Username is invalid."
  00401040  |.>push    edi                        ; |hOwner
  00401041  |.>call    [<&USER32.MessageBoxA>]    ; \MessageBoxA
  00401047  |.>pop     edi
  00401048  |.>pop     esi
  00401049  |.>pop     ebp
  0040104A  |.>pop     ebx
  0040104B  |.>add     esp, 1FC
  00401051  |.>retn
  00401052  |>>lea     ecx, [esp+34]
  00401056  |.>push    ecx
  00401057  |.>push    41
  00401059  |.>push    0D
  0040105B  |.>push    3F2
  00401060  |.>push    edi
  00401061  |.>call    esi
  00401063  |.>cmp     eax, 20                    ;  sn长度必须为32
  00401066  |.>je      short 00401086
  00401068  |.>push    10                         ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
  0040106A  |.>push    0040A264                   ; |Title = "Error"
  0040106F  |.>push    0040A21C                   ; |Text = "Length of Registration code is invalid."
  00401074  |.>push    edi                        ; |hOwner
  00401075  |.>call    [<&USER32.MessageBoxA>]    ; \MessageBoxA
  0040107B  |.>pop     edi
  0040107C  |.>pop     esi
  0040107D  |.>pop     ebp
  0040107E  |.>pop     ebx
  0040107F  |.>add     esp, 1FC
  00401085  |.>retn
  00401086  |>>xor     edx, edx
  00401088  |>>/mov     cl, [esp+edx+34]
  0040108C  |.>|cmp     cl, 30
  0040108F  |.>|jnb     short 00401092
  00401091  |.>|dec     eax
  00401092  |>>|cmp     cl, 46
  00401095  |.>|jbe     short 00401098
  00401097  |.>|dec     eax
  00401098  |>>|cmp     cl, 39
  0040109B  |.>|jbe     short 004010A3
  0040109D  |.>|cmp     cl, 41
  004010A0  |.>|jnb     short 004010A3
  004010A2  |.>|dec     eax
  004010A3  |>>|inc     edx
  004010A4  |.>|cmp     edx, 20
  004010A7  |.>\jb      short 00401088
  004010A9  |.>cmp     eax, 20
  004010AC  |.>je      short 004010CC
  004010AE  |.>push    10                         ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
  004010B0  |.>push    0040A210                   ; |Title = "Bad luck"
  004010B5  |.>push    0040A1E4                   ; |Text = "Wild guessing won't help you too much :-("
  004010BA  |.>push    edi                        ; |hOwner
  004010BB  |.>call    [<&USER32.MessageBoxA>]    ; \MessageBoxA
  004010C1  |.>pop     edi
  004010C2  |.>pop     esi
  004010C3  |.>pop     ebp
  004010C4  |.>pop     ebx
  004010C5  |.>add     esp, 1FC
  004010CB  |.>retn
  004010CC  |>>mov     edx, [esp+44]
  004010D0  |.>mov     eax, [esp+48]
  004010D4  |.>mov     ecx, [esp+4C]
  004010D8  |.>mov     [esp+B4], edx
  004010DF  |.>mov     edx, [esp+50]
  004010E3  |.>push    0
  004010E5  |.>mov     [esp+BC], eax
  004010EC  |.>mov     [esp+C0], ecx
  004010F3  |.>mov     [esp+C4], edx
  004010FA  |.>mov     byte ptr [esp+C8], 0
  00401102  |.>mov     byte ptr [esp+48], 0
  00401107  |.>call    <mirvar>    //可以看到下面一连串调用了这个函数,使用miracl的大数必须先用该函数初始化
                                   //用鼠标点击这一行,然后按回车键,再按Shift + :(英文冒号),输入mirvar给
                                   //该函数加个标签
  0040110C  |.>add     esp, 4
  0040110F  |.>mov     [esp+14], eax
  00401113  |.>push    0
  00401115  |.>call    <mirvar>
  0040111A  |.>add     esp, 4
  0040111D  |.>mov     esi, eax
  0040111F  |.>push    0
  00401121  |.>call    <mirvar>
  00401126  |.>add     esp, 4
  00401129  |.>mov     [esp+18], eax
  0040112D  |.>push    0
  0040112F  |.>call    <mirvar>
  00401134  |.>add     esp, 4
  00401137  |.>mov     [esp+10], eax
  0040113B  |.>push    0
  0040113D  |.>call    <mirvar>
  00401142  |.>add     esp, 4
  00401145  |.>mov     [esp+1C], eax
  00401149  |.>push    0
  0040114B  |.>call    <mirvar>
  00401150  |.>add     esp, 4
  00401153  |.>mov     ebp, eax
  00401155  |.>push    0
  00401157  |.>call    <mirvar>
  0040115C  |.>add     esp, 4
  0040115F  |.>mov     ebx, eax
  00401161  |.>push    0
  00401163  |.>call    <mirvar>
  00401168  |.>add     esp, 4
  0040116B  |.>mov     edi, eax
  0040116D  |.>lea     eax, [esp+134]
  00401174  |.>push    eax
  00401175  |.>call    <MD5_Init>                 ;===>跟进去
  
  //很明显的MD5初始化,和上面一样,我们加上MD5_Init标签,下面我就不再强调加标签了
    00401880 >/$>mov     eax, [esp+4]
    00401884  |.>xor     ecx, ecx
    00401886  |.>mov     [eax+14], ecx
    00401889  |.>mov     [eax+10], ecx
    0040188C  |.>mov     dword ptr [eax], 67452301
    00401892  |.>mov     dword ptr [eax+4], EFCDAB89
    00401899  |.>mov     dword ptr [eax+8], 98BADCFE
    004018A0  |.>mov     dword ptr [eax+C], 10325476
    004018A7  \.>retn
  \\
  
  0040117A  |.>mov     ecx, [esp+24]
  0040117E  |.>add     esp, 4
  00401181  |.>lea     edx, [esp+18C]
  00401188  |.>lea     eax, [esp+134]
  0040118F  |.>push    ecx                        ;  name长度
  00401190  |.>push    edx                        ;  name
  00401191  |.>push    eax
  00401192  |.>call    <MD5_Update>               //再根据name长度和name两个参数,猜测应该为MD5_Update,可以跟进去分析
  00401197  |.>add     esp, 0C
  0040119A  |.>lea     ecx, [esp+134]
  004011A1  |.>lea     edx, [esp+24]
  004011A5  |.>push    ecx
  004011A6  |.>push    edx                        ;先d edx一下
  
  0012F950  09 00 00 00 09 00 00 00 5C 00 F5 72 8C F9 12 00  ........\.躜?.
  
  004011A7  |.>call    <MD5_Final>                ;  MD5(name)
  004011AC  |.>mov     eax, [40CE08]              //内存区是不是变成了MD5(happy)的值,用DAMNHash验证通过
  
  0012F950  56 AB 24 C1 5B 72 A4 57 06 9C 5E A4 2F CF C6 40  V?鳞rぷ??掀@
   
  004011B1  |.>add     esp, 8
  004011B4  |.>lea     edx, [esp+24]
  004011B8  |.>mov     dword ptr [eax+22C], 100
  004011C2  |.>mov     ecx, [40CE08]
  004011C8  |.>push    edx
  004011C9  |.>push    ebp                        ;  h = MD5(name)
  004011CA  |.>mov     dword ptr [ecx+23C], 10
  004011D4  |.>call    <cinstr>
  004011D9  |.>mov     eax, [40CE08]
  004011DE  |.>add     esp, 8
  004011E1  |.>push    0040A1D0                   ;  ASCII "37A218F214C32D79"
  004011E6  |.>push    esi                        ;  m,同时在这里d esi,查看内存区
  
  00A32100  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  空空如也。
  
  004011E7  |.>mov     dword ptr [eax+22C], 10
  004011F1  |.>call    <cinstr>   //根据上面的ASCII "37A218F214C32D79"猜测这个应该是cinstr,
                                  //功能是把字符串转化为大数,执行完这个函数后查看内存区
  00A32100  02 00 00 00 79 2D C3 14 F2 18 A2 37 00 00 00 00  ...y-???....
  最前面的02意思是,这个大数占2个32位,后面的数字是不是"37A218F214C32D79"?倒过来看。+标签嘛^_^
  
  004011F6  |.>add     esp, 8
  004011F9  |.>push    ebp                        ;  h
  004011FA  |.>push    esi                        ;  m
  004011FB  |.>push    3
  004011FD  |.>push    ebp                        ;  h;d ebp一下:
  
  00A32780  04 00 00 00 40 C6 CF 2F A4 5E 9C 06 57 A4 72 5B  ...@葡/ま?Wを[
  
  004011FE  |.>call    <power>                    ;  h = h^3(mod m) = 0BD38C6FB54DE8FF
  
  00A32780  02 00 00 00 FF E8 4D B5 6F 8C D3 0B 00 00 00 00  ...?M碉?....
  执行完该call后,查看内存区;该函数共有4个参数,第二个为整型,常用的就只有power,
  该函数的功能可查看miracl手册,BigCalc验证通过。
  
  00401203  |.>add     esp, 10
  00401206  |.>mov     edx, [esp+10]
  0040120A  |.>lea     ecx, [esp+34]
  0040120E  |.>push    ecx                        ;  sn_1
  0040120F  |.>push    edx
  00401210  |.>call    <cinstr>
  00401215  |.>mov     ecx, [esp+24]
  00401219  |.>add     esp, 8
  0040121C  |.>lea     eax, [esp+B4]
  00401223  |.>push    eax                        ;  sn_2
  00401224  |.>push    ecx
  00401225  |.>call    <cinstr>
  0040122A  |.>add     esp, 8
  0040122D  |.>push    0040A1BC                   ;  ASCII "C9D94F46D0984F42"
  00401232  |.>push    esi                        ;  p_1
  00401233  |.>call    <cinstr>
  00401238  |.>mov     edx, [esp+1C]
  0040123C  |.>add     esp, 8
  0040123F  |.>push    0040A1A8                   ;  ASCII "91D4D6EF46B05C78"
  00401244  |.>push    edx                        ;  y
  00401245  |.>call    <cinstr>
  0040124A  |.>mov     eax, [esp+20]
  0040124E  |.>add     esp, 8
  00401251  |.>push    0040A194                   ;  ASCII "4B45042B684BCBD1"
  00401256  |.>push    eax                        ;  g
  00401257  |.>call    <cinstr>
  0040125C  |.>add     esp, 8
  0040125F  |.>push    esi                        ;  p
  00401260  |.>push    1
  00401262  |.>push    esi                        //d esi一下:
  
  00A32100  02 00 00 00 42 4F 98 D0 46 4F D9 C9 00 00 00 00  ...BO?FO偕....
  
  00401263  |.>call    <incr>                     ;  p = p_1 + 1 = C9D94F46D0984F43(素数,障眼法的使用?)
                                                  //执行完call后,再查看内存区:
  00A32100  02 00 00 00 43 4F 98 D0 46 4F D9 C9 00 00 00 00  ...CO?FO偕....
  变化在那里呢?呵呵,你肯定看出来了,42变成了43,所以这个函数应该为incr。
  
  00401268  |.>mov     ecx, [esp+28]
  0040126C  |.>mov     edx, [esp+1C]
  00401270  |.>add     esp, 0C
  00401273  |.>push    ebx                        ;  t
  00401274  |.>push    esi                        ;  p
  00401275  |.>push    ecx                        ;  sn_2
  00401276  |.>push    edx                        ;  sn_1
  00401277  |.>call    <powmod>                   ;  t = sn_1^sn_2 (mod p) = 5BA61D0BB0894B12
                                                  //使用miracl库却不使用powmod,那用它干什么?
  0040127C  |.>mov     eax, [esp+20]
  00401280  |.>mov     ecx, [esp+24]
  00401284  |.>add     esp, 10
  00401287  |.>push    edi                        ;  s
  00401288  |.>push    esi                        ;  p
  00401289  |.>push    eax                        ;  sn_1
  0040128A  |.>push    ecx                        ;  y
  0040128B  |.>call    <powmod>                   ;  s = y^sn_1 (mod p) = 240AB80995A29A16
  00401290  |.>add     esp, 10
  00401293  |.>push    edi                        ;  s
  00401294  |.>push    esi                        ;  p
  00401295  |.>push    esi                        ;  p
  00401296  |.>push    edi                        ;  s
  00401297  |.>push    edi                        ;  s
  00401298  |.>push    ebx                        ;  t
  00401299  |.>call    <mad>                      ;  s = t*s (mod p) = 4369A79E096FF8B6
              //这个函数相当好猜测,因为它有6个参数,另一个有6个参数的是powmod2(a,b,c,d,z,w),BigCalc验证应该为mad
  0040129E  |.>mov     edx, [esp+30]
  004012A2  |.>add     esp, 18
  004012A5  |.>push    ebx                        ;  t
  004012A6  |.>push    esi                        ;  p
  004012A7  |.>push    ebp                        ;  h
  004012A8  |.>push    edx                        ;  g
  004012A9  |.>call    <powmod>                   ;  t = g^h (mod p) = 66468FB8A8A01FDD
  004012AE  |.>add     esp, 10
  004012B1  |.>push    edi                        ;  s
  004012B2  |.>push    ebx                        ;  t
  004012B3  |.>call    <compare>                  //如果你对miracl库有所了解,这个函数还是经常被使用的
                                                  //它的后面肯定跟一判断跳转指令。
  004012B8  |.>add     esp, 8
  004012BB  |.>test    eax, eax
  004012BD  |.>jnz     short 004012D4
  004012BF  |.>push    eax
  004012C0  |.>mov     eax, [esp+214]
  004012C7  |.>push    0040A188                   ;  ASCII "Well done!"
  004012CC  |.>push    0040A15C                   ;  ASCII "Very good! Registration code is correct :-)"
  004012D1  |.>push    eax
  004012D2  |.>jmp     short 004012E8
  004012D4  |>>mov     ecx, [esp+210]
  004012DB  |.>push    10                         ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
  004012DD  |.>push    0040A210                   ; |Title = "Bad luck"
  004012E2  |.>push    0040A138                   ; |Text = "Registration code is incorrect. :-("
  004012E7  |.>push    ecx                        ; |hOwner
  004012E8  |>>call    [<&USER32.MessageBoxA>]    ; \MessageBoxA
  004012EE  |.>mov     edx, [esp+14]
  004012F2  |.>push    edx
  004012F3  |.>call    <mirkill>                  //大数变量使用完后要手动销毁
  004012F8  |.>add     esp, 4
  004012FB  |.>push    esi
  004012FC  |.>call    <mirkill>
  00401301  |.>mov     eax, [esp+1C]
  00401305  |.>add     esp, 4
  00401308  |.>push    eax
  00401309  |.>call    <mirkill>
  0040130E  |.>mov     ecx, [esp+14]
  00401312  |.>add     esp, 4
  00401315  |.>push    ecx
  00401316  |.>call    <mirkill>
  0040131B  |.>mov     edx, [esp+20]
  0040131F  |.>add     esp, 4
  00401322  |.>push    edx
  00401323  |.>call    <mirkill>
  00401328  |.>add     esp, 4
  0040132B  |.>push    ebp
  0040132C  |.>call    <mirkill>
  00401331  |.>add     esp, 4
  00401334  |.>push    ebx
  00401335  |.>call    <mirkill>
  0040133A  |.>add     esp, 4
  0040133D  |.>push    edi
  0040133E  |.>call    <mirkill>
  00401343  |.>add     esp, 4
  00401346  |.>pop     edi
  00401347  |.>pop     esi
  00401348  |.>pop     ebp
  00401349  |.>pop     ebx
  0040134A  |.>add     esp, 1FC
  00401350  \.>retn
  
--------------------------------------------------------------------------------
【经验总结】
  可以看出,这个keygenme使用了MD5和ElGamal,具体验证算法如下:
  
  1. h=MD5(name)^3 (mod m);
  2. (y^sn_1)*(sn_1^sn_2) (mod p - 1) ?= g^h (mod p - 1)
  
  知道了算法,做出注册机就很简单了,详见附件。
  给出一组可用的注册码:
  Username:happytown
  Registration Code:BD7DD4164F45497573CFE2ABD92A4B4A
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年10月16日 17:52:48


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 443
活跃值: (200)
能力值: ( LV9,RANK:1140 )
在线值:
发帖
回帖
粉丝
2
哇~~~这个更强~~~~膜拜得手也累了!
2006-10-17 17:16
0
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
3
你好快,我刚发布,你就跟了。
2006-10-17 17:19
0
雪    币: 443
活跃值: (200)
能力值: ( LV9,RANK:1140 )
在线值:
发帖
回帖
粉丝
4
碰巧而已,没啥快不快的!
2006-10-17 17:20
0
雪    币: 338
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
超级强!!还看不太懂!!学习先!
2006-10-17 23:39
0
雪    币: 405
活跃值: (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
6
只是支持,哪天有办法能看懂再说~
2006-10-18 11:43
0
雪    币: 233
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
7
学习  
2006-10-19 16:41
0
游客
登录 | 注册 方可回帖
返回
//