UGFLEX——传奇在继续

需要的工具 
Debugger (SICE, OllyDbg--非常棒的东东),Wadsm或者IDA,Flexlm SDK 7.2或者更高版本(非必须),一些最近的信息(从Pilgrim, Nolan Blender或其他的地方得到)。 
目标位置(对付得东东是个CAD软件,叫做Solidedge。) 
http://www.ugsolutions.com 
http://www.solid-edge.com 
正文 
经过最初的嗅听之后,发现了读取license文件(selicense.dat)的DLL。也许我们并没有创建License文件,所以License Key也没有,它是这样的: 
FEATURE SOLIDEDGECLASSIC sedemon 11.0 permanent uncounted / 
    123456789ABC HOSTID=ANY ISSUER="I don’t know" 
我们的ugflex.dll被jutil.dll替换。还有个MAP文件,格式如下: 
Address        Publics by Value              Rva+Base    Lib:Object 
0001:00000010  _JSetVACallback@4              5a001010 f    auto.obj 
0001:00000040  ?IsAutomationEnabled@@YAHXZ    5a001040 f    auto.obj 
0001:00000050  ?IsLicenceValidForAutomation@@YAHXZ 5a001050 auto.obj 

为了与idasym.exe文件一起使用这个MAP文件,将Rva+Base还有Lib:Object列删除。然 
后将创建的sym文件与symbol loader一起使用(设断点易如反掌,接着往下看就明白了) 

由经验得知,实际上对于License的检查是在LC_CHECKOUT进行的(摘自flexlm手册) 

lc_checkout() 
SYNTAX  status = lc_checkout( job ,feature ,version ,num_lic ,flag ,code , dup_group ) 
说明:查出一个或多个具体的feature(不好翻译,姑且用e文)。如果调用lc_checkout()的程序存在,那么check出的license将返回供另一用户使用。 
    如果将上面函数中的flag设置成LM_CO_WAIT,那么这个程序将等待,一直到达到这个feature需要的license数目。License文件的版本必须等于或高于lc_checkout调用中的version参数。 
    If the license file is counted, that is, if the number of users specified on the FEATURE line is non-zero, l

c_checkout() will request the license from alicense server. If the number of users on the FEATURE line is uncounted

, it will grant permission based on 

the contents of the license file onlyŠhostid,version, expiration date, etc.(感觉没什么用,没翻译) 

在5a04cf70 处的_lc_checkout是设断点的好地方!找到了FEATURE名后,就可以按照上面的格式建立自己的license文件了^_^。为了保证正确性,给出所有的FEATURE名:SOLIDEDGECLASSIC, SOLIDEDGEADVANCEDPAR, SOLIDEDGEXPRESROUTE, SOLIDEDGEFEATURERECO, SOLIDEDGEXPAND3D, 
SEWEBPUBLISHER, SOLIDEDGEHANDBOOK, SOLIDEDGEMANAGER(note:有些feature如expand3d要在别的可执行程序中采用的到,以后再说^_^) 
再来看l_good_lic_key函数。_lc_checkout命中三次而_l_good_lic_key只有一次。挺败吧?下面是程序片断: 
5A04DA6C loc_5A04DA6C:              ;CODE XREF _lm_start_real+343j 
5A04DA6C                mov    edx, [ebp+arg_14] 
5A04DA6F                push    edx            ; vendorcode 结构(这次有所改进-加密了) 
5A04DA70                mov    eax, [ebp+var_20] 
5A04DA73                push    eax 
5A04DA74                mov    ecx, [ebp+arg_0]    ;我们的license information 
5A04DA77                push    ecx 
5A04DA78                call    _l_good_lic_key    ;检查license 
5A04DA7D                add    esp, 0Ch 
5A04DA80                test    eax, eax 
5A04DA82                jnz    short loc_5A04DA89    ;这个你应该很熟悉了吧:-) 

