FolderView註冊部分的計算 (13千字)

看雪資料發表於2001-05-27

控制元件名稱:FolderView  3.0
軟體授權:共享軟體
下載地址:http://www.filelibrary.com:8080/cgi-bin/registered/download/New_Files/n/150/fldrvw30.zip
          該站點雖然免費下載,但需要密碼,因此需要先註冊一下
          http://www.ssware.com/fldrview/fldrvw30.zip    到該站點下載時,需要代理才能下載
控制元件簡介:FolderView is an ActiveX control that behaves like the left pane of Windows Explorer, showing all the files and folders on the system. Some of its features include context menus for items, the ability to execute shell commands, and automatic updating.
目標程式:FldrView.ocx,81408 bytes
破解工具:W32Dasm白金版,IDA Pro 4.15,Caspr v1.012
說明:本人想用VB編一個程式,需要用到只取得資料夾名稱的控制元件,而VB中的Dirlist控制元件只能顯示當前驅動器的資料夾,必須結合DriveList控制元件,但這樣用起來又太不方便了,然人感覺太彆扭,於是上網搜尋,奮戰了3個多小時,終於找到這兩個滿意的,確實比微軟的那個強,但都需要註冊,既然沒有條件進行註冊,那麼就只好Crack了^_^
這個控制元件同樣適用於Delphi、VC,用FI檢視,判別不出來(我的FI有點老),估計是Aspack壓縮,用Caspr v1.012成功去殼,再用FI檢視,VC++6.0編的,這回可以用W32Dasm和IDA了,閒話少說,開始幹,等等,忽然想到,W32Dasm對MFC函式支援不好,因此這回想用IDA試試,但用IDA反彙編後,還是出現了一個問題,輸入註冊碼和顯示註冊是否成功部分並沒有顯示出來,而W32Dasm則很容易地顯示出來了,以前沒怎麼用過IDA,不知道怎麼把這段程式碼改成彙編格式,經過一段探索之後,終於解決,方法是跳到10006E99,從選單中選擇Edit-->Functions-->Create Function即可,下面為IDA反彙編的結果

.text:10006E99 sub_10006E99    proc near              ; DATA XREF: .rdata:1000AB74
.text:10006E99                push    esi
.text:10006E9A                mov    esi, ecx
.text:10006E9C                push    1
.text:10006E9E                call    ?UpdateData@CWnd@@QAEHH@Z ; CWnd::UpdateData(int)
.text:10006EA3                mov    eax, [esi+68h]
.text:10006EA6                cmp    dword ptr [eax-8], 0
.text:10006EAA                jz      short loc_10006F17
.text:10006EAC                mov    ecx, [esi+64h]
.text:10006EAF                cmp    dword ptr [ecx-8], 0
.text:10006EB3                jz      short loc_10006F17
.text:10006EB5                push    eax
.text:10006EB6                push    offset aUsername ; "Username"
.text:10006EBB                call    sub_10006917    ====> Username填入到登錄檔中
.text:10006EC0                push    dword ptr [esi+64h]
.text:10006EC3                push    offset aRegcode ; "Regcode"
.text:10006EC8                call    sub_10006917    ====> Regcode填入到登錄檔中
.text:10006ECD                mov    ecx, [esi+60h]
.text:10006ED0                add    esp, 10h
.text:10006ED3                push    1
.text:10006ED5                call    ?SetModifiedFlag@COleControl@@QAEXH@Z ; COleControl::SetModifiedFlag(int)
.text:10006EDA                mov    eax, [esi+64h]  ====> "Regcode"
.text:10006EDD                mov    ecx, [esi+68h]  ====> "Username"
.text:10006EE0                push    eax
.text:10006EE1                push    ecx
.text:10006EE2                call    sub_10006958        ====> 註冊碼的計算部分,見後面的分析
.text:10006EE7                pop    ecx
.text:10006EE8                test    eax, eax            ====> eax為旗標
.text:10006EEA                pop    ecx
.text:10006EEB                jz      short loc_10006F09  ====> 等於0則註冊碼錯誤
.text:10006EED                push    40h
.text:10006EEF                push    offset aRegistrationSu ; "Registration successful"
.text:10006EF4                push    offset aThankYouForReg ; "Thank You for registering FolderView Ac"...
.text:10006EF9                mov    ecx, esi
.text:10006EFB                call    ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint)
.text:10006F00                mov    ecx, esi
.text:10006F02                call    ?OnOK@CDialog@@MAEXXZ ; CDialog::OnOK(void)
.text:10006F07                pop    esi
.text:10006F08                retn
.text:10006F09
.text:10006F09 loc_10006F09:                          ; CODE XREF: sub_10006E99+52j
.text:10006F09                push    10h
.text:10006F0B                push    offset aInvalidRegistr ; "Invalid registration code"
.text:10006F10                push    offset aInvalidRegcode ; "Invalid Regcode. Please enter the corre"...
.text:10006F15                jmp    short loc_10006F23
.text:10006F17
.text:10006F17 loc_10006F17:                          ; CODE XREF: sub_10006E99+11
.text:10006F17                                        ; sub_10006E99+1A
.text:10006F17                push    10h
.text:10006F19                push    offset aEnterInformati ; "Enter information"
.text:10006F1E                push    offset aPleaseEnterThe ; "Please enter the username and registrat"...
.text:10006F23
.text:10006F23 loc_10006F23:                          ; CODE XREF: sub_10006E99+7C
.text:10006F23                mov    ecx, esi
.text:10006F25                call    ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint)
.text:10006F2A                pop    esi
.text:10006F2B                retn

