且行且远
分类: 且行且远 由 ssfighter 于 2006年07月13日 发表

这两天在新水上自习,也就经常能路过二校门,这次可算是切身感受到了暑假清华园的拥挤,大大小小的旅游团,领着大大小小的学生们,在大礼堂、荷塘等地劈里啪啦地拍照,还有一些单独来清华参观的一家人,把二校门附近弄得水泄不通,似乎每年的暑假都是清华园最拥挤的时候,形形色色的旅行团,而且都是带着不大的小孩儿来参观的居多,想想挺不能理解的,怪热的天,在家呆着吹吹空调,看看电视,喝喝饮料不好吗?费得着遭这么大罪来清华参观吗?

据说我挺小的时候也来过清华呢,据说那次是我妈来清华开会,就顺便把我带来了,也许拍过照,但我肯定是不知道了,因为那时候我好像才三岁,家长都是好心吧,希望孩子看看这所谓的中国最高学府(姑且认为就是吧),然后长长志气,于是这样的旅行团也就应运而生,今年又看到了“我到北京上大学”这样的旅游团,想起来有一年我到南京旅游来看见了这个旅游团呢,当时还不知道干啥的,后来回到学校在二校门那里看到了这个团,终于明白了,就是带着一帮小孩儿到北京的几个比较有名的大学都转一圈吧,这钱挣的也真容易,哦,对不起,应该说家长这个钱扔的也真容易,不知道这些小孩子在这边参观能看到啥东西,尤其是一些很小的小学生,也许现在的小孩儿都早熟?反正我记得我小学的时候就是仅仅听过清华这两个字而已,对其他的没有任何了解了。可是家长不这么想,他们会觉得让自己的孩子来学校看看,长长见识,会增加他们学习的动力,可是事实上呢?这些小孩子只顾着找能代表清华的风物拍照了,我是看不出他们对这个学校有来啥了解,增强了啥动力,问题是这么小的孩子,他们能明白啥叫动力吗?家长们不觉得这个钱花的太冤枉了吗?这么热的天,花着这么多钱让孩子来这地方遭罪有意义吗?有钱的话就在家里多吹吹空调吧……


分类: 且行且远 由 ssfighter 于 2006年07月9日 发表

或许是我比较土,今天才听说的西安交大拍的《未曾雕刻的时光》这部学生DV,以前就比较喜欢西交拍的DV,02年的《我的黄金时代》就给我留下了很深的印象,那细腻的大学生活的描绘,那对大学生活无限的回味,以及那永远带着一些淡淡的忧伤,总是在那不经意间触及那许久未被触及的内心,以及对那未曾雕刻的时光的无尽的怀念。

最近心情一直都不是很好,对生活、对未来的很多的想法交织在一起,总是弄得心情很糟,也很烦乱,很多时候在大学的生活,我们自己都不知道自己在追求一些什么,只是浑浑噩噩地过日子,并非全然没有理想,只是理想离我们似乎过于遥远,我们也只是按照不知道谁制定的既定的轨迹走着自己的路,我们就这样漫不经心地走着,似乎全然没有注意到自己身边的风景,也来不及注意这些。然而恍惚间,四年韶光易逝,就在不经意间,那熟悉的风景,那熟悉的人,就将在我们不经意的回首间成为永远,大学时光到底给了我们怎样的回忆?或许我们每个人都说不清,然而大学生活的那段情愫却将伴随我们一世,永生难忘。

很多事情我们似乎已经习以为常,就像我们身边陪伴的那个人一样。就像片中所说,或许很多时候,我们身边的人并不一定是那个我们内心深处的那个人,只是那个人已经成为了我们的习惯和责任而已,而这种习惯和责任似乎已经进入了我们的血液,让我们已经熟悉了这一切,也逐渐接受了这一切。然而,当心中的那个人突然出现在自己面前的时候,当那个人猛然间出现在自己面前的时候,自己还能否恪守内心的底线?我不知道我会不会……也许我早已忘记自己的内心的那个人了,或许只有她出现的时候我才知道那人是不是已经在我的内心中隐藏了好久。或许我们每个人都是这样,只是我们不愿意承认,不愿意面对而已。然而,当那个人重新出现的时候,我们应该如何选择?或许这永远都是一个让所有人都无法选择的一个难题吧。我mm曾经问过我很多次,当zmy再回来找我的时候,我会不会接受她。我虽然知道这一切都不可能发生,但是这样的问题确实也曾经困扰过我,是因为什么?可能陆毅的一首歌里说得很好:不是放不开,是还有期待,因为有期待,才放不开。对我们每个人来说,心中的那个人,其实就是自己还有期待的那个,但是这份期待是否值得,这份期待成为现实是否就是最好,这是一个很难回答的问题,只是,也许,习惯就是最好,也许年轻的时候就该轰轰烈烈地爱一场?但是,谁又知道呢?大学,本就应该是一段未曾雕刻的时光,应该是一段恣情的时光,应该是一段敢爱敢恨的时光,谁能说什么是对,什么又是错呢?