如果运行part.exe而没有反应,可能是应为你没有运行seiges.exe。part.exe中有些反debug的代码的部分。运行seiges.exe并将eax置成非零,将得到status=OK.但是仅仅有patch并不能让人满意,所以我们接着往下看^_^ 

5A04E995                add    edx, 54h 


5A04E99C                push    eax 
5A04E99D                call    _l_extract_date 


5A04E9B1                push    ecx            ;我们的vendorcode structure 
5A04E9B2                mov    edx, [ebp+var_CC] 
5A04E9B8                push    edx          ;feature(特征名) 
5A04E9B9                mov    eax, [ebp+arg_4] 
5A04E9BC                push    eax 
5A04E9BD                mov    ecx, [ebp+arg_0] 
5A04E9C0                push    ecx 
5A04E9C1                call    _l_ckout_crypt 

跟踪上面的代码我们发现_l_ckout_crypt做了一些重要的工作。这里只改变了seed的值而没有改变key的值。由于key的值没有改变,我们姑且认为他们已经被解密了,但seed的值仍然隐藏着!继续追踪,_real_crypt出现了(败了,这么个败名字) 
5A050B44                mov    eax, [ebp+arg_0] 
5A050B47                push    eax 
5A050B48                call    _real_crypt    
5A050B4D                add    esp, 10h 

下面是_real_crypt的代码片断: 



5A050ECB                push    ecx 
5A050ECC                call    _l_getattr              ;取得license attributes 


5A05106A                push    eax 
5A05106B                call    _l_good_bin_date        ; date 


5A0510DA                mov    edx, [ebp+arg_0] 
5A0510DD                push    edx 
5A0510DE                call    _move_in_hostid    ; 从license文件里获取hostid 


