Sitman2.1 演算法分析 (5千字)

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

馬上就要英語考試了,所以對關於英語的軟體比較感興趣,
上網偶然發現 Sitman2.1,下之,沒想到一執行就過期了,
一大堆提示,實在不爽,以為是明碼比較,弄掉了事算了,
沒想到還挺複雜,氣不過,鑽了進去……
(差點沒找到註冊的地方 :P  , 雙擊‘未註冊’)
----------------------------------------------------------------

1、3=< 姓名長度 <=20
2、註冊碼長度 = 18

下hmemcpy 跟到此處:
0167:0049307D  MOV    ESI,00000001
0167:00493082  MOV    EBX,00000001
0167:00493087  MOV    EAX,[EBP-04]
0167:0049308A  CALL    00403EA0          *|
0167:0049308F  MOV    EDI,EAX          *| 計算姓名長度
0167:00493091  TEST    EDI,EDI          *|
0167:00493093  JLE    004930B6          *|
0167:00493095  MOV    ECX,00000001
0167:0049309A  MOV    EAX,[EBP-04]
0167:0049309D  MOVZX  EAX,Byte Ptr [EAX+1*ECX-01]    *| 姓名的地址
0167:004930A2  IMUL    EBX
0167:004930A4  ADD    EAX,ESI
0167:004930A6  ADD    EAX,ECX
0167:004930A8  MOV    EBX,00000165
0167:004930AD  CDQ   
0167:004930AE  IDIV    EBX
0167:004930B0  MOV    EBX,EDX
0167:004930B2  INC    ECX
0167:004930B3  DEC    EDI
0167:004930B4  JNZ    0049309A
0167:004930B6  MOV    EAX,EBX
0167:004930B8  MOV    ECX,00000024
0167:004930BD  CDQ   
0167:004930BE  IDIV    ECX
0167:004930C0  MOV    EAX,004931BC    *| 這是一張表:0~9和a~z 共36個字元
0167:004930C5  MOVZX  EAX,Byte Ptr [EAX+1*EDX]      *| 正確值
0167:004930C9  MOV    EDX,[EBP-08]
0167:004930CC  MOVZX  EDX,Byte Ptr [EDX+1*ESI-01]  *| 錯誤值
0167:004930D1  SUB    EDX,EAX
0167:004930D3  ADD    EDX,000000AE
0167:004930D9  CMP    EDX,000000AE
0167:004930DF  JNZ    00493167
0167:004930E5  INC    ESI
0167:004930E6  CMP    ESI,00000004
0167:004930E9  JNZ    00493082

到此,程式會執行三次,來檢查註冊碼的由使用者名稱計算出的前三位註冊碼
----------------------------------------------------------------------
接著走,以下這些程式碼是透過計算4~9位註冊碼,得出一個值

0167:004930EB  MOV    EBX,00000001
0167:004930F0  MOV    EDI,00000001
0167:004930F5  MOV    ESI,0000000A
0167:004930FA  MOV    ECX,00000001
0167:004930FF  MOV    EAX,[EBP-08]
0167:00493102  MOVZX  EAX,Byte Ptr [EAX+1*ECX-01]
0167:00493107  IMUL    EBX
0167:00493109  ADD    EAX,ECX
0167:0049310B  ADD    EAX,ESI
0167:0049310D  MOV    EBX,00000179
0167:00493112  CDQ   
0167:00493113  IDIV    EBX
0167:00493115  MOV    EBX,EDX
0167:00493117  INC    ECX
0167:00493118  CMP    ECX,0000000A
0167:0049311B  JNZ    004930FF
0167:0049311D  MOV    EAX,EBX
0167:0049311F  MOV    ECX,00000024
0167:00493124  CDQ   
0167:00493125  IDIV    ECX
0167:00493127  MOV    EAX,EDX
0167:00493129  IMUL    ESI
0167:0049312B  ADD    EAX,ESI
0167:0049312D  MOV    ECX,00000025
0167:00493132  CDQ   
0167:00493133  IDIV    ECX
0167:00493135  MOV    ECX,EDX
0167:00493137  MOV    EAX,EDI
0167:00493139  MOV    EDI,00000023
0167:0049313E  CDQ   
0167:0049313F  IDIV    EDI
0167:00493141  ADD    ECX,EDX
0167:00493143  MOV    EDI,ECX              *| 這個EDI很重要哦
0167:00493145  INC    ESI
0167:00493146  CMP    ESI,00000013
0167:00493149  JNZ    004930FA
0167:0049314B  LEA    EDX,[EBP-14]
0167:0049314E  MOV    EAX,[004AAAA4]
0167:00493153  SUB    EAX,EDI              *| EAX得零就OK了

不知道大家注意到[004AAAA4]這個地址沒有?程式拿這裡的值和EDI比較,
而在附近又看不到關於它的運算,很可能是在輸入時進行的運算……
-------------------------------------------------------------------
在輸入時下hmemcpy中斷,將會到此(註冊碼得夠18位)
透過註冊碼的9~18位計算出[004AAAA4]的值

0167:00493791  MOV    DWord Ptr [004AAAA4],00000001
0167:0049379B  MOV    EBX,00000001
0167:004937A0  MOV    EAX,[EBP-04]
0167:004937A3  MOV    AL,[EAX+1*EBX+08]  *| 註冊碼後九位的地址
0167:004937A7  CALL    0049396C            *| 進去看看……
0167:004937AC  LEA    EDX,[EBX+09]
0167:004937AF  IMUL    EDX
0167:004937B1  MOV    ECX,00000025
0167:004937B6  CDQ   
0167:004937B7  IDIV    ECX
0167:004937B9  MOV    ECX,EDX
0167:004937BB  MOV    EAX,[004AAAA4]
0167:004937C0  MOV    ESI,00000023
0167:004937C5  CDQ   
0167:004937C6  IDIV    ESI
0167:004937C8  ADD    ECX,EDX
0167:004937CA  MOV    [004AAAA4],ECX
0167:004937D0  INC    EBX
0167:004937D1  CMP    EBX,0000000A
0167:004937D4  JNZ    004937A0
===================================================0049396C
0167:0049396F  MOV    EDX,00000001
0167:00493974  MOV    EBX,00493998
0167:00493979  CMP    AL,[EBX+1*EDX-01]    *| 用來計算出9~18位註冊碼
0167:0049397D  JNZ    00493983              *| 在表中的位置,存放到了
0167:0049397F  MOV    ECX,EDX              *| EAX中.
0167:00493981  JMP    00493989
0167:00493983  INC    EDX
0167:00493984  CMP    EDX,00000025
0167:00493987  JNZ    00493974
0167:00493989  MOV    EAX,ECX
===================================================0049396C
用D5算出一個號,添上,OK!
可重啟一下,KAO,居然又成‘未註冊’的了,Shit !!
既然註冊時沒事,那肯定是啟動時做的手腳了。
又費了半天勁,用regqueryvaluea跟至:

0167:004A6FDB  MOV    EAX,EBX        *| EAX竟是4~9位的值!!!
0167:004A6FDD  MOV    ECX,000003E8
0167:004A6FE2  CDQ   
0167:004A6FE3  IDIV    ECX
0167:004A6FE5  CMP    EAX,00000064
0167:004A6FE8  JZ      004A6FF2

原來這裡在搞鬼!把4~9 位的值限制在100000~100999中,不能用字元,會出錯
------------------------------------------------------------

把4~9位換一下,測試透過!

感謝精華四中eCool[BCG]前輩的文章給我的啟示!

小弟淺薄,如有錯誤,還請指教。


                                                    Cyu

                                              cyu000@sina.com

相關文章