分类: 随心所记 由 ssfighter 于 2006年06月3日 发表

问题已经好久了,就是打开CHM文件的时候,经常会遇到一些页面根本无法打开,而有些页面就一点问题都没有。可以肯定的是CHM文件是没有坏的,因为我以前还看的好好的,而且从网上新下载的一个CHM文件,别人都说是好的,而好多页面也是只有我这里才打不开,郁闷至极。

刚才从网上下载了个查杀木马的程序,想扫描一下电脑看有没有病毒,结果查到了Windows目录下有一个wc98pp.dll的文件是木马文件,上网上查了一下,好像是说这个程序原本是微软的一个协议,一般用来防电子书的反编译的,但是也可能会被篡改,我看了一下那个文件修改的时间,5月31号,我装电脑是五一前后,估计就是被修改过了,索性直接删掉,然后再把注册表里所有有关这个文件的键值全cut掉,重新启动之后发现CHM文件又可以看了,哈哈,开心:)

虽然不明白具体的原因,但是电脑问题解决了:)


分类: 逆向手札 由 ssfighter 于 2006年06月2日 发表

【破文标题】十万个为什么 – 知识问答2006 破解分析
【破文作者】ssfighter@newsmth
【作者邮箱】ssfighter@gmail.com
【作者主页】
【破解工具】OllyICE PEiD0.94 VBExplorer
【破解平台】WinXP
【软件名称】十万个为什么 – 知识问答2006语言版
【软件大小】4.7M
【原版下载】
【保护方式】AsPack加壳,未注册有30次使用限制
【软件简介】一个知识问答的软件,有语言提示。
【破解声明】只是感兴趣,没有任何目的,如有错误之处还请大侠指出
————————————————————————
在天空软件站上找到的这个软件,题库还是很大的,没事的时候休闲一下还是很不错的选择,当然,我们的目的是破解这个软件。首先用PEiD侦壳,显示为 ASPack 2.12 -> Alexey Solodovnikov。用AsPackDie脱壳不表。脱壳之后程序无法启动,估计是有文件大小的检验,侦壳发现是用VB编写的。顺便说一句,这个程序防破解的限制还是比较多的,因此要有点耐心。
用Ollydbg载入,直接下API断点bp rtcFileLen,Ctrl+F9返回后来到这里:
004F0619   .  FF15 98114000 call    near ds:[<&MSVBVM60.#578>]       ;  MSVBVM60.rtcFileLen
004F061F   .  3D 70190800   cmp     eax, 81970                       ;  比较文件大小
004F0624   .  7E 12         jle     short unpacked.004F0638
004F0626   .  C745 FC 05000>mov     dword ptr ss:[ebp-4], 5
004F062D   .  FF15 34104000 call    near ds:[<&MSVBVM60.__vbaEnd>]   ;  MSVBVM60.__vbaEnd
若要这里跳过文件大小校验,只要把jle改成jmp强制跳转即可,这样程序就可以启动了。

但是如果你是用Ollydbg等调试器载入的,程序会出错并自动关机,说明程序检验了调试器,虽然我是用odbg的修改版OllyICE载入的,可以正常启动不会出问题,但是还是先把检验去掉好些。用Ultra String Reference插件搜索所有UNICODE字符串,找Ollydbg,发现了两处参考,先到第一处看看,来到这里:
0055B668   .  68 58804400   push    unpacked.00448058                ;  ollydbg
0055B66D   .  8D4D CC       lea     ecx, ss:[ebp-34]
0055B670   .  51            push    ecx
0055B671   .  FF15 B8114000 call    near ds:[<&MSVBVM60.__vbaStrToAn>;  MSVBVM60.__vbaStrToAnsi
0055B677   .  50            push    eax
0055B678   .  6A 00         push    0
0055B67A   .  6A 00         push    0
0055B67C   .  E8 0BC9EEFF   call    unpacked.00447F8C
0055B681   .  8945 A4       mov     ss:[ebp-5C], eax
0055B684   .  FF15 5C104000 call    near ds:[<&MSVBVM60.__vbaSetSyst>;  MSVBVM60.__vbaSetSystemError
0055B68A   .  8B55 A4       mov     edx, ss:[ebp-5C]
0055B68D   .  8955 D8       mov     ss:[ebp-28], edx
0055B690   .  8D4D CC       lea     ecx, ss:[ebp-34]
0055B693   .  FF15 10124000 call    near ds:[<&MSVBVM60.__vbaFreeStr>;  MSVBVM60.__vbaFreeStr
0055B699   .  C745 FC 10000>mov     dword ptr ss:[ebp-4], 10
0055B6A0   .  837D D8 00    cmp     dword ptr ss:[ebp-28], 0
0055B6A4   .  0F84 93000000 je      unpacked.0055B73D

注意这个跳转,如果不跳的话会来到这里:
0055CBD7   .  C745 FC 11000>mov     dword ptr ss:[ebp-4], 11
0055CBDE   .  C745 B4 F0834>mov     dword ptr ss:[ebp-4C], unpacked.>;  rundll32 user.exe,exitwindows
0055CBE5   .  C745 AC 08000>mov     dword ptr ss:[ebp-54], 8
0055CBEC   .  8D55 AC       lea     edx, ss:[ebp-54]
0055CBEF   .  8D4D BC       lea     ecx, ss:[ebp-44]
0055CBF2   .  FF15 BC114000 call    near ds:[<&MSVBVM60.__vbaVarDup>>;  MSVBVM60.__vbaVarDup
0055CBF8   .  6A 00         push    0
0055CBFA   .  8D55 BC       lea     edx, ss:[ebp-44]
0055CBFD   .  52            push    edx
0055CBFE   .  FF15 14114000 call    near ds:[<&MSVBVM60.#600>]       ;  MSVBVM60.rtcShell
0055CC04   .  DD5D A4       fstp    qword ptr ss:[ebp-5C]
0055CC07   .  8D4D BC       lea     ecx, ss:[ebp-44]
0055CC0A   .  FF15 20104000 call    near ds:[<&MSVBVM60.__vbaFreeVar>;  MSVBVM60.__vbaFreeVar
0055CC10   .  C745 FC 12000>mov     dword ptr ss:[ebp-4], 12
0055CC17   .  C745 B4 30844>mov     dword ptr ss:[ebp-4C], unpacked.>;  shutdown -s
0055CC1E   .  C745 AC 08000>mov     dword ptr ss:[ebp-54], 8
0055CC25   .  8D55 AC       lea     edx, ss:[ebp-54]
0055CC28   .  8D4D BC       lea     ecx, ss:[ebp-44]
0055CC2B   .  FF15 BC114000 call    near ds:[<&MSVBVM60.__vbaVarDup>>;  MSVBVM60.__vbaVarDup
0055CC31   .  6A 00         push    0
0055CC33   .  8D45 BC       lea     eax, ss:[ebp-44]
0055CC36   .  50            push    eax
0055CC37   .  FF15 14114000 call    near ds:[<&MSVBVM60.#600>]       ;  MSVBVM60.rtcShell

呵呵,看到上面的东西了吧,当程序检测到有调试器在运行的时候就会运行shutdown -s命令关机,因此把55B6A4处的je改成jmp强制跳转即可。当然,这还没完,程序还检测了一次调试器,记得刚才的ollydbg有两处参考吧,来到第二处,在这里:
0055E2A4   .  68 08854400   push    unpacked.00448508                ;  ollydbg
0055E2A9   .  FF15 D8104000 call    near ds:[<&MSVBVM60.__vbaStrCmp>>;  MSVBVM60.__vbaStrCmp
0055E2AF   .  F7D8          neg     eax
0055E2B1   .  1BC0          sbb     eax, eax
0055E2B3   .  40            inc     eax
0055E2B4   .  F7D8          neg     eax
0055E2B6   .  66:0BF0       or      si, ax

往前后翻翻看一看,这里简直汇集了众多破解工具,程序当检测到任何一种破解工具就会自动关机。来到下面的判断的地方:
0055E65A   .  83C4 64       add     esp, 64
0055E65D   .  0FBF8D ECFDFF>movsx   ecx, word ptr ss:[ebp-214]
0055E664   .  85C9          test    ecx, ecx
0055E666   .  0F84 E6000000 je      unpacked.0055E752
把这里的跳转也改成jmp即可,到此为止,放破解的限制基本解除,但是程序还是不允许Smart Check调试,我不知道他还有什么地方还有限制了,而且这个程序一启动的时候是启动一个fpj.frm的窗口,这个窗口先检查有没有调试器正在跟踪,如果没有的话就运行,否则自动关机。

到这里的时候我已经运行了20多次了,因此必须赶紧知道程序对30次使用限制的东西在哪儿,用 RegSnap可以看到程序在每次运行在注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\QQPP里面修改了 jiv1b这个键值,这里记录的就是已经使用的次数。注意,如果前面没有把放破解的限制去掉的话,是不能在程序运行的时候使用RegSnap的,否则就会关机,当然最简单的办法是在程序运行前执行一次扫描,程序运行后再执行一次扫描,呵呵,这属于小trick了,本不属于本文的范围的。

言归正传,来到选择帮助-注册菜单,程序又退出了,看来作者也真够狡猾的,这里居然又验了一次文件大小,仍然下API断点bp rtcFileLen,停在这里:
00566A6B    FF15 98114000   call    near ds:[<&MSVBVM60.#578>]       ; MSVBVM60.rtcFileLen
00566A71    3D 52FA0800     cmp     eax, 8FA52
00566A76    7E 0D           jle     short unpacked.00566A85
仍然是把这里对jle改成jmp强制跳转即可,至此所有限制都已取消了,就剩下分析注册码的计算过程了。

用VBExplorer查看一下确定按钮的地址00566B30,在这里下断点,odbg载入,运行,填入用户名ssfighter,注册码12345,确定后断在这里:
00566B30   > \55            push    ebp
00566B31   .  8BEC          mov     ebp, esp
00566B33   .  83EC 18       sub     esp, 18
00566B36   .  68 D6474000   push    <jmp.&MSVBVM60.__vbaExceptHandle>;  SE 处理程序安装
00566B3B   .  64:A1 0000000>mov     eax, fs:[0]
00566B41   .  50            push    eax

由于VB的程序比较长,全写下来太占地方了,我们一点点跟踪,略过前面一堆代码,来到这里:
00566FEF   .  50            push    eax                                  ;  用户名
00566FF0   .  FF15 24104000 call    near ds:[<&MSVBVM60.__vbaLenBstr>]   ;  取用户名长度
00566FF6   .  8BF0          mov     esi, eax
00566FF8   .  F7DE          neg     esi
00566FFA   .  1BF6          sbb     esi, esi
00566FFC   .  46            inc     esi
00566FFD   .  F7DE          neg     esi
00566FFF   .  8B4D B0       mov     ecx, ss:[ebp-50]
00567002   .  51            push    ecx                                  ;  注册码
00567003   .  FF15 24104000 call    near ds:[<&MSVBVM60.__vbaLenBstr>]   ;  取注册码长度
00567009   .  F7D8          neg     eax
0056700B   .  1BC0          sbb     eax, eax
0056700D   .  40            inc     eax
0056700E   .  F7D8          neg     eax
00567010   .  66:0BF0       or      si, ax
00567013   .  66:89B5 68FEF>mov     ss:[ebp-198], si
0056701A   .  8D55 B0       lea     edx, ss:[ebp-50]
0056701D   .  52            push    edx
0056701E   .  8D45 B4       lea     eax, ss:[ebp-4C]
00567021   .  50            push    eax
00567022   .  6A 02         push    2
00567024   .  FF15 8C114000 call    near ds:[<&MSVBVM60.__vbaFreeStrList>;  MSVBVM60.__vbaFreeStrList
0056702A   .  83C4 0C       add     esp, 0C
0056702D   .  8D4D 90       lea     ecx, ss:[ebp-70]
00567030   .  51            push    ecx
00567031   .  8D55 94       lea     edx, ss:[ebp-6C]
00567034   .  52            push    edx
00567035   .  6A 02         push    2
00567037   .  FF15 40104000 call    near ds:[<&MSVBVM60.__vbaFreeObjList>;  MSVBVM60.__vbaFreeObjList
0056703D   .  83C4 0C       add     esp, 0C
00567040   .  0FBF85 68FEFF>movsx   eax, word ptr ss:[ebp-198]
00567047   .  85C0          test    eax, eax
00567049   .  0F84 CB000000 je      unpacked.0056711A
这里只要用户名和注册码都不是空的即可,再往下跟,来到这里:

0056719B   > \6A 01         push    1
0056719D   .  8B4D B4       mov     ecx, ss:[ebp-4C]
005671A0   .  51            push    ecx
005671A1   .  FF15 D8114000 call    near ds:[<&MSVBVM60.#616>]           ;  MSVBVM60.rtcLeftCharBstr
这里是取用户名最左边一位,再往后看

00567245   > \6A 01         push    1
00567247   .  8B45 B4       mov     eax, ss:[ebp-4C]
0056724A   .  50            push    eax
0056724B   .  FF15 E4114000 call    near ds:[<&MSVBVM60.#618>]           ;  MSVBVM60.rtcRightCharBstr
这里是取用户名最后一位

00567251   .  8BD0          mov     edx, eax
00567253   .  8D4D DC       lea     ecx, ss:[ebp-24]
00567256   .  FF15 E8114000 call    near ds:[<&MSVBVM60.__vbaStrMove>]   ;  MSVBVM60.__vbaStrMove
0056725C   .  8D4D B4       lea     ecx, ss:[ebp-4C]
0056725F   .  FF15 10124000 call    near ds:[<&MSVBVM60.__vbaFreeStr>]   ;  MSVBVM60.__vbaFreeStr
00567265   .  8D4D 94       lea     ecx, ss:[ebp-6C]
00567268   .  FF15 14124000 call    near ds:[<&MSVBVM60.__vbaFreeObj>]   ;  MSVBVM60.__vbaFreeObj
0056726E   .  C745 FC 0E000>mov     dword ptr ss:[ebp-4], 0E
00567275   .  8B4D BC       mov     ecx, ss:[ebp-44]
00567278   .  51            push    ecx
00567279   .  FF15 44104000 call    near ds:[<&MSVBVM60.#516>]           ;  MSVBVM60.rtcAnsiValueBstr
0056727F   .  66:6BC0 0B    imul    ax, ax, 0B                           ;  用户名第一位ascii码乘以0B, 记作a
00567283   .  0F80 17110000 jo      unpacked.005683A0
00567289   .  66:8945 B8    mov     ss:[ebp-48], ax
0056728D   .  C745 FC 0F000>mov     dword ptr ss:[ebp-4], 0F
00567294   .  8B55 DC       mov     edx, ss:[ebp-24]
00567297   .  52            push    edx
00567298   .  FF15 44104000 call    near ds:[<&MSVBVM60.#516>]           ;  MSVBVM60.rtcAnsiValueBstr
0056729E   .  66:2D 4E00    sub     ax, 4E                               ;  用户名最后一位ascii码减去4E,记作b
005672A2   .  0F80 F8100000 jo      unpacked.005683A0
005672A8   .  66:8945 D0    mov     ss:[ebp-30], ax
005672AC   .  C745 FC 10000>mov     dword ptr ss:[ebp-4], 10
005672B3   .  66:8B45 B8    mov     ax, ss:[ebp-48]
005672B7   .  66:0345 D0    add     ax, ss:[ebp-30]                      ;  a+b,记作c
005672BB   .  0F80 DF100000 jo      unpacked.005683A0
005672C1   .  66:8945 D8    mov     ss:[ebp-28], ax
005672C5   .  C745 FC 11000>mov     dword ptr ss:[ebp-4], 11
005672CC   .  6A 04         push    4
005672CE   .  66:8B4D D8    mov     cx, ss:[ebp-28]
005672D2   .  51            push    ecx
005672D3   .  FF15 08104000 call    near ds:[<&MSVBVM60.__vbaStrI2>]     ;  c转化成字符串(10进制)
005672D9   .  8BD0          mov     edx, eax
005672DB   .  8D4D B4       lea     ecx, ss:[ebp-4C]
005672DE   .  FF15 E8114000 call    near ds:[<&MSVBVM60.__vbaStrMove>]   ;  MSVBVM60.__vbaStrMove
005672E4   .  50            push    eax
005672E5   .  FF15 E4114000 call    near ds:[<&MSVBVM60.#618>]           ;  取c的最右边4位
005672EB   .  8BD0          mov     edx, eax
005672ED   .  8D4D D4       lea     ecx, ss:[ebp-2C]
005672F0   .  FF15 E8114000 call    near ds:[<&MSVBVM60.__vbaStrMove>]   ;  MSVBVM60.__vbaStrMove
005672F6   .  8D4D B4       lea     ecx, ss:[ebp-4C]
005672F9   .  FF15 10124000 call    near ds:[<&MSVBVM60.__vbaFreeStr>]   ;  MSVBVM60.__vbaFreeStr
005672FF   .  C745 FC 12000>mov     dword ptr ss:[ebp-4], 12
00567306   .  8B55 D4       mov     edx, ss:[ebp-2C]
00567309   .  52            push    edx
0056730A   .  68 90644400   push    unpacked.00446490
0056730F   .  FF15 D8104000 call    near ds:[<&MSVBVM60.__vbaStrCmp>]    ;  c和”0″比较
00567315   .  8BF0          mov     esi, eax
00567317   .  F7DE          neg     esi
00567319   .  1BF6          sbb     esi, esi
0056731B   .  F7DE          neg     esi
0056731D   .  8B45 D4       mov     eax, ss:[ebp-2C]
00567320   .  50            push    eax
00567321   .  68 F0614400   push    unpacked.004461F0
00567326   .  FF15 D8104000 call    near ds:[<&MSVBVM60.__vbaStrCmp>]    ;  c和”"比较
0056732C   .  F7D8          neg     eax
0056732E   .  1BC0          sbb     eax, eax
00567330   .  F7D8          neg     eax
00567332   .  23F0          and     esi, eax
00567334   .  85F6          test    esi, esi
00567336   .  75 15         jnz     short unpacked.0056734D              ;  前面的两个比较取与,都不等则跳
00567338   .  C745 FC 13000>mov     dword ptr ss:[ebp-4], 13
0056733F   .  BA 8C8F4400   mov     edx, unpacked.00448F8C               ;  UNICODE “8723″
00567344   .  8D4D D4       lea     ecx, ss:[ebp-2C]
00567347   .  FF15 80114000 call    near ds:[<&MSVBVM60.__vbaStrCopy>]   ;  MSVBVM60.__vbaStrCopy
0056734D   > \C745 FC 15000>mov     dword ptr ss:[ebp-4], 15
注意这里,如果计算出来的c是”0″或者是空串则令c为”8723″。

再往下跳过一堆看不太懂的代码,来到这里:
005674D9   .  51            push    ecx
005674DA   .  6A 02         push    2
005674DC   .  8B55 B4       mov     edx, ss:[ebp-4C]
005674DF   .  52            push    edx
005674E0   .  FF15 B4104000 call    near ds:[<&MSVBVM60.#631>]           ;  取用户名第二位
005674E6   .  8BD0          mov     edx, eax
005674E8   .  8D4D B0       lea     ecx, ss:[ebp-50]
005674EB   .  FF15 E8114000 call    near ds:[<&MSVBVM60.__vbaStrMove>]   ;  MSVBVM60.__vbaStrMove
005674F1   .  50            push    eax
005674F2   .  68 08694400   push    unpacked.00446908
005674F7   .  FF15 D8104000 call    near ds:[<&MSVBVM60.__vbaStrCmp>]    ;  和”4″比较
005674FD   .  8BF0          mov     esi, eax
005674FF   .  F7DE          neg     esi
00567501   .  1BF6          sbb     esi, esi
00567503   .  46            inc     esi
00567504   .  F7DE          neg     esi
00567506   .  8B45 AC       mov     eax, ss:[ebp-54]
00567509   .  50            push    eax
0056750A   .  FF15 24104000 call    near ds:[<&MSVBVM60.__vbaLenBstr>]   ;  取用户名位数
00567510   .  33C9          xor     ecx, ecx
00567512   .  83F8 07       cmp     eax, 7                               ;  用户名位数和7比较
00567515   .  0F94C1        sete    cl                                   ;  如果不等则cl=0,相等则cl=1
00567518   .  F7D9          neg     ecx
0056751A   .  66:23F1       and     si, cx
0056751D   .  8B55 A8       mov     edx, ss:[ebp-58]
00567520   .  52            push    edx
00567521   .  6A 02         push    2
00567523   .  8B45 D4       mov     eax, ss:[ebp-2C]
00567526   .  50            push    eax
00567527   .  FF15 D8114000 call    near ds:[<&MSVBVM60.#616>]           ;  取c的前两位
0056752D   .  8BD0          mov     edx, eax
0056752F   .  8D4D A4       lea     ecx, ss:[ebp-5C]
00567532   .  FF15 E8114000 call    near ds:[<&MSVBVM60.__vbaStrMove>]   ;  MSVBVM60.__vbaStrMove
00567538   .  50            push    eax
00567539   .  68 9C8F4400   push    unpacked.00448F9C                    ;  UNICODE “0735″
0056753E   .  FF15 54104000 call    near ds:[<&MSVBVM60.__vbaStrCat>]    ;  c的前两位和0735连成一串
00567544   .  8BD0          mov     edx, eax
00567546   .  8D4D A0       lea     ecx, ss:[ebp-60]
00567549   .  FF15 E8114000 call    near ds:[<&MSVBVM60.__vbaStrMove>]   ;  MSVBVM60.__vbaStrMove
0056754F   .  50            push    eax
00567550   .  6A 02         push    2
00567552   .  8B4D D4       mov     ecx, ss:[ebp-2C]
00567555   .  51            push    ecx
00567556   .  FF15 E4114000 call    near ds:[<&MSVBVM60.#618>]           ;  取c的后两位
0056755C   .  8BD0          mov     edx, eax
0056755E   .  8D4D 9C       lea     ecx, ss:[ebp-64]
00567561   .  FF15 E8114000 call    near ds:[<&MSVBVM60.__vbaStrMove>]   ;  MSVBVM60.__vbaStrMove
00567567   .  50            push    eax
00567568   .  FF15 54104000 call    near ds:[<&MSVBVM60.__vbaStrCat>]    ;  把刚才得到的串和c的后两位再串起来
0056756E   .  8BD0          mov     edx, eax
00567570   .  8D4D 98       lea     ecx, ss:[ebp-68]
00567573   .  FF15 E8114000 call    near ds:[<&MSVBVM60.__vbaStrMove>]   ;  MSVBVM60.__vbaStrMove
00567579   .  50            push    eax
0056757A   .  FF15 D8104000 call    near ds:[<&MSVBVM60.__vbaStrCmp>]    ;  真假码比较
00567580   .  F7D8          neg     eax
00567582   .  1BC0          sbb     eax, eax
00567584   .  40            inc     eax
00567585   .  F7D8          neg     eax
00567587   .  66:23F0       and     si, ax
注意,这里真实的注册码已经计算出来,就是把0735插入到c的前两位与后两位之间,但是仅仅注册码对了还不行。再看下面:

005675DF   .  0FBF8D 60FEFF>movsx   ecx, word ptr ss:[ebp-1A0]
005675E6   .  85C9          test    ecx, ecx
005675E8   .  0F84 77090000 je      unpacked.00567F65
往前翻翻,这里其实是进行了三次判断,只有这三次判断都满足才能算注册通过,这三次分别是用户名第二位是否是4,用户名位数是否为7位,注册码是否正确,只有这三个都正确才能注册通过。当然如果想爆破都话把这里nop掉也就可以了,这个程序启动时不会验证用户名和注册码的关系,注册通过只是在注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\QQPP这里加上一个jiv3a的键,键值为5,启动时只判断这个是否正确来决定是否是注册版。

顺便写上启动时候的判断,在这里:
004F2252   .  BA 84714400   mov     edx, unpacked.00447184               ;  jiv3a
004F2257   .  8D4D C8       lea     ecx, ss:[ebp-38]
004F225A   .  FF15 80114000 call    near ds:[<&MSVBVM60.__vbaStrCopy>]   ;  MSVBVM60.__vbaStrCopy
004F2260   .  BA 50714400   mov     edx, unpacked.00447150               ;  software\microsoft\qqpp
004F2265   .  8D4D CC       lea     ecx, ss:[ebp-34]
004F2268   .  FF15 80114000 call    near ds:[<&MSVBVM60.__vbaStrCopy>]   ;  MSVBVM60.__vbaStrCopy
004F226E   .  C785 E4FEFFFF>mov     dword ptr ss:[ebp-11C], 80000002
004F2278   .  8D85 1CFFFFFF lea     eax, ss:[ebp-E4]
004F227E   .  50            push    eax
004F227F   .  8D4D C8       lea     ecx, ss:[ebp-38]
004F2282   .  51            push    ecx
004F2283   .  8D55 CC       lea     edx, ss:[ebp-34]
004F2286   .  52            push    edx
004F2287   .  8D85 E4FEFFFF lea     eax, ss:[ebp-11C]
004F228D   .  50            push    eax
004F228E   .  E8 CDC60600   call    unpacked.0055E960
004F2293   .  8D4D C8       lea     ecx, ss:[ebp-38]
004F2296   .  51            push    ecx
004F2297   .  8D55 CC       lea     edx, ss:[ebp-34]
004F229A   .  52            push    edx
004F229B   .  6A 02         push    2
004F229D   .  FF15 8C114000 call    near ds:[<&MSVBVM60.__vbaFreeStrList>;  MSVBVM60.__vbaFreeStrList
004F22A3   .  83C4 0C       add     esp, 0C
004F22A6   .  C745 FC 2B000>mov     dword ptr ss:[ebp-4], 2B
004F22AD   .  8B45 D4       mov     eax, ss:[ebp-2C]
004F22B0   .  50            push    eax
004F22B1   .  68 94714400   push    unpacked.00447194                    ;  5
004F22B6   .  FF15 D8104000 call    near ds:[<&MSVBVM60.__vbaStrCmp>]    ;  MSVBVM60.__vbaStrCmp
004F22BC   .  85C0          test    eax, eax
004F22BE   .  0F85 51010000 jnz     unpacked.004F2415
当然,把这里nop掉也可以实现爆破。

————————————————————————
总结一下,程序注册的规律是:用户名必须是7位,用户名第二位必须是4。
注册码的计算方法(以下均为10进制):取用户名第一位,ascii码乘以11,再取用户名最后一位,ascii码减去78,两者求和,如果这个和大于4位则取最后4位,如果结果是0或者不存在则令其是8723,并在这个数的前两位和后两位之间插入0735,这八位数字就是注册码。

顺便说一下,这个程序作者好像花了很多功夫在防破解上面,但是最后验证程序是否注册却只是单纯地检验了一个键值是否正确,不免显得有点头重脚轻,这样做可以很容易被爆破,希望作者能够将这里改进一下。
————————————————————————
【版权声明】转载请保持文章的完整性,并注明原作者的信息,谢谢:)


分类: 逆向手札 由 ssfighter 于 2006年05月25日 发表

和上次看的那个计算机等级考试的模拟软件是同一个公司出的,而且都是同一个毛病,就是只有一个主程序,特别的大,很ft。仍然是用VB编的,而且没有加壳,上次因为是用SmartCheck看的,得到的信息很少,这次用Odbg载入分析了一下,原来注册码是用浮点运算计算得到的,而SmartCheck 没有检测到浮点运算,因此SmartCheck里面显示的数都不知道是怎么得到的。

VBExplorer先查看注册按钮的入口点,然后ODBG设断点,具体的程序懒得在这里写了,VB的程序太长太麻烦了,看了好久再加上一些猜测才弄明白点。这里就把最后注册码的计算过程写一下算了。

序列号分为两部分,前面是字符串,后面是一串数,把这串数提取出来,分别取得数的1、3、5、7位。分别在每位后面依次加上2、5、7、6。这样得到四个数。

下面再对每个数进行处理,看一下各个数是在什么区间内,分析的时候记录如下:

ds:[4026C0]=20 再加上ds:[4026B8]=97
ds:[4026B0]=29 再加上ds:[4026A8]=28
ds:[4026A0]=30 这步无意义,末位不可能是9或0
ds:[402698]=55 再加上ds:[402690]=35(相等也加)
ds:[402688]=56 这步比较无意义,小于等于55执行上面的加法,大于55直接和81判断
ds:[402680]=81 再加上ds:[402678]=41
ds:[402670]=82 再减去ds:[402668]=17
实际上也就是按上面的几个数划分了一下区间,数落在不同的区间内进行不同的处理,这样就又可以得到四个数。

把最初得到的四个数求和,判断和处于如下哪个区间内,然后注册码即可求得

属于区间[0,100]:注册码=zgx+第一位+第二位+gf8+第三位+第四位
属于区间(100,200]:注册码=第一位+ygp+第二位+第三位+tx6+第四位
属于区间(200,300]:注册码=第四位+gmu+第一位+第二位+hu6+第三位
属于区间(300,正无穷):注册码=第二位+fre+第一位+kmh+第三位+第四位

注意上面所说的第?位都是以最初得到的数为ASCII码求得的字符。

写的挺凌乱的,基本都是边分析边记录的,还把注册机做了,以后有空补上算法分析吧,最近忙于考试和试验报告,实在没那么多时间,5555