首页
社区
课程
招聘
[原创]菜鸟也破易语言--小子的CM3的算法分析和注册机
发表于: 2007-7-20 02:45 7967

[原创]菜鸟也破易语言--小子的CM3的算法分析和注册机

2007-7-20 02:45
7967
菜鸟也破易语言--小子的CM3的算法分析和注册机

此文已在UnPack首发!
【文章标题】: 菜鸟也破易语言--小子的CM3的算法分析和注册机
【文章作者】: 狼孩
【编写语言】: 易语言
【破解工具】: OllyDbg.V1.10.Final.聆风听雨汉化第三版(请到到UnPack下载)
【操作平台】: 真正盗版的xp pro sp2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

呵呵,小子的CM3也挂了几天了,没有高手肯出手(肯定是嫌简单),昨天论坛开了虚拟股市,我在上面賠了不少,想赚点U用用(不知这张烂文能否赚得几个UB来用用?),于是,这个苦力还是由我来做了(写破文是苦力吗?无数牛人从四面八方杀过来,然后说:你说呢?我..我一身冷汗…然后..没有然后了)。
小子的CM3链接如下:
7d8K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4g2F1M7r3q4U0K9#2)9J5k6h3y4F1i4K6u0r3N6r3S2J5k6h3q4V1i4K6u0V1x3e0b7^5x3e0u0Q4x3X3b7I4i4K6u0V1x3g2)9J5k6h3S2@1L8h3H3`.
好,开工!
用PEiD查看,提示是Microsoft Visual C++ 6.0 [Overlay],查看EP 区段,发现有.ecode ,可以肯定,该cm是用易语言编译的。上网找找资料,发现maomaoma大牛在UnPack 发过一篇关于易语言程序的破解《易语言程序的一种破解思路》,链接如下:
87fK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4g2F1M7r3q4U0K9#2)9J5k6h3y4F1i4K6u0r3N6X3W2W2N6%4c8Z5M7X3g2S2k6q4)9J5k6i4m8Z5M7q4)9K6c8Y4c8A6k6q4)9K6c8o6p5I4x3K6R3&6i4K6t1$3K9r3W2Y4K9r3I4A6k6$3S2@1i4K6y4p5i4K6t1#2c8o6u0Q4x3U0g2p5y4#2)9J5y4f1b7K6i4K6t1#2c8f1k6Q4x3U0g2p5x3g2)9J5y4f1b7@1
maomaoma大牛说易语言要在.ecode区段下断点,呵呵,我就照搬了,感谢maomaoma大牛!

好,废话少说,拿刀开工。用OD载入,按F9运行,Alt+M调出内存空间,在.ecode区段按F2下断,.ecode区段如下:
Memory map, 项目 26

地址=0040C000

大小=00002000 (8192.)

属主=CrAckMe
00400000

区段=.ecode

类型=映像 01001002

访问=R

初始访问=RWE

然后输入用户名和注册码,我输入的是lang和1234,按确定,OD立刻断下,

