首页
社区
课程
招聘
[原创]History Sweeper 2.82破解
发表于: 2007-6-6 14:25 4909

[原创]History Sweeper 2.82破解

2007-6-6 14:25
4909
【文章标题】: History Sweeper 2.82破解
【文章作者】: wadic
【作者邮箱】: wadicracke@126.com
【作者主页】: 无
【作者QQ号】: 无
【软件名称】: History Sweeper 2.82
【软件大小】: 333KB
【下载地址】: http://www.itcompany.com/sweeper.htm
【加壳方式】: 无壳
【保护方式】: 注册表检测
【编写语言】: Microsoft Visual C++ 6.0
【使用工具】: PEiD、OD
【操作平台】: XP
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【软件介绍】: History Sweeper 是一个可以清除你计算机中无用文件和历史记录的一个非常小巧的软件,如注册表无用项,文档、运行、查找记录。清理的非常快速、安全。
--------------------------------------------------------------------------------
【详细过程】
  1、信息收集:
        未注册版本有15天使用限制,将日期改后,软件无法使用。
        没有注册码输入框。
        查壳:Microsoft Visual C++ 6.0,无壳。
        加密算法:MD5 :: 000088D9 :: 004088D9

  2、破解:
        (1)OD载入,查超级字串参考,找到:
Ultra String Reference, 条目 184
Address=0040C1F3
Disassembly=push    00423AD4
Text String=history sweeper (%d day(s) left)                ;这是未注册版在标题条上显示的信息。
Ultra String Reference, 条目 185
Address=0040C382
Disassembly=mov     edi, 00423AB4
Text String=history sweeper (registered)

        (2)来到0040C382   > \BF B43A4200   mov     edi, 00423AB4  ;  history sweeper (registered)
        发现跳转来自0040C150,看看:
0040C130   .  8D4C24 10     lea     ecx, dword ptr [esp+10]
0040C134   .  C68424 FC0200>mov     byte ptr [esp+2FC], 2
0040C13C   .  E8 83DE0000   call    <jmp.&MFC42.#800_CString::~CString>
0040C141   .  68 F83A4200   push    00423AF8                                      ;  xywy
0040C146   .  E8 0594FFFF   call    00405550
0040C14B   .  83C4 04       add     esp, 4
0040C14E   .  84C0          test    al, al
0040C150   .  0F85 2C020000 jnz     0040C382        ;关键跳

        (3)初步判断CALL 405550为关键CALL,在40C141处下断,F9运行。
        F7跟进CALL 405550
