• 标 题:Sitman2.1 算法分析 (5千字)
  • 作 者:Cyu_
  • 时 间:2002-6-15 19:47:49
  • 链 接:http://bbs.pediy.com

马上就要英语考试了,所以对关于英语的软件比较感兴趣,
上网偶然发现 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