翻譯FLEXlm9.2的破解教學四
翻譯第四篇 On Software Reverse Engineering - 4
Reverse Engineering, FLEXlm, IMSL
因此,我們有了兩個處理:在cmath.exe中進行檢查和在lmcrypt.exe或makekey.exe.中產生金鑰(keygen)。它們都可以產生相同的正確的許可證程式碼,但這兩個處理不是完全相同的。我們已經在前面的章節對第一個處理進行了一定深度的分析,現在按順序列出重要的呼叫連結。
1.lc_new_job() ® l_n36_buf() ® l_x77_buf()
2.lc_new_job() ® lc_init() ® l_init() ® l_sg() ® l_key() ® l_zinit()
3.lc_set_attr() ® l_set_attr() ® l_set_license_path() ® l_flush_config() ® l_init_file() ®
l_allfeat() ® l_parse_feature_line() ® oldkey() ® l_crypt_private() ® real_crypt() ®l_string_key()
4.lc_checkout() ® l_checkout() ® lm_start_real() ® l_good_lic_key() ® l_xorname()
5.lc_checkout() ® l_checkout() ® lm_start_real() ® l_good_lic_key() ® l_sg() ® l_n36_buff()
6.lc_checkout() ® l_checkout() ® lm_start_real() ® l_good_lic_key() ® l_crypt_private() ®
real_crypt() ® l_string_key()
一個很感興趣的問題是:為什麼l_sg()在第二個連結呼叫l_key()而在第五個連結呼叫l_n36_buff()?檢查程式碼摘錄,我們發現答案在於LM_OPTFLAG_CUSTOM_KEY5和 L_UNIQ_KEY5_FUNC。後者由l_x77_buf()(也就是L_SET_KEY5_FUNC) 在第一個連結中設定,因此在兩個呼叫中,l_n36_buff將非空。那麼原因就是LM_OPT_FLAG_CUSTOM_KEY5了:它在呼叫lc_init()後進行開關轉換,這就是為什麼l_key() 在第二個連結中被呼叫。有趣的是,在現在的FLEXLM版本中,l_key()是一個無用的子程式(它在引入l_n36_buff()之前用於早期的版本)。此外,它完全沒有必要在初始化階段呼叫譯碼加密種子的l_sg();那本應該在檢查時進行的。
lm_njob.c:
int lc_new_job(oldjob, l_new_job, vcode, newjobp)
{
... ...
(*L_NEW_JOB)(vendor_name, vcode, 0, 0, 0, &sign_level);
(*L_NEW_JOB)(0, 0, 0, 0, 0, 0);
if (!(ret = lc_init(oldjob, vendor_name, vcode, newjobp)))
{
(*newjobp)->options->flags |= LM_OPTFLAG_CUSTOM_KEY5;
... ...
}
return ret;
}
lm_ckout.c:
void l_sg(LM_HANDLE* job, char* vendor_id, VENDORCODE* key)
{
... ...
unsigned long x = 0x6f7330b8; /* v8.x */
if (( job->options->flags & LM_OPTFLAG_CUSTOM_KEY5) && L_UNIQ_KEY5_FUNC)
{
(*L_UNIQ_KEY5_FUNC)(job, vendor_id, key);
return;
}
l_key(vendor_id, &(key->keys[0]), keys, 4); /* Pre v6.1 style */
... ... /* 在VKEY5()中進行相同的與或操作(xor) */
}
lm_init.c:
void (*L_UNIQ_KEY5_FUNC)() = 0;
void L_SET_KEY5_FUNC( void (*f)())
{
if (!L_UNIQ_KEY5_FUNC) L_UNIQ_KEY5_FUNC = f;
}
在檢查處理的同時,我們也在金鑰產生(keygen)處理中呼叫連結。我們將使用lmcrypt.exe用於分析,因為它比makekey.exe來得更直接 (它們都執行相同的工作)。
1.lmcrypt.c!main() ® lc_init() ® l_init() ® l_sg() ® l_key() ® l_zinit()
2.lmcrypt.c!main() ® dofilecrypt() ® dofpcrypt() ® lm_crstr.c!lc_cryptstr() ® parsefeaturelist()
® l_parse_feature_line() ® oldkey() ® l_crypt_private() ® real_crypt() ® l_string_key()
3.lmcrypt.c!main() ® dofilecrypt() ® dofpcrypt() ® lm_crstr.c!lc_cryptstr() ® cryptfeaturelist()
® docryptfeat() ® lc_crypt() = l_crypt_private() ® real_crypt() ® l_string_key()
注意:對於Vendor和job的初始化,cmath.exe將呼叫lc_new_job(),(該函式)輪流呼叫lc_init();但是lmcrypt.exe將直接呼叫lc_init(),因為vendor金鑰、種子和名稱都已經包含於lmcrypt.exe中了(一起透過宏放到vendor結構中),因此僅需要初始化工作。在這兩個處理中,有對l_string_key()的兩個呼叫;在這兩種情況下,第一個返回不重要的 oldkey()號為21D5B6E8572E,僅第二個呼叫其實質。這兩個處理在呼叫l_string_key()上僅有細微的差別。基本上,對於checksum(總和檢查)比較,checkout(檢查)需要提供使用者許可證金鑰,但是keygen則不需要。但是,對於計算實際的雜亂資訊上則是相同的。
int idx = (*job->vendor) % XOR_SEEDS_ARRAY_SIZ; /* idx = V % 20 = 86 % 20 = 6 */
... ...
memset(y, 0, L_STRKEY_BLOCKSIZE); /* L_STRKEY_BLOCKSIZE = 8, in lmachdep.h */
length = (inputlen) / L_STRKEY_BLOCKSIZE;
XOR_SEEDS_INIT_ARRAY(xor_arr) /*在l_strkey.h中定義的替換表 */
... ... /* memcpy() 從輸入到newinput和其他充填(值)*/
p = newinput;
for (i = 0; i < length; i++)
{
XOR(p, y, y);/*在l_strkey.h中定義的與或(XOR)和L_MOVELONG */
if (i == 0)
{
if (!user_crypt_filter && !user_crypt_filter_gen
&& (job->flags & LM_FLAG_MAKE_OLD_KEY))
{
q = y; /*在l_privat.h中定義的SEEDS_XOR = mem_ptr2_bytes */
L_MOVELONG(code->data[0]
^((long)(job->SEEDS_XOR[xor_arr[idx][0]])<<0)
^((long)(job->SEEDS_XOR[xor_arr[idx][1]])<<8)
^((long)(job->SEEDS_XOR[xor_arr[idx][2]])<<16)
^((long)(job->SEEDS_XOR[xor_arr[idx][3]])<<24), q)
L_MOVELONG(code->data[1]
^((long)(job->SEEDS_XOR[xor_arr[idx][0]])<<0)
^((long)(job->SEEDS_XOR[xor_arr[idx][1]])<<8)
^((long)(job->SEEDS_XOR[xor_arr[idx][2]])<<16)
^((long)(job->SEEDS_XOR[xor_arr[idx][3]])<<24), q)
}
... ...
}
if (!(job->flags & LM_FLAG_MAKE_OLD_KEY) && !demo)
our_encrypt2(y);
else
our_encrypt(y); /* our_encrypt()並不涉及程式碼或工作*/
p += L_STRKEY_BLOCKSIZE;
}
if (len == L_SECLEN_SHORT) /* 在l_privat.h中,L_SECLEN_SHORT = 0x66D8B337 */
{
... ...
y[6] = y[7] = 0;
}
因為它們共享了相同的程式碼,因此為了計算相同的雜亂資訊,傳入的引數必須相同。實際的追蹤結果為:
cmath.exe:
job = 00887630, input = 0012e170, inputlen = 0x16, code = 0012ee20, len = 66d8b337, license_key = 6d5c...
[00887630] - 00000066 f... 整型;
[00887634] - 0089008e .... char *mem_ptr2;
[00887638] - a06aa84e N.j. unsigned char mem_ptr2_bytes[12]; (12是視進位制)
[0088763C] - 00c3a047 G...
[00887640] - 00660000 ..f.
[00887644] - 00000000 ....
[00887648] - 00000000 ....
[0088764C] - 00000000 ....
[00887650] - 00000000 ....
[00887654] - 54414d43 CMAT
[00887658] - 00000048 H...
[0012E170] - ab370fd2 ..7. 輸入串用於雜亂資訊,取決於FEATURE行資訊
[0012E174] - 414d4300 .CMA
[0012E178] - 88054854 TH..
[0012E17C] - 6a000113 ...j
[0012E180] - c5876e61 an..
[0012E184] - 000073d0 .s.. 總長度= 0x16 = 22,在73結束
[0012E188] - 00000000 ....
[0012EE20] - 00000004 .... 整型;
[0012EE24] - 52ed15b8 ...R 52xxxxb8, xxxx 是隨機的,在每次執行是不同的
[0012EE28] - 75cf780f .x.u 75yyyy0f, yyyy 是隨機的,在每次執行是不同的
[0012EE2C] - 7c2adb6a j.*| VENDOR_KEY1
[0012EE30] - b927f5a9 ..'. VENDOR_KEY2
[0012EE34] - 9cf311f8 .... VENDOR_KEY3
[0012EE38] - 0dbf7621 !v.. VENDOR_KEY4
[0012EE3C] - 00020009 .... FLEXlm 版本(這裡是 9.2)
[0012EE40] - 39300020 .09
[0012EE44] - 0000302e .0..
[0012EE48] - 00000000 ....
lmcrypt.exe:
job = 008C49E8, input = 0012D8D4, inputlen = 0x16, code = 004D7B48, len = 66D8B337
0x008C49E8 66 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f...............
0x008C49F8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x008C4A08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x008C4A18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0012D8D4 d2 0f 37 ab 00 43 4d 41 54 48 05 88 13 01 00 6a Ò.7«.CMATH.....j
0x0012D8E4 61 6e 87 c5 d0 73 00 00 00 00 00 00 00 00 00 00 an.ÅÐs..........
0x0012D8F4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0012D904 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x004D7B48 04 00 00 00 b8 39 c1 52 0f 54 e3 75 6a db 2a 7c ....¸9ÁR.TãujÛ*|
0x004D7B58 a9 f5 27 b9 f8 11 f3 9c 21 76 bf 0d 09 00 02 00 ©õ'¹ø.ó.!v¿.....
0x004D7B68 20 00 30 38 2e 30 00 00 c3 80 f4 83 2c c0 1c 77 .08.0..Ã.ô.,À.w
0x004D7B78 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
注意:我們在這裡處理諸如6D5C01FD71C9的非-CRO的短金鑰,它由12個ASCII字元組成表示6個十六進位制位,這也就是為什麼我們在上面的程式碼中看到“y[6] = y[7] = 0;”。除了VENDORCODE和job結構之外,所有其它引數是相等的[9],且在這兩個結構中並非所有的組成部分都是重要的。很容易勾勒出在雜亂化(hashing?)輸入串中所參與的東西為:code->data[], code->keys[] 和job->mem_ptr2_bytes[]。
我們立即複製在檢查(checkout)處理中揭示的四個vendor金鑰到lm_code.h中(並證實在記憶體資訊轉儲中),但是我們仍然缺少加密種子和神秘的VENDOR_LEY5。現在,更進一步察看n金鑰產生(keyge)處理,它在檢查(checkout)的code->data[]和job->mem_ptr2_bytes[](它的job結構是空的)中出現不同。那是為什麼呢?
#include "lmprikey.h"
#include "lmclient.h"
#include "lm_code.h"
#include "lmseeds.h"
... ...
/* 設定site_code.data = {ENCRYPTION_SEED1 ^ VENDOR_KEY5,
ENCRYPTION_SEED2 ^ VENDOR_KEY5}
site_code.keys = {VENDOR_KEY1, VENDOR_KEY2, VENDOR_KEY3, VENDOR_KEY4} */
LM_CODE(site_code, ENCRYPTION_SEED1, ENCRYPTION_SEED2, VENDOR_KEY1,
VENDOR_KEY2, VENDOR_KEY3, VENDOR_KEY4, VENDOR_KEY5);
... ...
int main(int argc, char **argv)
{
... ...
/*設定site_code.data = {ENCRYPTION_SEED1, ENCRYPTION_SEED2} */
LM_CODE_GEN_INIT(&site_code);
if (lc_init((LM_HANDLE *)0, VENDOR_NAME, &site_code, &lm_job))
{
lc_perror(lm_job, "lc_init failed");
exit(-1);
}
... ...
/*呼叫連結dofilecrypt() -> dofpcrypt() -> lc_cryptstr() */
estat |= dofilecrypt(infilename, outfilename, &site_code);
return 0;
}
這是lmcrypt.c的簡明原始碼及其自身說明。仔細注意到在lmclient.h中定義的兩個宏LM_CODE和LM_CODE_GEN_INIT。前者初始化site_code.data為與VENDOR_KEY5進行與或的加密種子(與omcode.c一致),但後者很快逆向它為原始的加密種子。我是否曾告訴你FLEXLM有很糟的程式碼型別?:)
不管怎樣,原始的加密種子和零job->mem_ptr2_bytes值被用於金鑰產生(keygen),它不同於檢查(checkout)。很自然的事情是從檢查處理複製code->data到lmseeds.h作為加密種子1和2,並重新編譯lmcrypt.exe。但它並不工作,因為在表格52xxxxB8和75yyyy0F中,code->data是隨機的,而xxxx和yyyy在每次執行中都將改變。相同的是,對於job->mem_ptr2_bytes是真實的。我們推斷,加密種子必定被模糊並儲存在vendor軟體中的兩個地方:code->data[]和job->mem_ptr2_bytes[](它們應該是關係很近的一對),因為它提供給終端使用者而原始種子需要保護。相反,lmcrypt.exe僅對vendor可獲得,因此加密種子可以以一般形式出現。
相關文章
- 翻譯FLEXlm9.2的破解教學五2004-12-10Flex
- 翻譯FLEXlm9.2的破解教學三2015-11-15Flex
- 翻譯FLEXlm9.2的破解教學一2015-11-15Flex
- Yurii談翻譯(四)怎樣翻譯更地道:翻譯如鋪路2012-01-08
- 翻譯:Zendenc
FLEXlm 7.2 破解資訊[TT]2004-12-27Flex
- Drill官網文件翻譯四Drill的效能2016-02-02
- TWAIN規範的第四章的翻譯2013-04-09AI
- Apache Storm 的歷史及經驗教訓——Nathan Marz【翻譯】2015-10-30ApacheORM
- Yurii談翻譯(五)怎樣翻譯更地道:so…that…的翻譯2012-01-08
- 《wifi加密破解論文》翻譯介紹-wifi不再安全2017-10-17WiFi加密
- 組複製官方翻譯四、MonitoringGroupReplication2019-01-15
- ollydbg破解教學之--------萬能斷點篇2015-11-15斷點
- Yurii談翻譯(九)怎樣翻譯更地道:冠詞a的翻譯2012-01-09
- Yurii談翻譯(十)怎樣翻譯更地道:最高階的翻譯2012-01-09
- 翻譯的未來:翻譯機器和譯後編譯2013-06-13編譯
- 學php之翻譯wordpress(2)2020-04-04PHP
- Yurii談翻譯(六)怎樣翻譯更地道:“as somebody said…”的翻譯2012-01-08AI
- Yurii談翻譯(十三)怎樣翻譯更地道:It is…that…句型諺語的翻譯2012-01-09
- Yurii談翻譯(十四)怎樣翻譯更地道:否定句的翻譯2012-01-09
- 一道英文數學題的翻譯2013-09-25
- dumping_oracle_blocks翻譯(一)個人翻譯,學習總結用2011-11-30OracleBloC
- 有趣的翻譯2016-06-28
- 痛苦的翻譯2007-05-16
- 有求 bing 的四大英語翻譯網站2013-07-14網站
- 翻譯2020-12-29
- 各種數學名詞的英語翻譯2007-12-01
- 遊戲製作相關---HAM教程翻譯本(四)(轉)2007-08-12遊戲
- 如何完成中文翻譯日文線上翻譯2019-09-23
- [翻譯]JavaScript的成本2019-02-27JavaScript
- Symbol 的作用[翻譯]2019-04-05Symbol
- Before的翻譯2013-07-28
- Google翻譯的API2008-03-25GoAPI
- 本人翻譯的文件2005-03-02
- 偶翻譯的小說2007-09-24
- Ubuntu安裝劃詞翻譯軟體Goldendict 單詞翻譯 句子翻譯2021-01-05UbuntuGo
- 裝模作樣學翻譯:樂譯隨想之一2012-04-11
- 人工翻譯的分類 安睿傑線上翻譯平臺2022-08-11
- Serilog文件翻譯系列(四) - 結構化資料2024-09-06