5A051456                push    offset aDup_group ; "DUP_GROUP" ;DUP_GROUP=UHD意味着可能的分组为(DUP_USER|DUP_HOST|DUP_DISPLAY), 
所以对于用户在一台主机上,另外的对于feature的使用不会销毁另外的licenses. (看不太懂哦:(  ) 

5A05145B                mov    eax, [ebp+arg_4] 
5A05145E                mov    ecx, [eax+94h] 
5A051464                push    ecx 
5A051465                call    _addi            ;把这个加到license中 


5A051855                push    ecx 
5A051856                call    _l_ckout_string_key            ;这个怎样? 
5A05185B                add    esp, 18h 

_l_ckout_string_key值得注意! 
5A052902 _l_ckout_string_key proc near          ; CODE XREF: _real_crypt+AD1p 


5A052902                push    ebp 
5A052903                mov    ebp, esp 
5A052905                sub    esp, 1E4h 



5A053755              call      _our_encrypt2            5A05375A                add    esp, 4 
5A05375D                jmp    short loc_5A05376C 
5A05375F ; ΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖ 
5A05375F 
5A05375F loc_5A05375F:          ; CODE XREF: _l_ckout_string_key+E43j 
5A05375F                                        ; _l_ckout_string_key+E4Cj 
5A05375F                push    offset byte_5A0C5820 
5A053764                call    _our_encrypt        ;the second encrypt 



5A05384B                mov    ecx, [ebp+var_188] 
5A053851                add    ecx, 1 
5A053854                mov    [ebp+var_188], ecx 
5A05385A 
5A05385A loc_5A05385A:          ; CODE XREF: _l_ckout_string_key+F47j 
5A05385A                mov    edx, [ebp+var_188] 
5A053860                cmp    edx, [ebp+var_18C] 
5A053866                jge    loc_5A0539E0 
5A05386C                mov    eax, [ebp+var_188] 
5A053872                mov    cl, [ebp+eax*2+var_168] 
5A053879                mov    [ebp+var_1CC], cl 
5A05387F                call    ds:__p___mb_cur_max 
5A053885                cmp    dword ptr [eax], 1 




5A0539CB                xor    eax, eax 
5A0539CD                mov    al, byte_5A0C5820[edx]              ; 最终 - 比较license 
5A0539D3                cmp    ecx, eax 
5A0539D5                jz      short loc_5A0539DB              ;比较下一个byte 
5A0539D7                xor    eax, eax                  ;错误的key 
5A0539D9                jmp    short loc_5A053A01              
5A0539DB ; ΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖΖ 
5A0539DB 
5A0539DB loc_5A0539DB:        ; CODE XREF: _l_ckout_string_key+10D3j 
5A0539DB                jmp    loc_5A05384B        ;loop back 

上面的循环与版本7中的有些类似(现在是7.2)。5A0C5820是产生真正的key的地方!这里有必要说明一下key的产生:如果没有license key,我们的license(格式正确)是混乱的,两者好像是通过addi function函数联系到一起的。所以现在程序的任务就是计算vendorseed,并在4个vendorkey的帮助下同混乱的license混合(可能是做某种运算^_^)。上面说得工作将在5A0C5820处完成。在5A0C5820处bpm,我们得到: 



5A053334                mov    byte_5A0C5820[ecx], al    ;here we go 
5A05333A                jmp    short loc_5A0532F9 
5A05333C loc_5A05333C:          ; CODE XREF: _l_ckout_string_key+A0Dj 
5A05333C                cmp    [ebp+var_188], 0 

从5A05333C处开始追踪,我们发现了计算seed的代码: 

5A0533EA                xor    eax, ebx        ;计算正确的seed 
5A0533EC                push    eax            ;入栈 
5A0533ED                call    sub_5A053AD3 
5A0533F2                add    esp, 4 
5A0533F5                mov    [ebp+seed_one], eax 
5A0533FB                mov    edx, [ebp+seed_one] 
5A053401                and    edx, 0FFh 


5A0534C9                add    eax, 1 
5A0534CC                mov    [ebp+var_10], eax 
5A0534CF                mov    [ebp+seed_one], 3D4DA1D6h  ;隐藏seed 


5A053548                push    eax    ;第二个seed入栈 
5A053549                call    sub_5A053AD3 
5A05354E                add    esp, 4 
5A053551                mov    [ebp+seed_two], eax 
5A053557                mov    edx, [ebp+seed_two] 


5A053628                mov    [ebp+var_10], eax 
5A05362B                mov    [ebp+seed_two], 3D4DA1D6h  ;隐藏5A053635                jmp    loc_5A053735 

将seed隐藏能很好的防止内存dump工具将seed解出来。解seed的过程只能在特定位置并且是运行时才可以! 

总结: 
LC_CHECKOUT --- 
        | 
        | 
        _l_good_lic_key— /*加密的keys*/ 
                  | 
                  | 
                  _l_ckout_crypt---/*解密的keys*/ 
                            | 
                            | 
                            _real_crypt--- 
                                  | 
                                | 
                        _l_ckout_string_key--- 
                        | 
                        | 
                5A0533EA  /*计算第一个seed*/ 
                        | 
                        | 
                5A053547  /*计算第二个seed*/ 
                        | 
                        | 
                5A0539DB <- 
                        | 
                        | 
                5A0539CD---  /*license比较*/ 
现在我们可以修改lm_code.h并且编译lmcrypt。使用3D4DA1D6h这样的字节模式,我们在AddInlm.dll中找类似的位置。其实我们只需要LC_CHECKOUT作为feature名。使用其他的模式能得到相应的位置(对于没有flexlm SDK的朋友来说,比较有用): 
jutil.dll          AddInlm.dll        Selicwiz.exe 
5A0533EC        046CAEDC         00428C6C 

5A0539CD        046CB4BD         0042924D 

The origin of the above code is the object lm_ckout.obj winthin the lmgr.lib library.(大体意思是上面的代码从那里来的) 

                                             | 
                                             | 
                                             5A0533EA  /*计算第一个seed*/ 
                                             | 
                                             5A053547  /*计算第二个seed*/ 
                                             | 
                                             5A0539DB <-                                                    
                                                 |      | 
                                                  5A0539CD---  /*license比较*/ 
                                             | 
                                            -- 
翻译得不好,大虾莫笑:P

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值