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经过这个call取公司名 0167:51098C6D MOV EAX,[EBP-08] ==>Corporation 0167:51098C70 CALL 51003F28 ==>计算长度 0167:51098C75 CMP EAX,BYTE +0C ==>Corporation在这里取注册码 0167:51098C8C MOV EAX,[EBP-0C] ==>我们输入的注册码 0167:51098C8F CALL 51003F28 ==>计算长度 0167:51098C94 CMP EAX,BYTE +06 ==>长度再取一遍? 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用来存放地址的一个指针 0167:51098CD5 POP EDX ==>edx关键,跟进! 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: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用edx来从字符串定位字符 0167:51097FDE MOV AL,[EAX+EDX-01] ==>一次取一个字符 0167:51097FE2 MOV EDX,[EBP-08] ==>edx中间为查表过程,过会详细看看 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用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 ==>eaxIt'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下了,没法帖出来,见谅,不过到这里,大家也能自己写出来了吧!