演算法分析: <獻給初學者> 之四 (9千字)

看雪資料發表於2002-06-06

演算法分析:  <獻給初學者> 之四

▲ 作  者 : goodbao[P.J.CHINA]

▲軟體名稱:象棋大戰 v1.05

▲下載地址:
http://www.softreg.com/shareware_view.asp?id={31EC207B-10AC-4216-86C7-7A3C4058B0EA}

▲軟體簡介:
  一款不錯的象棋遊戲,採用DirectDraw程式設計,標準Window遊戲介面,畫面精美,支援人機對戰,雙人對戰。

▲破解難度:非明碼比較,較難(反正我是沒有跟蹤明碼,直接看演算法就會知道是非明碼的。其實,如果使用“偷天換日大法”來破解的話,也可以很快破解成功的,只是需要改變跳轉方向的地方稍顯多了些。呵呵。。。。。。。。。。)

▲演算法難度:較難

▲演算法分析▲
  這又是一個非明碼的共享軟體。應該說其加密並不怎麼深奧,之所以把它的演算法難度列為較難,是因為作為一名初學者,如果不認真細緻地分析其演算法的話,很容易失手的。所以,姑且這樣評價吧。

  首先,應該說明的是:此款遊戲的畫面並非精美,而且有種迴歸DOS的感覺。況且其註冊時,註冊名是不參與演算法之中的,所以註冊名可以任意。再者,它的註冊碼必須有9位,多或少都不行。為什麼?請隨我來吧!準備好了嗎?Let's go!!!!!!!!!

  設斷、註冊、攔截、清斷,不必細說了吧?然後我們按11次F12,就會到達下邊這裡:

* Reference To: USER32.GetDlgItemTextA, Ord:0104h
|
:004071EC 8B35A8734100 mov esi, dword ptr [004173A8]
:004071F2 8D442440 lea eax, dword ptr [esp+40]
:004071F6 6A13 push 00000013
:004071F8 50 push eax
:004071F9 68E8030000 push 000003E8
:004071FE 53 push ebx
:004071FF FFD6 call esi
:00407201 8D4C2420 lea ecx, dword ptr [esp+20] ==>停在這裡。F10直到
:00407205 6A1C push 0000001C
:00407207 51 push ecx

…… 略去 ……

:0040723E AE scasb
:0040723F F7D1 not ecx
:00407241 49 dec ecx
:00407242 83F909 cmp ecx, 00000009 ==>註冊碼是否是9位?
:00407245 0F85A9010000 jne 004073F4 ==>不是則跳,那就死嘍!

==================演算法開始===================

:0040724B 8A442420 mov al, byte ptr [esp+20]==>取第一位註冊碼的16進位制值
:0040724F 3C4D cmp al, 4D =======>是否等於4D(即字母M)?
:00407251 740C je 0040725F =======>是就跳!如不是,那麼……
:00407253 3C41 cmp al, 41 =======>是否等於41(即字母A)?
:00407255 7408 je 0040725F =======>是就跳!如不是,那麼……
:00407257 3C4F cmp al, 4F =======>是否等於4F(即字母O)?
:00407259 0F8595010000 jne 004073F4 =======>全不是?對不起,死嘍!!

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00407251(C), :00407255(C)
|
:0040725F 8A442421 mov al, byte ptr [esp+21]==>取第二位註冊碼的16進位制值
:00407263 3C57 cmp al, 57 =======>是否等於57(即字母W)?
:00407265 7410 je 00407277 =======>是就跳!如不是,那麼……
:00407267 3C45 cmp al, 45 =======>是否等於45(即字母E)?
:00407269 740C je 00407277 =======>是就跳!如不是,那麼……
:0040726B 3C4E cmp al, 4E =======>是否等於4E(即字母N)?
:0040726D 7408 je 00407277 =======>是就跳!如不是,那麼……
:0040726F 3C47 cmp al, 47 =======>是否等於47(即字母G)?
:00407271 0F857D010000 jne 004073F4 =======>還不是?慘嘍,跳死啦!!

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00407265(C), :00407269(C), :0040726D(C)
|
:00407277 0FBE442422 movsx eax, byte ptr [esp+22]=>取第三位註冊碼的16進位制值
並將此值賦給EAX
:0040727C 99 cdq
:0040727D B911000000 mov ecx, 00000011 =======>ECX=11(16進位制)
:00407282 F7F9 idiv ecx =======>EAX除以ECX,餘數送EDX
:00407284 85D2 test edx, edx =======>整除盡了嗎?
:00407286 0F8568010000 jne 004073F4 =======>除不盡就跳死嘍!!!!


