海月圖片獵手(SeaMoon Pic Hunter) 1.52 註冊演算法分析

看雪資料發表於2015-11-15

海月圖片獵手(SeaMoon Pic Hunter) 1.52 註冊演算法分析

破解目標:海月圖片獵手(SeaMoon Pic Hunter) 1.52
官方主頁:http://www.seamoontech.com/
軟體簡介:從因特網上搜尋,下載圖片的工具,並可瀏覽或播放多種格式檔案等。使用多執行緒方式自動搜尋和下載。網路上有成百上千的圖片,而人們常想將一些漂亮的圖片下載到本地來供以後使用。當然您可以一頁一頁的瀏覽網頁然後一張一張的另存來達到目的,但這種方法顯然是非常耗時的。海月圖片獵手就是為了解決這個問題而誕生的。海月圖片獵手將訪問並分析您所指定的網站或頁面的結構,把其中的圖片如GIF和JPEG等快速地下載到本地來。成百上千的圖片很快即可下載完畢,遠非人工所能比擬。
下載地址:http://cbbndown.skycn.net/down/PicHunterSetup.exe

使用工具:PEiD 0.8、W32Dasm、Ollydbg、Windows 自帶的計算器、32bit Calculator 1.6 by cybult、UltraEdit

作者:炎之川[BCG]
時間:2003.4.28
主頁:http://skipli.yeah.net/

========================================================================
宣告: 本文純屬技術交流,無其他任何目的,轉載請註明作者並保持文章的完整。
========================================================================


最近兩週寫了幾篇漢化方面的文章,基本上都沒有碰破解……中午 lllufh[BCG] 兄弟在QQ上提到這個,於是順便找來看了一下,這個軟體和我上次寫過的 EZ MP3 Recorder 似乎是同一個軟體作者寫的,感覺在註冊流程上差不多:)

經 PEiD 0.8 檢查可知,EZ MP3 Recorder 的主程式為 VC++ 6.0 編寫且無殼,程式要求重啟驗證註冊碼。輸入的註冊碼儲存在登錄檔。

經過分析發現,軟體將輸入的註冊名和假註冊名寫入登錄檔中,鍵值名稱為 SearchNum。

直接用 OD 裝入程式。載入完成後,在 CPU 視窗中右擊,選擇“搜尋”->“字串參考”,然後在出現的視窗中搜尋 SearchNum,一共有兩處,分別下斷點。重新執行程式,被 OD 斷下,斷在 4067E8(你需要先輸入註冊名和假註冊碼,我輸入 Name: lovefire[BCG],S/N: 78787878),另一個下斷點處與軟體演算法無關,現在可以把它關掉:)

