貼一篇不完整的――從SemCAD1.4的暴破談FlexLM 7.2保護的破解 (10千字)
軟接縫的弱點――從SemCAD1.4的暴破談FlexLM 7.2保護的破解
Passion拋磚引玉
2001年底
(感謝看雪提供的FlexLM
7.2的SDK和其中的SIG檔案)
早聽說過高手關於狗加密弱點的論述,說許多作者過於相信狗的保護能力,在程式的保護部分中沒有作過多的手腳,甚至只讀狗驗證一次即透過,狗的多種加密與保護本領沒有得到利用。遺憾的是運氣不好,這種“接縫”的弱點我偏偏沒有碰到過。不過最近在對付Flexible
Licence Manager保護的軟體的時候,倒是領會了一點點這個“接縫”的弱點,這裡寫出來讓大夥兒“斧正斧正”,算是拋磚引玉,嘿嘿。^_^
Flexible
Licence Manager的保護不同於加殼,後者是對軟體產品的可執行檔案進行處理,而前者提供的是原始碼的形式,需要開發者手工將加密保護程式碼加入產品中再重新編譯。這種原始碼保護比加殼在形式上更復雜,至少不存在對這種保護“脫殼”的說法。據我的一點點見識,FlexLM所保護的軟體大多是CAD等或者其他大型一點的工程軟體,像我初學的時候對付的Rational
Rose 2000(當然,當時沒破出來,^_^)和最近看到的SemCAD便是這樣。
FlexLM同樣有其弱點。SDK中即使原始碼不公開,其加密介面也算是公開的,只是不同軟體中使用的加密種子和Features等引數不同,因此Licence檔案也就不通用,不是隨便生成一個冒牌貨就能矇混過關。
用FlexLM進行保護,需要在自己的原始碼中加入FlexLM帶的各種庫和標頭檔案,然後在需要保護的部分加保護程式碼,FlexLM 7.2的SDK文件中的例子程式是這樣的:
#include "lmpolicy.h"
LP_HANDLE *lp_handle;
/*...*/
if (lp_checkout(LPCODE, LM_RESTRICTIVE|LM_MANUAL_HEARTBEAT,
"myfeature","1.0", 1, "license.dat", &lp_handle))
{
fprintf(stderr, "Checkout
failed: %s",
lp_errstring(lp_handle));
exit(-1);
/* FlexLM校驗出錯 */
}
/*
*
檢驗透過,執行程式。
*/
/*...*/
/*
*
校驗完畢,釋放Licence佔用的資源。
*/
lp_checkin(lp_handle);
既然正兒八經的文件裡頭是這麼指導的,那麼有幾個軟體的保護程式碼會和這裡的流程不同?倘若找到了呼叫lp_checkout的地方再人為修改掉返回值,那麼FlexLM的保護就算被暴力砍掉了,不管lp_checkout裡面演算法多複雜都沒用。
(IDA中載入FLEXLM7.2 SDK的SIG檔案,反SEMCad.exe,18M,費了半個上午、一箇中午加一個下午。)
反出來的程式碼中有這麼一段:
.text:006A19E4
push offset a1_4 ; "1.4"
.text:006A19E9
push offset aSemcad_core
; "SEMCAD_CORE"
.text:006A19EE
push eax
.text:006A19EF
push edx
.text:006A19F0
call sub_69DCE0
.text:006A0210
push offset a1_4
; "1.4"
.text:006A0215
push offset aSemcad_gui ; "SEMCAD_GUI"
.text:006A021A
push eax
.text:006A021B
push edx
.text:006A021C
call sub_69DCE0
(這裡sub_69DCE0大概是初始化。暴露了Features是"SEMCAD_GUI"和"SEMCAD_CORE")
lp_checkout函式的一般呼叫形式是:
lp_checkout(LPCODE, policy, feature, version,
1, path, &lp)
正巧對應到程式中的這段程式碼:
.text:0069DDDB
push esp
.text:0069DDDC
push eax
// lp地址
.text:0069DDDD
push edx
// Licence檔案路徑
.text:0069DDDE
push 1
// 就是那個1
.text:0069DDE0
push ecx //
Feature版本地址
.text:0069DDE1
push ebx
// Feature地址
.text:0069DDE2
push 0A00h
// policy
.text:0069DDE7
push offset off_1409940 // LPCODE地址
.text:0069DDEC
call _lp_checkout
//.text:00841820處是_lp_checkout的地址。
.text:0069DDF1
add esp, 20h
.text:0069DDF4 test
eax, eax
.text:0069DDF6
jnz loc_69E618
再看看loc_69E618:嘿嘿!
.text:0069E618 loc_69E618:
; CODE XREF: sub_69DCE0+116j
.text:0069E618 lea
ecx, [ebp+var_94]
.text:0069E61E
lea eax, [ebp+var_84]
.text:0069E624
push eax
.text:0069E625 push
offset aLicenseCheckFa ;
"License check failed: "
這裡是多麼的明顯哇。
.text:0069ddec處呼叫_lp_checkout。
.data1:015DB960 aLicense_dat
db '\license.dat',0 ; DATA XREF: sub_69DCE0+60o
.data1:015DB960
; sub_6A1940+45o
因此,要暴力解決SemCAD,只需要把.text:0069DDF4處的test eax,eax和jnz loc_69e618改為mov eax,0和三個nop即可。
_________________________________________________________________________________
如果要跟蹤出正確的Key和Seed以生成永久Licence檔案,可以從lp_checkout的引數處分析:
lp_checkout(LPCODE, policy, feature, version, 1, path, &lp)
#define
LPCODE &_lpcode 所以第一個引數是一個叫_lpcode變數的地址。
static LPCODE_HANDLE _lpcode
= { &lp_code,
#if defined (WINNT) && defined(FLEXLM_DLL)
VENDOR_NAME
#else
0
#endif
};
這裡定義了_lpcode變數,它是一個靜態的結構,其第一個屬性是一個叫lp_code變數的地址。
#if defined (WINNT) && defined(FLEXLM_DLL)
LM_CODE(lp_code,
ENCRYPTION_SEED1, ENCRYPTION_SEED2, VENDOR_KEY1,
VENDOR_KEY2,
VENDOR_KEY3, VENDOR_KEY4, VENDOR_KEY5);
// 這裡其實也就是定義一個VENDERCODE型的變數lp_code,具體見下一個宏定義。
#else
static VENDORCODE lp_code;
#endif
// 到這裡為止,不管條件如何,總歸定義了一個全域性變數lp_code
#define LM_CODE(name, x, y, k1, k2, k3, k4, k5) \
static
VENDORCODE name = \
{ VENDORCODE_6, \
{ (x)^(k5), (y)^(k5) }, \
{
(k1), (k2), (k3), (k4) }, \
{0},
\
{0}, \
LM_STRENGTH,
\
0, \
FLEXLM_VERSION,
\
FLEXLM_REVISION, \
FLEXLM_PATCH, \
LM_VER_BEHAVIOR, \
CRO_KEY1, \
CRO_KEY2 \
}
這裡常數VENDORCODE_6的值是4,因為有一句#define
VENDORCODE_6 4
VENDORCODE結構定義如下:
#define
VENDORCODE VENDORCODE6
// 這裡說明VENDORCODE其實就是VENDORCODE6型的結構
下面是核心VENDORCODE6結構的定義:
typedef struct vendorcode6 {
short type; /* Type of structure
*/
unsigned long data[2];
/* 64-bit code 放兩個ENCRYPTION_SEED和VENDOR_KEY5異或後的數值*/
unsigned
long keys[4]; /* 放四個VENDOR_KEY*/
#define LM_PUBKEYS 3
#define LM_MAXPUBKEYSIZ 40
/*
*
pubkey is for both the public and private keys
* The public
key goes here when authenticating
*
the private key when generating licenses
*/
int pubkeysize[LM_PUBKEYS];
unsigned
char pubkey[LM_PUBKEYS][LM_MAXPUBKEYSIZ];
int pubkeyinfo1;
int (*pubkey_fptr)();
short flexlm_version;
short flexlm_revision;
char
flexlm_patch[2];
#define LM_MAX_BEH_VER 4
char behavior_ver[LM_MAX_BEH_VER
+ 1];
unsigned long crokeys[2];
} VENDORCODE6, *VENDORCODE_PTR;
// 以上定義了VENDORCODE型也就是VENDORCODE6的結構
(這裡defined裡頭是根據開發平臺上的條件定義的,被保護軟體採用的是何種define可根據軟體本身適應的平臺、是否使用了FLEXLM的DLL等來稍微確定一下。)
現在顆顆珠子終於串到一起來了。
從呼叫實現過程上來說,lp_checkout傳入的第一個引數是一個地址,根據這個地址找到一個指向的記憶體區域,該區域是LPCODE_HANDLE型結構,變數名為
_lpcode,它的第一個屬性還是一個地址,指向lp_code結構(第二個屬性不是一個不相干的數便是0,因此不用管了)。所以,將lp_checkout傳入的第一個引數進行二次定址便能找到lp_code結構,該結構的第一個部分是type,從第二個部分開始的24個位元組也就是6個DWord分別儲存了兩個ENCRYPTION_SEED和VENDOR_KEY5異或後的數值加上四個VENDOR_KEY。
由於變數是自左至右推入堆疊的,因此程式中最近的一個push便是LPCODE引數:
.text:0069DDE7
push offset off_1409940
.text:0069DDEC call
_lp_checkout
由此可知,地址1409940處是LPCODE_HANDLE結構,1409940處的值在本程式中是1552260,它是VENDORCODE6結構的地址。
值得注意的是,根據FlexLM SDK的宣告,該處是存放一個VENDORCODE6結構,但並沒規定呼叫_lp_checkout前此結構必須要填充必要的數值。事實上剛進入_lp_checkout的時候該記憶體區域全是0,VendorKey等數值是_lp_checkout內部才進行填充的,如下:
_lp_checkout內部:
.text:00841820
push ebp
.text:00841821
mov ebp, esp
.text:00841823
sub esp, 0E4h
.text:00841829 mov
[ebp+var_68], 0
.text:00841830
mov [ebp+var_C], 0
.text:00841837
mov [ebp+var_10], 0
.text:0084183E mov
eax, [ebp+arg_18]
.text:00841841
mov dword ptr [eax], offset unk_157D6B8
.text:00841847 lea
ecx, [ebp+var_5C]
.text:0084184A
push ecx
.text:0084184B
mov edx, [ebp+arg_0]
.text:0084184E
mov eax, [edx]
.text:00841850 push
eax
.text:00841851
push 0
.text:00841853
push 0
.text:00841855
call _lc_new_job
這裡呼叫完_lc_new_job後,EAX所指的區域(也就是VendorCode結構所在地)才被填入兩個加密Seed和四個Key。其值如下:
5E51FD8:
04 00 00 00 A2 0A BD 51 84 0F BE CC FA FE 77 FF
32 46 AC C8 CF DF D0 35 F8 AD 1E 83
倒序後:
00000004 51BD0AA2 CCBE0F84
FAFE77FF C8AC4632 35D0DFCF 831EADF8
這裡剛好對應到:
static VENDORCODE
name = \
{ VENDORCODE_6, \ // 其實就是一個4。
{ (x)^(k5), (y)^(k5)
}, \
{ (k1), (k2),
(k3), (k4) }, \
……
(下面的不管了)
所以可知:
VENDOR_KEY1 0xFAFE77FF
VENDOR_KEY2 0xC8AC4632
VENDOR_KEY3 0x35D0DFCF
VENDOR_KEY4 0x831EADF8
VENDOR_KEY5 0x0 //還不知道,^_^
寫到這裡,本人水平有限,在跟蹤下面的程式碼過程中始終找不到第五個Key的校驗處,也就沒法子完成這篇文章,請高手指教指教。
――――――――――――――――――――――――――――――――――――――
下面是另外一些有用的定義:
typedef struct _lp_handle {
char feature[MAX_FEATURE_LEN
+ 1];
char lickey[MAX_CRYPT_LEN + 1];
#ifdef LM_INTERNAL
long last_failed_reconnect;
long
*recent_reconnects;
int num_minutes;
LM_HANDLE
*job;
int policy;
#endif /* LM_INTERNAL */
}
LP_HANDLE, FAR * LP_HANDLE_PTR;
typedef struct _lpcode_handle {
VENDORCODE * code;
char *
vendor_name;
} LPCODE_HANDLE;
VENDORCODE
vendorkeys[] = { /* Possible keys for vendor
daemons */
{ VENDORCODE_5,
ENCRYPTION_SEED1^VENDOR_KEY5, ENCRYPTION_SEED2^VENDOR_KEY5,
VENDOR_KEY1, VENDOR_KEY2, VENDOR_KEY3,
VENDOR_KEY4,
{0}, {0}, LM_STRENGTH,
0,
FLEXLM_VERSION, FLEXLM_REVISION,
FLEXLM_PATCH,
LM_BEHAVIOR_CURRENT,
{CRO_KEY1, CRO_KEY2}},
};
相關文章
- 翻譯:Zendenc
FLEXlm 7.2 破解資訊[TT]2004-12-27Flex
- 硬碟保護卡的破解 (轉)~~~~ (2千字)2001-11-23硬碟
- winrar2.71的破解和對暴破的一點想法 (4千字)2001-04-16
- 請看小弟KeyFile保護的破解 (7千字)2001-02-01
- 同學翻譯的一篇FlexLm文章 (9千字)2003-03-31Flex
- 一個簡單的keyfile保護的破解 (3千字)2001-06-15
- 貼個程式的smc破解。 (1千字)2001-09-24
- 關於幾個簡單遊戲的CD保護破解。 (3千字)2001-01-05遊戲
- 談談VB程式的破解 (5千字)2002-10-28
- 硬碟保護卡破解--小哨兵篇 (1千字)2002-06-16硬碟
- 再貼一篇cd-chcek破解譯文 (4千字)2000-08-27
- 破解EXCLE保護2010-06-05
- VB黑客程式的暴破(修改)一例 (9千字)2003-02-06黑客
- 破文一篇:易經八卦占卜程式7.0的破解(高手莫入) (8千字)2001-08-31
- 轉貼一篇:FlashFXP v1.4.1 build 823 的脫殼與破解 (16千字)2001-12-30UI
- 翻譯FLEXlm9.2的破解教學四2004-12-08Flex
- 翻譯FLEXlm9.2的破解教學五2004-12-10Flex
- 翻譯FLEXlm9.2的破解教學三2015-11-15Flex
- 翻譯FLEXlm9.2的破解教學一2015-11-15Flex
- 談談保護敏感資料的最佳實踐2023-10-31
- 一個CrackMe的破解 *KeyFIle保護* (教你如何獲得
KeyFile) (5千字)2001-02-06
- 談談如何使用加殼保護自己的軟體不被常用方法脫殼(2千字)2000-10-10
- 貼一篇破解過程,本想作為加入BCG的第三篇.但: (2千字)2001-08-09
- 硬碟保護卡的原理分析 (2千字)2015-11-15硬碟
- 轉載一篇破解教程(LeapFTP) (10千字)2001-03-29FTP
- 轉貼 Ronnier 的 AcqURL 5.1 註冊黑名單的破解 (7千字)2001-05-14
- I am Back :) 貼個安裝程式的破解 (6千字)2003-04-06
- 轉貼:破解時間限制的老文章(一) (2千字)2000-10-23
- 轉貼:破解時間限制的老文章(二) (2千字)2000-10-23
- 反射破壞單例的私有建構函式保護2019-01-07反射單例函式
- 我的第一篇破文,獻給看學學院的!^_^高手免進! (10千字)2015-11-15
- 轉一篇比較簡單的installshiled的破解 (2千字)2001-05-14
- 從000webhost空間被黑談使用免費空間的自我保護2015-11-04Web
- 初學者請進(一篇破解javagirl的心得) (2千字)2000-05-09Java
- 應妖二妖二的要求,貼上SHOWURL的破解過程。 (11千字)2001-05-05
- win10 保護眼睛的方法 win10 保護眼睛怎麼設定2020-10-05Win10
- Mac下面的SecureCRT(附破解方案) 更新到最新的7.2的破解方案2018-01-16MacSecurecrt
- 破解Word檔案密碼保護的簡單方法(轉)2007-08-12密碼