0040CC44    55              PUSH EBP                //断在这里,下面有很多垃圾代码,我就不分析了,直接看有注释的就行!
0040CC45    8BEC            MOV EBP,ESP
0040CC47    81EC 40000000   SUB ESP,40
0040CC4D    C745 FC 0000000>MOV DWORD PTR SS:[EBP-4],0
0040CC54    C745 F8 0000000>MOV DWORD PTR SS:[EBP-8],0
0040CC5B    C745 F4 0000000>MOV DWORD PTR SS:[EBP-C],0
0040CC62    C745 F0 0000000>MOV DWORD PTR SS:[EBP-10],0
0040CC69    C745 EC 0000000>MOV DWORD PTR SS:[EBP-14],0
0040CC70    C745 E4 0000000>MOV DWORD PTR SS:[EBP-1C],0
0040CC77    C745 E8 0000000>MOV DWORD PTR SS:[EBP-18],0
0040CC7E    C745 E0 0000000>MOV DWORD PTR SS:[EBP-20],0
0040CC85    C745 DC 0000000>MOV DWORD PTR SS:[EBP-24],0
0040CC8C    6A FF           PUSH -1
0040CC8E    6A 08           PUSH 8
0040CC90    68 02000116     PUSH 16010002
0040CC95    68 01000152     PUSH 52010001
0040CC9A    E8 A5030000     CALL CrAckMe.0040D044      
0040CC9F    83C4 10         ADD ESP,10
0040CCA2    8945 D8         MOV DWORD PTR SS:[EBP-28],EAX
0040CCA5    8B45 D8         MOV EAX,DWORD PTR SS:[EBP-28]
0040CCA8    50              PUSH EAX
0040CCA9    8B5D FC         MOV EBX,DWORD PTR SS:[EBP-4]
0040CCAC    85DB            TEST EBX,EBX
0040CCAE    74 09           JE SHORT CrAckMe.0040CCB9
0040CCB0    53              PUSH EBX
0040CCB1    E8 82030000     CALL CrAckMe.0040D038
0040CCB6    83C4 04         ADD ESP,4
0040CCB9    58              POP EAX
0040CCBA    8945 FC         MOV DWORD PTR SS:[EBP-4],EAX
0040CCBD    6A FF           PUSH -1
0040CCBF    6A 08           PUSH 8
0040CCC1    68 1B000116     PUSH 1601001B
0040CCC6    68 01000152     PUSH 52010001
0040CCCB    E8 74030000     CALL CrAckMe.0040D044
0040CCD0    83C4 10         ADD ESP,10
0040CCD3    8945 D8         MOV DWORD PTR SS:[EBP-28],EAX
0040CCD6    8B45 D8         MOV EAX,DWORD PTR SS:[EBP-28]
0040CCD9    50              PUSH EAX
0040CCDA    8B5D F8         MOV EBX,DWORD PTR SS:[EBP-8]
0040CCDD    85DB            TEST EBX,EBX
0040CCDF    74 09           JE SHORT CrAckMe.0040CCEA
0040CCE1    53              PUSH EBX
0040CCE2    E8 51030000     CALL CrAckMe.0040D038
0040CCE7    83C4 04         ADD ESP,4
0040CCEA    58              POP EAX
0040CCEB    8945 F8         MOV DWORD PTR SS:[EBP-8],EAX
0040CCEE    6A FF           PUSH -1
0040CCF0    6A 08           PUSH 8
0040CCF2    68 02000116     PUSH 16010002
0040CCF7    68 01000152     PUSH 52010001
0040CCFC    E8 43030000     CALL CrAckMe.0040D044
0040CD01    83C4 10         ADD ESP,10
0040CD04    8945 D8         MOV DWORD PTR SS:[EBP-28],EAX
0040CD07    68 04000080     PUSH 80000004
0040CD0C    6A 00           PUSH 0
0040CD0E    8B45 D8         MOV EAX,DWORD PTR SS:[EBP-28]
0040CD11    85C0            TEST EAX,EAX
0040CD13    75 05           JNZ SHORT CrAckMe.0040CD1A
0040CD15    B8 CBC04000     MOV EAX,CrAckMe.0040C0CB
0040CD1A    50              PUSH EAX
0040CD1B    68 01000000     PUSH 1
0040CD20    BB 30010000     MOV EBX,130
0040CD25    E8 14030000     CALL CrAckMe.0040D03E
0040CD2A    83C4 10         ADD ESP,10
0040CD2D    8945 D4         MOV DWORD PTR SS:[EBP-2C],EAX
0040CD30    8B5D D8         MOV EBX,DWORD PTR SS:[EBP-28]
0040CD33    85DB            TEST EBX,EBX
0040CD35    74 09           JE SHORT CrAckMe.0040CD40
0040CD37    53              PUSH EBX
0040CD38    E8 FB020000     CALL CrAckMe.0040D038
0040CD3D    83C4 04         ADD ESP,4
0040CD40    8B45 D4         MOV EAX,DWORD PTR SS:[EBP-2C]
0040CD43    8945 F4         MOV DWORD PTR SS:[EBP-C],EAX
0040CD46    6A FF           PUSH -1
0040CD48    6A 08           PUSH 8
0040CD4A    68 1B000116     PUSH 1601001B
0040CD4F    68 01000152     PUSH 52010001
0040CD54    E8 EB020000     CALL CrAckMe.0040D044
0040CD59    83C4 10         ADD ESP,10
0040CD5C    8945 D8         MOV DWORD PTR SS:[EBP-28],EAX
0040CD5F    68 04000080     PUSH 80000004
0040CD64    6A 00           PUSH 0
0040CD66    8B45 D8         MOV EAX,DWORD PTR SS:[EBP-28]
0040CD69    85C0            TEST EAX,EAX
0040CD6B    75 05           JNZ SHORT CrAckMe.0040CD72
0040CD6D    B8 CBC04000     MOV EAX,CrAckMe.0040C0CB
0040CD72    50              PUSH EAX
0040CD73    68 01000000     PUSH 1
0040CD78    BB 30010000     MOV EBX,130
0040CD7D    E8 BC020000     CALL CrAckMe.0040D03E
0040CD82    83C4 10         ADD ESP,10
0040CD85    8945 D4         MOV DWORD PTR SS:[EBP-2C],EAX
0040CD88    8B5D D8         MOV EBX,DWORD PTR SS:[EBP-28]
0040CD8B    85DB            TEST EBX,EBX
0040CD8D    74 09           JE SHORT CrAckMe.0040CD98
0040CD8F    53              PUSH EBX
0040CD90    E8 A3020000     CALL CrAckMe.0040D038  
0040CD95    83C4 04         ADD ESP,4
0040CD98    8B45 D4         MOV EAX,DWORD PTR SS:[EBP-2C]     
0040CD9B    8945 F0         MOV DWORD PTR SS:[EBP-10],EAX
0040CD9E    837D F4 04      CMP DWORD PTR SS:[EBP-C],4        //将注册码的长度与4比较
0040CDA2    0F8C 0B020000   JL CrAckMe.0040CFB3         //小于4就跳,跳就Over,就是说,用户名可以为空,但注册码必须要大于4
0040CDA8    8B45 F4         MOV EAX,DWORD PTR SS:[EBP-C]         //将注册码的长度放进EAX
0040CDAB    33C9            XOR ECX,ECX       //将ECX置零,此时ECX=0
0040CDAD    50              PUSH EAX          //将EAX压入堆栈
0040CDAE    8D45 EC         LEA EAX,DWORD PTR SS:[EBP-14]
0040CDB1    8BD8            MOV EBX,EAX
0040CDB3    58              POP EAX         //EAX出栈

