FLEXLM9.5该洗洗睡了吧---200水帖纪念

【郑重声明】:本文纯属技术交流,无其他目的。 请勿用于商业或其他非法用途,否则后果自负。转载需征得看雪论坛同意。
【软件名称】:Imaris 4.16版本,官方网站有DOWN。
【下载页面】:http://www1.skycn.com/soft/20059.html
【软件简介】:Flexlm9.5保护,医学用(汗,我不懂-:))
【调试环境】:XP、OLLYICE、PEID0.93、calcseed.exe、lmcryptgui.exe、SIG文件
    不会写破文,发了199个水帖,一直潜水不敢再发。据说200帖就可以成为中级了,我汗---我这么菜水平的都成中级?细想一下,我想看雪上的级别资格更多的是给那些有所奉献的朋友吧,不完全代表水平,于是菜鸟我心释然。
    论坛上有很多值得我尊敬的人:看雪、fly、一二三水(哈哈)、laoqian等,无私奉献技术,指导菜鸟提高。当然,我在学习FLEXLM的时候,请教时也曾遇到有人索要RMB的问题(至今心里忿然BS)。学CRACK仅仅是我的兴趣而非职业,是想了解别人的思想,因此绝不会靠CRACK去谋取一分钱,这也不是我学习的目的。
    受大水写了第500帖纪念的启发,于是发第200水帖纪念,希望大锅们不要扁我哈。论坛上有很多水牛,发了那么多帖子,按说水平也该很高了,希望大家也能在整百帖的时候发帖纪念一下,总结一下自己的经验,共同提高!
   转入正题:本文是学习CRACKZ的文章《FLEXlm latest information by CrackZ》后总结的。同样的软件,版本不同。

一、信息收集

1、-8,著名标志,许可证密码错误(0xFFFFFFF8 如果爆破的话,有用)
2、-5,著名标志,FEATURE名称错误
3、-2,许可证语法错误
4、验证逻辑:
如果许可证里面给的种子不对,做出的许可证即使过期了,也会提示-8错误,表示许可证密码无效。这说明是先进行种子参与的密码运算,接着进行密码验证;而后,才是进行日期检查。
如果给出的种子对了,而日期过期了,则会提示-10,表示FEATUER到期;也说明先进行密码检查,后进行日期检查。哈哈。
5、使用假的许可证,启动后出现提示-8提示,表示密码不正确
6、通过分析,比较容易发现VENDOR DAEMON是哪个可执行程序。
7、对于多进程情况,直接调试主干程序;如果调试创建进程的程序,则可能不中断,因为新进程在附加前已经完成了许可证检查
8、认真读看雪大锅的书,学习FLEXLM的基本知识。另外CRACKZ上也有不少好文章。

二、制作一个假的许可证FAKE.LIC

FEATURE feature_name vendor_name 1.000 permanent uncounted 123456654321\
 HOSTID=ANY SIGN=123456789123   
格式一定要正确。如果用lmcryptgui.exe检查许可证时提示格式错误,它会自动校正;将前面的错误信息删除,再检查一次,则会成功。

三、确定VEDNDOR NAME

目的:确定VENDOR NAME
方法:搜索字符串“DEMO”,其前面的je跳转处会出现VENDOR NAME名称。(其实程序中多处出现,该步可略去)

006CE285  |.  05 0C030000   add     eax, 30C
006CE28A  |.  85C0          test    eax, eax
006CE28C  |.  74 2B         je      short 006CE2B9                     确定VENDOR=bitplane
006CE28E  |.  B9 B8A28E00   mov     ecx, 008EA2B8                    ;  ASCII "demo"
006CE293  |.  85C9          test    ecx, ecx
006CE295  |.  74 22         je      short 006CE2B9
006CE297  |.  68 C0A28E00   push    008EA2C0                         ; /s2 = "demo"
006CE29C  |.  8B95 6CFDFFFF mov     edx, [ebp-294]                   ; |
006CE2A2  |.  81C2 0C030000 add     edx, 30C                         ; |

四、定位_l_init()函数

函数目的:定位_l_init()函数可确定_l_sg函数,确定VENDOR NAME
方法:查找默认的种子0x12345678 & 0x87654321 可以确定_l_init() 函数

该函数调用时堆栈出现正确的VENDOR NAME;
006CE309  |.  51            push    ecx                              ; |Arg2
006CE30A  |.  8B95 6CFDFFFF mov     edx, [ebp-294]                   ; |
006CE310  |.  52            push    edx                              ; |lc_init函数
006CE311  |.  E8 453DFFFF   call    006C205B                         ; \调用_l_sg函数,F7跟进
006CE316  |.  83C4 0C       add     esp, 0C
006CE319  |.  81BD 84FDFFFF>cmp     dword ptr [ebp-27C], 87654321    ;   默认的种子1,定位标志1
006CE323  |.  74 0C         je      short 006CE331                   
006CE325  |.  81BD 88FDFFFF>cmp     dword ptr [ebp-278], 12345678    ;  默认的种子2,定位标志2
006CE32F  |.  75 5D         jnz     short 006CE38E
006CE331  |>  8B85 6CFDFFFF mov     eax, [ebp-294]
注意调用_l_sg函数完毕后不会填入正确的种子,因为在_l_sg函数中会提前跳转

