作者: laoqian [FCG]
时 间:2005-12-15
软件名称: Zendenc (FLEXlm 7.1d)
软件类别:Nolan Blender提供的经典例子
软件介绍: FLEXlm 7.1d加密
破解工具:ollydbg 1.10(FLY修改) ,w32Dasm_2002828_pll621,UltraEdit10.0,Flexlm7.2 SDK,calcseed,lmkg7,lmcryptgui,flexlm9.2
sdk的源码等
破解目的:制作无限制使用license文件
通过这篇文章我们将向你介绍如何制作FlexLm的license,并总结经验
第一部分: 废话
Zendenc这个软件是Nolan Blender提供的经典例题,crackZ或网上有下载和分析文章。玩了几个Flexlm, 想总结一下, 就拿它来开刀方便!本
文是关于7.x的,但有部分适用于8.x和9.x,甚至10.x。
第二部分: 转入正题
破解FlexLm最主要的是找到4样东西.
1. 确定版本号
2. 找vendor
3. 计算ENCRYPTION_SEED
4. 找FEATURE
有了这几个,就可以使用FlexLm SDK(如果你有)或工具做出注册机了.
btw:FlexLm SDK一般是通用兼容的的,比如7.2就可以制作7.1的,甚至有时7.1也可以制作7.2的,关键是参数设置。
1. 确定FlexLm版本号 BEHAVIOR Version
方法一:
* 用二进制编辑器,推荐使用HexWorkshop(我用UltraEdit10.0,呵呵),它的查找功能很强,特别是Find All Instances更是我最最常用的.
在查找对话框Type中选择类型Text String,Value中输入"@(#) FLEXlm v",查找,"@(#) FLEXlm v"后面的就是版本号.
【以上是tulipfan[CCG]大虾说的】
方法二:
用Flexlm SDK里的lmtools(在\flexlm\v7.1\i86_n3目录里),运行进入Utilities,点击“Browse”查找你的Flexlm加密的程序主exe或dll,
然后“find version”,在下面就会显示你的Flexlm版本,用v7.1版甚至可以看到8.3版以后,是通用的。有个别程序可能此法不行!
方法三:在反汇编以后,搜索“87654321”,在前面设断点
在Flexlm SDK里lm_code.h文件里你可以看到一下几句:
* Vendor's private seeds, -- replace with 32-bit numbers that
* you make up.
*/
#define ENCRYPTION_SEED1 0x87654321
#define ENCRYPTION_SEED2 0x12345678
/*
* FLEXlm vendor keys -- enter as received from Globetrotter.
* Changing these keys has NO impact on license files (unlike
* the ENCRYPTION_SEEDs).
*/
/*-
* Generate these keys with: lmvkey -v demo -d (+3 months) -p ALL -c DEMO
* (Use a date approx 3 months out)
*/
这说明demo的SEED1=0x87654321,SEED2=0x12345678
对应Zendenc里是:
0043391D E8 184B0400 call <jmp.&MSVCRT.memcpy>
00433922 83C4 0C add esp,0C
00433925 8D8D 40FFFFFF lea ecx,dword ptr ss:[ebp-C0] ;我们可以在这里设断点!
0043392B 51 push ecx
0043392C 8B95 30FFFFFF mov edx,dword ptr ss:[ebp-D0] ;ebp-D0地址是以后要用的!
00433932 81C2 4C010000 add edx,14C ;计算得到VENDOR地址
00433938 52 push edx ;VENDOR入栈!(ASCII "zend")
00433939 8B85 30FFFFFF mov eax,dword ptr ss:[ebp-D0]
0043393F 50 push eax
00433940 E8 95560000 call zendenc.00438FDA ;这个call就是著名的所谓7648B98E标志call!后面要进去的!!!
00433945 83C4 0C add esp,0C
00433948 81BD 44FFFFFF 214>cmp dword ptr ss:[ebp-BC],87654321 ;此处比较是否是demo的seed1,当然在此seed1已被加密!
00433952 74 0C je short zendenc.00433960 ;此处比较是否是demo的seed2,当然在此seed2已被加密!
00433954 81BD 48FFFFFF 785>cmp dword ptr ss:[ebp-B8],12345678
0043395E 75 5D jnz short zendenc.004339BD
00433960 8B8D 30FFFFFF mov ecx,dword ptr ss:[ebp-D0]
00433966 8379 14 00 cmp dword ptr ds:[ecx+14],0
0043396A 74 17 je short zendenc.00433983
我们在断点停下d ebp-c0
0012D404 00000004 ...
0012D408 E0AAA4A0 _お? 此seed1已被加密
0012D40C C0121579 y 此seed2已被加密!
0012D410 3F9F6A79 yj? 此VENDOR_KEY1已被加密!
0012D414 25DC750E u? 此VENDOR_KEY2已被加密!
0012D418 B8B046C5 牌案
0012D41C 0B2EAC4E N?
......向下拉看
0012D4A8 00000000 ....
0012D4AC 00010007 ..
0012D4B0 37300064 d.07 此处显示7.1d
0012D4B4 0000312E .1.. 7.1
0012D4B8 00000000 ....
这之后,等我们第一次走过著名的所谓7648B98E标志call,“00433940 call zendenc.00438FDA”以后,会发现被加密seed又改变了,其实
就是简单的xor,可是这个xor我们不得而知!
我们得到BEHAVIOR Version V7.1d
btw:87654321此处,在6.x版时,可以得到真seed,
参考文章“Ansoft Serenade v8.5 - Tutorial”
http://www.woodmann.com/crackz/Tutorials/Serenade.htm
I also remembered that the checks for the default seed codes (shipped with the SDK) was a good place to fish the correct
seeds, a simple disassembly search for '87654321' finds this code :-
:00429C4C CMP D, [EBP-34], 87654321 <-- Check for encryption_seed1.
:00429C53 JZ 00429C5E <-- Jump to Error.
:00429C55 CMP D, [EBP-30], 12345678 <-- Check for encryption_seed2.
:00429C5C JNZ 00429C85 <-- Good jump.
:00429C5E MOV EDI, FFFFFFA5 <-- Error Code (-91).
Routines inside Ser85.exe detect bpx type breakpoints and patching of key files, the checking code starts at 0040EFD3, here
you'll see the names of the files that are checked and the rather obvious 'PUSH 7' instructions which produce a cryptic error
message box asking you to call Ansoft for assistance. The files verified should give us a good idea where to look for other
parts of the protection, Ansoft's developers evidently tried (as is good policy) to identify possible points of attack. Using
bpmb style breakpoints we can quickly recover (what we think are valid) encryption_seed1 (0x7CB2B081) & encryption_seed2
(0x2DFE22B6).
.....
最后用方法一、二可以确定Zendenc版本号是7.1d,这一步的目的有两个,一是在lmkg.exe中生成Vendor信息时用,二是在使用FlexLm SDK制作
FlexLm的license时使用。
2. 先找FEATURE
方法一:
不用IDA,太麻烦了,既然有SDK和前人的经验,我偷个懒。我偷懒的办法,还是用安装Flexlm SDK里的lmtools!打开“Server status”项,
点击“Perform status Equiry”,你就会看到服务器端的正版license.dat内容!前提是你要配置好,而且有正版程序和license,废话!
比如显示如下:
101: SERVER main 001234567890 (我的服务器网卡号,我隐去正确的,避免麻烦啊!)
80: VENDOR adskflex port=8080
150: INCREMENT 41100ACD_2002_0F adskflex 1.000 permanent 100 VENDOR_STRING=(中间有很多参数,省略避免麻烦)SIGN=787878787878
(我隐去正确的,避免麻烦,为什么是78 ?)
关联信息: 省略
170: (overall file checksum)
看到了吗!
VENDOR adskflex
INCREMENT 41100ACD_2002_0F,这个INCREMENT其实就是FEATURE,后面那个1.000就是Version
permanent 是用户数
VENDOR_STRING= 这个也参与计算验证的
中间有很多参数也参与计算验证的,省略避免麻烦
SIGN=787878787878 我就不说了
如果你没有像我的条件就只好去看别的资料学习,很简单的!
btw:如果你的选项得当,现在你甚至就可以在客户端控制license服务器,你可以关闭license服务――慎用!!!,我曾在几次无意的操作中
关闭了license服务,结果单位的所有机器cad罢工,管理员还不知道怎么回事,只好重启服务器,那几天可忙坏了她!这是flexlm的一个bug吧
!
方法二:
用IDA+相应版本的sig+sdk,找到_lc_checkout函数,设断点,你会找到FEATURE。我采用的是7.2得sig,显示是_lp_checkout
00478043 68 00400000 push 4000
00478048 51 push ecx
00478049 6A 00 push 0
0047804B 6A 01 push 1
0047804D 68 ECDB4900 push zendenc.0049DBEC ;FEATURE版本 ASCII "1.0"
00478052 56 push esi ;FEATURE id, ASCII "Zend_Encoder"
00478053 52 push edx
00478054 E8 57DFFBFF call zendenc.00435FB0 ; lp_checkout
00478059 83C4 4C add esp,4C
0047805C 85C0 test eax,eax ; 0,jmp
0047805E 74 3F je short zendenc.0047809F
00478060 8A8424 18090000 mov al,byte ptr ss:[esp+918]
00478067 84C0 test al,al
00478069 75 12 jnz short zendenc.0047807D
0047806B 8B4424 10 mov eax,dword ptr ss:[esp+10]
0047806F 68 DCDB4900 push zendenc.0049DBDC ; ASCII "Checkout failed"一般搜索这个字符,上面的就是checkout了!
00478074 50 push eax
在00478054中断,你会看到堆栈窗口里出现了FEATURE id和版本,或者d esi。
3. 找vendor以及计算seed的关键数据
方法一同前,不说了。
方法二:
下面引用自tulipfan[CCG]:
********
“要找vendor_id就需要找到l_sg这个函数了(至于为什么要找这个函数建议看一些更基础的文章),在这儿我主要是介绍一下如何定位l_sg函数,
这个是FlexLm的一个内部使用的函数. lc_init,lc_checkout都会调用它下面是它们的调用关系,括号里面的数字是调用的次数。
a. lc_init -> l_init
b. l_init -> l_sg(1)
a. lc_checkout -> l_checkout
b. l_checkout -> lm_start_real(2)
c. lm_start_real -> l_good_lic_key(3)
d. l_good_lic_key -> l_sg(2)
从上面可以看到它们的调用关系.
我们可以通过l_sg确定vendor_id和ENCRYPTION_SEED,通过lc_checkout可以确定FEATURE
IDA通过FlexLm的sig文件可以确定上面的大部分函数,再通过他们的调用关系,很容易找到其他函数.
制作FlexLm的批处理文件和工具包可去CrackZ去下载.
最后定位到l_sg函数”
************
我们有9.2的source,我们看到lm_ckout.c中有下面一段,那几个数就是确定l_sg函数上很有用的,针对
0x7648b98e; v7.x */
0x6f7330b8; /*- v8.x,9.x*/
下面给出参考:
V7
glseed = 0x788F71D2
seedval = 0x7648B98E
V8
glseed = 0x3CDE3EBF
seedval = 0x6F73330B8
V9
glseed = 0x72346B53
seedval = 0x6F7330B8
v10
glseed = 0x5332322F
seedval = 0x6F7330B8
关于这一段,zhanzixin 有一点小小的补充。
0x7648b98e这个数字,被称为seedval的,
在版本4、5、6中是 0xa8f38730
在版本7.0-8.0c中是 0x7648b98e
在版本8.0d以后,一直没变,是0x6f7330b8。
/*-
* Also used by flexcrypt -- notify if API changes.
*/
void
l_sg(
LM_HANDLE * job,
char * vendor_id,
VENDORCODE * key) /*- l_sg means "signature vendor_key5" */
{
unsigned long keys[4];
char sig[SIGSIZE] = {'\0'};
/*- If you change this, you must change it also in utils/lmnewgen.c */
/*- unsigned long x = 0xa8f38730; v3.1 */
/*- unsigned long x = 0x7648b98e; v7.0 */
unsigned long x = 0x6f7330b8; /*- v8.x */
extern void (*L_UNIQ_KEY5_FUNC)();
unsigned long d0 = 0, d1 = 0;
int i = SIGSIZE-1;
if (( job->options->flags & LM_OPTFLAG_CUSTOM_KEY5) && L_UNIQ_KEY5_FUNC)
{
(*L_UNIQ_KEY5_FUNC)(job, vendor_id, key);
return;
}
废话少说,我们直接反汇编zendenc.exe,我们查找“7648B98E”,来到下面,好像就这么1,2处
。前人的经验就是宝贵啊,我省了很多事!
.text:00438FDA ; =============== S U B R O U T I N E ?=====================================
.text:00438FDA
.text:00438FDA ; Attributes: bp-based frame
.text:00438FDA
.text:00438FDA sub_438FDA proc near ; CODE XREF: sub_432CC4+C7Cp
.text:00438FDA ; sub_437621+B9p ...
.text:00438FDA
.text:00438FDA push ebp ====先在这个地方下断
.text:00438FDB mov ebp, esp
.text:00438FDD sub esp, 30h
.text:00438FE0 mov [ebp+var_10], 7648B98Eh ====就是这个数在确定l_sg函数上很有用
.text:00438FE7 mov [ebp+var_14], 3
.text:00438FEE mov eax, [ebp+arg_0]
.text:00438FF1 mov ecx, [eax+6Ch]
.text:00438FF4 mov edx, [ecx+1D4h]
.text:00438FFA and edx, 8000h
.text:00439000 test edx, edx
.text:00439002 jz short loc_439027 ====这个跳前面分析了,第一次肯定会跳的!第二次再来!
.text:00439004 cmp dword_49E5EC, 0
.text:0043900B jz short loc_439027
.text:0043900D mov eax, [ebp+arg_8]
.text:00439010 push eax
.text:00439011 mov ecx, [ebp+arg_4]
.text:00439014 push ecx
.text:00439015 mov edx, [ebp+arg_0]
.text:00439018 push edx
.text:00439019 call dword_49E5EC ====在这个地方下断,F8之后就是我们要的!
.text:0043901F add esp, 0Ch
.text:00439022 jmp loc_43913A
.text:00439027 ; ---------------------------------------------------------------------------
.text:00439027 loc_439027: ; CODE XREF: sub_438FDA+28j
.text:00439027 ; sub_438FDA+31j
.text:00439027 push 4
.text:00439029 lea eax, [ebp+var_28]
.text:0043902C push eax
.text:0043902D mov ecx, [ebp+arg_8]
.text:00439030 add ecx, 0Ch
.text:00439033 push ecx
.text:00439034 mov edx, [ebp+arg_4]
.text:00439037 push edx
.text:00439038 call sub_451F26
*************************
别急,先做一下准备工作:
*************************
前面我们在00433938 处可以得到VENDOR为 "zend",而0043392C处的ebp-D0是初始化VENDORkey的地方!
0043391D E8 184B0400 call <jmp.&MSVCRT.memcpy>
00433922 83C4 0C add esp,0C
00433925 8D8D 40FFFFFF lea ecx,dword ptr ss:[ebp-C0] ;我们可以在这里设断点!
0043392B 51 push ecx
0043392C 8B95 30FFFFFF mov edx,dword ptr ss:[ebp-D0] ;ebp-D0地址是以后要用的!
00433932 81C2 4C010000 add edx,14C ;计算得到VENDOR地址
00433938 52 push edx ;VENDOR入栈!(ASCII "zend")
00433939 8B85 30FFFFFF mov eax,dword ptr ss:[ebp-D0]
0043393F 50 push eax
00433940 E8 95560000 call zendenc.00438FDA ;这个call就是著名的所谓7648B98E标志call!后面要进去的!!!
00433945 83C4 0C add esp,0C
00433948 81BD 44FFFFFF 214>cmp dword ptr ss:[ebp-BC],87654321 ;此处比较是否是demo的seed1,当然在此seed1已被加密!
00433952 74 0C je short zendenc.00433960 ;此处比较是否是demo的seed2,当然在此seed2已被加密!
00433954 81BD 48FFFFFF 785>cmp dword ptr ss:[ebp-B8],12345678
0043395E 75 5D jnz short zendenc.004339BD
00433960 8B8D 30FFFFFF mov ecx,dword ptr ss:[ebp-D0]
00433966 8379 14 00 cmp dword ptr ds:[ecx+14],0
0043396A 74 17 je short zendenc.00433983
但是问题又来了,我们并没有license.dat,这就要我们做一个假的,否则第二次不会来到text:00438FDA,那就前功尽弃了!
license.dat格式我不说了看雪的书上以及很多资料说得很清楚了。
我们根据我们上面得到的正版license.dat内容,做一个假的license.dat,放在zendenc目录里下:
***************
FEATURE Zend_Encoder zend 1.0 permanent uncounted VENDOR_STRING=www.FCGchina.com \
HOSTID=ANY SIGN=787878787878 (怎么又是78 !?)
***************
因为断开网络,所以运行zendenc.exe会找不到license,我们把它指向我们的假的license.dat,当然是出错退出!经过仔细跟踪还会发现
license文件名必须是Zend_Encoder.dat!
好,工作开始:
下面我启动ollydbg 1.10调入zendenc.exe,在入口停下,直接下bp 00438FDA ,bp 00439019
F9执行,中断在00438FDA。
这时第一次来到00439002 jz short loc_439027时它是要跳过去的,注意要跳就让他跳吧。
若开始第一次时强制不跳,倒是能来到00439019,结果跟出了错误的seed1和seed2,而且多少次结果还都一样。
再次F9,我们又回来中断在00438FDA,F8单步执行,这次不跳了,直到过了00439019,暂停!
我们在命令栏下如下命令,可以看到:(可以纪录了多次的调试结果)
输入 d [esp+4] 在内存窗口看到,【长型――ASCII 转存】
**********
003983AC 646E657A zend
输入 d [esp+8] 在内存窗口看到,【长型――ASCII 转存】
****1****
0012CF98 00000004 ...
0012CF9C B68ACAC8 仁? data[0]
0012CFA0 96327B11 {2 data[1]
0012CFA4 534D01FB ?MS
0012CFA8 2D607B98 ?`-
0012CFAC B069483D =Hi
0012CFB0 67FCD8B6 敦?
0012CFB4 00000000 ....
********1************
输入d [esp] 【长型――ASCII 转存】
******2*****
00398260 00000066 f...
00398264 00F400E6 ??
00398268 B9DEDAA8 ㄚ薰 job+08
0039826C EB6E4C33 3Ln job+0c
00398270 BEF9AA16 ? job+10
********2***********
这些数据就是我们计算seed1和seed2的关键!
4. 计算ENCRYPTION_SEED
使用工具calcseed.exe,输入data[0],data[1],job+08,job+0c,job+10,VENDORname为 "zend"上述信息,计算
ENCRYPTION_SEED1 0xfa5410de
ENCRYPTION_SEED2 0xdaeca107
多次结果是一样的,注意是第二次自然来到时!
至此,分析已经基本完成,可以使用SDK写license.dat
第三部分: 制作license.dat
方法一:
我们得到数据如下:
Feathure Zend_Encoder
FeathureVersion 1.0
ENCRYPTION_SEED1 0xfa5410de
ENCRYPTION_SEED2 0xdaeca107
VENDOR Zend
BEHAVIOR Version V7.1d
使用lmkg.exe,选择version 7.0,在vendor_id输入"Zend"得到:
/* Version 7 keys */
#define VENDOR_KEY1 0xdb5c129b
#define VENDOR_KEY2 0x7c9d919a
#define VENDOR_KEY3 0x1ee3b786
#define VENDOR_KEY4 0x01745090
#define VENDOR_KEY5 0x2c2dd7f7
#define CRO_KEY1 0xdf7c1093
#define CRO_KEY2 0x3abff31c
#define VENDOR_NAME "Zend"
按照上面的信息,编辑\flexlm\v7.2\machind\lm_code.h
**********************************
#ifndef LM_CODE_H
#define LM_CODE_H
#include "lm_cro.h"
/*
* Pick an LM_STRENGTH.
*
* If you're not using CRO public-key, then leave this as
* LM_STRENGTH_DEFAULT.
* If you're upgrading from pre-v7.1, and want no changes,
* set this to LM_STRENGTH_LICENSE_KEY.
*/
#define LM_STRENGTH LM_STRENGTH_DEFAULT /*注意12位的SIGN要这个参数 */
/*
* LM_STRENGTH Options are
* LM_STRENGTH_DEFAULT Public key protection unused
* Use SIGN= attribute
* sign length = 12
* Public key:
* LM_STRENGTH_113BIT, LOW sign length = 58 chars
* LM_STRENGTH_163BIT, MEDIUM sign length = 84 chars
* LM_STRENGTH_239BIT, HIGH sign length = 120 chars
*
* Use pre-v7.1, non-CRO
* LM_STRENGTH_LICENSE_KEY Use pre-v7.1 license-keys.
* Doesn't use SIGN= attribute.
*/
/*
* Vendor's private seeds, -- replace with 32-bit numbers that
* you make up.
*/
#define ENCRYPTION_SEED1 0xfa5410de /*我们找到的SEED1 */
#define ENCRYPTION_SEED2 0xdaeca107 /*我们找到的SEED2 */
#define ENCRYPTION_SEED3 0x22222222 /*没用,不变 */
#define ENCRYPTION_SEED4 0x32323232 /*没用,不变 */
/*
* FLEXlm vendor keys -- enter as received from Globetrotter.
* Changing these keys has NO impact on license files (unlike
* the ENCRYPTION_SEEDs).
*/
/*-
* Generate these keys with: lmvkey -v demo -d (+3 months) -p ALL -c DEMO
* (Use a date approx 3 months out)
*/
#define VENDOR_KEY1 0xdb5c12db /*我们算出的 */
#define VENDOR_KEY2 0x7c9d91ba
#define VENDOR_KEY3 0x1ee3b7c6
#define VENDOR_KEY4 0x017450b0
#define VENDOR_KEY5 0x0c2dd7f7 /*我们算出的 */
#define CRO_KEY1 0xdf7c10d3 /* Used to enable CRO -- turned off by default */
#define CRO_KEY2 0x3abff33c /* Be sure to reset LM_STRENGTH above if
CRO_KEY is non-zero */
/*
* FLEXlm vendor name. Leave as "demo" if evaluating FLEXlm. Otherwise
* set to your vendor daemon name.
*/
#define VENDOR_NAME "Zend" /*我们找到的VENDOR */
/*
* Older customers with newer versions may want to set
* behavior defaults to previous version, though this is usually
* discouraged. Behaviors can be changed individually using
* LM_A_xxx in the flexible API. New customers should use the
* current default, as set below
*
* Valid settings include:
* LM_BEHAVIOR_V2, _V3, _V4, _V5, _V5_1, _V6, _V7, _V7_1
*/
#define LM_VER_BEHAVIOR LM_BEHAVIOR_V7_1
#endif /* LM_CODE_H */
**************************************
编辑好了,存盘,OK
打开\flexlm\v7.2\i86_n3\genlic.exe开始我们的制作吧
看附图:
1.basic窗口内填好Feathure,选择permanent打勾,选择run anywhere
2.进入advance窗口,version内填FEATURE的Version1就是.000,Vendor info填上Cracked by laoqian[FCG]
3.其余不改了,回到basic窗口,点击make license,然后save你的license.dat文件
大功告成!
你可以制作各种限制条件的license.dat,随你便了,我做的是无限制!
本
方法二:
用lmcryptgui可以制作成功以上的license!
我们得到数据如下:
Feathure Zend_Encoder
Feathure Version 1.0
ENCRYPTION_SEED1 0xfa5410de
ENCRYPTION_SEED2 0xdaeca107
VENDOR Zend
BEHAVIOR Version V7.1d
1.手动找到vendor,seed1,seed2,FEATURE和版本7.1,7.2....,8.x等
2.填写vendor,seed1,seed2,和BEHAVIOR Version 7等,注意没有0x
3.执行,生成一个exe文件.
4.制作一个假的license.dat文件,格式参考其他资料了,一定要正确的格式,只有sign=是随便写一个!
5.把这个假的license.dat文件往那个生成的exe文件上一拖放,及自动生成正确的license.dat文件,sign已经是正确的了,前提是你前面得到的
vendor,seed1,seed2,FEATURE和版本等都是正确的!
附license.dat的写法:
FEATURE xxxxx VENDORxxx 1.000 permanent uncounted \
VENDOR_STRING=WWW.FCGCHINA.COM HOSTID=ANY ISSUER="by \
laoqian[FCG] 献给自由的FCG" ISSUED=11-NOV-2004 \
SIGN=123456789012
其中“xxxxx ”FEATURE这个需要你手动找,“VENDORxxx”版本 Feathure Version“1.000 ”也需要你手动找确定,不过Feathure Version可
以随便呢,我试了几个都可以运行的。
SIGN=123456789012随便填写12位16进制的数。其余一样。
license.dat文件格式根据版本不一样,以上是flexlm7.1版本之后的格式。
flexlm7.1之前的格式,没有SIGN=,而且位置在前面。
又说明:VENDOR_STRING,ISSUER,ISSUED可以不要的 。
btw:这个的license文件名必须是Zend_Encoder.dat,且必须放在zendenc.exe同目录里!zendenc.exe程序在DOS窗口运行!
FEATURE Zend_Encoder zend 1.0 permanent uncounted VENDOR_STRING=blah \
HOSTID=ANY SIGN=B6457F8A4618
第四部分: 原创发挥
分析得知flexlm9.22。sdk的源码
我们在flexlm9.22 sdk的源码里看到l_privat.h
*-
* -------------------------------------------------------------
* license-key-length stuff
*/
#define LM_OPTFLAG_LKEY_LONG 0x800 /* default False */
#define L_SECLEN_SHORT 0x66D8B337
#define L_SECLEN_LONG 0x289BEB8A
#define L_SECLEN_SET_LONG job->options->flags |= LM_OPTFLAG_LKEY_LONG; \
job->options->sf = L_SECLEN_LONG;
#define L_SECLEN_SET_SHORT job->options->flags &= ~LM_OPTFLAG_LKEY_LONG; \
job->options->sf = L_SECLEN_SHORT;
#define L_SECLEN_OK (((job->options->flags & LM_OPTFLAG_LKEY_LONG) && \
(job->options->sf == L_SECLEN_LONG)) || \
(job->options->sf == L_SECLEN_SHORT))
0x66D8B337是license-key-length 的一个标志,估计是12位sign!
0043C545 25 FF000000 and eax,0FF
0043C54A 25 FF000000 and eax,0FF
0043C54F A2 41E64900 mov byte ptr ds:[49E641],al
0043C554 C605 47E64900 00 mov byte ptr ds:[49E647],0
0043C55B 8A15 47E64900 mov dl,byte ptr ds:[49E647]
0043C561 8815 46E64900 mov byte ptr ds:[49E646],dl
0043C567 C785 74FEFFFF 08000000 mov dword ptr ss:[ebp-18C],8
0043C571 817D 18 37B3D866 cmp dword ptr ss:[ebp+18],66D8B337 ;就在这里断下!走到这看看!
0043C578 75 0F jnz short zendenc.0043C589
0043C57A 8B85 74FEFFFF mov eax,dword ptr ss:[ebp-18C]
输入d 49E641 【长型――ASCII 转存】可以看到如下:
0049E63D B6000000 ...
0049E641 468A7F45 E?
0049E645 EE000018 ..
这是看到我的SIGN=B6457F8A4618,再看上面是什么B6+“468A7F45”+18!其中“468A7F45”低位在前的原则,你发现原来明码在这里!
怎么找到这里的0043C571?
0043C6D0 83BD 8CFEFFFF 00 cmp dword ptr ss:[ebp-174],0
0043C6D7 74 2A je short zendenc.0043C703
0043C6D9 8B95 78FEFFFF mov edx,dword ptr ss:[ebp-188]
0043C6DF 33C0 xor eax,eax
0043C6E1 8A82 40E64900 mov al,byte ptr ds:[edx+49E640]
0043C6E7 50 push eax
0043C6E8 8B8D 78FEFFFF mov ecx,dword ptr ss:[ebp-188]
0043C6EE 51 push ecx
0043C6EF 8D95 30FEFFFF lea edx,dword ptr ss:[ebp-1D0]
0043C6F5 52 push edx
0043C6F6 8B45 08 mov eax,dword ptr ss:[ebp+8]
0043C6F9 50 push eax
0043C6FA FF95 8CFEFFFF call dword ptr ss:[ebp-174]
0043C700 83C4 10 add esp,10
0043C703 8B8D 30FEFFFF mov ecx,dword ptr ss:[ebp-1D0]
0043C709 81E1 FF000000 and ecx,0FF
0043C70F 8B95 78FEFFFF mov edx,dword ptr ss:[ebp-188]
0043C715 33C0 xor eax,eax
0043C717 8A82 40E64900 mov al,byte ptr ds:[edx+49E640] ;看到49E640地址了吗?我们去那里下内存断点吧
0043C71D 3BC8 cmp ecx,eax ; eax=真sign的一位和ecx=假sign的一位比较
0043C71F 74 04 je short zendenc.0043C725 ;比较
0043C721 33C0 xor eax,eax ;不对就拜拜了!
0043C723 EB 26 jmp short zendenc.0043C74B
0043C725 ^ E9 6BFEFFFF jmp zendenc.0043C595 ;再比较下一位!
0043C72A 8B4D 18 mov ecx,dword ptr ss:[ebp+18]
怎么找到这里的0043C71D? 因为我们要读假license文件,读出假sign要在内存存着,我们在那里下内存断点(硬件断点),一步一步跟到这
里,呵呵,需要耐心!不过也不难找,第二次进入“7648B98E”的call,之后慢慢跟就来到了,中间过程不再罗嗦了!
现在,你只要查找66D8B337,看到上面上面的类似代码,下断吧!此发适用于8.x,9.x可能也适用!因为66D8B337没有变!
就是说我们可以找明码,至少在0043C71D处可以一位一位找到!前提,你做了一个正确的假license文件,而且路径正确,还要解决一下anti(
如果有的话)
第五部分:一个问题:
就是我们在跟踪某些flexlm加密的软件时,有时不会来到类似00439019 call dword_49E5EC的地方,应该是2次来到这个地址所在的call,一般
第一次跳过00439019 call dword_49E5EC,第二次才真正进入这个00439019,此时才能得到文中那些值;问题是很多第二次就不来了!直接出
错退出,即使是假licese文件格式参数正确(除了sign以外),也不过来第二次,因此无法得到需要的值,强制跳来是不行的!遇到此问题,
如何解决呢?一般此情况出现是,关键call断点在dll中!个人感觉是license文件名或路径不对,或者有anti和crc校验,再或者是ecc作怪!此问题需要有心之人来解决!
注:经过朋友提示,发现出现以上现象,基本上是软件使用了自定义检测函数来检测license文件,flexlm提供接口的!
第六部分: 感谢
CrackZ
Nolan Blender
Oleh Yuschuk
tulipfan[CCG]
allenzhu[CCG]
zhanzixin
FCG的同仁
和所有看学论坛上的朋友们!
[课程]FART 脱壳王!加量不加价!FART作者讲授!