• 标 题:HappyEO算法分析 (11千字)
  • 作 者:bbbsl
  • 时 间:2002-6-30 12:26:27
  • 链 接:http://bbs.pediy.com

HappyEO 2.40.2 算法分析

作者:bbbsl
使用工具:trw v1.23
分析平台:盗版Win98se
软件介绍:HappyEO是一款用声卡模拟电子琴的软件。有了它,您可以用计算机的键盘奏出美妙的乐曲。还有录音、自动伴奏和效果等功能。假如您没有声卡,您仍然可以用计算机内部的扬声器来发音。
(不是我说的,是作者说的,不过确实挺好玩的,只可惜我不识谱,唉,只能瞎弹!^_*)
分析过程:
先运行trw及该软件,然后选注册后,会出现注册窗口,依次填入姓名,公司名及注册码,作者很细心,如果填错位数他会提醒你的,然后下断点
bpx hmemcpy,填getwindowtexta及getdlgitemtexta均不行,那样就过了关键地方了!:-P,不过在Win2000下怎么设断点呢?有那位大虾能告诉我吗?谢谢!
废话不多说了,回到注册界面点击确定按钮,然后程序会断下,然后F10,经过N个ret后,我们来到这里:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//                第一个程序段                    
//                                        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    0167:51098C40  LEA      EDX,[EBP-04]
    0167:51098C43  MOV      EAX,[EBX+02D0]
    0167:51098C49  CALL    510312E0            ==>我们从这里出来停在下一行!
    0167:51098C4E  MOV      EAX,[EBP-04]        ==>Name
    0167:51098C51  CALL    51003F28            ==>这里计算长度
    0167:51098C56  CMP      EAX,BYTE +04        ==>Name<4?报错:继续
    0167:51098C59  JL      NEAR 51098DB0        
    0167:51098C5F  LEA      EDX,[EBP-08]        
    0167:51098C62  MOV      EAX,[EBX+02EC]
    0167:51098C68  CALL    510312E0            ==>经过这个call取公司名
    0167:51098C6D  MOV      EAX,[EBP-08]        ==>Corporation
    0167:51098C70  CALL    51003F28            ==>计算长度
    0167:51098C75  CMP      EAX,BYTE +0C        ==>Corporation<12?报错:继续
    0167:51098C78  JL      NEAR 51098DB0
    0167:51098C7E  LEA      EDX,[EBP-0C]        
    0167:51098C81  MOV      EAX,[EBX+02D4]        
    0167:51098C87  CALL    510312E0            ==>在这里取注册码
    0167:51098C8C  MOV      EAX,[EBP-0C]        ==>我们输入的注册码
    0167:51098C8F  CALL    51003F28            ==>计算长度
    0167:51098C94  CMP      EAX,BYTE +06        ==>长度<6?报错:继续
    0167:51098C97  JNZ      NEAR 51098DB0
    0167:51098C9D  LEA      EDX,[EBP-10]
    0167:51098CA0  MOV      EAX,[EBX+02D4]
    0167:51098CA6  CALL    510312E0            
    0167:51098CAB  MOV      EAX,[EBP-10]        ==>再取一遍?
    0167:51098CAE  PUSH    EAX            ==>注册码进栈
    0167:51098CAF  LEA      EDX,[EBP-18]        
    0167:51098CB2  MOV      EAX,[EBX+02EC]        
    0167:51098CB8  CALL    510312E0            
    0167:51098CBD  MOV      EAX,[EBP-18]            
    0167:51098CC0  PUSH    EAX            ==>Corp进栈    
    0167:51098CC1  LEA      EDX,[EBP-1C]
    0167:51098CC4  MOV      EAX,[EBX+02D0]
    0167:51098CCA  CALL    510312E0            
    0167:51098CCF  MOV      EAX,[EBP-1C]        ==>eax<--Name
    0167:51098CD2  LEA      ECX,[EBP-14]        ==>用来存放地址的一个指针
    0167:51098CD5  POP      EDX            ==>edx<--Corp    
    0167:51098CD6  CALL    510980B4            ==>关键,跟进!
    0167:51098CDB  MOV      EDX,[EBP-14]        ==>这里D edx可得注册码
    0167:51098CDE  POP      EAX            ==>假注册码
    0167:51098CDF  CALL    51004038            ==>比较是否正确,就不看怎么比较的了吧!
    0167:51098CE4  JNZ      NEAR 51098D9A        
    0167:51098CEA  MOV      EAX,51098E00
    0167:51098CEF  CALL    51056968
    0167:51098CF4  CALL    51009688
   
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//              这里是刚才我说的关键call                    
//                                        
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
   
    0167:510980B4  PUSH    EBP
    0167:510980B5  MOV      EBP,ESP
    0167:510980B7  ADD      ESP,BYTE -10
    0167:510980BA  PUSH    EBX
    0167:510980BB  XOR      EBX,EBX
    0167:510980BD  MOV      [EBP-10],EBX        ==>相当于四个变量
    0167:510980C0  MOV      [EBP-0C],ECX        
    0167:510980C3  MOV      [EBP-08],EDX
    0167:510980C6  MOV      [EBP-04],EAX
    0167:510980C9  MOV      EAX,[EBP-04]        
    0167:510980CC  CALL    510040DC            
    0167:510980D1  MOV      EAX,[EBP-08]        
    0167:510980D4  CALL    510040DC            
    0167:510980D9  XOR      EAX,EAX            
    0167:510980DB  PUSH    EBP            
    0167:510980DC  PUSH    DWORD 5109814A        
    0167:510980E1  PUSH    DWORD [FS:EAX]        
    0167:510980E4  MOV      [FS:EAX],ESP        
    0167:510980E7  MOV      EAX,[EBP-0C]        
    0167:510980EA  CALL    51003CA8            
    0167:510980EF  MOV      EAX,[EBP-04]        ==>又来了,判断名字长度
    0167:510980F2  CALL    51003F28            
    0167:510980F7  CMP      EAX,BYTE +04        
    0167:510980FA  JL      51098127            
    0167:510980FC  MOV      EAX,[EBP-08]        ==>判断公司名长度
    0167:510980FF  CALL    51003F28
    0167:51098104  CMP      EAX,BYTE +0C        
    0167:51098107  JL      51098127            
    0167:51098109  LEA      EAX,[EBP-10]        
    0167:5109810C  MOV      ECX,[EBP-08]        ==>公司名
    0167:5109810F  MOV      EDX,[EBP-04]        ==>Name
    0167:51098112  CALL    51003F74            ==>这里用来合并姓名和公司名
    0167:51098117  MOV      EAX,[EBP-10]        ==>eax<--合并后的字符串
    0167:5109811A  CALL    51097F9C            ==>用这个字符串来算一个重要数!跟进!
    0167:5109811F  MOV      EDX,[EBP-0C]        ==>通过运算得到一个数
    0167:51098122  CALL    51098024            ==>用这个数求最后的六位注册码
    0167:51098127  XOR      EAX,EAX            
    0167:51098129  POP      EDX            
    0167:5109812A  POP      ECX            
    0167:5109812B  POP      ECX            
    0167:5109812C  MOV      [FS:EAX],EDX        
    0167:5109812F  PUSH    DWORD 51098151        
    0167:51098134  LEA      EAX,[EBP-10]        
    0167:51098137  CALL    51003CA8
    0167:5109813C  LEA      EAX,[EBP-08]
    0167:5109813F  MOV      EDX,02
    0167:51098144  CALL    51003CCC
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//                算注册码的CALL一                    
//                                        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    0167:51097F9C  PUSH    EBP
    0167:51097F9D  MOV      EBP,ESP
    0167:51097F9F  ADD      ESP,BYTE -10
    0167:51097FA2  MOV      [EBP-04],EAX
    0167:51097FA5  MOV      EAX,[EBP-04]
    0167:51097FA8  CALL    510040DC
    0167:51097FAD  XOR      EAX,EAX
    0167:51097FAF  PUSH    EBP
    0167:51097FB0  PUSH    DWORD 51098016
    0167:51097FB5  PUSH    DWORD [FS:EAX]
    0167:51097FB8  MOV      [FS:EAX],ESP
    0167:51097FBB  MOV      DWORD [EBP-08],FFFFFFFF    ==>设[ebp-8]为tempvar
    0167:51097FC2  MOV      EAX,[EBP-04]        ==>那串字符串设为str[]
    0167:51097FC5  CALL    51003F28            
    0167:51097FCA  TEST    EAX,EAX            
    0167:51097FCC  JNG      51097FF5            
    0167:51097FCE  MOV      [EBP-10],EAX        ==>设[ebp-10]为lenofnc
    0167:51097FD1  MOV      DWORD [EBP-0C],01    ==>设[ebp-c]为i
    0167:51097FD8  MOV      EAX,[EBP-04]        ==>字符串地址addrofstr<--[ebp-4]
    0167:51097FDB  MOV      EDX,[EBP-0C]        ==>用edx来从字符串定位字符
    0167:51097FDE  MOV      AL,[EAX+EDX-01]        ==>一次取一个字符
    0167:51097FE2  MOV      EDX,[EBP-08]        ==>edx<--tempvar,初值为-1
    0167:51097FE5  CALL    51097F48            ==>中间为查表过程,过会详细看看
    0167:51097FEA  MOV      [EBP-08],EAX        ==>得到的结果放入tempvar
    0167:51097FED  INC      DWORD [EBP-0C]        ==>i++
    0167:51097FF0  DEC      DWORD [EBP-10]        ==>lenofnc--
    0167:51097FF3  JNZ      51097FD8            ==>lenofnc==0?往下走:循环
    0167:51097FF5  MOV      EAX,[EBP-08]        
    0167:51097FF8  CALL    51097F80            ==>得到的最终结果取反
    0167:51097FFD  MOV      [EBP-08],EAX        
    0167:51098000  XOR      EAX,EAX            
    0167:51098002  POP      EDX
    0167:51098003  POP      ECX
    0167:51098004  POP      ECX
    0167:51098005  MOV      [FS:EAX],EDX
    0167:51098008  PUSH    DWORD 5109801D
    0167:5109800D  LEA      EAX,[EBP-04]
    0167:51098010  CALL    51003CA8
   
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//                注册码从call                    
//                                        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////   
   
   
    0167:51097F48  PUSH    EBP
    0167:51097F49  MOV      EBP,ESP
    0167:51097F4B  ADD      ESP,BYTE -0C
    0167:51097F4E  MOV      [EBP-08],EDX        ==>tempvar
    0167:51097F51  MOV      [EBP-01],AL        ==>所取字符
    0167:51097F54  MOV      AL,[EBP-08]        
    0167:51097F57  XOR      AL,[EBP-01]        ==>tempvar^str[i]
    0167:51097F5A  AND      EAX,FF            ==>temp<--tempvar^str[i]&0xff
    0167:51097F5F  MOV      EAX,[EAX*4+510DFEB4]    ==>用temp查表送往eax
    0167:51097F66  MOV      EDX,[EBP-08]        
    0167:51097F69  SHR      EDX,08            ==>tempvar>>=8
    0167:51097F6C  AND      EDX,00FFFFFF        ==>tempvar&=0xffffff
    0167:51097F72  XOR      EAX,EDX            ==>eax<--tempvar^[temp*4+510dfeb4]
    0167:51097F74  MOV      [EBP-0C],EAX        
    0167:51097F77  MOV      EAX,[EBP-0C]
    0167:51097F7A  MOV      ESP,EBP
    0167:51097F7C  POP      EBP
   
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//                在这里面,刚才的最终数被取反                
//                                        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    0167:51097F80  PUSH    EBP
    0167:51097F81  MOV      EBP,ESP
    0167:51097F83  ADD      ESP,BYTE -08
    0167:51097F86  MOV      [EBP-04],EAX
    0167:51097F89  MOV      EAX,[EBP-04]
    0167:51097F8C  XOR      EAX,BYTE -01        ==>It's here!!!
    0167:51097F8F  MOV      [EBP-08],EAX
    0167:51097F92  MOV      EAX,[EBP-08]
    0167:51097F95  POP      ECX
    0167:51097F96  POP      ECX
    0167:51097F97  POP      EBP

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//                最后一个call,用来算六位注册码                
//                                        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    0167:51098024  PUSH    EBP
    0167:51098025  MOV      EBP,ESP
    0167:51098027  ADD      ESP,BYTE -14
    0167:5109802A  XOR      ECX,ECX
    0167:5109802C  MOV      [EBP-14],ECX
    0167:5109802F  MOV      [EBP-08],EDX
    0167:51098032  MOV      [EBP-04],EAX
    0167:51098035  XOR      EAX,EAX
    0167:51098037  PUSH    EBP
    0167:51098038  PUSH    DWORD 510980A6
    0167:5109803D  PUSH    DWORD [FS:EAX]
    0167:51098040  MOV      [FS:EAX],ESP
    0167:51098043  MOV      EAX,[EBP-08]
    0167:51098046  CALL    51003CA8
    0167:5109804B  XOR      EAX,EAX
    0167:5109804D  MOV      [EBP-0C],EAX
    0167:51098050  MOV      EAX,[EBP-04]            ==>刚才求得的那个数字
    0167:51098053  MOV      ECX,24                ==>除数为0x24
    0167:51098058  XOR      EDX,EDX                
    0167:5109805A  DIV      ECX                ==>edx=eax%0x24
    0167:5109805C  MOV      DL,[EDX+510E02B5]        ==>用余数来查表
    0167:51098062  LEA      EAX,[EBP-14]            ==>这里的地址用来存放注册码
    0167:51098065  CALL    51003E50                ==>存注册码
    0167:5109806A  MOV      EDX,[EBP-14]            
    0167:5109806D  MOV      EAX,[EBP-08]            
    0167:51098070  CALL    51003F30
    0167:51098075  MOV      EAX,[EBP-08]
    0167:51098078  MOV      EAX,[EBP-04]
    0167:5109807B  MOV      ECX,24
    0167:51098080  XOR      EDX,EDX
    0167:51098082  DIV      ECX
    0167:51098084  MOV      [EBP-04],EAX            ==>将除完了的数放回ebp-4
    0167:51098087  INC      DWORD [EBP-0C]            ==>循环计数器
    0167:5109808A  CMP      DWORD [EBP-0C],BYTE +06        ==>是否已经六位了?
    0167:5109808E  JNZ      51098050
    0167:51098090  XOR      EAX,EAX
    0167:51098092  POP      EDX
    0167:51098093  POP      ECX
    0167:51098094  POP      ECX
    0167:51098095  MOV      [FS:EAX],EDX
    0167:51098098  PUSH    DWORD 510980AD
    0167:5109809D  LEA      EAX,[EBP-14]
    0167:510980A0  CALL    51003CA8
   
##############################################################
我认为我分析的挺详细了,有什么地方不对谢谢指教!其实就是这么简单,不过我的注册机放2000下了,没法帖出来,见谅,不过到这里,大家也能自己写出来了吧!