首页
社区
课程
招聘
新手对happytown老大的KeyGenMe_01的分析,兄弟们看看对没,顺便请教下一步该怎么做
发表于: 2006-12-22 08:52 5361

新手对happytown老大的KeyGenMe_01的分析,兄弟们看看对没,顺便请教下一步该怎么做

2006-12-22 08:52
5361

我是新手,以happytown老大这系列东东作为起步点,在此谢谢老大:)以后多多向大家学习。

对于W32Dasm等的反汇编这里就不说了,这里直接从OD开始。

首先运行KeyGenMe_01.exe,尝试输入name:rageliu和serial:12345,点击Check,没有任何反应,看来是要注册码正确才会有提示信息。我们用OD加载KeyGenMe_01.exe,在反汇编的代码区域右键点击,选择“查找“后点“所有参考文本字串”,会在Text string里面发现“Good job,man!”,呵呵,我们猜测这是在注册码正确后给我们的提示,这里注意到上面还有个字串“Congratulations”恭喜的意思啊:)呵呵,双击“Good job,man!”串来到下面代码的地方:

004025BB   .  C785 7CFFFFFF>MOV DWORD PTR SS:[EBP-84],KeyGenMe.00401>;  UNICODE "Good job,man!"

贴出这附近的代码,并加了些猜测的注释,需要我们调试来证实:

