首页
社区
课程
招聘
[原创]成功的保护――Calendarscope注册算法分析
发表于: 2005-7-26 12:11 9741

[原创]成功的保护――Calendarscope注册算法分析

2005-7-26 12:11
9741

=============================
Calendarscope 2V5 Beta Crack Tutorial
=============================

=============================
程序说明

    Calendarscope is a full-featured calendar program for planning, managing,
    and scheduling appointments, meetings, birthdays, vacations, and special
    events. It allows you to view all your events in a daily, weekly, monthly,
    or yearly overview. You can get a quick look at the events of a single day
    in any calendar view.
    ....
    总之很强大的功能。^_^
=============================

=============================
破解说明

限制方式:
时间限制+Nag

保护方式
KeyCode [RSA1024][MD5]

保存位置:
注册表

破解目的:
周末闲极无聊,随便从onlinedown当了写软件准备玩玩。
先是肯了1天的FeedDemon,总于搞明白Serial和ActiveKey的算法了,
正准备写KeyGen,忽然灵光一闪,上网查了查,FAINT,发现ECLiPSE小组早就放出KEYGEN了,郁闷。

于是又换了个小东东,叫什么DocRepair的,竟然是最新版ASProtect加壳的。
只好用OD附加,发现里面竟然是MD5,不能爆(有壳),也找不到注册码,更郁闷。

最后只好蹂躏这个Calendarscope了,因为它。。。。。。没壳!!!^_^
不过搞了一天之后,发现其实是自己被这个东西蹂躏了,竟然是RSA1024+MD5!
唉,时不与我啊。不过好歹也折腾了1天,基本的注册流程也搞清楚了,还是出来SHOW一下吧。