:0040728C 8A442423 mov al, byte ptr [esp+23]====>取第四位註冊碼的16進位制值
:00407290 3C4A cmp al, 4A =======>是否等於4A(即字母J)?
:00407292 7410 je 004072A4 =======>是就跳!如不是,那麼……
:00407294 3C49 cmp al, 49 =======>是否等於49(即字母I)?
:00407296 740C je 004072A4 =======>是就跳!如不是,那麼……
:00407298 3C41 cmp al, 41 =======>是否等於41(即字母A)?
:0040729A 7408 je 004072A4 =======>是就跳!如不是,那麼……
:0040729C 3C4E cmp al, 4E =======>是否等於4E(即字母N)?
:0040729E 0F8550010000 jne 004073F4 =======>都不是呀?那死定嘍!!!


* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00407292(C), :00407296(C), :0040729A(C)
|
:004072A4 8A442424 mov al, byte ptr [esp+24]====>取第五位註冊碼的16進位制值
:004072A8 3C58 cmp al, 58 =======>是否等於58(即字母X)?
:004072AA 740C je 004072B8 =======>是就跳!如不是,那麼……
:004072AC 3C49 cmp al, 49 =======>是否等於49(即字母I)?
:004072AE 7408 je 004072B8 =======>是就跳!如不是,那麼……
:004072B0 3C55 cmp al, 55 =======>是否等於55(即字母U)?
:004072B2 0F853C010000 jne 004073F4 =======>還不是呀?完蛋啦!!!!


* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004072AA(C), :004072AE(C)
|
:004072B8 0FBE442425 movsx eax, byte ptr [esp+25]=>取第六位註冊碼的16進位制值
並將此值賦給EAX
:004072BD 99 cdq
:004072BE B903000000 mov ecx, 00000003 =======>ECX=03(16進位制)
:004072C3 F7F9 idiv ecx =======>EAX除以ECX,餘數送EDX
:004072C5 85D2 test edx, edx =======>整除盡了嗎?
:004072C7 0F8527010000 jne 004073F4 =======>除不盡?完蛋啦!嗚嗚~~


:004072CD 8A442426 mov al, byte ptr [esp+26]====>取第七位註冊碼的16進位制值
:004072D1 3C51 cmp al, 51 =======>是否等於51(即字母Q)?
:004072D3 7408 je 004072DD =======>是就跳!如不是,那麼……
:004072D5 3C49 cmp al, 49 =======>是否等於49(即字母I)?
:004072D7 0F8517010000 jne 004073F4 =======>全不是?玩完大吉啦!!!


* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004072D3(C)
|
:004072DD 8A442427 mov al, byte ptr [esp+27]====>取第八位註冊碼的16進位制值
:004072E1 3C59 cmp al, 59 =======>是否等於59(即字母Y)?
:004072E3 740C je 004072F1 =======>是就跳!如不是,那麼……
:004072E5 3C55 cmp al, 55 =======>是否等於55(即字母U)?
:004072E7 7408 je 004072F1 =======>是就跳!如不是,那麼……
:004072E9 3C4E cmp al, 4E =======>是否等於4E(即字母N)?
:004072EB 0F8503010000 jne 004073F4 =======>千萬不能跳呀!!!!!!

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004072E3(C), :004072E7(C)
|
:004072F1 0FBE442428 movsx eax, byte ptr [esp+28]=>取第九位註冊碼的16進位制值
:004072F6 99 cdq
:004072F7 B90D000000 mov ecx, 0000000D =======>ECX=0D(16進位制)
:004072FC F7F9 idiv ecx =======>EAX除以ECX,餘數送EDX
:004072FE 85D2 test edx, edx =======>整除盡了嗎?
:00407300 0F85EE000000 jne 004073F4 =======>千萬不能跳呀!!!!!