(; 後是 Ollydbg 所分析的內容,// 後是我加的註釋,文中數值均為十六進位制值)


004067E3  . 68 60CE4800  PUSH PicHunte.0048CE60
004067E8  . 68 E8834800  PUSH PicHunte.004883E8          ; ASCII "SearchNum"  //斷點
004067ED  . 8D4424 24   LEA EAX,DWORD PTR SS:[ESP+24]
004067F1  . 68 F4834800  PUSH PicHunte.004883F4          ; ASCII "Settings"
004067F6  . 50       PUSH EAX
004067F7  . 8BCE      MOV ECX,ESI
004067F9  . E8 DBBB0500  CALL PicHunte.004623D9
004067FE  . C68424 5401000>MOV BYTE PTR SS:[ESP+154],3
00406806  . 50       PUSH EAX
00406807  . 8D4C24 14   LEA ECX,DWORD PTR SS:[ESP+14]
0040680B  . E8 AC1F0400  CALL PicHunte.004487BC
00406810  . 8D4C24 1C   LEA ECX,DWORD PTR SS:[ESP+1C]
00406814  . 889C24 5401000>MOV BYTE PTR SS:[ESP+154],BL
0040681B  . E8 631E0400  CALL PicHunte.00448683
00406820  . 51       PUSH ECX
00406821  . 8D5424 14   LEA EDX,DWORD PTR SS:[ESP+14]
00406825  . 8BCC      MOV ECX,ESP
00406827  . 896424 18   MOV DWORD PTR SS:[ESP+18],ESP  //取註冊名
0040682B  . 52       PUSH EDX
0040682C  . E8 C71B0400  CALL PicHunte.004483F8  //取假碼
00406831  . 51       PUSH ECX
00406832  . C68424 5C01000>MOV BYTE PTR SS:[ESP+15C],4
0040683A  . 8BCC      MOV ECX,ESP
0040683C  . 896424 28   MOV DWORD PTR SS:[ESP+28],ESP
00406840  . 57       PUSH EDI
00406841  . E8 B21B0400  CALL PicHunte.004483F8  //關鍵call㈠,檢查是否已存在註冊名,如果已存在,則繼續驗證,有興趣的可以進去看看
00406846  . 8BCE      MOV ECX,ESI               ; |
00406848  . 889C24 5C01000>MOV BYTE PTR SS:[ESP+15C],BL       ; |
0040684F  . E8 8C090000  CALL PicHunte.004071E0          ; \PicHunte.004071E0  //關鍵call㈡,註冊碼演算法
00406854  . 6A 11     PUSH 11                 ; /ObjType = DEFAULT_GUI_FONT
00406856  . 8986 CC000000 MOV DWORD PTR DS:[ESI+CC],EAX      ; |
0040685C  . 8DBE 10010000 LEA EDI,DWORD PTR DS:[ESI+110]      ; |

------------------------------------------------------------------------
進入 4483F8 的關鍵call㈠

004483F8 /$ 56       PUSH ESI
004483F9 |. 8BF1      MOV ESI,ECX
004483FB |. 8B4C24 08   MOV ECX,DWORD PTR SS:[ESP+8]
004483FF |. 8B01      MOV EAX,DWORD PTR DS:[ECX]  //註冊名放入eax
00448401 |. 8378 F4 00   CMP DWORD PTR DS:[EAX-C],0  //比較註冊名長度是否為0,即是否已有註冊名
00448405 |. 7C 0E     JL SHORT PicHunte.00448415  //登錄檔中沒有註冊名則跳
00448407 |. 8906      MOV DWORD PTR DS:[ESI],EAX
00448409 |. 83C0 F4    ADD EAX,-0C
0044840C |. 50       PUSH EAX                 ; /pVar
0044840D |. FF15 B0034700 CALL DWORD PTR DS:[<&KERNEL32.Interlocke>; \InterlockedIncrement
00448413 |. EB 10     JMP SHORT PicHunte.00448425
00448415 |> A1 18AC4800  MOV EAX,DWORD PTR DS:[48AC18]
0044841A |. 8906      MOV DWORD PTR DS:[ESI],EAX
0044841C |. FF31      PUSH DWORD PTR DS:[ECX]
0044841E |. 8BCE      MOV ECX,ESI
00448420 |. E8 E7030000  CALL PicHunte.0044880C
00448425 |> 8BC6      MOV EAX,ESI
00448427 |. 5E       POP ESI
00448428 \. C2 0400    RETN 4


------------------------------------------------------------------------
進入 4071E0 的關鍵call㈡

004071E0 /$ 6A FF     PUSH -1
004071E2 |. 68 D0A74600  PUSH PicHunte.0046A7D0          ; SE handler installation
004071E7 |. 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
004071ED |. 50       PUSH EAX
004071EE |. 64:8925 000000>MOV DWORD PTR FS:[0],ESP
004071F5 |. 81EC D0000000 SUB ESP,0D0
004071FB |. 56       PUSH ESI
004071FC |. 8BF1      MOV ESI,ECX
004071FE |. B8 01000000  MOV EAX,1
00407203 |. 68 60CE4800  PUSH PicHunte.0048CE60          ; /Arg2 = 0048CE60
00407208 |. 898424 E000000>MOV DWORD PTR SS:[ESP+E0],EAX      ; |
0040720F |. 8986 C8000000 MOV DWORD PTR DS:[ESI+C8],EAX      ; |
00407215 |. 8B8424 E800000>MOV EAX,DWORD PTR SS:[ESP+E8]      ; |  //取使用者名稱到 eax
0040721C |. 50       PUSH EAX                 ; |Arg1 = 00B46F38 ASCII "lovefire[BCG]"
0040721D |. E8 4FB10200  CALL PicHunte.00432371          ; \PicHunte.00432371
00407222 |. 83C4 08    ADD ESP,8
00407225 |. 85C0      TEST EAX,EAX
00407227 |. 0F84 7C010000 JE PicHunte.004073A9
0040722D |. 8B8C24 E800000>MOV ECX,DWORD PTR SS:[ESP+E8]  //取假碼到 ecx
00407234 |. 68 60CE4800  PUSH PicHunte.0048CE60          ; /Arg2 = 0048CE60
00407239 |. 51       PUSH ECX                 ; |Arg1
0040723A |. E8 32B10200  CALL PicHunte.00432371          ; \PicHunte.00432371
0040723F |. 83C4 08    ADD ESP,8
00407242 |. 85C0      TEST EAX,EAX
00407244 |. 0F84 5F010000 JE PicHunte.004073A9

//接下來是blacklist,不幸上板的都是喜歡用自己的網站名公開註冊碼的網站^^
0040724A |. 68 5C854800  PUSH PicHunte.0048855C          ; ASCII "ttdown"
0040724F |. 8D8C24 E800000>LEA ECX,DWORD PTR SS:[ESP+E8]
00407256 |. E8 B5A20300  CALL PicHunte.00441510  //441510 這個call比較註冊名是否上了黑名單,每個blacklist專案都是呼叫這個call比較的,有興趣的可以跟進去看看:)
0040725B |. 83F8 FF    CMP EAX,-1
0040725E |. 75 42     JNZ SHORT PicHunte.004072A2
00407260 |. 68 54854800  PUSH PicHunte.00488554          ; ASCII "crsky"
00407265 |. 8D8C24 E800000>LEA ECX,DWORD PTR SS:[ESP+E8]
0040726C |. E8 9FA20300  CALL PicHunte.00441510
00407271 |. 83F8 FF    CMP EAX,-1
00407274 |. 75 2C     JNZ SHORT PicHunte.004072A2
00407276 |. 68 4C854800  PUSH PicHunte.0048854C          ; ASCII ".com"
0040727B |. 8D8C24 E800000>LEA ECX,DWORD PTR SS:[ESP+E8]
00407282 |. E8 89A20300  CALL PicHunte.00441510
00407287 |. 83F8 FF    CMP EAX,-1
0040728A |. 75 16     JNZ SHORT PicHunte.004072A2
0040728C |. 68 44854800  PUSH PicHunte.00488544          ; ASCII "jetdown"
00407291 |. 8D8C24 E800000>LEA ECX,DWORD PTR SS:[ESP+E8]
00407298 |. E8 73A20300  CALL PicHunte.00441510
0040729D |. 83F8 FF    CMP EAX,-1
004072A0 |. 74 0A     JE SHORT PicHunte.004072AC
004072A2 |> C786 C8000000 >MOV DWORD PTR DS:[ESI+C8],0
004072AC |> 8B9424 E400000>MOV EDX,DWORD PTR SS:[ESP+E4]  //註冊名放入edx
004072B3 |. B0 6F     MOV AL,6F  //al 賦值為“6F”,即“o”
004072B5 |. 33C9      XOR ECX,ECX  //ecx清零,做記數器
004072B7 |. 53       PUSH EBX
004072B8 |. 8B72 F8    MOV ESI,DWORD PTR DS:[EDX-8]  //註冊名長度送 esi
004072BB |. C64424 08 73  MOV BYTE PTR SS:[ESP+8],73  //73 = s
004072C0 |. 85F6      TEST ESI,ESI  //再次檢查使用者名稱輸入了麼
004072C2 |. C64424 09 65  MOV BYTE PTR SS:[ESP+9],65  //65 = e
004072C7 |. C64424 0A 61  MOV BYTE PTR SS:[ESP+A],61  //61 = a
004072CC |. C64424 0B 6D  MOV BYTE PTR SS:[ESP+B],6D  //6D = m
004072D1 |. 884424 0C   MOV BYTE PTR SS:[ESP+C],AL  //AL = o
004072D5 |. 884424 0D   MOV BYTE PTR SS:[ESP+D],AL  //AL = o
004072D9 |. C64424 0E 6E  MOV BYTE PTR SS:[ESP+E],6E  //6E = n
004072DE |. C64424 0F 00  MOV BYTE PTR SS:[ESP+F],0  //結束
//這是預設的“表”,即“seamoon”,軟體公司的名字^^
004072E3 |. 7E 3E     JLE SHORT PicHunte.00407323  //嗯?要沒輸入我們是怎麼到這裡的?^^
004072E5 |. 55       PUSH EBP
004072E6 |. 57       PUSH EDI
004072E7 |. 8D7C34 17   LEA EDI,DWORD PTR SS:[ESP+ESI+17]

//下面開始就是演算法了
004072EB |> 8B8424 F000000>/MOV EAX,DWORD PTR SS:[ESP+F0]  //註冊名放入eax
004072F2 |. BD 07000000  |MOV EBP,7  //ebp 賦值為7,下面運算需要用到
004072F7 |. 8A1C01     |MOV BL,BYTE PTR DS:[ECX+EAX]  //ecx是計數器呢,這裡是逐位取註冊名的ascii值到bl
004072FA |. 8BC1      |MOV EAX,ECX  //eax=ecx
004072FC |. 99       |CDQ  //edx清零
004072FD |. F7FD      |IDIV EBP  //eax=eax/ebp=eax/7=ecx/7
004072FF |. 0FBEC3     |MOVSX EAX,BL  //註冊名的ascii放回eax
00407302 |. BB 09000000  |MOV EBX,9  //ebx=9
00407307 |. 0FBE5414 10  |MOVSX EDX,BYTE PTR SS:[ESP+EDX+10]  //從表中取對應迴圈次數的字元(第N次迴圈就取第N個,預設字串長度為7,所以7次後從頭開始取)
0040730C |. 03D6      |ADD EDX,ESI  //edx=edx+esi,esi是註冊名長度
0040730E |. 8D144A     |LEA EDX,DWORD PTR DS:[EDX+ECX*2]  //edx=edx+ecx*2,ecx是計數器,edx的值是對應位的“表”的值+註冊名長度
00407311 |. 03C2      |ADD EAX,EDX  //eax=eax+edx,eax 是註冊名的 ASCII
00407313 |. 99       |CDQ  //edx 清零
00407314 |. F7FB      |IDIV EBX  //eax=eax mod ebx,ebx是上面賦值的9,餘數放入edx
00407316 |. 80C2 30    |ADD DL,30  //取模之後的餘數+30,結果即對應此位註冊名的註冊碼
00407319 |. 41       |INC ECX  //計數器+1
0040731A |. 8817      |MOV BYTE PTR DS:[EDI],DL  //dl->[EDI],dl中是對應註冊名計算出來的註冊碼
0040731C |. 4F       |DEC EDI//edi-1,地址往前推,所以求出的註冊碼是逆著放的,即註冊名第一個字元計算出來的數,應該是此部分註冊碼的最後一個數
0040731D |. 3BCE      |CMP ECX,ESI  //比較註冊名是否已取完
0040731F |.^7C CA     \JL SHORT PicHunte.004072EB  //沒有取完則跳回去繼續
//演算法迴圈結束
//透過以上迴圈,可以得到對應註冊名的註冊碼的第一部分“7125506504722”

//以上迴圈演算法可總結如下:
//註冊名長度為L,N(I)為註冊名第I位字元,M(I)為預設字串“seamoon”第I位字元,迴圈次數為X,則
//註冊碼(X-I+1)位為:((N(I)+M(I)+X1)%9)+30

//以我填入的註冊名第1位“l”為例,註冊碼第(0D-1+1)為:
//(6C+73+0D1)%9+30=32,即“2”
//所以倒數第一位註冊碼為2

00407321 |. 5F       POP EDI
00407322 |. 5D       POP EBP
00407323 |> 8D46 4D    LEA EAX,DWORD PTR DS:[ESI+4D]  //esi中是註冊名長度,所以這裡是取註冊名長度+4D
00407326 |. B9 09000000  MOV ECX,9  //ecx=9
0040732B |. 99       CDQ  //edx 清零
0040732C |. F7F9      IDIV ECX  //eax=eax/ecx,餘數放入 edx
0040732E |. 8B8424 EC00000>MOV EAX,DWORD PTR SS:[ESP+EC]  //假碼放入eax
00407335 |. 80C2 30    ADD DL,30  //dl+30,這是註冊碼的最後一位
00407338 |. 885434 10   MOV BYTE PTR SS:[ESP+ESI+10],DL  //dl 放入[ESP+ESI+10],ESP+10 是第一部分註冊碼的起始地址,所以這裡就是放到之前算出的第一部分註冊碼之後

//這是註冊碼第二部分的計算,其值為 ((L+72)%9)+30
//我輸入的註冊名為0D個字元,則(0D+4D)%9=0,所以這一位註冊碼為0

0040733C |. C64434 11 00  MOV BYTE PTR SS:[ESP+ESI+11],0
00407341 |. 8D7424 10   LEA ESI,DWORD PTR SS:[ESP+10]

//以下是逐位對比輸入的註冊碼和真碼是否相同
00407345 |> 8A10      /MOV DL,BYTE PTR DS:[EAX]
00407347 |. 8A1E      |MOV BL,BYTE PTR DS:[ESI]
00407349 |. 8ACA      |MOV CL,DL
0040734B |. 3AD3      |CMP DL,BL
0040734D |. 75 1E     |JNZ SHORT PicHunte.0040736D
0040734F |. 84C9      |TEST CL,CL
00407351 |. 74 16     |JE SHORT PicHunte.00407369
00407353 |. 8A50 01    |MOV DL,BYTE PTR DS:[EAX+1]
00407356 |. 8A5E 01    |MOV BL,BYTE PTR DS:[ESI+1]
00407359 |. 8ACA      |MOV CL,DL
0040735B |. 3AD3      |CMP DL,BL
0040735D |. 75 0E     |JNZ SHORT PicHunte.0040736D
0040735F |. 83C0 02    |ADD EAX,2
00407362 |. 83C6 02    |ADD ESI,2
00407365 |. 84C9      |TEST CL,CL
00407367 |.^75 DC     \JNZ SHORT PicHunte.00407345

00407369 |> 33C0      XOR EAX,EAX
0040736B |. EB 05     JMP SHORT PicHunte.00407372
0040736D |> 1BC0      SBB EAX,EAX
0040736F |. 83D8 FF    SBB EAX,-1
00407372 |> 85C0      TEST EAX,EAX
00407374 |. 5B       POP EBX
00407375 |. C68424 DC00000>MOV BYTE PTR SS:[ESP+DC],0
0040737D |. 8D8C24 E400000>LEA ECX,DWORD PTR SS:[ESP+E4]
00407384 |. 75 32     JNZ SHORT PicHunte.004073B8
00407386 |. E8 F8120400  CALL PicHunte.00448683
0040738B |. 8D8C24 E800000>LEA ECX,DWORD PTR SS:[ESP+E8]
00407392 |. C78424 DC00000>MOV DWORD PTR SS:[ESP+DC],-1
0040739D |. E8 E1120400  CALL PicHunte.00448683
004073A2 |. B8 01000000  MOV EAX,1
004073A7 |. EB 2D     JMP SHORT PicHunte.004073D6
004073A9 |> C68424 DC00000>MOV BYTE PTR SS:[ESP+DC],0
004073B1 |. 8D8C24 E400000>LEA ECX,DWORD PTR SS:[ESP+E4]
004073B8 |> E8 C6120400  CALL PicHunte.00448683
004073BD |. 8D8C24 E800000>LEA ECX,DWORD PTR SS:[ESP+E8]
004073C4 |. C78424 DC00000>MOV DWORD PTR SS:[ESP+DC],-1
004073CF |. E8 AF120400  CALL PicHunte.00448683
004073D4 |. 33C0      XOR EAX,EAX
004073D6 |> 8B8C24 D400000>MOV ECX,DWORD PTR SS:[ESP+D4]
004073DD |. 5E       POP ESI
004073DE |. 64:890D 000000>MOV DWORD PTR FS:[0],ECX
004073E5 |. 81C4 DC000000 ADD ESP,0DC
004073EB \. C2 0800    RETN 8


所以註冊碼由兩部分組成,長度為註冊名長度+1。至此,海月圖片獵手(SeaMoon Pic Hunter) 1.52 註冊演算法分析完成,由於是國產軟體,所以不提供註冊碼。

------------------------------------------------------------------------

炎之川
屬於中國破解組織BCG (BeGiNnEr'S CrAcKiNg Group)

  _/_/_/   _/_/_/   _/_/_/
  _/  _/ _/     _/
 _/_/_/  _/     _/ _/_/
_/  _/ _/     _/  _/
_/_/_/   _/_/_/   _/_/_/

相關文章