破解结果:
无。。。。:-(,可恶的MD5,可恶的RSA。
=============================

=============================
破解分析

1. 第一步是对程序进行查壳/脱壳,无壳。
   这也是我决定研究它的原因。本人脱壳实在弱项。
   
2. 第二步是侦测软件的加密算法,这一步大大减小了手动跟踪算法的强度。
   这一步使用PEiD的插件Kanal:
   BASE64/CRC32/MD5/RsaEuro NN_ModMult/RsaRef2 NN_ModExp/TWOFISH。
   因为这是一个PIM类软件,初步估计BASE64/CRC32/TWOFISH是与用户数据有关的;
   MD5与RSA可能与注册有关。。。。上帝保佑,希望别都用了。。。结果上帝TMD休假了。
   
3. 第三步是运行程序,进行注册,观察程序反应。
   启动程序,出现NAG提示注册,点Active按钮,进入注册对话框。
   随便输入一些字符,发现OK按钮一直是灰色,不能激活。。。。狡猾啊。
      
4. 静态分析,用PLL621大侠的C32ASM找到关键的注册码判断提示字串:
   "Thank you for the registering Calendarscope.............."
   "This is not a valid registration. ......................."
   向上搜索,发现。。。。。找不到这个CALL的地址!
   估计作者使用的是CALL [EAX]的形式调用这个函数的,郁闷:
   输入注册码的OK按钮无法激活,也就跟踪不到这些关键判断的地方。
   看来第一步是要解决注册码格式的问题,只有正确的注册码格式,才能激活OK按钮。
   
5. 要找到合适的注册码格式,只能使用动态跟踪了。
   OD载入,下断GetWindowTextA,这样每当注册表单里的注册码发生改变时,都会被拦截。
   通过跟踪,发现注册码要求有172(0xAC)个字符,最后一个字符是"="。
   这样,OK按钮就激活了。
   万里长征走完第一步。
   
   注册码的172个字符的ASCII码经过0x40进制压缩,成为128(0x80)个字节数据。
   然后程序使用RSA算法对该80个字节数据进行解密,其中:
   N=0xBB4F91978B3D881D4AC1671B74402EA34687D13BF5300689E00C5110003EA36014C4F572B7DDD6DB7F26719C016BD51C664CACD478ED63FB797AE0AE7C2761E3DD938D33F349933FBEA342B2E054E5EDAFE92247AEBED97B8F45F511A413C397334FD03A14D1E8585E2EE996ACF89F0D7C88C5E502AAD08EA6055BA3BC1A79AF
   E=0x10001
   密钥长度位1024BITS。
   想用RSATOOL分解?呵呵,免了。先不说消耗多少时间的问题,
   我随便试了一下,虚拟内存开2G,用MPQS算法,内存不够直接退出,呵呵。
   
   RSA这到关过不去的话,后边的工作也没法进行。
   所以,采用替换N的方法,让RSATOOL生成一组1024BITS的密钥,将程序中的N替换掉。
   方法是用ULTRAEDIT打开程序,搜索上面的N,注意要在HEX模式下,因为本程序将N直接作为数据存储,
   而没有作为字符串存储。
   替换完程序的N,RSA的编码解码就可以自己搞定了。   
   
   继续跟踪,得到经过RSA解密后的数据要求。
   数据共0x80个字节,最多共包含7个字段:
   倒数第1个字段,11个字节,要求符合MD5校验。郁闷啊,11个字节啊,不知道格式,不要妄想穷举破解了;
   倒数第2个字段,8个字节,表示过期时间,格式是yyyymmdd。如果小于当前日期,则软件过期;
   倒数第3个字段,长度不定,还没分析出作用;
   倒数第4个字段,长度不定,要求0x23开头,后边个的数字大于0则软件会判断后边倒数第2个字段的时间字段;
   倒数第5个字段,长度不定,表示产品ID;
   倒数第6个字段,长度不定,表示注册的计算机数量;
   倒数第7个字段,长度不定,表示注册人的ID。
   每个字段间,用一个0x0D,或0x0A隔开;
   数据以0x00 0x01开头,所有字段、间隔符长度不足0x80个字节的在0x00 0x01后以0xFF填充,
   并且要求0xFF的数量不少于8个。0xFF与倒数第7个字段间用0x00间隔。
   
   现举例说明:(括号内表示ASCII,因为显示不出来)
   (0x00)(0x01)(75*0xFF)(0x00)MrBeer[CCG](0x0D)999(0x0D)10111(0x0D)(0x23)22(0x0D)110(0x0D)99991230(0x0D)11111022222
                                注册ID       注册数量   产品ID                            过期日期
                                
   虽然注册成功了,但是因为有部分字段含义不明,估计程序运行过程中可能还有暗桩。
   
   总的来讲,这个软件的保护还是非常成功的。
   只要不发生密钥外泄的事,想写注册机是不可能的。
   另外因为程序里可能有暗桩,爆破也是非常危险的。
   唯一的遗憾就是没有做一机一码,注册码还是会外泻的。
=============================

=============================
源码分析

通过对GetWindowTextA设断,跟踪到这里

004CF010   /$  8B4424 08     mov eax,dword ptr ss:[esp+8]
004CF014   |.  81EC 10030000 sub esp,310
004CF01A   |.  3D AC000000   cmp eax,0AC                                ; --->判断输入注册码是否等于172个字节,不跳!!
004CF01F   |.  56            push esi
004CF020   |.  57            push edi
004CF021   |.  0F85 9A010000 jnz cs.004CF1C1
004CF027   |.  8B8424 1C0300>mov eax,dword ptr ss:[esp+31C]
004CF02E   |.  68 AC000000   push 0AC
004CF033   |.  8D4C24 18     lea ecx,dword ptr ss:[esp+18]
004CF037   |.  50            push eax
004CF038   |.  51            push ecx
004CF039   |.  E8 C2CDFFFF   call cs.004CBE00
004CF03E   |.  8D9424 200100>lea edx,dword ptr ss:[esp+120]
004CF045   |.  68 AC000000   push 0AC
004CF04A   |.  8D4424 24     lea eax,dword ptr ss:[esp+24]
004CF04E   |.  52            push edx
004CF04F   |.  50            push eax
004CF050   |.  E8 BB4EF3FF   call cs.00403F10                            ; --->对输入注册码做0x40进制压缩
004CF055   |.  83C4 18       add esp,18
004CF058   |.  3D 80000000   cmp eax,80
004CF05D   |.  0F85 5E010000 jnz cs.004CF1C1                             ; --->判断压缩结果是否为0x80个字节,不跳!!
004CF063   |.  8D4C24 08     lea ecx,dword ptr ss:[esp+8]
004CF067   |.  51            push ecx
004CF068   |.  68 AA000000   push 0AA
004CF06D   |.  E8 6E010000   call cs.004CF1E0
004CF072   |.  83C4 08       add esp,8
004CF075   |.  85C0          test eax,eax
004CF077   |.  0F84 44010000 je cs.004CF1C1
004CF07D   |.  817C24 08 020>cmp dword ptr ss:[esp+8],102
004CF085   |.  0F85 36010000 jnz cs.004CF1C1
004CF08B   |.  68 02010000   push 102
004CF090   |.  8D9424 180200>lea edx,dword ptr ss:[esp+218]
004CF097   |.  50            push eax
004CF098   |.  52            push edx
004CF099   |.  E8 62CDFFFF   call cs.004CBE00
004CF09E   |.  8D8424 200200>lea eax,dword ptr ss:[esp+220]
004CF0A5   |.  8D8C24 200100>lea ecx,dword ptr ss:[esp+120]
004CF0AC   |.  50            push eax
004CF0AD   |.  68 80000000   push 80
004CF0B2   |.  8D5424 24     lea edx,dword ptr ss:[esp+24]
004CF0B6   |.  51            push ecx
004CF0B7   |.  8D4424 2C     lea eax,dword ptr ss:[esp+2C]
004CF0BB   |.  52            push edx
004CF0BC   |.  50            push eax
004CF0BD   |.  E8 AECDFFFF   call cs.004CBE70                            ; --->RSA解密运算
004CF0C2   |.  83C4 20       add esp,20
004CF0C5   |.  85C0          test eax,eax
004CF0C7   |.  0F85 F4000000 jnz cs.004CF1C1                             ; --->不跳
004CF0CD   |.  8B4424 10     mov eax,dword ptr ss:[esp+10]
004CF0D1   |.  83F8 0A       cmp eax,0A
004CF0D4   |.  0F82 E7000000 jb cs.004CF1C1                             ; --->不跳
004CF0DA   |.  3D 00010000   cmp eax,100
004CF0DF   |.  0F83 DC000000 jnb cs.004CF1C1                            ; --->不跳
004CF0E5   |.  C64404 14 00  mov byte ptr ss:[esp+eax+14],0
004CF0EA   |.  40            inc eax
004CF0EB   |.  3D 80000000   cmp eax,80
004CF0F0   |.  72 05         jb short cs.004CF0F7
004CF0F2   |.  B8 80000000   mov eax,80
004CF0F7   |>  8D4C24 14     lea ecx,dword ptr ss:[esp+14]
004CF0FB   |.  50            push eax
004CF0FC   |.  51            push ecx
004CF0FD   |.  68 DCC95500   push cs.0055C9DC
004CF102   |.  E8 F9CCFFFF   call cs.004CBE00
004CF107   |.  8B5424 1C     mov edx,dword ptr ss:[esp+1C]
004CF10B   |.  6A 0B         push 0B
004CF10D   |.  8D8C24 240100>lea ecx,dword ptr ss:[esp+124]
004CF114   |.  8D4414 19     lea eax,dword ptr ss:[esp+edx+19]
004CF118   |.  50            push eax
004CF119   |.  51            push ecx
004CF11A   |.  E8 E1CCFFFF   call cs.004CBE00
004CF11F   |.  8D9424 2C0100>lea edx,dword ptr ss:[esp+12C]
004CF126   |.  6A 0B         push 0B
004CF128   |.  52            push edx
004CF129   |.  68 D0C95500   push cs.0055C9D0
004CF12E   |.  E8 CDCCFFFF   call cs.004CBE00
004CF133   |.  6A 05         push 5
004CF135   |.  8D8424 3C0100>lea eax,dword ptr ss:[esp+13C]
004CF13C   |.  6A 0B         push 0B
004CF13E   |.  8D4C24 38     lea ecx,dword ptr ss:[esp+38]
004CF142   |.  50            push eax
004CF143   |.  8D5424 44     lea edx,dword ptr ss:[esp+44]
004CF147   |.  51            push ecx
004CF148   |.  52            push edx
004CF149   |.  E8 22CCFFFF   call cs.004CBD70                            ;  --->注册信息最后11位的MD5运算
004CF14E   |.  83C4 38       add esp,38
004CF151   |.  85C0          test eax,eax
004CF153   |.  75 4A         jnz short cs.004CF19F
004CF155   |.  8D4424 08     lea eax,dword ptr ss:[esp+8]
004CF159   |.  50            push eax
004CF15A   |.  68 AB000000   push 0AB
004CF15F   |.  E8 7C000000   call cs.004CF1E0
004CF164   |.  8BF0          mov esi,eax
004CF166   |.  83C4 08       add esp,8
004CF169   |.  85F6          test esi,esi
004CF16B   |.  74 32         je short cs.004CF19F
004CF16D   |.  8B4C24 08     mov ecx,dword ptr ss:[esp+8]
004CF171   |.  8B4424 0C     mov eax,dword ptr ss:[esp+C]
004CF175   |.  8D3C31        lea edi,dword ptr ds:[ecx+esi]
004CF178   |.  8D1430        lea edx,dword ptr ds:[eax+esi]
004CF17B   |.  3BD7          cmp edx,edi
004CF17D   |.  77 20         ja short cs.004CF19F
004CF17F   |>  50            /push eax
004CF180   |.  8D4424 18     |lea eax,dword ptr ss:[esp+18]
004CF184   |.  56            |push esi
004CF185   |.  50            |push eax
004CF186   |.  E8 95CCFFFF   |call cs.004CBE20                                  ; --->与预存MD5值比较
004CF18B   |.  83C4 0C       |add esp,0C
004CF18E   |.  85C0          |test eax,eax
004CF190   |.  74 3A         |je short cs.004CF1CC                        ; --->与某组MD5相同,则跳
004CF192   |.  8B4424 0C     |mov eax,dword ptr ss:[esp+C]
004CF196   |.  03F0          |add esi,eax
004CF198   |.  8D0C30        |lea ecx,dword ptr ds:[eax+esi]
004CF19B   |.  3BCF          |cmp ecx,edi
004CF19D   |.^ 76 E0         \jbe short cs.004CF17F
004CF19F   |>  68 80000000   push 80
004CF1A4   |.  6A 00         push 0
004CF1A6   |.  68 DCC95500   push cs.0055C9DC
004CF1AB   |.  E8 30CCFFFF   call cs.004CBDE0
004CF1B0   |.  6A 0B         push 0B
004CF1B2   |.  6A 00         push 0
004CF1B4   |.  68 D0C95500   push cs.0055C9D0
004CF1B9   |.  E8 22CCFFFF   call cs.004CBDE0
004CF1BE   |.  83C4 18       add esp,18
004CF1C1   |>  5F            pop edi
004CF1C2   |.  33C0          xor eax,eax
004CF1C4   |.  5E            pop esi
004CF1C5   |.  81C4 10030000 add esp,310
004CF1CB   |.  C3            retn
004CF1CC   |>  E8 1F020000   call cs.004CF3F0                            ; --->分析注册信息各字段内容
004CF1D1   |.  5F            pop edi
004CF1D2   |.  5E            pop esi
004CF1D3   |.  81C4 10030000 add esp,310
004CF1D9   \.  C3            retn

各功能call的详细分析不再做了。
=============================

=============================
KeyGen

N/A

=============================

=============================
Greets

感谢PEiD/C32ASM/OllyDbg及其插件的开发、修改者,没有他们的杰出工作也就没有本文。
感谢SUNBIRD对PDiD Kanal插件使用的指导。
=============================

=============================
MrBeer[CCG]
26/Jul/2005
=============================


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (9)
雪    币: 97697
活跃值: (200829)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
2
步骤详细,适合初学。建议加精。
2005-7-26 12:13
0
雪    币: 442
活跃值: (1216)
能力值: ( LV12,RANK:1130 )
在线值:
发帖
回帖
粉丝
3
上帝都搬出来了, 支持!
2005-7-26 12:22
0
雪    币: 47147
活跃值: (20450)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
4
用RSA保护的也得防这招

最初由 middlebeer 发布
RSA这到关过不去的话,后边的工作也没法进行。所以,采用替换N的方法,让RSATOOL生成一组1024BITS的密钥,将程序中的N替换掉。
方法是用ULTRAEDIT打开程序,搜索上面的N,注意要在HEX模式下,因为本程序将N直接作为数据存储,而没有作为字符串存储。


2005-7-26 12:36
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
5
如果再加上强壳,爆破也不可行了~
2005-7-26 12:36
0
雪    币: 235
活跃值: (160)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
6
最初由 prince 发布
如果再加上强壳,爆破也不可行了~


是啊,以后没得玩了
2005-7-26 12:47
0
雪    币: 235
活跃值: (160)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
7
忘了说了,注册码还经过了BASE64转换,呵呵。
2005-7-26 12:55
0
雪    币: 136
活跃值: (105)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
8
hehe 那我着初学者 也来试试吧 
2005-7-26 13:03
0
雪    币: 221
活跃值: (2326)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
BASE64转换能给段代码分析码?
2005-7-26 14:10
0
雪    币: 235
活跃值: (160)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
10
最初由 lhglhg 发布
BASE64转换能给段代码分析码?


程序我已经卸载。

应该在这个CALL里:
004CF050   |.  E8 BB4EF3FF   call cs.00403F10
2005-7-26 15:29
0
游客
登录 | 注册 方可回帖
返回
//