▲以下略去…………▲

:00407306 8D4C2410 lea ecx, dword ptr [esp+10]
:0040730A E8F6960000 call 00410A05

* Possible StringData Ref from Data Obj ->"chess.mjq"
|
:0040730F BF78B14100 mov edi, 0041B178
:00407314 83C9FF or ecx, FFFFFFFF
:00407317 33C0 xor eax, eax
:00407319 8D542454 lea edx, dword ptr [esp+54]
:0040731D F2 repnz
:0040731E AE scasb
:0040731F F7D1 not ecx
:00407321 2BF9 sub edi, ecx
:00407323 C784246001000000000000 mov dword ptr [esp+00000160], 00000000
:0040732E 8BC1 mov eax, ecx
:00407330 8BF7 mov esi, edi
:00407332 8BFA mov edi, edx
:00407334 C644240F0B mov [esp+0F], 0B
:00407339 C1E902 shr ecx, 02
:0040733C F3 repz
:0040733D A5 movsd
:0040733E 8BC8 mov ecx, eax
:00407340 83E103 and ecx, 00000003
:00407343 F3 repz
:00407344 A4 movsb
:00407345 8D4C2454 lea ecx, dword ptr [esp+54]
:00407349 51 push ecx
:0040734A E8B1FDFFFF call 00407100
:0040734F 83C404 add esp, 00000004
:00407352 8D542454 lea edx, dword ptr [esp+54]
:00407356 8D4C2410 lea ecx, dword ptr [esp+10]
:0040735A 6A00 push 00000000
:0040735C 6802300000 push 00003002
:00407361 52 push edx
:00407362 E8B0970000 call 00410B17
:00407367 6A02 push 00000002
:00407369 6A00 push 00000000
:0040736B 8B442418 mov eax, dword ptr [esp+18]
:0040736F 8D4C2418 lea ecx, dword ptr [esp+18]
:00407373 FF5028 call [eax+28]
:00407376 6A01 push 00000001
:00407378 6AFF push FFFFFFFF
:0040737A 8D4C2418 lea ecx, dword ptr [esp+18]
:0040737E E836990000 call 00410CB9
:00407383 8D4C240F lea ecx, dword ptr [esp+0F]
:00407387 6A01 push 00000001
:00407389 51 push ecx
:0040738A 8D4C2418 lea ecx, dword ptr [esp+18]
:0040738E E8DB980000 call 00410C6E
:00407393 8D4C2410 lea ecx, dword ptr [esp+10]
:00407397 E896990000 call 00410D32
:0040739C 6A00 push 00000000
:0040739E 53 push ebx

* Reference To: USER32.ShowWindow, Ord:026Ah
|
:0040739F FF15AC734100 Call dword ptr [004173AC]
:004073A5 6A00 push 00000000

* Possible StringData Ref from Data Obj ->"謝謝"
|
:004073A7 68CCB14100 push 0041B1CC

* Possible StringData Ref from Data Obj ->"非常感謝您的註冊!"
|
:004073AC 68B8B14100 push 0041B1B8
:004073B1 53 push ebx

▲演算法總結▲
  寫了這麼多,真地有點兒累啦!好了,讓我們總結一下吧!
第一位註冊碼:必須為M或A或O。
第二位註冊碼:必須為W或E或N或G。
第三位註冊碼:必須能被11(16進位制)整除。
第四位註冊碼:必須為J或I或A或N。
第五位註冊碼:必須為X或I或U。
第六位註冊碼:必須能被03(16進位制)整除。
第七位註冊碼:必須為Q或I。
第八位註冊碼:必須為Y或U或N。
第九位註冊碼:必須能被0D(16進位制)整除。

  好累呀!!!!!呵呵,演算法真地不是好搞的,只除錯過程中的手抄、記錄和除錯後的演算法分析就夠讓人受得了。哈哈!!!!!!!!!!!!!!

--------------------------------------------------------------------------------
   神龍寶寶
goodbao[P.J.CHINA][BCG][CNCG]

相關文章