00402595   .  C785 6CFFFFFF>MOV DWORD PTR SS:[EBP-94],KeyGenMe.00401>;  UNICODE "Congratulations"//提示窗体的Caption????
0040259F   .  BF 08000000   MOV EDI,8
004025A4   .  89BD 64FFFFFF MOV DWORD PTR SS:[EBP-9C],EDI
004025AA   .  8D95 64FFFFFF LEA EDX,DWORD PTR SS:[EBP-9C]
004025B0   .  8D4D A4       LEA ECX,DWORD PTR SS:[EBP-5C]
004025B3   .  8B35 98104000 MOV ESI,DWORD PTR DS:[<&MSVBVM60.__vbaVa>;  MSVBVM60.__vbaVarDup
004025B9   .  FFD6          CALL ESI                                 ;  <&MSVBVM60.__vbaVarDup>
004025BB   .  C785 7CFFFFFF>MOV DWORD PTR SS:[EBP-84],KeyGenMe.00401>;  UNICODE "Good job,man!" //我们猜测是注册码正确后的提示
004025C5   .  89BD 74FFFFFF MOV DWORD PTR SS:[EBP-8C],EDI
004025CB   .  8D95 74FFFFFF LEA EDX,DWORD PTR SS:[EBP-8C]
004025D1   .  8D4D B4       LEA ECX,DWORD PTR SS:[EBP-4C]
004025D4   .  FFD6          CALL ESI
004025D6   .  8D55 84       LEA EDX,DWORD PTR SS:[EBP-7C]
004025D9   .  52            PUSH EDX
004025DA   .  8D45 94       LEA EAX,DWORD PTR SS:[EBP-6C]
004025DD   .  50            PUSH EAX
004025DE   .  8D4D A4       LEA ECX,DWORD PTR SS:[EBP-5C]
004025E1   .  51            PUSH ECX
004025E2   .  6A 40         PUSH 40
004025E4   .  8D55 B4       LEA EDX,DWORD PTR SS:[EBP-4C]  //下面是调用MessageBox,那么上面应该就是设置它的参数了??
004025E7   .  52            PUSH EDX
004025E8   .  FF15 34104000 CALL DWORD PTR DS:[<&MSVBVM60.#595>]     ;  MSVBVM60.rtcMsgBox//这里是不是好熟悉??MessageBox??

由于我们注册码是不正确的,所以上面代码没有被执行到,那就是说前面的某个地方有个判断的东东,将后面的正确提示跳转过了??带着这样的猜测,我们帖出紧接着"Good job,man!"前面的代码:
00402564   .  8B4D DC       MOV ECX,DWORD PTR SS:[EBP-24]
00402567   .  51            PUSH ECX
00402568   .  FF15 80104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaR8Str>;  MSVBVM60.__vbaR8Str//这个应该就是关键call了吧???
0040256E   .  DC9D 14FFFFFF FCOMP QWORD PTR SS:[EBP-EC]              ;  
00402574   .  DFE0          FSTSW AX
00402576   .  F6C4 40       TEST AH,40       //注意这里的TEST
00402579   .  0F84 86000000 JE KeyGenMe.00402605                     ;  //看到这里了吗???有个跳转,初步估计它应该就是关键跳转了。也就是说它跳过了前面分析的提示窗体部分的代码。执行到了注册码错误的逻辑分支。
0040257F   .  B9 04000280   MOV ECX,80020004
00402584   .  894D 8C       MOV DWORD PTR SS:[EBP-74],ECX
00402587   .  B8 0A000000   MOV EAX,0A
0040258C   .  8945 84       MOV DWORD PTR SS:[EBP-7C],EAX
0040258F   .  894D 9C       MOV DWORD PTR SS:[EBP-64],ECX
00402592   .  8945 94       MOV DWORD PTR SS:[EBP-6C],EAX
00402595   .  C785 6CFFFFFF>MOV DWORD PTR SS:[EBP-94],KeyGenMe.00401>;  UNICODE "Congratulations"//提示窗体的Caption????
0040259F   .  BF 08000000   MOV EDI,8
004025A4   .  89BD 64FFFFFF MOV DWORD PTR SS:[EBP-9C],EDI
004025AA   .  8D95 64FFFFFF LEA EDX,DWORD PTR SS:[EBP-9C]
004025B0   .  8D4D A4       LEA ECX,DWORD PTR SS:[EBP-5C]
004025B3   .  8B35 98104000 MOV ESI,DWORD PTR DS:[<&MSVBVM60.__vbaVa>;  MSVBVM60.__vbaVarDup
004025B9   .  FFD6          CALL ESI                                 ;  <&MSVBVM60.__vbaVarDup>
004025BB   .  C785 7CFFFFFF>MOV DWORD PTR SS:[EBP-84],KeyGenMe.00401>;  UNICODE "Good job,man!" //我们猜测是注册码正确后的提

分析到这里我们心里应该就有个大概的眉目了,不过前面的猜测正确与否,我们就开始动态调试来证实。

我们在关键call的前面点00402567   .  51            PUSH ECX处下端,F9执行,输入name:rageliu和serial:12345,点击Check,OD断在了00402567我们下的端点处。先不用F7跟进,直接F8一直到00402579   .  0F84 86000000 JE KeyGenMe.00402605,也就是我们猜测的关键跳的地方,果然如我们猜想的一样,跳转被执行,跳到了00402605,也就是跳过了正确的处理代码去到了注册码错误的处理部分,看来我们上面猜测的基本是对的,下面来做进一步的证实,我们先用暴破的方式。

重新用OD加载程序,输入注册码后断在我们的断点处,这时候我们双击00402579   .  0F84 86000000 JE KeyGenMe.00402605后将JE改为JNE,汇编,F8过断点后直接F9执行,呵呵,出来了一个窗体,信息是“Good job,man!”,Caption也正是我们猜想的""Congratulations",到这里已基本证明我们前面的分析是正确的了,如果暴破也就是成功了,不过我们学东西啊,所以目标是要写出注册机:)让我们接着来。

由于我是新手,还是按照破解的一般步骤来吧,我们考虑F7进关键call,追出注册码先,这样注册机就是时间的问题了,嘿嘿。

OD加载KeyGenMe_01.exe后断在00402567我们的断点处,看到右边寄存器里面的ECX了吗?里面是"12345",好象我们刚才填的注册码也是12345哦?先不管它。F8运行到我们猜测的关键call的地方,F7进去,这时候我突然发现已经不在KeyGenMe的空间了,进入了系统功能调用的空间,怎么回事????????????

用Alt+F9返回KeyGenMe的空间后仔细一看,原来那个call不是call的KeyGenMe.XXXX的形式,而是一个系统功能调用,也就不是我们所说的关键call。看来上面关于这里的猜测是不对的。再仔细分析下这段代码:
00402564   .  8B4D DC       MOV ECX,DWORD PTR SS:[EBP-24]            ;  "12345"地址进ECX
00402567   .  51            PUSH ECX                                 ;  ECX入栈保存
00402568   .  FF15 80104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaR8Str>;  MSVBVM60.__vbaR8Str//这里不是什么关键call,应该是调用                                              //一个系统功能,前面的PUSH ECX                                                                                             //是给这个调用压参吗?????
0040256E   .  DC9D 14FFFFFF FCOMP QWORD PTR SS:[EBP-EC]              ;  没有关键call,比较应该在这里??
00402574   .  DFE0          FSTSW AX         ;  保存状态字的值到AX
00402576   .  F6C4 40       TEST AH,40                               ;  //AH 值与40("@")比较,不相同就会执行下面的关键跳,也                      ;  //就失败了
00402579      0F84 86000000 JE KeyGenMe.00402605                     ;  关键跳转,跳了就完蛋

这里说下FCOMP/FCOMPP指令:FCOMP将栈顶数据与另一个操作数进行比较,该操作数可以存储在堆栈寄存器中,也可存储在内存中。根据上面的代码,栈顶数据显然就是PUSH ECX所压入的“12345”,也就是我们填写的注册码的明码。。看来注册码没有变化,只是name变换后和注册码比较,那现在的关键就是对name的变换操作了。

目前就研究到这里,其他的我还没搞明白,太菜了,郁闷:)

高手来补上啊,我分析到这个程度也不知道对没对,花我半天时间了,后面还不知如何下手...

我分析了下TEST前面部分的代码,发现有一个循环处理,可能是对name的变换,不过还没弄懂,大家使劲鄙视我吧

这里追到的一组name和注册码:(就是FCOMP QWORD PTR SS:[EBP-EC]的时候看到的就是了)
name:rageliu
serial:287195202


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

收藏
免费 7
支持
分享
最新回复 (4)
雪    币: 228
活跃值: (16)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
2
比我好多了,我只会爆啊!
2006-12-24 23:13
0
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
3
排版有问题,乱的很
2006-12-24 23:46
0
雪    币: 10885
活跃值: (3288)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
4
那个循环是注册码算法部分

004024AF   > /66:3B75 D0    cmp     si, [ebp-30]  //si 初始值为1,[ebp-30]存放的输入注册码的长度,循环开始;
004024B3   . |0F8F 93000000 jg      0040254C      //si值大于输入的注册码长度,则退出循环
004024B9   . |C745 BC 01000>mov     dword ptr [ebp-44], 1
004024C0   . |C745 B4 02000>mov     dword ptr [ebp-4C], 2
004024C7   . |8D45 CC       lea     eax, [ebp-34]
004024CA   . |8985 7CFFFFFF mov     [ebp-84], eax
004024D0   . |C785 74FFFFFF>mov     dword ptr [ebp-8C], 4008
004024DA   . |8D4D B4       lea     ecx, [ebp-4C]
004024DD   . |51            push    ecx
004024DE   . |0FBFD6        movsx   edx, si
004024E1   . |52            push    edx
004024E2   . |8D85 74FFFFFF lea     eax, [ebp-8C]
004024E8   . |50            push    eax
004024E9   . |8D4D A4       lea     ecx, [ebp-5C]
004024EC   . |51            push    ecx
004024ED   . |FF15 44104000 call    [<&MSVBVM60.#632>]              
004024F3   . |8D55 A4       lea     edx, [ebp-5C]
004024F6   . |52            push    edx
004024F7   . |8D45 C8       lea     eax, [ebp-38]
004024FA   . |50            push    eax
004024FB   . |FF15 74104000 call    [<&MSVBVM60.__vbaStrVarVal>]     
00402501   . |50            push    eax
00402502   . |FF15 18104000 call    [<&MSVBVM60.#516>]              //取注册名的第si个字符
00402508   . |66:0FAFC6     imul    ax, si              //将第si个字符的16进制值乘以si
0040250C   . |0F80 5F010000 jo      00402671
00402512   . |0FBFC8        movsx   ecx, ax
00402515   . |03CF          add     ecx, edi           //乘完后加edi ,edi初始为1
00402517   . |0F80 54010000 jo      00402671
0040251D   . |8BF9          mov     edi, ecx          //所得值存放在edi中
0040251F   . |8D4D C8       lea     ecx, [ebp-38]
00402522   . |FF15 B4104000 call    [<&MSVBVM60.__vbaFreeStr>]      
00402528   . |8D55 A4       lea     edx, [ebp-5C]
0040252B   . |52            push    edx
0040252C   . |8D45 B4       lea     eax, [ebp-4C]
0040252F   . |50            push    eax
00402530   . |6A 02         push    2
00402532   . |FFD3          call    ebx
00402534   . |83C4 0C       add     esp, 0C
00402537   . |B8 01000000   mov     eax, 1
0040253C   . |66:03C6       add     ax, si
0040253F   . |0F80 2C010000 jo      00402671
00402545   . |8BF0          mov     esi, eax           //esi加1
00402547   .^\E9 63FFFFFF   jmp     004024AF           //继续循环
0040254C   >  69FF 96740100 imul    edi, edi, 17496    //将得到的edi值乘以0x17496 (即得到注册码)
00402552   .  0F80 19010000 jo      00402671
00402558   .  897D D8       mov     [ebp-28], edi   
0040255B   .  DB45 D8       fild    dword ptr [ebp-28]   
0040255E   .  DD9D 14FFFFFF fstp    qword ptr [ebp-EC]  //将所得值存入 [ebp-ec]
00402564   .  8B4D DC       mov     ecx, [ebp-24]
00402567   .  51            push    ecx          //将输入的注册码压栈
00402568   .  FF15 80104000 call    [<&MSVBVM60.__vbaR8Str>]         //将输入的注册码放入FPU栈寄存器顶  
0040256E   .  DC9D 14FFFFFF fcomp   qword ptr [ebp-EC]  //将FPU栈寄存器顶的用户输入的注册码与正确注册码比较
00402574   .  DFE0          fstsw   ax                  //将状态寄存器值给ax
00402576   .  F6C4 40       test    ah, 40              //若不相等ax为0100,ah为01;若相等ax 为1000,ah为10
00402579      0F84 86000000 je      00402605            //ah为0则错误跳转

所以注册码算法为:
edi=1;
i=1;
while(i<=strlen(name))
edi+=name[i]*i;
edi*=0x17496;
edi就为注册码.

本人也是个新菜鸟,上面可能有很多错误,如果有错请高手指正,谢谢!
2006-12-25 13:08
0
雪    币: 228
活跃值: (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
5
谢谢楼上:)帅呆了你
2006-12-25 15:22
0
游客
登录 | 注册 方可回帖
返回
//