五、定位_lc_checkout()函数以及对其的调用处

目的:确定FEATURE和产品版本号(不是FLEXLM的版本号)
方法:在字符串参考中查找'lm_ckout.c';总共也就出现几次,比较容易确定。一般是挨着的两个才是;另外有四个挨着的不是。
定位_lc_checkout()函数比较容易,可以执行到其返回,再F8,就可以确定主程序中对它的调用处。(直接查找可能有多处,运行一次找到)006BE4C0  /$  55            push    ebp
1、定位_lc_checkout函数
006BE4E8  |.  8990 FC030000 mov     [eax+3FC], edx
006BE4EE  |.  68 95000000   push    95                            ; /Arg3 = 00000095
006BE4F3  |.  68 8C9B8E00   push    008E9B8C                   ; |Arg2 = 008E9B8C ASCII "lm_ckout.c",确定标志1,
                                                        //堆栈和寄存器出现FEATURE
006BE4F8  |.  8B4D 08       mov     ecx, [ebp+8]                  ; |
。。。。。
006BE543  |.  E8 B3000000   call    006BE5FB                         ; \堆栈出现产品版本和FEATUER名称
。。。。。
006BE5A6  |.  E8 50000000   call    006BE5FB                         ; \如果许可证密码错误,这里会间接调用_l_sg函数
(跟进发现有对l_valid_version 验证版本;lc_check_key 调用_l_sg函数等函数的调用)
(!!!注意:在这里初次不会调用该CALL。慢慢来,呵呵。我们在该函数里能得到FEATURE和版本号就足够了!)
。。。。。
006BE5DE  |.  68 A6000000   push    0A6                           ; /Arg3 = 000000A6
006BE5E3  |.  68 989B8E00   push    008E9B98                      ; |Arg2 = 008E9B98 ASCII "lm_ckout.c 确定标志2
006BE5E8  |.  8B55 08       mov     edx, [ebp+8]                  ; |
2、定位对其的调用
0041E785    .  51            push    ecx
0041E786    .  53            push    ebx
0041E787    .  52            push    edx
0041E788    .  E8 33FD2900   call    006BE4C0                        ;  调用_l_checkout
0041E78D    .  8BE8          mov     ebp, eax                        ; |
0041E78F    .  8B46 2C       mov     eax, [esi+2C]                   ; |
0041E792    .  53            push    ebx                             ; |Arg2
0041E793    .  50            push    eax                             ; |Arg1
0041E794    .  E8 BDEC2900   call    <_lc_hostid 009E:_l_hostid>     ; \堆栈出现产品版本号与FEATURE
0041E799    .  8B4E 08       mov     ecx, [esi+8]
0041E79C    .  83C4 24       add     esp, 24
记录前面的版本号和FEATURE(有的软件可能有几个产品版本号)

六、修改假的许可证

为什么我们在前面不能再次调用_l_sg函数?这是因为FLEXLM的验证机制,如果FEATUER和产品号验证不正确,眼看要煮熟的鸭子_l_sg就直接飞了,就不会再断下来!
修改许可证,_l_sg函数就可以再次停下来了,这就相当于帅哥有钱,MM停下来;看来造假还是不好,来接近于真的:
FEATURE ImarisBase bitplane 4.1 permanent uncounted 123456654321\
 HOSTID=ANY SIGN=123456789123   

七、定位_l_sg函数及其返回

函数目的:_l_sg的意思是"签名vendor_key5",呵呵。其返回处是恢复加密种子的关键!
方法:搜索常量SEEDVAL,9.2版本的是6F7330B8;注意,有两个出现,其中一个是混淆函数_l_svk()里面的。可以在?_l_init函数里面通过F7跟进确定,也结合后面的固定结构
V7           glseed?=?0x788F71D2                  seedval?=?0x7648B98E
V8           glseed?=?0x3CDE3EBF                 seedval?=?0x6F73330B8
V9           glseed?=?0x72346B53                  seedval?=?0x6F7330B8
v10          glseed?=?0x5332322F                   seedval?=?0x6F7330B8
(seedval:用于确定_l_sg函数;glseed:可以用来确定vendor name,堆栈出现)
(这些值最早出现于WOODOOM网站,laoqian大锅的总结一文也提及了-惠及众生,爽)
可以执行到返回,然后用dd命令
1、定位函数
006C205B  /$  55            push    ebp                              ;  _l_sg函数
。。。。。
006C206B  |.  8845 EF       mov     [ebp-11], al
006C206E  |.  C745 F4 B8307>mov     dword ptr [ebp-C], 6F7330B8      ;  seedval 寻找L_SG,注意混淆函数
006C2075  |.  C745 FC 00000>mov     dword ptr [ebp-4], 0
。。。。。
006C21D7  |.  5D            pop     ebp                              ;  _l_sg函数返回