int __cdecl sub_10006958(int,int);
.text:10006958 sub_10006958    proc near    ; CODE XREF: .text:10004249  .text:10004498
.text:10006958                              ; 因為IDA沒有將10006E99反編譯出來,故這裡程式碼參考沒有列出來
.text:10006958 var_160        = qword ptr -160h
.text:10006958 var_158        = qword ptr -158h
.text:10006958 var_14C        = byte ptr -14Ch
.text:10006958 var_20          = qword ptr -20h
.text:10006958 var_18          = qword ptr -18h
.text:10006958 var_10          = qword ptr -10h
.text:10006958 var_8          = qword ptr -8
.text:10006958 arg_0          = dword ptr  8    ====> "Username"
.text:10006958 arg_4          = dword ptr  0Ch  ====> "Regcode"
.text:10006958
.text:10006958                push    ebp
.text:10006959                mov    ebp, esp
.text:1000695B                sub    esp, 14Ch
.text:10006961                fld    ds:dbl_1000A900    ====> 雙擊此處可知dbl_1000A900=56
.text:10006967                push    esi
.text:10006968                mov    esi, [ebp+arg_0]
.text:1000696B                fstp    [ebp+var_18]
.text:1000696E                fldz
.text:10006970                push    esi
.text:10006971                fstp    [ebp+var_10]
.text:10006974                call    strlen            ====> Username的長度
.text:10006979                pop    ecx
.text:1000697A                xor    ecx, ecx
.text:1000697C                test    eax, eax
.text:1000697E                jle    short loc_100069B1
.text:10006980                movsx  edx, byte ptr [esi]
.text:10006983                mov    [ebp+arg_0], edx
.text:10006986                fild    [ebp+arg_0]        ====> st0=第1個Username字元

.text:10006989                movsx  edx, byte ptr [ecx+esi]    ====> 取1個Username字元
.text:1000698D                mov    [ebp+arg_0], edx
.text:10006990                inc    ecx
.text:10006991                fild    [ebp+arg_0]
.text:10006994                cmp    ecx, eax
.text:10006996                fadd    st, st(1)          ====> st0=[ebp+arg_0],st1=Username(1)
.text:10006998                fmul    [ebp+var_18]
.text:1000699B                fadd    [ebp+var_10]
.text:1000699E                fstp    [ebp+var_10]
.text:100069A1                fld    [ebp+var_18]
.text:100069A4                fadd    ds:dbl_1000A8F8    ====> dbl_1000A8F8=2
.text:100069AA                fstp    [ebp+var_18]
.text:100069AD                jl      short loc_10006989

10006989-100069AD的計算過程:
for i=1 to strlen(Username);Code1=Code1+(Username(1)+Username(i))*(56+(i-1)*2);next

.text:100069AF                fstp    st
.text:100069B1                fld    [ebp+var_10]
.text:100069B4                fadd    ds:dbl_1000A8F0    ====> dbl_1000A8F0=3419821
.text:100069BA                push    offset aEqualizer ; "equalizer"
.text:100069BF                fst    [ebp+var_10]      ====> 令RegCode1=Code1+3419821
.text:100069C2                fstp    [ebp+var_8]
.text:100069C5                call    strlen            ====> "equalizer"的長度
.text:100069CA                pop    ecx
.text:100069CB                xor    ecx, ecx
.text:100069CD                test    eax, eax
.text:100069CF                jle    short loc_100069F0
.text:100069D1                movsx  edx, byte ptr [esi]
.text:100069D4                push    edi

.text:100069D5                movsx  edi, byte ptr [ecx+offset aEqualizer] ; "equalizer"
.text:100069DC                add    edi, edx
.text:100069DE                inc    ecx
.text:100069DF                mov    [ebp+arg_0], edi
.text:100069E2                cmp    ecx, eax
.text:100069E4                fild    [ebp+arg_0]
.text:100069E7                fsubr  [ebp+var_8]
.text:100069EA                fstp    [ebp+var_8]
.text:100069ED                jl      short loc_100069D5

100069D5-100069ED的計算過程:
for i=1 to strlen("equalizer");Code2=Code2+Username(1)+"equalizer"(i);next
RegCode2=RegCode1-Code2

.text:100069EF                pop    edi
.text:100069F0                fld    [ebp+var_8]
.text:100069F3                fsub    ds:dbl_1000A8F0
.text:100069F9                push    esi
.text:100069FA                fst    [ebp+var_8]

100069D5-100069ED的計算過程:
RegCode2=RegCode2-3419821

