|
論壇說明 |
歡迎您來到『史萊姆論壇』 ^___^ 您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的! 請點擊這裡:『註冊成為我們的一份子!』 |
|
主題工具 | 顯示模式 |
2003-12-12, 03:41 AM | #1 |
榮譽會員
|
FolderView 1.7 註冊算法分析
FolderView 1.7 註冊算法分析
破解目標:FolderView 1.7 官方主頁:http://www.southbaypc.com/ 軟體簡介:這是一個簡單易用的小工具,可以將資料夾當中的每個文件,依照大小(byte)、日期、名稱作詳細列表,並匯出成TXT純文字文件或者將文件資料打列出來。 下載位址:http://hn-down.skycn.net/down/fvsetup.exe 使用工具:W32Dasm、Ollydbg、Windows 自帶的計算器 作者:炎之川 時間:2003.3.3 主頁:http://skipli.yeah.net/ 宣告: 此文僅用於學習及交流,若要轉載請保持文章完整。 我的第三篇算法分析,前兩篇都是crackme,而這篇文章的分析目標是共享軟體,不過算法不算難。分析沒有花太多時間,而寫文章卻花費了很長的時間... 用 PEiD 0.8 檢查可知文件未加殼。用 W32Dasm 反彙編並初步分析,先在串式參考中找到註冊碼錯誤的提示:「Sorry, you have entered an incorrect registration code.」,雙按來到下面的程式碼段: * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00407424(C) //使用之處,右鍵雙按之... | :00407469 6A00 push 00000000 * Possible StringData Ref from Data Obj ->"FolderView" | :0040746B 6874354100 push 00413574 * Possible StringData Ref from Data Obj ->"Sorry, you have entered an incorrect " ->"registration code." | :00407470 68083A4100 push 00413A08 :00407475 56 push esi 來到這裡: * Reference To: USER32.GetDlgItemTextA, Ord:0113h | :004073EC 8B3D1C124100 mov edi, dword ptr [0041121C] :004073F2 68EF030000 push 000003EF :004073F7 56 push esi :004073F8 FFD7 call edi :004073FA 8D542408 lea edx, dword ptr [esp+08] :004073FE 6800010000 push 00000100 :00407403 52 push edx :00407404 68ED030000 push 000003ED :00407409 56 push esi :0040740A FFD7 call edi :0040740C 8D442408 lea eax, dword ptr [esp+08] :00407410 8D8C2408010000 lea ecx, dword ptr [esp+00000108] :00407417 50 push eax :00407418 51 push ecx :00407419 E882030000 call 004077A0 //我們在這裡下斷點 :0040741E 83C408 add esp, 00000008 :00407421 85C0 test eax, eax :00407423 5F pop edi :00407424 7443 je 00407469 //光棒停在這裡 :00407426 8D542404 lea edx, dword ptr [esp+04] :0040742A 8D842404010000 lea eax, dword ptr [esp+00000104] :00407431 52 push edx :00407432 50 push eax 可知程序使用 GetDlgItemTextA 來取輸入的字串,且我們可以在 407419 處下斷點。 Ollydbg 載入文件,在 407419 處按 F2 下斷點,然後 ctrl+F2 重新開始,F9 執行程序,填入註冊名和假註冊碼,我填入: Name: lovefire S/N: 78787878 按 Check,被 Ollydbg 斷下, (; 後是 Ollydbg 所分析的內容,// 後是我加的註釋) 004073FE . 68 00010000 PUSH 100 ; /Count = 100 (256.) 00407403 . 52 PUSH EDX ; |Buffer 00407404 . 68 ED030000 PUSH 3ED ; |ControlID = 3ED (1005.) 00407409 . 56 PUSH ESI ; |hWnd 0040740A . FFD7 CALL EDI ; \GetDlgItemTextA 0040740C . 8D4424 08 LEA EAX, DWORD PTR SS:[ESP+8] //取假碼到 EAX 00407410 . 8D8C24 080100>LEA ECX, DWORD PTR SS:[ESP+108] //取註冊名到 ECX 00407417 . 50 PUSH EAX //假碼入棧,保留到最後比較 00407418 . 51 PUSH ECX //註冊名入棧 00407419 . E8 82030000 CALL FolderVi.004077A0 //F7 跟進 0040741E . 83C4 08 ADD ESP, 8 00407421 . 85C0 TEST EAX, EAX 00407423 . 5F POP EDI 00407424 . 74 43 JE SHORT FolderVi.00407469 ---------------------------------------------------------------- 進入 407419 的call 004077A0 /$ 8B4C24 04 MOV ECX, DWORD PTR SS:[ESP+4] 004077A4 |. 81EC 00010000 SUB ESP, 100 004077AA |. 8D4424 00 LEA EAX, DWORD PTR SS:[ESP] 004077AE |. 50 PUSH EAX 004077AF |. 51 PUSH ECX 004077B0 |. E8 AB000000 CALL FolderVi.00407860 004077B5 |. 8B8424 100100>MOV EAX, DWORD PTR SS:[ESP+110] 004077BC |. 8D5424 08 LEA EDX, DWORD PTR SS:[ESP+8] 004077C0 |. 52 PUSH EDX 004077C1 |. 50 PUSH EAX 004077C2 |. E8 89FFFFFF CALL FolderVi.00407750 //關鍵call,F7 跟進 004077C7 |. F7D8 NEG EAX 004077C9 |. 1BC0 SBB EAX, EAX 004077CB |. F7D8 NEG EAX 004077CD |. 81C4 10010000 ADD ESP, 110 004077D3 \. C3 RETN ---------------------------------------------------------------- 進入 4077C2 的call,算法開始 00407860 /$ 81EC 00010000 SUB ESP, 100 00407866 |. A0 7C684100 MOV AL, BYTE PTR DS:[41687C] 0040786B |. 53 PUSH EBX 0040786C |. 55 PUSH EBP 0040786D |. 56 PUSH ESI 0040786E |. 57 PUSH EDI 0040786F |. 884424 10 MOV BYTE PTR SS:[ESP+10], AL 00407873 |. B9 3F000000 MOV ECX, 3F 00407878 |. 33C0 XOR EAX, EAX 0040787A |. 8D7C24 11 LEA EDI, DWORD PTR SS:[ESP+11] 0040787E |. F3:AB REP STOS DWORD PTR ES:[EDI] 00407880 |. 66:AB STOS WORD PTR ES:[EDI] 00407882 |. AA STOS BYTE PTR ES:[EDI] 00407883 |. 8BBC24 140100>MOV EDI, DWORD PTR SS:[ESP+114] //取輸入的註冊用戶名,放到 edi 0040788A |. 57 PUSH EDI ; /String //edi 入棧 0040788B |. FF15 68114100 CALL DWORD PTR DS:[<&KERNEL32.lstrlen>; \lstrlenA //取輸入的註冊名長度,然後放到eax(可以通過經過此call後,eax值的變化看出) 00407891 |. 8BF0 MOV ESI, EAX //註冊名長度送到 esi 00407893 |. 33C9 XOR ECX, ECX //清零 00407895 |. 33C0 XOR EAX, EAX //清零,做計數器 00407897 |. 85F6 TEST ESI, ESI //比較esi是否為0,即是否已輸入註冊名 00407899 |. 76 13 JBE SHORT FolderVi.004078AE //如果沒有輸入,後果很明顯... //下面開始的第一個循環 0040789B |. 8B15 F8394100 MOV EDX, DWORD PTR DS:[4139F8] //給edx賦值,發現這裡類BIOS是賦值32 004078A1 |> 0FBE1C38 /MOVSX EBX, BYTE PTR DS:[EAX+EDI] //逐位取註冊名的字串,第一次取「l」,即6C 004078A5 |. 03DA |ADD EBX, EDX //ebx = ebx+edx = 6C+32 = 9E 004078A7 |. 03CB |ADD ECX, EBX //ecx = ecx+ebx = 0+9E = 9E 004078A9 |. 40 |INC EAX //eax+1,計數器+1 004078AA |. 3BC6 |CMP EAX, ESI //比較eax與esi,esi 中是整個註冊名長度值,所以這裡比較是否已取完註冊名 004078AC |.^ 72 F3 \JB SHORT FolderVi.004078A1 //沒有取完就繼續循環 //第一個循環結束 第一次循環完成後得到的ebx的值,放入第二次循環繼續計算,每次循環最終值放入ecx中。 這個部分的註冊算法為: 設 ecx 的值從初始到所有循環完成,分別為N(0),N(1),N(2),N(3),N(4)...則: ecx = ((註冊名字串的ASCII值)+32)+N(n-1) 以我填入的註冊名「lovefire」為例: N(0) = 0 (初始的 ecx=0) N(1) = 6C+32+0 = 9E //第一次循環,所以N(1-1)=N(0)=0 N(2) = 6F+32+9E = 13F //第二次循環,所以 N(2-1)=N(1)=9E N(3) = 76+32+13F = 1E7 //以下類推 N(4) = 65+32+1E7 = 27E N(5) = 66+32+27E = 316 N(6) = 69+32+316 = 3B1 N(7) = 72+32+3B1 = 455 N(8) = 65+32+455 = 4EC = 1260(十進制) 接下來一段是對這個算出來的數做一些處理: 004078AE |> 8B9C24 180100>MOV EBX, DWORD PTR SS:[ESP+118] 004078B5 |. 51 PUSH ECX ; /<%u> //ecx 入棧 004078B6 |. 68 503A4100 PUSH FolderVi.00413A50 ; |Format = "%u-" //格式 004078BB |. 53 PUSH EBX ; |s 004078BC |. FF15 0C124100 CALL DWORD PTR DS:[<&USER32.wsprintfA>; \wsprintfA //給ecx的數值後加上「-」符號 到此處得到一個值「1260-」。 然後開始進行第二個循環,先是一些準備事項: 004078C2 |. 83C4 0C ADD ESP, 0C 004078C5 |. 33C9 XOR ECX, ECX //清零 004078C7 |. 33C0 XOR EAX, EAX //清零 004078C9 |. 85F6 TEST ESI, ESI //比較esi是否為0,即是否已輸入註冊名 004078CB |. 76 14 JBE SHORT FolderVi.004078E1 //如果沒有輸入,後果很明顯... //下面開始第二個循環 004078CD |. 8B15 FC394100 MOV EDX, DWORD PTR DS:[4139FC] //給 edx 賦值,這個值是類BIOS的,為 28 004078D3 |> 0FBE2C38 /MOVSX EBP, BYTE PTR DS:[EAX+EDI] //逐位取註冊名的字串,第一次取「l」,即6C,放到 ebp 004078D7 |. 0FAFEA |IMUL EBP, EDX //ebp = ebp*edx 004078DA |. 03CD |ADD ECX, EBP //ecx = ecx+ebp 004078DC |. 40 |INC EAX //eax+1,計數器+1 004078DD |. 3BC6 |CMP EAX, ESI //是否已取完註冊名? 004078DF |.^ 72 F2 \JB SHORT FolderVi.004078D3 //沒有取完就繼續循環 //循環完成 這個部分的註冊算法為: 設 ecx 的值從初始到所有循環完成,分別為N(0),N(1),N(2),N(3),N(4)...則: ecx=(註冊名字串的ASCII值)*28+N(n-1) 以我填入的註冊名「lovefire」為例: N(0) = 0 (初始的 ecx=0) N(1) = 6C*28+0 = 10E0 //第一次循環,所以N(1-1)=N(0)=0 N(2) = 6F*28+ 10E0 = 2238 //第二次循環,所以 N(2-1)=N(1)=10E0 N(3) = 76*28+ 2238 = 34A8 //以下類推 N(4) = 65*28+ 34A8 = 4470 N(5)= 66*28+ 4470 = 5460 N(6) = 69*28+ 5460 = 64C8 N(7) = 72*28+ 64C8 = 7698 N(8) = 65*28+ 7698 = 8660 = 34400(十進制) 接下來繼續對得到的數進行一些處理: 004078E1 |> 51 PUSH ECX ; /<%u> = 8660 (34400.) 004078E2 |. 8D4C24 14 LEA ECX, DWORD PTR SS:[ESP+14] ; | 004078E6 |. 68 503A4100 PUSH FolderVi.00413A50 ; |Format = "%u-" 004078EB |. 51 PUSH ECX ; |s 004078EC |. FF15 0C124100 CALL DWORD PTR DS:[<&USER32.wsprintfA>; \wsprintfA //將得到的 34400 加上「-」,得到註冊碼的第二部分 34400-,並放入ecx 004078F2 |. 83C4 0C ADD ESP, 0C 004078F5 |. 8D5424 10 LEA EDX, DWORD PTR SS:[ESP+10] 004078F9 |. 52 PUSH EDX ; /StringToAdd 004078FA |. 53 PUSH EBX ; |ConcatString 004078FB |. FF15 94114100 CALL DWORD PTR DS:[<&KERNEL32.lstrcat>; \lstrcatA //和第一次算出的碼合併為「1260-34400-」 至此得到一個新的字串「1260-34400-」。 第三次循環: 00407901 |. 33C9 XOR ECX, ECX 00407903 |. 33C0 XOR EAX, EAX 00407905 |. 85F6 TEST ESI, ESI 00407907 |. 76 13 JBE SHORT FolderVi.0040791C //對循環3進行一些初始設定,與循環1、2類似,不再多做解釋 00407909 |. 8B15 003A4100 MOV EDX, DWORD PTR DS:[413A00] //給edx賦初始值 1E(類BIOS值) //下面開始的三次循環 0040790F |> 0FBE2C38 /MOVSX EBP, BYTE PTR DS:[EAX+EDI] //逐位取註冊名的字串的ASCII值,放到 ebp 00407913 |. 03EA |ADD EBP, EDX //ebp = ebp+edx 00407915 |. 03CD |ADD ECX, EBP //ecx = ecx+ebp 00407917 |. 40 |INC EAX //計數器+1 00407918 |. 3BC6 |CMP EAX, ESI //比較是否已取完註冊名 0040791A |.^ 72 F3 \JB SHORT FolderVi.0040790F //沒有則繼續循環 //循環結束 這個部分的註冊算法為: 設 ecx 的值從初始到所有循環完成,分別為N(0),N(1),N(2),N(3),N(4)...則: ecx=(註冊名字串的ASCII值)+1E+N(n-1) 可知,輸入的註冊名「lovefire」,經過循環計算後得到一個數「44C」,轉換為十進制則為「1100」 接下來…… 0040791C |> 51 PUSH ECX ; /<%u> = 44C (1100.) 0040791D |. 8D4424 14 LEA EAX, DWORD PTR SS:[ESP+14] ; | 00407921 |. 68 503A4100 PUSH FolderVi.00413A50 ; |Format = "%u-" 00407926 |. 50 PUSH EAX ; |s 00407927 |. FF15 0C124100 CALL DWORD PTR DS:[<&USER32.wsprintfA>; \wsprintfA 0040792D |. 83C4 0C ADD ESP, 0C 00407930 |. 8D4C24 10 LEA ECX, DWORD PTR SS:[ESP+10] 00407934 |. 51 PUSH ECX ; /StringToAdd 00407935 |. 53 PUSH EBX ; |ConcatString 00407936 |. FF15 94114100 CALL DWORD PTR DS:[<&KERNEL32.lstrcat>; \lstrcatA 以上分別程式碼先給算出的「1100」加上「-」,得到「1100-」,在和前面的字串合併,得到「1260-34400-1100」 第四次循環: 0040793C |. 33C9 XOR ECX, ECX 0040793E |. 33C0 XOR EAX, EAX 00407940 |. 85F6 TEST ESI, ESI 00407942 |. 76 14 JBE SHORT FolderVi.00407958 00407944 |. 8B15 043A4100 MOV EDX, DWORD PTR DS:[413A04] //給edx賦初始值 0B(類BIOS值) //循環開始 0040794A |> 0FBE2C38 /MOVSX EBP, BYTE PTR DS:[EAX+EDI] //逐位取註冊名的字串的ASCII值,放到 ebp 0040794E |. 0FAFEA |IMUL EBP, EDX //ebp = ebp*edx 00407951 |. 03CD |ADD ECX, EBP //ecx = ecx+ebp 00407953 |. 40 |INC EAX //計數器+1 00407954 |. 3BC6 |CMP EAX, ESI //比較是否已取完註冊名? 00407956 |.^ 72 F2 \JB SHORT FolderVi.0040794A //沒有則繼續循環 //循環結束 這個部分的註冊算法為: 設 ecx 的值從初始到所有循環完成,分別為N(0),N(1),N(2),N(3),N(4)...則: ecx=(註冊名字串的ASCII值)*0B+N(n-1) 可知,輸入的註冊名「lovefire」,經過循環計算後得到一個數「24F4」,轉換為十進制則為「9460」。 00407958 |> 51 PUSH ECX ; /<%u> 00407959 |. 8D5424 14 LEA EDX, DWORD PTR SS:[ESP+14] ; | 0040795D |. 68 6C384100 PUSH FolderVi.0041386C ; |Format = "%u" 00407962 |. 52 PUSH EDX ; |s 00407963 |. FF15 0C124100 CALL DWORD PTR DS:[<&USER32.wsprintfA>; \wsprintfA 00407969 |. 83C4 0C ADD ESP, 0C 0040796C |. 8D4424 10 LEA EAX, DWORD PTR SS:[ESP+10] 00407970 |. 50 PUSH EAX ; /StringToAdd 00407971 |. 53 PUSH EBX ; |ConcatString 00407972 |. FF15 94114100 CALL DWORD PTR DS:[<&KERNEL32.lstrcat>; \lstrcatA 以上程式碼將前後算出的數值合併為「1260-34400-1100-9460」,這就是真正的註冊碼。 再繼續往下走,是對比假碼與真碼,先對比真假註冊碼長度,如果相等,則逐位比較,如果輸入的註冊名與計算出的註冊碼相同,則註冊成功,將註冊信息寫入「HKEY_CURRENT_USER\Software\FolderView\Registration」,分別是"Name"和"Code"兩個子鍵。因為與算法關係不大,且很容易看懂,所以比較註冊碼這部分的程式碼就不複製出來了 至此,FolderView 1.7 註冊算法分析完成。 一組可用的註冊碼:Name: lovefire S/N: 1260-34400-1100-9460 ;by 炎之川 2003.3.3 注冊機: #include<stdio.h> main() { char name[80]; int i,name_len; unsigned long sn1=0,sn2=0,sn3=0,sn4=0; clrscr(); gets(name); name_len=strlen(name); for (i=0;i<name_len;i++) { sn1=sn1+(name[i]+0x32); sn2=sn2+(name[i]*0x28); sn3=sn3+(name[i]+0x1E); sn4=sn4+(name[i]*0xB); } printf("%ld-%ld-%ld-%ld\n",sn1,sn2,sn3,sn4); printf("Power By POW ^_^\n"); getch(); } |
送花文章: 3,
|