注意,从下面开始程序就进入注册码的计算。
0040CDB4    41              INC ECX          //ECX加1,此处就是注册码计算的循环的开始点
0040CDB5    51              PUSH ECX         //ECX入栈
0040CDB6    53              PUSH EBX
0040CDB7    890B            MOV DWORD PTR DS:[EBX],ECX
0040CDB9    50              PUSH EAX            //EAX入栈,EAX为注册码的位数
0040CDBA    3BC8            CMP ECX,EAX         //ECX与EAX比较
0040CDBC    0F8F 5B000000   JG CrAckMe.0040CE1D      //若ECX大于EAX就跳,就是说,计算完所有的注册码后就跳出循环
0040CDC2    68 01030080     PUSH 80000301
0040CDC7    6A 00           PUSH 0
0040CDC9    FF75 EC         PUSH DWORD PTR SS:[EBP-14]
0040CDCC    68 04000080     PUSH 80000004
0040CDD1    6A 00           PUSH 0
0040CDD3    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]        //假码压进EAX
0040CDD6    85C0            TEST EAX,EAX
0040CDD8    75 05           JNZ SHORT CrAckMe.0040CDDF
0040CDDA    B8 CBC04000     MOV EAX,CrAckMe.0040C0CB
0040CDDF    50              PUSH EAX
0040CDE0    68 02000000     PUSH 2
0040CDE5    BB 44010000     MOV EBX,144
0040CDEA    E8 4F020000     CALL CrAckMe.0040D03E   
//取注册码每一位ASCII代码压进EAX,由循环来完成
0040CDEF    83C4 1C         ADD ESP,1C   //ESP=ESP+1C
0040CDF2    8945 D8         MOV DWORD PTR SS:[EBP-28],EAX         //将EAX放进SS:[EBP-28]备用
0040CDF5    DF6D E4         FILD QWORD PTR SS:[EBP-1C]
//典型的易语言计算,从内存中将整数转换成一个浮点数并压入FPU的浮点寄存器栈,开始时SS:[EBP-1C]处为零
0040CDF8    DD5D D0         FSTP QWORD PTR SS:[EBP-30]
//从FPU的浮点寄存器栈中弹出一个浮点数,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址,开始时SS:[EBP-30]为零,随着循环的进行,SS:[EBP-30]处就是上一次计算所得到的十六进制值转为的浮点值
0040CDFB    DD45 D0         FLD QWORD PTR SS:[EBP-30]
//从内存将一个浮点数压入FPU的浮点寄存器栈,就是0040CDF5处所转换得到的浮点值
0040CDFE    DB45 D8         FILD DWORD PTR SS:[EBP-28]
//将SS:[EBP-28] 的整数转换成一个浮点数并压入FPU的浮点寄存器栈,这里就是将每一位注册码的ASCII值的十六进制转为浮点值
0040CE01    DD5D C8         FSTP QWORD PTR SS:[EBP-38]
//从FPU的浮点寄存器栈中弹出一个浮点数,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址,就是上一条指令所转换得到的浮点数
0040CE04    DC45 C8         FADD QWORD PTR SS:[EBP-38]
//两个浮点数相加,SS:[EBP-38]堆栈为上一条指令所转换得到的浮点数;
此处的目的就是将每一位注册码的ASCII值的十进制相加,得到的值就放进浮点寄存器栈ST处。
0040CE07    DD5D C0         FSTP QWORD PTR SS:[EBP-40]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-40]处
0040CE0A    DD45 C0         FLD QWORD PTR SS:[EBP-40]   
//从内存将一个浮点数压入FPU的浮点寄存器栈,此值就是0040CE07处存入SS:[EBP-40]的浮点值
0040CE0D    E8 0BFEFFFF     CALL CrAckMe.0040CC1D                //将以上所得的浮点值转为十六进制,并存进EAX
0040CE12    8945 E4         MOV DWORD PTR SS:[EBP-1C],EAX           //将EAX压进SS:[EBP-1C]备用
0040CE15    8955 E8         MOV DWORD PTR SS:[EBP-18],EDX
0040CE18    58              POP EAX       //出栈
0040CE19    5B              POP EBX       //出栈
0040CE1A    59              POP ECX       //出栈
0040CE1B  ^ EB 97           JMP SHORT CrAckMe.0040CDB4             //无条件的跳转,此处就是循环结束点,跳回开始点
0040CE1D    83C4 0C         ADD ESP,0C    //ESP=ESP+C
0040CE20    DF6D E4         FILD QWORD PTR SS:[EBP-1C]
//将SS:[EBP-1C] 的整数转换成一个浮点数并压入FPU的浮点寄存器栈,这里就是将刚才计算注册码所得到的十六进制值转为浮点
0040CE23    DD5D D4         FSTP QWORD PTR SS:[EBP-2C]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-2C]处
0040CE26    DD45 D4         FLD QWORD PTR SS:[EBP-2C]
//从内存将一个浮点数压入FPU的浮点寄存器栈,此值就是刚才计算注册码所得到的十六进制值转为浮点后的值存入SS:[EBP-2C]的浮点值
0040CE29    DB45 F4         FILD DWORD PTR SS:[EBP-C]
//将SS:[EBP-C] 的整数转换成一个浮点数并压入FPU的浮点寄存器栈,这里就是刚才得到的注册码的位数转为浮点值
0040CE2C    DD5D CC         FSTP QWORD PTR SS:[EBP-34]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-34]处
0040CE2F    DC4D CC         FMUL QWORD PTR SS:[EBP-34]
//浮点乘法运算,将浮点寄存器栈ST中的刚才计算注册码所得到的浮点值乘以注册码位数的浮点值
0040CE32    DD5D C4         FSTP QWORD PTR SS:[EBP-3C]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-3C]处
0040CE35    DD45 C4         FLD QWORD PTR SS:[EBP-3C]
//从内存将一个浮点数压入FPU的浮点寄存器栈,此值就是刚才所得到的浮点值存入SS:[EBP-3C]
0040CE38    E8 E0FDFFFF     CALL CrAckMe.0040CC1D           //将以上所得的浮点值转为十六进制,并存进EAX
0040CE3D    8945 E4         MOV DWORD PTR SS:[EBP-1C],EAX         //将EAX压进SS:[EBP-1C]备用
0040CE40    8955 E8         MOV DWORD PTR SS:[EBP-18],EDX
0040CE43    DF6D E4         FILD QWORD PTR SS:[EBP-1C]
//将SS:[EBP-1C] 的整数转换成一个浮点数并压入FPU的浮点寄存器栈,这里就是将刚才所得到的十六进制值转为浮点值
0040CE46    DD5D D4         FSTP QWORD PTR SS:[EBP-2C]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-2C]处
0040CE49    DD45 D4         FLD QWORD PTR SS:[EBP-2C]        //从内存将一个浮点数压入FPU的浮点寄存器栈,此值就是刚才所得到的浮点值存入SS:[EBP-2C]
0040CE4C    DC35 CCC04000   FDIV QWORD PTR DS:[40C0CC]
//浮点除法运算,将浮点寄存器栈ST中的刚才计算注册码所得到的浮点值除以DS:[40C0CC]处的浮点值,DS:[40C0CC]处的浮点值是固定的,此数为5.000
0040CE52    DD5D CC         FSTP QWORD PTR SS:[EBP-34]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-34]处
0040CE55    DD45 CC         FLD QWORD PTR SS:[EBP-34]
//从内存将一个浮点数压入FPU的浮点寄存器栈,此值就是刚才所得到的浮点值存入SS:[EBP-34]
0040CE58    E8 C0FDFFFF     CALL CrAckMe.0040CC1D                //将以上所得的浮点值转为十六进制,并存进EAX
0040CE5D    8945 E4         MOV DWORD PTR SS:[EBP-1C],EAX         //将EAX压进SS:[EBP-1C]备用
0040CE60    8955 E8         MOV DWORD PTR SS:[EBP-18],EDX
0040CE63    8145 E4 9514000>ADD DWORD PTR SS:[EBP-1C],1495
//将SS:[EBP-1C]处的值加上十六进制的1495,所得的值存回SS:[EBP-1C]处
0040CE6A    8355 E8 00      ADC DWORD PTR SS:[EBP-18],0
0040CE6E    8B45 F0         MOV EAX,DWORD PTR SS:[EBP-10]
0040CE71    33C9            XOR ECX,ECX