.text:100069FD                fadd    [ebp+var_18]
.text:10006A00                fstp    [ebp+var_20]
.text:10006A03                call    strlen
.text:10006A08                pop    ecx
.text:10006A09                xor    ecx, ecx
.text:10006A0B                test    eax, eax
.text:10006A0D                jle    short loc_10006A37
.text:10006A0F                fld    [ebp+var_18]
.text:10006A12                fadd    ds:dbl_1000A8E8    ====> dbl_1000A8E8=1
                                                          ====> st0=(56+2*strlen(Username))+1
.text:10006A18                movsx  edx, byte ptr [ecx+esi]
.text:10006A1C                mov    [ebp+arg_0], edx
.text:10006A1F                inc    ecx
.text:10006A20                fild    [ebp+arg_0]
.text:10006A23                cmp    ecx, eax
.text:10006A25                fmul    st, st(1)
.text:10006A27                fadd    [ebp+var_20]
.text:10006A2A                fsub    ds:dbl_1000A8E0    ====> dbl_1000A8E0=5
.text:10006A30                fstp    [ebp+var_20]
.text:10006A33                jl      short loc_10006A18

100069D5-100069ED的計算過程:
RegCode3=RegCode2+(56+2*strlen(Username))
for i=1 to strlen(Username);RegCode3=RegCode3+Username(i)*((56+2*strlen(Username))+1)-5;next

.text:10006A35                fstp    st
.text:10006A37                fld    [ebp+var_20]
.text:10006A3A                push    ecx
.text:10006A3B                push    ecx
.text:10006A3C                fstp    [esp+158h+var_158]
.text:10006A3F                fld    [ebp+var_8]
.text:10006A42                push    ecx
.text:10006A43                push    ecx
.text:10006A44                fstp    [esp+160h+var_160]
.text:10006A47                fld    [ebp+var_10]
.text:10006A4A                call    _ftol
.text:10006A4F                push    eax
.text:10006A50                lea    eax, [ebp+var_14C]
.text:10006A56                push    offset aX_0f_0f ; "%X-%.0f-%.0f"    ====> 註冊碼格式("0XRegCode1-RegCode2-RegCode3")
.text:10006A5B                push    eax
.text:10006A5C                call    ds:sprintf
.text:10006A62                push    [ebp+arg_4]
.text:10006A65                lea    eax, [ebp+var_14C]
.text:10006A6B                push    eax
.text:10006A6C                call    strcmp            ====> 註冊碼比較
.text:10006A71                add    esp, 24h
.text:10006A74                neg    eax
.text:10006A76                sbb    eax, eax
.text:10006A78                pop    esi
.text:10006A79                inc    eax                ====> 結果放到eax
.text:10006A7A                leave
.text:10006A7B                retn
.text:10006A7B sub_10006958    endp

引數值:
.rdata:1000A8E0 dbl_1000A8E0    dq 5.0                  ; DATA XREF: sub_10006958+D2
.rdata:1000A8E8 dbl_1000A8E8    dq 1.0                  ; DATA XREF: sub_10006958+BA
.rdata:1000A8F0 dbl_1000A8F0    dq 3.419821e6          ; DATA XREF: sub_10006958+5C
.rdata:1000A8F8 dbl_1000A8F8    dq 2.0                  ; DATA XREF: sub_10006958+4C
.rdata:1000A900 dbl_1000A900    dq 5.6e1                ; DATA XREF: sub_10006958+9

總結:註冊碼由3部分組成:(分別為RegCode1、RegCode2、RegCode3)
RegCode1=3419821+求和((使用者名稱的第1個字元+使用者名稱各字元的ASCII值)*(56+2*使用者名稱各字元的位置))
RegCode2=RegCode1-3419821-求和(使用者名稱的第1個字元+"equalizer"各字元的ASCII值)+(56+2*使用者名稱長度+1)
RegCode3=求和((RegCode2+56+2*使用者名稱長度)+使用者名稱各字元的ASCII值*(56+2*使用者名稱長度+1)-5)
註冊碼的第1部分用16進位制顯示,第2、3部分用十進位制顯示,各部分之間用"-"連上
註冊器已做成

後記:IDA和W32Dasm相比較,各有各的優點,W32Dasm比較簡單,上手快,字串參考窗非常實用,可以說就是專為Cracker定製,但對於MFC函式支援不足,並且有一些如本例子的引數(在rdata段)並不能顯示出來,要想得出註冊碼的計算過程,需要結合SoftICE,要想修改程式程式碼進行暴破,還須結合HIEW、HexWorkshop、UE等;而IDA相對來說就難懂一些,但它支援MFC函式,這樣程式讀起來就要容易,另外,就向本程式那樣,檢視註冊碼的計算引數很容易,當然,它的功能不止這些。對於一個程式,要想破解它,應該結合具體情況來選擇不同的反編譯器,通常首先選擇W32Dasm――容易、直觀,而對於象由VC++等編譯的程式以及註冊部分有內部引數計算的,最好還是用IDA,以上是我的淺見,不當指出請予指出。
2001.05.26 15:00

相關文章