...
0040556B  |.  68 0C334200   push    0042330C                             ;  software\classes\{b3cb56e0-cbdb-22ca-15bf-8858-00aa0070fd48}
00405570  |.  8D4C24 04     lea     ecx, dword ptr [esp+4]
00405574  |.  E8 934A0100   call    <jmp.&MFC42.#537_CString::CString>
00405579  |.  8D4424 00     lea     eax, dword ptr [esp]
0040557D  |.  68 01000080   push    80000001
...
///这一段就是读取注册表了,定位主键后,就应该是打开子项了:
004055F9  |.  51            push    ecx
004055FA  |.  52            push    edx
004055FB  |.  50            push    eax
004055FC  |.  8D8C24 A80000>lea     ecx, dword ptr [esp+A8]
00405603  |.  C74424 10 000>mov     dword ptr [esp+10], 400
0040560B  |.  E8 30570000   call    0040AD40
//F7跟进,
...
0040AD57  |.  FF15 18D04100 call    dword ptr [<&ADVAPI32.RegQueryValueE>; \RegQueryValueExA        读子项
0040AD5D  |.  85C0          test    eax, eax
0040AD5F  |.  0F94C0        sete    al                ;没有子项就是假
0040AD62  \.  C2 0C00       retn    0C

//此时看堆栈窗:
        0012F4E4   0000005C  \...  |hKey = 5C
        0012F4E8   00376E48  Hn7.  |ValueName = "Data1"
        0012F4EC   00000000  ....  |Reserved = NULL
        0012F4F0   00000000  ....  |pValueType = NULL
        0012F4F4   0012F7F0  瘅.   |Buffer = 0012F7F0
        0012F4F8   0012F510  ?.   \pBufSize = 0012F510
//要读一个Data1的子项。打开注册表看看,发现没有这个子项,如果没有,sete al就是假了。
//手动添加一个字串型子项,值就随意给吧,我给的是"123456"
//F8走到返回
00405610  |.  84C0          test    al, al
00405612  |.  75 2E         jnz     short 00405642                ;如果没有Data1子项,没有跳,就是未注册版本了。
00405614  |.  8D8C24 9C0000>lea     ecx, dword ptr [esp+9C]
0040561B  |.  C78424 EC0600>mov     dword ptr [esp+6EC], -1
00405626  |.  E8 E5560000   call    0040AD10
0040562B  |.  32C0          xor     al, al
0040562D  |.  8B8C24 E40600>mov     ecx, dword ptr [esp+6E4]
00405634  |.  64:890D 00000>mov     dword ptr fs:[0], ecx
0040563B  |.  81C4 F0060000 add     esp, 6F0
00405641  |.  C3            retn                ;没跳在这里返回,al清0了
00405642  |>  53            push    ebx
00405643  |.  8D4C24 0C     lea     ecx, dword ptr [esp+C]
00405647  |.  E8 643C0000   call    004092B0
        //F7跟进这个CALL,我们看到了MD5的四个常数:
                00408720  /$  8B4424 04     mov     eax, dword ptr [esp+4]
                00408724  |.  33C9          xor     ecx, ecx
                00408726  |.  8948 14       mov     dword ptr [eax+14], ecx
                00408729  |.  8948 10       mov     dword ptr [eax+10], ecx
                0040872C  |.  C700 01234567 mov     dword ptr [eax], 67452301
                00408732  |.  C740 04 89ABC>mov     dword ptr [eax+4], EFCDAB89
                00408739  |.  C740 08 FEDCB>mov     dword ptr [eax+8], 98BADCFE
                00408740  |.  C740 0C 76543>mov     dword ptr [eax+C], 10325476
                00408747  \.  C3            retn

0040564C  |.  8B9424 F80600>mov     edx, dword ptr [esp+6F8]
00405653  |.  8D8C24 E80200>lea     ecx, dword ptr [esp+2E8]
0040565A  |.  51            push    ecx                                  ; /Arg2
0040565B  |.  52            push    edx                                  ; |Arg1
0040565C  |.  8D4C24 14     lea     ecx, dword ptr [esp+14]              ; |
00405660  |.  C68424 F80600>mov     byte ptr [esp+6F8], 3                ; |
00405668  |.  E8 633F0000   call    004095D0                             ; \sweeper.004095D0
//看来CALL 4095D0就是MD5运算了,走到这里,堆栈窗如下:
        0012F500   00423AF8  ?B.   |Arg1 = 00423AF8 ASCII "XYWY"
        0012F504   0012F7F0  瘅.   \Arg2 = 0012F7F0 ASCII "123456"
//参数一是常数"XYWY",参数二是刚建的假值,MD5运算需要两个字串吗?难道是合并后再作运算?抖擞精神,咬把牙,跟进:)
004095D0  /$  8B15 8C364200 mov     edx, dword ptr [42368C]              ;  sweeper.00423698
004095D6  |.  83EC 40       sub     esp, 40
004095D9  |.  33C0          xor     eax, eax
004095DB  |.  56            push    esi
004095DC  |.  8BF1          mov     esi, ecx
004095DE  |.  57            push    edi
004095DF  |.  8BFA          mov     edi, edx
004095E1  |.  83C9 FF       or      ecx, FFFFFFFF
004095E4  |.  F2:AE         repne   scas byte ptr es:[edi]
004095E6  |.  A1 90364200   mov     eax, dword ptr [423690]
004095EB  |.  8BFA          mov     edi, edx
004095ED  |.  F7D1          not     ecx
004095EF  |.  49            dec     ecx
004095F0  |.  8B15 94364200 mov     edx, dword ptr [423694]
004095F6  |.  89440C 08     mov     dword ptr [esp+ecx+8], eax
004095FA  |.  83C9 FF       or      ecx, FFFFFFFF
004095FD  |.  33C0          xor     eax, eax
004095FF  |.  F2:AE         repne   scas byte ptr es:[edi]
00409601  |.  8B4424 4C     mov     eax, dword ptr [esp+4C]
00409605  |.  F7D1          not     ecx
00409607  |.  49            dec     ecx
00409608  |.  50            push    eax
00409609  |.  89540C 10     mov     dword ptr [esp+ecx+10], edx
0040960D  |.  8BCE          mov     ecx, esi
0040960F  |.  E8 FCFCFFFF   call    00409310
00409614  |.  8BCE          mov     ecx, esi
00409616  |.  E8 15FDFFFF   call    00409330
0040961B  |.  8B7C24 50     mov     edi, dword ptr [esp+50]
0040961F  |.  B9 08000000   mov     ecx, 8
00409624  |.  8BF0          mov     esi, eax
00409626  |.  33D2          xor     edx, edx
00409628  |.  F3:A7         repe    cmps dword ptr es:[edi], dword ptr [>
0040962A  |.  5F            pop     edi
0040962B  |.  5E            pop     esi
0040962C  |.  0F94C0        sete    al
0040962F  |.  83C4 40       add     esp, 40
00409632  \.  C2 0800       retn    8

//大致一看,并不长,这里有几个关键点:
1、004095E1  |.  83C9 FF       or      ecx, FFFFFFFF                ;串扫描前奏,得到串长
   004095E4  |.  F2:AE         repne   scas byte ptr es:[edi]        ;扫描串
2、两个CALL
3、00409628  |.  F3:A7         repe    cmps dword ptr es:[edi], dword ptr [>        ;串比较
4、0040962C  |.  0F94C0        sete    al        ;关键!真与假,注册与未注册...

        (4)这两个CALL就省略了,我粗跟了一下,前一个CALL做些MD5运算前的准备,后一个CALL非常冗长,N多的xor/or/not...我是大段大段的F4过。
        有一点很重要,我跟的时候,发现"123456"这个假码并没有参与运算!
        说明程序只是将XYWY进行了运算,得到的结果再和假码"123456"比较而已。
        这样就好办了,直接在串比较的409628处下断,F9过来,嘿嘿,EAX和ESI同时指向一串字符,而EDI则指向了假码:
EAX 0012F529 ASCII "c18da8dc4814f8fc7089fe2e7042b3fd"
ECX 00000008
EDX 00000000
EBX 00426700 sweeper.00426700
ESP 0012F4B4
EBP 00000000
ESI 0012F529 ASCII "c18da8dc4814f8fc7089fe2e7042b3fd"
EDI 0012F7F0 ASCII "123456"
//至此,不管MD5运算多么复杂,都不用管了,来到堆栈12F7F0处,改吧...
//懒得改的话就把sete al改成mov al,1吧,让al带着1一路返回...

3、结论:
在HKEY_CURRENT_USER\Software\Classes\{B3CB56E0-CBDB-22CA-15BF-8858-00AA0070FD48}下新建子项Data1,值为c18da8dc4814f8fc7089fe2e7042b3fd,即可成为正式版。

4、一点体会:刚拿到这个软件时,发现竟没有注册码输入框,有点不知从何入手。幸好在字串参考中找到了点头绪,才能很快定位到关键处。
如果没有这点提示呢?嘿嘿,不知怎么办了,能想到的办法是从开始一步步跟了...

本人新手,第一次写破文,失误之处,还请指教,谢谢。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 47147
活跃值: (20415)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
恭喜一下。
如有时间,建议将算法分析出来,这样进步快些。
2007-6-6 14:45
0
雪    币: 242
活跃值: (112)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢看雪老大的指点,晚上一定细细研究。

另:发现TAB在贴子里显示不出来,在记事本里很清晰的文章,贴这儿来,有点惨不忍睹了,抱歉...
2007-6-6 14:52
0
雪    币: 47147
活跃值: (20415)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
4
论坛对TAB支持不好,有机会改进一下,你先用空格对齐。
2007-6-6 15:00
0
雪    币: 4441
活跃值: (805)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
学习了,谢谢楼主分享破解心得
2007-6-6 15:13
0
雪    币: 164
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
厉害,恭喜,谢谢,支持
2007-6-6 18:34
0
游客
登录 | 注册 方可回帖
返回
//