注册码计算到此为止!下面将是用户名的计算。
0040CE73    50              PUSH EAX         //EAX入栈
0040CE74    8D45 E0         LEA EAX,DWORD PTR SS:[EBP-20]
0040CE77    8BD8            MOV EBX,EAX
0040CE79    58              POP EAX
0040CE7A    41              INC ECX           //ECX加1,此处就是用户名的计算的循环的开始点
0040CE7B    51              PUSH ECX        //ECX入栈
0040CE7C    53              PUSH EBX  
0040CE7D    890B            MOV DWORD PTR DS:[EBX],ECX
0040CE7F    50              PUSH EAX              //EAX入栈,此时EAX为用户名的位数
0040CE80    3BC8            CMP ECX,EAX
0040CE82    0F8F 58000000   JG CrAckMe.0040CEE0          //若ECX大于EAX就跳,就是说,计算完所有的用户名后就跳出循环
0040CE88    68 01030080     PUSH 80000301
0040CE8D    6A 00           PUSH 0
0040CE8F    FF75 E0         PUSH DWORD PTR SS:[EBP-20]
0040CE92    68 04000080     PUSH 80000004
0040CE97    6A 00           PUSH 0
0040CE99    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]         //将用户名压进EAX
0040CE9C    85C0            TEST EAX,EAX
0040CE9E    75 05           JNZ SHORT CrAckMe.0040CEA5
0040CEA0    B8 CBC04000     MOV EAX,CrAckMe.0040C0CB
0040CEA5    50              PUSH EAX            //EAX入栈
0040CEA6    68 02000000     PUSH 2
0040CEAB    BB 44010000     MOV EBX,144
0040CEB0    E8 89010000     CALL CrAckMe.0040D03E
//取用户名的每一位ASCII代码压进EAX,由循环来完成
0040CEB5    83C4 1C         ADD ESP,1C
0040CEB8    8945 D8         MOV DWORD PTR SS:[EBP-28],EAX         //将EAX放进SS:[EBP-28]备用
0040CEBB    DB45 DC         FILD DWORD PTR SS:[EBP-24]
//与上面注册码的计算一样,从内存中将整数转换成一个浮点数并压入FPU的浮点寄存器栈,开始时SS:[EBP-24]处为零
0040CEBE    DD5D D0         FSTP QWORD PTR SS:[EBP-30]
//从FPU的浮点寄存器栈中弹出一个浮点数,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址,开始时SS:[EBP-30]为零,随着循环的进行,SS:[EBP-30]处就是上一次计算所得到的十六进制值转为的浮点值
0040CEC1    DD45 D0         FLD QWORD PTR SS:[EBP-30]
//从内存将一个浮点数压入FPU的浮点寄存器栈,就是0040CEBB处所转换得到的浮点值
0040CEC4    DB45 D8         FILD DWORD PTR SS:[EBP-28]
//将SS:[EBP-28] 的整数转换成一个浮点数并压入FPU的浮点寄存器栈,这里就是将每一位用户名的ASCII值的十六进制转为浮点值
0040CEC7    DD5D C8         FSTP QWORD PTR SS:[EBP-38]
//从FPU的浮点寄存器栈中弹出一个浮点数,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址,就是上一条指令所转换得到的浮点数
0040CECA    DC45 C8         FADD QWORD PTR SS:[EBP-38]
//两个浮点数相加,SS:[EBP-38]堆栈为上一条指令所转换得到的浮点数;
此处的目的就是将每一位用户名的ASCII值的十进制相加,得到的值就放进浮点寄存器栈ST处。
0040CECD    DD5D C0         FSTP QWORD PTR SS:[EBP-40]              
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-40]处
0040CED0    DD45 C0         FLD QWORD PTR SS:[EBP-40]            
//从内存将一个浮点数压入FPU的浮点寄存器栈,此值就是0040CECD 处存入SS:[EBP-40]的浮点值
0040CED3    E8 45FDFFFF     CALL CrAckMe.0040CC1D              //将以上所得的浮点值转为十六进制,并存进EAX
0040CED8    8945 DC         MOV DWORD PTR SS:[EBP-24],EAX       //将EAX压进SS:[EBP-1C]备用
0040CEDB    58              POP EAX        //出栈
0040CEDC    5B              POP EBX        //出栈
0040CEDD    59              POP ECX       //出栈
0040CEDE  ^ EB 9A           JMP SHORT CrAckMe.0040CE7A      //无条件的跳转,此处就是循环结束点,跳回开始点
0040CEE0    83C4 0C         ADD ESP,0C
0040CEE3    DB45 DC         FILD DWORD PTR SS:[EBP-24]
//将SS:[EBP-24] 的整数转换成一个浮点数并压入FPU的浮点寄存器栈,这里就是将刚才计算用户名所得到的十六进制值转为浮点值
0040CEE6    DD5D D4         FSTP QWORD PTR SS:[EBP-2C]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-2C]处
0040CEE9    DD45 D4         FLD QWORD PTR SS:[EBP-2C]
//从内存将一个浮点数压入FPU的浮点寄存器栈,此值就是刚才计算用户名所得到的十六进制值转为浮点后的值存入SS:[EBP-2C]的浮点值
0040CEEC    DB45 F0         FILD DWORD PTR SS:[EBP-10]
//将SS:[EBP-10] 的整数转换成一个浮点数并压入FPU的浮点寄存器栈,这里就是刚才得到的用户名的位数转为浮点值
0040CEEF    DD5D CC         FSTP QWORD PTR SS:[EBP-34]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-34]处
0040CEF2    DC4D CC         FMUL QWORD PTR SS:[EBP-34]
//浮点乘法运算,将浮点寄存器栈ST中的刚才计算用户名所得到的浮点值乘以用户名位数的浮点值
0040CEF5    DD5D C4         FSTP QWORD PTR SS:[EBP-3C]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-3C]处
0040CEF8    DD45 C4         FLD QWORD PTR SS:[EBP-3C]
//从内存将一个浮点数压入FPU的浮点寄存器栈,此值就是刚才所得到的浮点值存入SS:[EBP-3C]
0040CEFB    E8 1DFDFFFF     CALL CrAckMe.0040CC1D       //将以上所得的浮点值转为十六进制,并存进EAX
0040CF00    8945 DC         MOV DWORD PTR SS:[EBP-24],EAX   //将EAX压进SS:[EBP-24]备用
0040CF03    8345 DC 05      ADD DWORD PTR SS:[EBP-24],5     //将以上所得的浮点值转为十六进制后的值加5,并存回SS:[EBP-24]处
0040CF07    DB45 DC         FILD DWORD PTR SS:[EBP-24]
//将SS:[EBP-24] 的整数转换成一个浮点数并压入FPU的浮点寄存器栈,这里就是将刚才所得到的十六进制值转为浮点值
0040CF0A    DD5D D4         FSTP QWORD PTR SS:[EBP-2C]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-2C]处
0040CF0D    DD45 D4         FLD QWORD PTR SS:[EBP-2C]
//从内存将一个浮点数压入FPU的浮点寄存器栈,就是0040CF07 处所转换得到的浮点值
0040CF10    DC35 D4C04000   FDIV QWORD PTR DS:[40C0D4]
//浮点除法运算,将浮点寄存器栈ST中的刚才计算用户名所得到的浮点值除以DS:[40C0D4]处的浮点值,DS:[40C0D4]处的浮点值是固定的,此数为7.000
0040CF16    DD5D CC         FSTP QWORD PTR SS:[EBP-34]
//从FPU的浮点寄存器栈中弹出一个浮点数,此时该浮点数就是上一条指令计算得到的值,依据目标内存空间的大小转换成对应的精度,存入指定的内存地址SS:[EBP-34]处
0040CF19    DD45 CC         FLD QWORD PTR SS:[EBP-34]
//从内存将一个浮点数压入FPU的浮点寄存器栈,此值就是刚才所得到的浮点值存入SS:[EBP-34]
0040CF1C    E8 FCFCFFFF     CALL CrAckMe.0040CC1D             //将以上所得的浮点值转为十六进制,并存进EAX
0040CF21    8945 DC         MOV DWORD PTR SS:[EBP-24],EAX           //将EAX压进SS:[EBP-24]备用
0040CF24    8145 DC 9514000>ADD DWORD PTR SS:[EBP-24],1495      
//将SS:[EBP-24]处的值加上十六进制的1495,所得的值存回SS:[EBP-24]处
0040CF2B    8B45 DC         MOV EAX,DWORD PTR SS:[EBP-24]         //将SS:[EBP-24]处的值存进EAX备用
0040CF2E    99              CDQ             //双字扩展.  (把EAX中的字的符号扩展到EDX中去)
0040CF2F    3945 E4         CMP DWORD PTR SS:[EBP-1C],EAX      
// SS:[EBP-1C]的值与EAX比较,还记得SS:[EBP-1C]这里吗?这里就是刚才计算注册码得到的十六进制值!将计算后的用户名与计算后的注册码比较,相同就成功,不同就Game Over。
0040CF32    75 03           JNZ SHORT CrAckMe.0040CF37          //不相等就跳,跳就Over。
0040CF34    3955 E8         CMP DWORD PTR SS:[EBP-18],EDX      //这里是EDX与SS:[EBP-18]比较
0040CF37    0F85 3B000000   JNZ CrAckMe.0040CF78            //不同就跳,跳就Over
0040CF3D    68 04000080     PUSH 80000004
0040CF42    6A 00           PUSH 0
0040CF44    68 DCC04000     PUSH CrAckMe.0040C0DC
0040CF49    68 01030080     PUSH 80000301
0040CF4E    6A 00           PUSH 0
0040CF50    68 40000000     PUSH 40
0040CF55    68 04000080     PUSH 80000004
0040CF5A    6A 00           PUSH 0
0040CF5C    68 E5C04000     PUSH CrAckMe.0040C0E5
0040CF61    68 03000000     PUSH 3
0040CF66    BB 00030000     MOV EBX,300
0040CF6B    E8 CE000000     CALL CrAckMe.0040D03E        //弹出成功注册框,呵呵,成功了!
0040CF70    83C4 28         ADD ESP,28
0040CF73    E9 36000000     JMP CrAckMe.0040CFAE
0040CC44    55              PUSH EBP