2、定位函数的返回:
006C02FF  |.  8B45 08       mov     eax, [ebp+8]                     ; |
006C0302  |.  50            push    eax                              ; |Arg1
006C0303  |.  E8 531D0000   call    006C205B                         ; \调用_l_sg函数
006C0308  |.  83C4 0C       add     esp, 0C                          ;  返回到这里,该处下断,用dd [esp]和dd [esp+8]命令
006C030B  |.  8B4D 08       mov     ecx, [ebp+8]

八、追踪加密种子和许可证

方法:在调用_l_sg函数的返回处(后面一般是一个add…命令,就可以在add命令处下断,使用dd命令),用dd [esp]   dd [esp+8]命令查看内存中的内容。
dd [esp]     得到的是00000066。。。job[]结构内容
dd [esp+8]   得到的是00000004。。。data[]内容
如果是正确的许可证,与调用_l_sg函数的次数关系不大,除了_l_init函数不填充正确的job结构外,每一个FEATUER都要调用_l_sg函数一次;
其返回值将是正确的job和data结构数据;也就是说,每个FEATUER对应的job和data值不相等,但用它们算出的加密种子却一样。
1、追踪加密种子
在_l_sg函数的返回处,使用dd命令
006C0308  |.  83C4 0C       add     esp, 0C                  ;  返回到这里,该处下断,用dd [esp]和dd [esp+8]命令

dd [esp]
03A7C350  00000066
03A7C354  00000000
03A7C358  ********    job+08
03A7C35C  ********    job+0c
03A7C360  ********    job+10
03A7C364  00000000

dd [esp+8]
0012F5CC  00000004
0012F5D0  ********     data[0]
0012F5D4  ********     data[1]
0012F5D8  18A011ED
0012F5DC  274BE197
0012F5E0  E26A21A8
0012F5E4  52580441
0012F5E8  00020009

用calcseed.exe计算加密种子
vendor=bitplane
enseed1=*******         enseed2=********         与VENDOR NAME的关系是仅仅与其第一个字母有关

vendor=Bitplane

追出的VENDOR NAME是小写:bitplane,算出的LIC正确;
而网上有DOWN的许可证,第一个字母是大写的VENDOR NAME:Bitplane也正确。这里将VENDOR换成大、小写都没有关系,但用小写VENDOR计算的加密SEEDS。
2、做出许可证
用lmcryptgui.exe。具体方法参见laoqian大锅的文章。
用SDK也可以制作,只不过在lm_code.h中要添加一些信息,麻烦哦。我懒,如果你做好了,别忘了送我一份啊:)

后记:该文的方法对于7.2、8.0、9.2的版本都适用。7之前的版本应该也可以用该方法,因为FLEXLM的某些关键结构(哈哈)一直没有改变!这是通用的方法。
本想做个循序渐进册子,突然发现该方法其实对老版本的_l_init,_l_new_job等方法都包容了。
可以这样说,对于没有使用ECC等技术(需要PATCH,SIGN超过12位则使用了该技术,以后讨论)的情况,FLEXLM就像一张纸。
    关键点:定位对_l_sg函数的调用返回处,逐步修改假许可证(格式正确)中的内容,就会在_l_sg函数处停下来恢复加密的种子。

感谢

CrackZ
Nolan Blender
tulipfan[CCG]
laoqian
看雪论坛上的朋友们! 

附:一些常见问题的处理,希望大家补充:
1、FLEXLM追出了正确加密种子,7.2等SDK做不出正确的许可证?
   如果能正确启动genlic32.exe,恭喜你找对了加密的种子,试试添加选项"advanced->Add Compatible License Key"
2、_l?_sg函数函数只调用一次,不来第二次?
  CRACKZ的文章也曾提及,但没有说明原因和处理办法。常见处理:
   A:许可证格式要正确
   B:设置正确的环境变量,可在"我的电脑->属性"里面或者autoexec.bat里面设置
   C:许可证里面逐步填入正确的VENDOR,FEATUER,产品版本号等
   CRACKZ的另外一篇文章还提及了另外一种处理办法:终止DAEMON进程,在许可证里面加入UER_...信息,但我没有用它试验成功过。
3、如何让后台程序安息?
  运行程序,会发现至少有三样不少:lmgrd.exe是一陪,vendor daemon是二陪,Cracker是“三陪”,哈哈。
  将许可证做成无任何限制的格式,前面两陪直接上床睡觉(进程不启动),晕吧。如果不知道什么是无任何限制的格式,赶快买看雪大锅的书看看(书店一般脱销,我托人才买到)。
4、有了正确的许可证,怎么找加密种子?
  实在恭喜你,省事啊。VENDOR,FEATURE等等都不用找了。
  一般情况了,有了正确的许可证,_l_sg函数会在每个FEATURE的验证后返回正确的值,用通用的种子恢复技术就可以了。
5、相互交流,才能共同提高!仅作技术交流,恳请不要用于非法用途!