【软件名称】Multigen vega prime 2.0
【应用平台】Win2000 SP4
【作者邮箱】chubing6143@sina.com
【使用工具】OllyDbg1.10,FlexLM 7.2 SDK
【软件限制】FLEXlm v9.2.0 需要120位长度的SIGN
【软件简介】大名鼎鼎的视景仿真软件,具体我就不介绍了.
【关于本文】呵呵,由于这个软件是采用的120位长度的SIGN的FLEXLM9.2的加密,如果要想产生真正的License文件,我没有这个水平了.而如果要想爆破的话,很简单了.但由于我想仔细跟踪一下该软件的FlexLM加密的具体过程,呵呵,我是菜鸟,这下可费劲了,经过几个日夜不停的工作,加上资料的消化,我终于有了点感觉了.因此,写出来希望给我这样的菜鸟有一定的帮助.
前几天,师弟毕业,大家喝高了,教授(62岁)临别赠言"扶摇直上九万里",多么豪迈啊,想想我自己,虽然也老大不小了.但是和他比起来,我还年轻,可心已经没劲了.激励自己一下,该来个"扶摇直上九厘米"了啊!呵呵,跑题了啊!
补充说明,最近一直和自己说要好好干点正事了(毕业压力好大),因此手头一直只有FlexLM 7.2 SDK,没有9.2的SDK,因此,自己分析全靠死功夫了,有错的地方,请大家指点一下啊!
【跟踪过程】利用LMTOOLS可以发现该软件是采用FLEXlm v9.2.0 (lmgr.lib)加密的,而加密的文件是vsgu2_0.dll,而软件中主要限制就是运行时检查License文件,我刚开始直接利用OD加载LynxPrime.exe分析,可是总断不下来,后来仔细一看,运行部分其实是vprun.exe,利用OD加载它,逐步分析,很快就爆破掉了,然后才有动力仔细寻找加密全过程,为今后找其他软件的爆破点做点积累了.为了叙述方便,我将软件中主要函数调用过程都列出来了,当然有些函数不重要,我懒得整理了.函数嵌套调用层次以"-"代表.我想如果你根据我的下面笔记一定能看明白了.文字就叙述的少点了.
-00402E14 . E8 8CE2FFFF call vprun.004010A5
--00402736 . FF15 98A44000 call dword ptr ds:[<&vp2_0.vp::initialize>] ; vp2_0.vp::initialize
---1003FAFF FF15 14030C10 call dword ptr ds:[<&vsgu2_0.vsgu::initialize>] ; vsgu2_0.vsgu::initialize
----005C5C5C E8 FFAF0400 call vsgu2_0.CLicenseManager::CLicenseManager
-----00610CE0 E8 CBFCFFFF call vsgu2_0.CLicenseManager::OpenJob
------00610A45 E8 26950000 call vsgu2_0.lc_new_job
-------00619FB8 E8 72950200 call vsgu2_0.lc_init
--------00643544 E8 05000000 call vsgu2_0.l_init
---------0064366F E8 8CAF0100 call vsgu2_0.lu_getdtablesize
---------00643814 E8 EC00FFFF call vsgu2_0.l_getenv
---------00643973 E8 B8B1FEFF call vsgu2_0.l_more_featdata
---------00643C3D E8 C3FCFEFF call vsgu2_0.l_getenv
---------00643F90 E8 999B0100 call vsgu2_0.l_get_attr
---------00643FA8 E8 819B0100 call vsgu2_0.l_get_attr
---------006440E0 E8 0590FFFF call vsgu2_0.l_getattr_init
---------00644162 E8 098FFFFF call vsgu2_0.l_getattr
---------006441B1 E8 555CFEFF call vsgu2_0.l_sg ;第一次调用l_sg
----------00629E83 E8 AB490200 call vsgu2_0.l_key
-----------0064E851 E8 74FFFFFF call vsgu2_0.l_zinit
---------00644363 E8 088DFFFF call vsgu2_0.l_getattr
---------0064439C E8 BD35FDFF call vsgu2_0.l_set_attr 设置FLEXLM版本,此处为9.0
---------006443F1 E8 0FF5FEFF call vsgu2_0.l_getenv
---------00644496 E8 6AF4FEFF call vsgu2_0.l_getenv
---------00644544 E8 BCF3FEFF call vsgu2_0.l_getenv
---------00644851 E8 1A88FFFF call vsgu2_0.l_getattr
---------00644A7E E8 ADE9FFFF call vsgu2_0.l_add_key_filter
------00610A8D E8 2E6E0000 call vsgu2_0.lc_set_attr
------00610A98 E8 236E0000 call vsgu2_0.lc_set_attr
------00610AAD E8 0E6E0000 call vsgu2_0.lc_set_attr
------00610AED FF15 D4916900 call dword ptr ds:[<&MSVCR71.getenv>>; MSVCR71.getenv
堆栈压入:0012DE80 00699CE0 \name = "MPI_INSTALL_DEFAULT"
------00610B2D FF15 88936900 call dword ptr ds:[<&MSVCR71._access>; MSVCR71._access判断license文件存在否
堆栈压入:0012DE64 0012DE94 |path = "C:\Program Files\MultiGen-Paradigm/flexlmCRO/serverlist.dat"
------00610B84 E8 376D0000 call vsgu2_0.lc_set_attr
------00610B8F E8 2C6D0000 call vsgu2_0.lc_set_attr
------00610BAB E8 106D0000 call vsgu2_0.lc_set_attr
------00610BBA E8 016D0000 call vsgu2_0.lc_set_attr
------00610BC9 E8 F26C0000 call vsgu2_0.lc_set_attr
省略部分函数call vsgu2_0.lc_set_attr
------00610C44 E8 075F0000 call vsgu2_0.l_flush_config
-------00616B57 E8 D46D0200 call vsgu2_0.l_init_file
--------0063DD36 E8 B15CFDFF call vsgu2_0.l_free_job_license
--------0063DF8C E8 DFAB0100 call vsgu2_0.l_open_file
--------0063DFD7 E8 839F0100 call vsgu2_0.l_master_list_lfp
--------0063E1C0 E8 AB7CFFFF call vsgu2_0.l_allfeat
---------00635EFC E8 52A9FFFF call vsgu2_0.l_lfseek
---------00635F1A E8 F1A8FFFF call vsgu2_0.l_lfgets
堆栈数据: ASCII "INCREMENT bb3d_dev MPICRO 2.9 permanent uncounted VENDOR_STRING=D99999:MPI/d>.....
00635F1F 83C4 14 add esp,14
00635F22 85C0 test eax,eax
00635F24 0F84 F5010000 je vsgu2_0.0063611F
上面这段代码决定了程序将循环取license文件,并分析每一个Feature
---------00635FBA E8 6C010000 call vsgu2_0.l_parse_feature_line
----------006361A2 E8 C9970100 call vsgu2_0.l_parse_decimal
----------00636275 E8 96E4FFFF call vsgu2_0.l_keyword_eq
----------0063629E E8 6DE4FFFF call vsgu2_0.l_keyword_eq判断license文件中是Feature还是Increment
----------006362B0 E8 BB6D0000 call vsgu2_0.l_getattr
----------00636733 FF15 C8926900 call dword ptr ds:[<&MSVCR71.s>; MSVCR71.sscanf
堆栈数据:00123E68 001248AC |s = "INCREMENT bb3d_dev MPICRO 2.9 permanent uncounted VENDOR_STRING=D99999:MPI/dk>
00123E6C 006D5C9C |format = "%s %s %s %s %s %s %s %[^
]
"
00123E70 00123EE0 ASCII "INCREMENT"
00123E74 09030FB0 ASCII "bb3d_dev"
00123E78 090317B1 ASCII "MPICRO"
----------00636768 E8 03E1FFFF call vsgu2_0.l_keyword_eq_nlicense文件是否有start选项
----------006367BB E8 E3250100 call vsgu2_0.l_isxdigit
----------00636843 FF15 C8926900 call dword ptr ds:[<&MSVCR71.s>; MSVCR71.sscanf
堆栈数据:00123E6C 001248AC |s = "INCREMENT bb3d_dev MPICRO 2.9 permanent uncounted VENDOR_STRING=D99999:MPI/dk>
00123E70 006D5CC0 |format = "%s %s %s %s %s %s %[^
]
"
00123E74 00123EE0 ASCII "INCREMENT"
00123E78 09030FB0 ASCII "bb3d_dev"
00123E7C 090317B1 ASCII "MPICRO"
00123E80 09031FB2 ASCII "2.9"
00123E84 090327B3 ASCII "permanent"
00123E88 09032FB4 ASCII "uncounted"
00123E8C 09033FB6 ASCII "HOSTID=DEMO SN=demo SIGN="013C 9A5D C920 7271 C073 4D35 52D8 42E8 2528 D201 >
----------006368A0 E8 DE070000 call vsgu2_0.l_valid_version版本检查
----------006368C7 E8 B1BDFFFF call vsgu2_0.l_zcp
----------006369FD E8 0EDDFFFF call vsgu2_0.l_keyword_eq是否属于permenant license文件
----------00636AE6 E8 85DDFFFF call vsgu2_0.l_keyword_eq_n
----------00636B98 E8 73DBFFFF call vsgu2_0.l_keyword_eq获取节点限制信息
----------00636CBF E8 DCDE0000 call vsgu2_0.l_uppercase
----------00636EAC E8 CFDA0100 call vsgu2_0.l_parse_attr
----------0063705F E8 57030000 call vsgu2_0.006373BB
-----------006373CC E8 FBE9FEFF call vsgu2_0.l_extract_date
堆栈数据: 00123E28 00124770 ASCII "013C 9A5D C920 7271 "
-----------0063740C E8 45000000 call vsgu2_0.l_crypt_private传说中的检查license文件是否正确的地方,此处略过不分析了,但是给出函数原型,F7会来到下面的地方:
00637456 vs> 55 push ebp
00637457 8BEC mov ebp,esp
00637459 83EC 08 sub esp,8
0063745C C745 FC 00000000 mov dword ptr ss:[ebp-4],0
00637463 C745 F8 00000000 mov dword ptr ss:[ebp-8],0
0063746A 8B45 14 mov eax,dword ptr ss:[ebp+14]
0063746D 50 push eax
0063746E 8B4D 10 mov ecx,dword ptr ss:[ebp+10]
00637471 51 push ecx
00637472 8B55 0C mov edx,dword ptr ss:[ebp+C]
00637475 52 push edx
00637476 8B45 08 mov eax,dword ptr ss:[ebp+8]
00637479 50 push eax
0063747A E8 0D000000 call vsgu2_0.0063748C
0063747F 83C4 10 add esp,10
00637482 8945 FC mov dword ptr ss:[ebp-4],eax
00637485 8B45 FC mov eax,dword ptr ss:[ebp-4]
00637488 8BE5 mov esp,ebp
0063748A 5D pop ebp
0063748B C3 retn
而call vsgu2_0.0063748C函数如下:
0063748C 55 push ebp
0063748D 8BEC mov ebp,esp
0063748F 81EC AC090000 sub esp,9AC
00637495 57 push edi
00637496 C685 C4F6FFFF 00 mov byte ptr ss:[ebp-93C],0
0063749D B9 4D020000 mov ecx,24D
006374A2 33C0 xor eax,eax
006374A4 8DBD C5F6FFFF lea edi,dword ptr ss:[ebp-93B]
006374AA F3:AB rep stos dword ptr es:[edi]
006374AC 66:AB stos word ptr es:[edi]
006374AE C785 ACF6FFFF 00000000 mov dword ptr ss:[ebp-954],0
006374B8 8D85 C4F6FFFF lea eax,dword ptr ss:[ebp-93C]
-----------00637427 E8 51B2FFFF call vsgu2_0.l_zcp
-----------0063743E E8 012AFEFF call vsgu2_0.l_err_info_cp
-----------0063744A E8 9B29FEFF call vsgu2_0.l_free_err_info
--------0063E255 E8 E6960100 call vsgu2_0.l_supersede
--------0063E261 E8 5E880100 call vsgu2_0.l_post_pkg
--------0063E26F E8 CC960100 call vsgu2_0.l_supersede
--------0063E2E0 E8 2126FFFF call vsgu2_0.l_lfclose关闭文件
----005C5E67 E8 24EDFFFF call vsgu2_0.vsgu::checkOutRTL
-----005C4BC0 E8 1BFFFFFF call vsgu2_0.vsgu::licenseIsAllowed
-----005C4C05 E8 D6FEFFFF call vsgu2_0.vsgu::licenseIsAllowed
-----005C4C1F E8 CCFDFFFF call vsgu2_0.vsgu::checkOutLicense
堆栈数据:0012EE3C 0012EE48 ASCII "vsg_rtl"
0012EE40 0069A030 ASCII "2.0"
0012EE44 0012EEF0 ASCII "C:\Program Files\MultiGen-Paradigm\bin\vprun.exe"
------005C4A26 E8 D5C20400 call vsgu2_0.CLicense::CLicense构造相应的Featrue和版本号的CLicense类
------005C4A35 E8 A6CD0400 call vsgu2_0.CLicense::Checkout
-------00611808 E8 53EBFFFF call vsgu2_0.CLicenseManager::AttachLicense
下面这段代码我不能不先提一下了:
00611843 3BF8 cmp edi,eax
00611845 7F 18 jg short vsgu2_0.0061185F ;注意这里,关键跳转(1)
00611847 8B86 A4160000 mov eax,dword ptr ds:[esi+16A4]
0061184D 0FAFC7 imul eax,edi
00611850 5F pop edi
00611851 5E pop esi
00611852 C1E0 02 shl eax,2
00611855 5D pop ebp
00611856 81C4 54040000 add esp,454
0061185C C2 0400 retn 4
0061185F 57 push edi
00611860 8BCE mov ecx,esi 程序在这里关键跳转(1)要跳了,所以我们暂时不管了.让它跳吧。
-------00611862 E8 F9FAFFFF call vsgu2_0.CLicense::DoDisableLicensingCallback
-------0061196E E8 AD280000 call vsgu2_0.MPITrim
-------00611993 E8 08F8FFFF call vsgu2_0.CLicense::Checkout注意此处与005C4A35 进入的地方不一样,这就是C++的特点吧,允许形参不同相同函数名称了。
--------006111CC E8 EF660000 call vsgu2_0.lc_set_attr设置FEATURE
--------006111ED E8 7E500100 call vsgu2_0.lc_checkout
---------006262AC E8 04880000 call vsgu2_0.l_mt_lock
---------006262C0 E8 B11B0700 call vsgu2_0._setjmp3
---------006262F3 E8 B3000000 call vsgu2_0.l_checkout
堆栈数据:0012E944 09029AD8
0012E948 0903BF1C ASCII "vsg_rtl"
0012E94C 0903BEF4 ASCII "2.0"
----------006263E3 E8 95C20000 call vsgu2_0.l_zcp
----------006263F1 E8 7A6C0100 call vsgu2_0.l_getattr
----------00626520 E8 689D0100 call vsgu2_0.l_ckout_borrow
-----------00640342 E8 BE35FFFF call vsgu2_0.l_getenv
-----------00640353 E8 18C70000 call vsgu2_0.l_baddate
-----------0064047B FF15 F4916900 call dword ptr ds:[<&MSVCR71.sprintf>]
函数调用后的结果堆栈如下:
0012E664 0012E6DC ASCII "borrow-d8f349a2-vsg_rtl"
0012E668 006D868C ASCII "borrow-%s-%s"
0012E66C 0012E71C ASCII "d8f349a2"
0012E670 0903BF1C ASCII "vsg_rtl"
----------00626548 FF15 24366E00 call dword ptr ds:[6E3624] ; vsgu2_0.00626AD5
-----------00626B4B E8 33050100 call vsgu2_0.l_valid_version
-----------00626BF9 E8 7FBA0000 call vsgu2_0.l_zcp
-----------00626C58 E8 2700FFFF call vsgu2_0.l_next_conf_or_marker
-----------00626CA7 E8 5C0A0000 call vsgu2_0.l_local_verify_conf
-----------00626E61 E8 89110000 call vsgu2_0.l_good_lic_key 小心了,如果是正确的license将返回1,错误的License返回0
------------00628096 E8 6B570100 call vsgu2_0.l_xorname
------------006280B3 E8 531D0000 call vsgu2_0.l_sg ;第二次调用L_SG
-------------00629E64 FF15 98396E00 call dword ptr ds:[l_n36_buff] ; vsgu2_0.00624600
-------------00628267 E8 E52B0000 call vsgu2_0.0062AE51 ;小心了
--------------0062AE75 E8 38020000 call vsgu2_0.0062B0B2 ;小心了
F7进去看一下,看到没有,发现是不是与前面介绍的0063740C call vsgu2_0.l_crypt_private代码基本一样啊!!!
0062B0B2 55 push ebp
0062B0B3 8BEC mov ebp,esp
0062B0B5 81EC AC090000 sub esp,9AC
0062B0BB 57 push edi
0062B0BC C685 C4F6FFFF 00 mov byte ptr ss:[ebp-93C],0
0062B0C3 B9 4D020000 mov ecx,24D
0062B0C8 33C0 xor eax,eax
0062B0CA 8DBD C5F6FFFF lea edi,dword ptr ss:[ebp-93B]
0062B0D0 F3:AB rep stos dword ptr es:[edi]
0062B0D2 66:AB stos word ptr es:[edi]
0062B0D4 C785 ACF6FFFF 00000000 mov dword ptr ss:[ebp-954],0
0062B0DE 8D85 C4F6FFFF lea eax,dword ptr ss:[ebp-93C]
呵呵,发现了吧,其实这里也是l_crypt_private传说中的检查license文件是否正确的地方了,但是如果你用"搜索-当前模块中的名称"的方法,是不能发现这处参考的.
由于这个函数太重要了,因此我将其关键代码列在此了:
---------------0062B3D9 E8 45ADFFFF call vsgu2_0.l_good_bin_date
经过一系列对日期和序列号,Vendor Info的判断之后
然后关键比较出现了
---------------0062BC24 E8 46110000 call vsgu2_0.0062CD6F
0062BBFB 8B95 C0F6FFFF mov edx,dword ptr ss:[ebp-940]
0062BC01 52 push edx ; SN
0062BC02 8B85 A4F6FFFF mov eax,dword ptr ss:[ebp-95C]
0062BC08 50 push eax ; 66D8B337
0062BC09 8B4D 14 mov ecx,dword ptr ss:[ebp+14]
0062BC0C 51 push ecx
0062BC0D 8B55 FC mov edx,dword ptr ss:[ebp-4]
0062BC10 8D85 C4F6FFFF lea eax,dword ptr ss:[ebp-93C]
0062BC16 2BD0 sub edx,eax
0062BC18 52 push edx ; 30
0062BC19 8D8D C4F6FFFF lea ecx,dword ptr ss:[ebp-93C]
0062BC1F 51 push ecx
0062BC20 8B55 08 mov edx,dword ptr ss:[ebp+8]
0062BC23 52 push edx
0062BC24 E8 46110000 call vsgu2_0.0062CD6F
----------------这里给出call vsgu2_0.0062CD6F函数的部分分析:
......
0062CFF2 8A0A mov cl,byte ptr ds:[edx]
0062CFF4 888C05 60FEFFFF mov byte ptr ss:[ebp+eax-1A0],cl
0062CFFB 8B95 54FEFFFF mov edx,dword ptr ss:[ebp-1AC]
0062D001 83C2 01 add edx,1
0062D004 8995 54FEFFFF mov dword ptr ss:[ebp-1AC],edx
0062D00A 83BD 54FEFFFF 02 cmp dword ptr ss:[ebp-1AC],2
0062D011 75 49 jnz short vsgu2_0.0062D05C
0062D013 C785 54FEFFFF 00000000 mov dword ptr ss:[ebp-1AC],0
0062D01D 8D85 68FEFFFF lea eax,dword ptr ss:[ebp-198]
0062D023 50 push eax
0062D024 68 3C526D00 push vsgu2_0.006D523C ; ASCII "%02X"
0062D029 8D8D 60FEFFFF lea ecx,dword ptr ss:[ebp-1A0]
0062D02F 51 push ecx
0062D030 FF15 C8926900 call dword ptr ds:[<&MSVCR71.sscanf>] ; MSVCR71.sscanf
0062D036 83C4 0C add esp,0C
0062D039 8B95 50FEFFFF mov edx,dword ptr ss:[ebp-1B0]
0062D03F 0395 48FEFFFF add edx,dword ptr ss:[ebp-1B8]
0062D045 8A85 68FEFFFF mov al,byte ptr ss:[ebp-198]
0062D04B 8802 mov byte ptr ds:[edx],al
0062D04D 8B8D 48FEFFFF mov ecx,dword ptr ss:[ebp-1B8]
0062D053 83C1 01 add ecx,1
0062D056 898D 48FEFFFF mov dword ptr ss:[ebp-1B8],ecx
0062D05C ^ E9 4CFFFFFF jmp vsgu2_0.0062CFAD ;循环取SIGN的值并转化为16进制值
0062D061 8B95 7CFEFFFF mov edx,dword ptr ss:[ebp-184]
0062D067 8B82 94000000 mov eax,dword ptr ds:[edx+94]
0062D06D 50 push eax
0062D06E 8B8D 7CFEFFFF mov ecx,dword ptr ss:[ebp-184]
0062D074 8B91 8C000000 mov edx,dword ptr ds:[ecx+8C]
0062D07A 52 push edx
0062D07B 8B85 7CFEFFFF mov eax,dword ptr ss:[ebp-184]
0062D081 83C0 14 add eax,14
0062D084 50 push eax
0062D085 8B8D 7CFEFFFF mov ecx,dword ptr ss:[ebp-184]
0062D08B 83C1 08 add ecx,8
0062D08E 51 push ecx
0062D08F 8B95 48FEFFFF mov edx,dword ptr ss:[ebp-1B8]
0062D095 52 push edx
0062D096 8B85 50FEFFFF mov eax,dword ptr ss:[ebp-1B0]
0062D09C 50 push eax
0062D09D 8B4D 10 mov ecx,dword ptr ss:[ebp+10]
0062D0A0 51 push ecx
0062D0A1 8B55 0C mov edx,dword ptr ss:[ebp+C]
0062D0A4 52 push edx
0062D0A5 8B45 08 mov eax,dword ptr ss:[ebp+8]
0062D0A8 50 push eax
0062D0A9 FF95 64FEFFFF call dword ptr ss:[ebp-19C] ;l_pubkey_verify 看到没有
0062D0AF 83C4 24 add esp,24
0062D0B2 8985 4CFEFFFF mov dword ptr ss:[ebp-1B4],eax
0062D0B8 8B8D 50FEFFFF mov ecx,dword ptr ss:[ebp-1B0]
0062D0BE 51 push ecx
0062D0BF E8 D2190000 call vsgu2_0.l_free
0062D0C4 83C4 04 add esp,4
0062D0C7 83BD 4CFEFFFF 00 cmp dword ptr ss:[ebp-1B4],0
0062D0CE 74 0C je short vsgu2_0.0062D0DC ; 关键跳转(2),必须跳
0062D0D0 C785 84FEFFFF 00000000 mov dword ptr ss:[ebp-17C],0
0062D0DA EB 0A jmp short vsgu2_0.0062D0E6
0062D0DC C785 84FEFFFF 44526D00 mov dword ptr ss:[ebp-17C],vsgu2_0.006D5244 ; ASCII "ok"
0062D0E6 E9 D30C0000 jmp vsgu2_0.0062DDBE
-----------------关键函数l_pubkey_verify如果是正确的license将返回0,错误的License返回FFFFFFF8,呵呵,很熟悉吧,分析如下:
------------------006464B3 E8 A8850100 call vsgu2_0.sb_dataSize
------------------00646509 E8 B2840100 call vsgu2_0.sb_heapSize
------------------006465A3 E8 A8810100 call vsgu2_0.sb_initialize
------------------006465F1 E8 1A8B0100 call vsgu2_0.sb_ecdsaVerifyBegin
------------------00646681 E8 2A870100 call vsgu2_0.sb_ecdsaSign
------------------006466D9 E8 D2860100 call vsgu2_0.sb_ecdsaSign
------------------00646728 E8 538A0100 call vsgu2_0.sb_ecdsaVerifyEnd
0064672D 83C4 14 add esp,14
00646730 8945 AC mov dword ptr ss:[ebp-54],eax
00646733 837D AC 00 cmp dword ptr ss:[ebp-54],0
00646737 74 1E je short vsgu2_0.00646757
00646739 8B4D AC mov ecx,dword ptr ss:[ebp-54]
0064673C 51 push ecx
0064673D 68 30290000 push 2930
00646742 8B55 08 mov edx,dword ptr ss:[ebp+8]
00646745 52 push edx
00646746 E8 40F1FFFF call vsgu2_0.l_pubkey_err
0064674B 83C4 0C add esp,0C
0064674E C745 B0 8DFFFFFF mov dword ptr ss:[ebp-50],-73
00646755 EB 5E jmp short vsgu2_0.006467B5
00646757 837D 9C 00 cmp dword ptr ss:[ebp-64],0
0064675B 75 58 jnz short vsgu2_0.006467B5 ; 关键跳转(3),必须跳
0064675D 8B45 08 mov eax,dword ptr ss:[ebp+8]
00646760 8378 14 00 cmp dword ptr ds:[eax+14],0
00646764 74 14 je short vsgu2_0.0064677A
00646766 33C9 xor ecx,ecx
00646768 85C9 test ecx,ecx
0064676A 74 0E je short vsgu2_0.0064677A
0064676C 8B55 08 mov edx,dword ptr ss:[ebp+8]
0064676F 8B42 14 mov eax,dword ptr ds:[edx+14]
00646772 8985 10FFFFFF mov dword ptr ss:[ebp-F0],eax
00646778 EB 0A jmp short vsgu2_0.00646784
0064677A C785 10FFFFFF F8FFFFFF mov dword ptr ss:[ebp-F0],-8
00646784 8B4D 08 mov ecx,dword ptr ss:[ebp+8]
00646787 8B95 10FFFFFF mov edx,dword ptr ss:[ebp-F0]
0064678D 8951 14 mov dword ptr ds:[ecx+14],edx
00646790 6A 00 push 0
00646792 68 FF000000 push 0FF
00646797 6A 00 push 0
00646799 6A 00 push 0
0064679B 68 14020000 push 214
006467A0 6A F8 push -8
006467A2 8B45 08 mov eax,dword ptr ss:[ebp+8]
006467A5 50 push eax
006467A6 E8 E533FDFF call vsgu2_0.l_set_error
006467AB 83C4 1C add esp,1C
006467AE C745 B0 F8FFFFFF mov dword ptr ss:[ebp-50],-8
006467B5 8B45 B0 mov eax,dword ptr ss:[ebp-50]
006467B8 8BE5 mov esp,ebp
006467BA 5D pop ebp
006467BB C3 retn
下面经过一堆代码直到call vsgu2_0.l_good_lic_key返回了,如果是正确的license将返回1,错误的License返回0
如果前面爆破后的代码:
-----------00626E90 E8 B0DDFEFF call vsgu2_0.l_featon
-----------00626EB6 E8 85D7FEFF call vsgu2_0.l_check_conf
-----------0062735B E8 1DB30000 call vsgu2_0.l_zcp
-----------006273A4 E8 67D30000 call vsgu2_0.l_keyword_eq
-----------0062740E E8 87B70000 call vsgu2_0.l_update_license_file
---------00626308 E8 813AFFFF call vsgu2_0.l_clear_error
---------0062639C E8 0F870000 call vsgu2_0.l_mt_unlock
--------0061121E E8 C3480000 call vsgu2_0.lc_auth_data
--------00611264 E8 73470100 call vsgu2_0.lc_expire_days
-------
00611998 8BE8 mov ebp,eax
0061199A 85ED test ebp,ebp
0061199C 7D 7F jge short vsgu2_0.00611A1D ;关键跳转(4),必须跳转.
0061199E 85FF test edi,edi
006119A0 74 19 je short vsgu2_0.006119BB
006119A2 803F 00 cmp byte ptr ds:[edi],0
006119A5 74 14 je short vsgu2_0.006119BB
006119A7 6A 01 push 1
006119A9 6A 00 push 0
006119AB 8D4424 1C lea eax,dword ptr ss:[esp+1C]
006119AF 50 push eax
006119B0 57 push edi
006119B1 E8 3A290000 call vsgu2_0.MPIAddToBuf
006119B6 83C4 10 add esp,10
006119B9 8BF8 mov edi,eax
006119BB 53 push ebx
006119BC E8 80850000 call vsgu2_0.lc_err_info
006119C1 50 push eax
006119C2 E8 A9250000 call vsgu2_0.BuildErrorString
006119C7 6A 01 push 1
006119C9 50 push eax
006119CA 8D4C24 24 lea ecx,dword ptr ss:[esp+24]
006119CE 51 push ecx
006119CF 57 push edi
006119D0 E8 1B290000 call vsgu2_0.MPIAddToBuf
006119D5 83C4 18 add esp,18
006119D8 83FD FC cmp ebp,-4
006119DB 8BF8 mov edi,eax
006119DD 74 05 je short vsgu2_0.006119E4
006119DF 83FD E8 cmp ebp,-18
006119E2 75 3E jnz short vsgu2_0.00611A22
006119E4 85FF test edi,edi
006119E6 74 19 je short vsgu2_0.00611A01
006119E8 803F 00 cmp byte ptr ds:[edi],0
006119EB 74 14 je short vsgu2_0.00611A01
006119ED 6A 01 push 1
006119EF 6A 00 push 0
006119F1 8D5424 1C lea edx,dword ptr ss:[esp+1C]
006119F5 52 push edx
006119F6 57 push edi
006119F7 E8 F4280000 call vsgu2_0.MPIAddToBuf
006119FC 83C4 10 add esp,10
006119FF 8BF8 mov edi,eax
00611A01 8B4424 20 mov eax,dword ptr ss:[esp+20]
00611A05 50 push eax
00611A06 53 push ebx
00611A07 8D5C24 1C lea ebx,dword ptr ss:[esp+1C]
00611A0B 8BC7 mov eax,edi
00611A0D E8 4EF5FFFF call vsgu2_0.00610F60
00611A12 8B5C24 24 mov ebx,dword ptr ss:[esp+24]
00611A16 83C4 08 add esp,8
00611A19 8BF8 mov edi,eax
00611A1B EB 05 jmp short vsgu2_0.00611A22
00611A1D C64424 13 01 mov byte ptr ss:[esp+13],1
00611A22 68 589C6900 push vsgu2_0.00699C58
00611A27 6A 00 push 0
00611A29 FF15 04926900 call dword ptr ds:[<&MSVCR71.strtok>] ; MSVCR71.strtok
00611A2F 8A4C24 1B mov cl,byte ptr ss:[esp+1B]
00611A33 83C4 08 add esp,8
00611A36 84C9 test cl,cl
00611A38 ^ 0F84 22FFFFFF je vsgu2_0.00611960
00611A3E EB 50 jmp short vsgu2_0.00611A90
00611A40 8A4424 13 mov al,byte ptr ss:[esp+13]
00611A44 84C0 test al,al
00611A46 75 48 jnz short vsgu2_0.00611A90
00611A48 85FF test edi,edi
00611A4A 74 18 je short vsgu2_0.00611A64
00611A4C 8BC7 mov eax,edi
00611A4E 8D50 01 lea edx,dword ptr ds:[eax+1]
00611A51 8A08 mov cl,byte ptr ds:[eax]
00611A53 40 inc eax
00611A54 84C9 test cl,cl
00611A56 ^ 75 F9 jnz short vsgu2_0.00611A51
00611A58 2BC2 sub eax,edx
00611A5A 894424 1C mov dword ptr ss:[esp+1C],eax
00611A5E 74 04 je short vsgu2_0.00611A64
00611A60 8BC7 mov eax,edi
00611A62 EB 0F jmp short vsgu2_0.00611A73
00611A64 53 push ebx
00611A65 E8 D7840000 call vsgu2_0.lc_err_info
00611A6A 50 push eax
00611A6B E8 00250000 call vsgu2_0.BuildErrorString
00611A70 83C4 08 add esp,8
00611A73 8B8E 38170000 mov ecx,dword ptr ds:[esi+1738]
00611A79 8B19 mov ebx,dword ptr ds:[ecx]
00611A7B 8D96 84120000 lea edx,dword ptr ds:[esi+1284]
00611A81 52 push edx
00611A82 68 2CD66A00 push vsgu2_0.006AD62C ; ASCII "Cannot check out feature "%s" because:
" 呵呵,NAG在这里了.
00611A87 50 push eax
00611A88 55 push ebp
00611A89 51 push ecx
00611A8A FF53 04 call dword ptr ds:[ebx+4]
00611A8D 83C4 14 add esp,14
00611A90 8BCE mov ecx,esi
00611A92 E8 09FAFFFF call vsgu2_0.CLicense::setHostIds
00611A97 8BCE mov ecx,esi
00611A99 E8 72FAFFFF call vsgu2_0.CLicense::setHostName
00611A9E 8BCE mov ecx,esi
00611AA0 E8 CBFAFFFF call vsgu2_0.CLicense::setHostUser
00611AA5 8BCE mov ecx,esi
00611AA7 E8 24FBFFFF call vsgu2_0.CLicense::setHostDiskID
00611AAC 8BCE mov ecx,esi
00611AAE E8 7DFBFFFF call vsgu2_0.CLicense::setHostDisplay
00611AB3 8BCE mov ecx,esi
00611AB5 E8 D6FBFFFF call vsgu2_0.CLicense::setHostCPU
00611ABA 8BCE mov ecx,esi
00611ABC E8 2FFCFFFF call vsgu2_0.CLicense::setHostEther
00611AC1 8BCE mov ecx,esi
00611AC3 E8 88FCFFFF call vsgu2_0.CLicense::setHostIP
00611AC8 8BCE mov ecx,esi
00611ACA E8 E1FCFFFF call vsgu2_0.CLicense::setLicenseFile
......
RETN
-----005C4C2F E8 74B00400 call vsgu2_0.__security_check_cookie
----005C5EB2 E8 19FBFFFF call vsgu2_0.vsgu::initializeClassSessio>
---1003FB31 FF15 ACF40B10 call dword ptr ds:[<&vsgc2_0.vsgc::initialize>] ; vsgc2_0.vsgc::initialize
下面开始对下一个FEATURE进行License检查了.流程一样的,我就不分析了. 到此,基本上将该软件FLEXLM9.0加密的全流程跟踪一遍了.
写到这,好累好累.
回到前面留下的关键跳转(1)处,其实这里是软件判断到底需不需要对该Feature进行检查了.程序中肯定是部分软件需要部分Feature的支持了.但这里给爆破者留下来的想象空间太大了,而且太容易了.
爆破点上面都列出来了.如果你想用该软件可以参考一下了.但我负其他责任哦.
总结:爆破FlexLM加密主要应该是分析清楚其加密流程,发现重点函数,然后关键点爆破.
对于关键函数要敏感了,而且其特征要自己整理出来,这样方便下个软件的定位了。
问题:在sln翻译的" FLEXlm latest information by CrackZ"介绍到了"对于新长度的SIGN,破解者会选择对_lm_pubkey_verify()打补丁然后用自己的LM_SEED制作SIGN=许可证。然而,可以用另外一种方法,就是强制许可授权层(licensing layer)进行旧格式的SIGN=12字符的校验方式。该法仅涉及简单地对我们发现的存在于_l_n36_buf()(如上)里面的第2个坏标记处补丁。我们可以象以前那样回收到加密过的SEED并用SDK或本站可下载的Lmgryptgui制作license。该补丁的工作原理是告诉许可授权层(licensing layer)别去取_lm_pubkey_verify()的地址,_lm_pubkey_verify()会在_l_sg()之后马上就行校验。"这个办法,我没有试验成功,高手能够详细解释一下吗!!!
感谢:
学习过程中大量参考了
laoqian
sln
newsearch
的文章.
感谢看雪上所有人.
2007年4月12日
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)