算法到此结束,下面的就无需分析了!

________________________________________________________________________________________
【破解总结】
此CrackMe够厉害的,很有创新,它先计算用户输入的注册码(就是我们所说的假码),再计算用户名,将两者所得的值比较,相等的就注册成功,不等的就 Game Over ,这样的注册方式很不错,这样的注册机比较难写(相对于我等菜鸟而言),不过,这种注册方式会导致一个用户名有多个注册码,或者说一个注册码用多个用户名。

注册码计算方式如下:
将每一位假码的ASCII代码相加,然后乘以注册码的位数,又除以固定的十六进制数字5 ,最后加上固定的十六进制值1495 。
下面是我输入的注册码的计算:
注册码:1234
31+32+33+34=CA
CA*4=328
328/5=A1
A1+1495=1536
计算最后得到的值是1536
用户名计算方式如下:
计算方式大体上与注册码相同,将每一位用户名的ASCII代码相加,然后乘以用户名的位数,加上固定的十六进制数值5(呵呵,这里与注册码的不同),又除以固定的十六进制数字7 ,最后加上固定的十六进制值1495。
下面是我的用户名的计算:
用户名:lang
6C+61+6E+67=1A2
1A2*4=688
688+5=68D
68D/7=EF

EF+1495=1584

计算最后得到的值是1584

