首页
社区
课程
招聘
[旧帖] [原创]CM破解手记与疑问[邀请码已发] 0.00雪花
发表于: 2009-12-21 19:58 1845

[旧帖] [原创]CM破解手记与疑问[邀请码已发] 0.00雪花

2009-12-21 19:58
1845
找了个练习的CM小程序
自己破解着玩
应该算是最简单的那种了
爆破实在是没什么意思,
但在我阅读这个CM程序计算序列号的代码时
我可是有点懵了……
倒不是多难,是我实在觉得这个序列号的算法有问题……

先是追踪USER32.GetDlgItemTextA函数

在该函数前下断

跑程序,然后随便输入一个序列号

停在之前下断的函数前,Alt+F9回到之前的程序领空

开始单步走程序,很快就会看到程序调用一个函数,这便是计算序列号的函数:

以下是计算代码……
问题就出来了:
0040134A   PUSH EBP                      ;保护现场
0040134B   MOV EBP,ESP
0040134D   SUB ESP,68
00401350   PUSH DWORD PTR SS:[EBP+8]     ;将用户名压入堆栈
00401353   CALL <JMP.&CRTDLL.atof>       ;将用户名转换为双精度浮点数
00401358   FST QWORD PTR SS:[EBP-18]
0040135B   SUB ESP,8
0040135E   FSTP QWORD PTR SS:[ESP]
00401361   CALL <JMP.&CRTDLL.floor>      ;将浮点数小数位向下舍去(记为s1)
00401366   FSTP QWORD PTR SS:[EBP-8]
00401369   PUSH DWORD PTR SS:[EBP+C]     ;将注册码压入堆栈
0040136C   CALL <JMP.&CRTDLL.atof>       ;将注册码转换为双精度浮点数
00401371   FST QWORD PTR SS:[EBP-28]
00401374   SUB ESP,8
00401377   FSTP QWORD PTR SS:[ESP]
0040137A   CALL <JMP.&CRTDLL.floor>      ;将浮点数小数位向下舍去(记为s2)
0040137F   ADD ESP,18
00401382   FST QWORD PTR SS:[EBP-10]
00401385   FMUL QWORD PTR SS:[EBP-8]     ;sm=s1*s2
00401388   FLDZ                          ;ST(0)置零
0040138A   FCOMPP                        ;检查相乘结果是否为零
0040138C   FSTSW AX
0040138E   SAHF
0040138F   JNZ SHORT zebrone.00401398    ;不为零则跳转(此处不跳则失败)
00401391   XOR EAX,EAX
00401393   JMP zebrone.0040142E
00401398   FLD QWORD PTR SS:[EBP-8]      ;装入s1
0040139B   FCOMP QWORD PTR SS:[EBP-10]   ;与s2对比
0040139E   FSTSW AX
004013A0   SAHF
004013A1   JNZ SHORT zebrone.004013AA    ;不等则跳(此处不跳则失败)
004013A3   XOR EAX,EAX
004013A5   JMP zebrone.0040142E
004013AA   FLD QWORD PTR SS:[EBP-8]      ;装入s1
004013AD   FSTP QWORD PTR SS:[EBP-38]    ;存储s1并出栈
004013B0   FLD1                          ;ST(0)装入1
004013B2   FST QWORD PTR SS:[EBP-40]     ;存储1
004013B5   FCOMP QWORD PTR SS:[EBP-38]   ;对比1与s1(1-s1)
004013B8   FSTSW AX
004013BA   SAHF
004013BB   JA SHORT zebrone.004013EA     ;高于则跳(此处跳转则失败)
004013BD   FILD QWORD PTR DS:[403038]    ;装入10000000000
004013C3   FST QWORD PTR SS:[EBP-48]     ;存储10000000000
004013C6   FCOMP QWORD PTR SS:[EBP-38]   ;对比10000000000与s1
004013C9   FSTSW AX
004013CB   SAHF
004013CC   JB SHORT zebrone.004013EA     ;低于则跳(此处跳转则失败)
004013CE   FLD QWORD PTR SS:[EBP-10]     ;装入s2
004013D1   FSTP QWORD PTR SS:[EBP-50]
004013D4   FLD QWORD PTR SS:[EBP-40]
004013D7   FCOMP QWORD PTR SS:[EBP-50]   ;对比1与s2
004013DA   FSTSW AX
004013DC   SAHF
004013DD   JA SHORT zebrone.004013EA     ;高于则跳(此处跳转则失败)
004013DF   FLD QWORD PTR SS:[EBP-48]
004013E2   FCOMP QWORD PTR SS:[EBP-50]   ;对比10000000000与s2
004013E5   FSTSW AX
004013E7   SAHF
004013E8   JNB SHORT zebrone.004013EE    ;不低于则跳(此处不跳则失败)
004013EA   XOR EAX,EAX
004013EC   JMP SHORT zebrone.0040142E
004013EE   FLD QWORD PTR SS:[EBP-8]      ;装入s1
004013F1   FSIN                          ;k1=sin(s1)
004013F3   FSTP QWORD PTR SS:[EBP-58]    ;存储k1
004013F6   FLD QWORD PTR SS:[EBP-10]     ;装入s2
004013F9   FSIN                          ;k2=sin(s2)
004013FB   FSTP QWORD PTR SS:[EBP-60]    ;存储k2
004013FE   FLD QWORD PTR SS:[EBP-58]     ;装入k1
00401401   FMUL QWORD PTR SS:[EBP-60]    ;km=k1*k2
00401404   FILD QWORD PTR DS:[403030]    ;装入1.0e+16
0040140A   FMULP ST(1),ST                ;km*1.0e+16
0040140C   SUB ESP,8
0040140F   FSTP QWORD PTR SS:[ESP]       ;结果存入12F99C
00401412   CALL <JMP.&CRTDLL.floor>      ;小数位向下舍去记为k
00401417   ADD ESP,8
0040141A   FSTP QWORD PTR SS:[EBP-68]    ;存储k
0040141D   FLDZ                          ;装入0
0040141F   FCOMP QWORD PTR SS:[EBP-68]   ;对比0与k
00401422   FSTSW AX
00401424   SAHF
00401425   JNZ SHORT zebrone.0040142C    ;不等则跳(此处跳转则失败)
00401427   XOR EAX,EAX                   ;EAX清零
00401429   INC EAX                       ;EAX自加1
0040142A   JMP SHORT zebrone.0040142E
0040142C   XOR EAX,EAX                   ;EAX清零
0040142E   LEAVE
0040142F   RETN


    原来的困惑所在,atof函数算一个。一直以为atof函数是将每个字符的ASCII值累加转换成双精度浮点型是,后来才算明白,其意义其实是将字符串以双精度浮点形式读出。那也就是说如果字符串本身是字母,那结果一定是0.0……
    弄明白这个,结合OllyDBG的FPU查看器,很多问题就能迎刃而解了。从上面的注释,我想大家也很容易可以推断出序列号的计算方法了:
    将用户名以双精度浮点形式读出,将小数位舍去,记为s1.序列号以同样的方法处理记为s2,那么,验证该用户名与序列号相符的条件为:
1)s1!=s2
2)s1*s2!=0
3)1<=s1<=1.0e+10
4)1<=s2<=1.0e+10
    按照上述条件验证s1与s2后,再进行运算:sin(s1)*sin(s2)*1.0e+16.结果的小数位舍去,记为k.若k=0,则认为用户名与序列号相符,验证成功!其实也就是说:s1或s2中任意一个数的正弦函数为0,则成功。

    但有个问题……现在有两种可能:一是我的分析有误,二是这个CM程序的作者在耍我!s1与s2均为经过舍去小数位处理过的,也就是说虽然是以双精度浮点形式存储,但实质上他们都可以算作是整数……那么,有没有一个不为0的整数的正弦值为0?没有!也就是说……如果我的分析没有出错,那么这个程序只能爆破,根本就没有正确的序列号……

如果有大牛能耐着性子看完我这个帖子……
希望能帮忙分析一下,是怎么回事……

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 54
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
是不是写的太多……大家都懒的看啊……
2009-12-22 14:24
0
雪    币: 21
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
厉害呀,楼主,我来学习了
2010-1-17 10:49
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
无语了.......................................

LZ真的很强!
2010-1-18 00:11
0
雪    币: 776
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
楼主 真是厉害啊
2010-1-18 00:42
0
雪    币: 50
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
是自己总结出来的,大家就要学习,不是么
2010-1-18 01:50
0
雪    币: 11
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
没写多少呀,都是复制的嘛!~
2010-1-18 06:30
0
雪    币: 58
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
楼主很强,语言弄得很好,我等望尘未及!
2010-1-18 08:35
0
雪    币: 96
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
不错,,谢谢分享。
2010-1-18 10:13
0
游客
登录 | 注册 方可回帖
返回
//