用户名的计算值与注册码计算的值不同,最后当然是Game Over啦。

一组可用注册信息:
======================
用户名:lang
注册码:zo!!
======================
成功注册的图片如下:



呵呵,终于到了注册机这一部分!
  我觉得这部分时是整个破解最难,当然这是相对我等菜鸟来说的。对于这种比较方式来说,我认为要用暴力破解的方式来写注册机才行。就是说,先计算用户名,将得到的值用计算注册码的方式逆向推理,这种方式的最大缺点是计算时间很长,在这个注册机中,我只允许用户名为四位字符,注册码也将是四位。我只是计算一个四位的用户名lang,在我的配置(赛扬4 2.0 OC到2.8 ,384内存)就用了78.56201秒钟 !没办法,谁叫我是菜鸟?  
注册机界面如下:



注意:本注册机只能计算用户名为四位字符的注册码,而且不能保证所有的用户名都能算出注册码 ,算不出来的就换一个吧。由于本注册机使用了暴力破解的方式,所以,配置低的朋友慎用,死机就不要怪我啊!

   注册机以及代码我都发上来了,由于时间紧,在注册机的代码中,我没有写注释,而且所使用的变量也很糊涂 ,看不懂的也不要怪我哦 ,就怪我水平低吧 (注意,不是人品问题,是水平问题  )!

在附件中,
RegCrAckMe.rar  为注册机和注册机的源代码
CraCkmE.rar    为本文所破的CrackMe

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
2
小子的东西很简单哈,这东西我搞定了!!
帮你顶上去!!顶到第一位``````````顶
沙发`
2007-7-20 08:59
0
雪    币: 347
活跃值: (30)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
3
偶要发奋
2007-7-20 11:46
0
雪    币: 498
活跃值: (1562)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wxq
4
很强,我做的crackme没一下子就被yingyue 给破了
2007-9-4 19:47
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
小子现在还会用 E 语言啊 ,俺越来越落后了,555555555555555
2007-9-5 07:40
0
雪    币: 347
活跃值: (30)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
6
会定义变量
2007-9-6 17:16
0
游客
登录 | 注册 方可回帖
返回