吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4100|回复: 7
收起左侧

[原创] [CM分析]新手CM 无壳无花 业界良心 的分析

[复制链接]
currwin 发表于 2014-6-13 18:32
本帖最后由 currwin 于 2014-6-13 18:31 编辑

破解作者】  currwin(F8LEFT)
【联系方式】  QQ:不能留Q来着。。。。
【作者主页】  不好说啊
【破解工具】  OllyDbg 1.1、IDE
【破解声明】  师傅写的cm,不敢不玩,不过又不会玩。唉,只能写一点小小的分析了,如果有错的话不要介意啊

【软件名称】  新手CM 无壳无花 业界良心
【加壳信息】  VC
【软件简介】  一个很有趣的cm,带了一点掩眼法,需要多加一点心思才能搞定的啊

      一个小小的cm,无壳无花,代码一目了然,只是可以参考的字符串不多,但还是有的,我们右键查找一下ASCII,会找到几条有趣的中文提示:

00401759   .  68 F48B4300   push 无壳无花.00438BF4                       ;  用户名和序列号不可为空!  ;判断输入的数据是否为空
00401712   .  68 D08B4300   push 无壳无花.00438BD0                       ; |c:\reg.ini
00401741   .  68 DC8B4300   push 无壳无花.00438BDC                       ;  验证通过,请重启软件!    ;要求重启程序进行验证

    估计这附近就是关键的比较的地方了,我们先来猜测一下程序的验证流程:输入数据->验证数据->保存数据->重启验证。
     应该就是这么几点的,于是我们就来在这一段的段首下段,输入好信息后,慢慢跟踪吧。
     段首为 00401610,下F2断点,点注册,然后慢慢跟踪,确定每一个函数的大致作用

[Asm] 纯文本查看 复制代码
00401610   .  6A FF         push -0x1
00401612   .  68 90264300   push 无壳无花.00432690
           .......            ;此处省略掉无关的代码
00401693   .  8D4C24 0C     lea ecx,dword ptr ss:[esp+0xC]
00401697   .  51            push ecx
00401698   .  8D8E D0000000 lea ecx,dword ptr ds:[esi+0xD0]
0040169E   .  C64424 24 01  mov byte ptr ss:[esp+0x24],0x1
004016A3   .  E8 C6870000   call <无壳无花.Edit_GetText>                 ;  GetPass
004016A8   .  8D5424 10     lea edx,dword ptr ss:[esp+0x10]
004016AC   .  52            push edx
004016AD   .  8D8E 78010000 lea ecx,dword ptr ds:[esi+0x178]
004016B3   .  E8 B6870000   call <无壳无花.Edit_GetText>                 ;  GetName
004016B8   .  8B4424 0C     mov eax,dword ptr ss:[esp+0xC]
004016BC   .  68 678F4300   push 无壳无花.00438F67                       ;  push NULL
004016C1   .  50            push eax                                 ;  push Pass
004016C2   .  C74424 1C 000>mov dword ptr ss:[esp+0x1C],0x0
004016CA   .  E8 FCDB0100   call <无壳无花.strcmp>                       ;  把Pass与空字符串比较,确定Pass是否为空
004016CF   .  83C4 08       add esp,0x8
004016D2   .  85C0          test eax,eax
004016D4   .  0F95C0        setne al
004016D7   .  84C0          test al,al
004016D9   .  74 7A         je short 无壳无花.00401755                   ;  为空的话,跳向错误提示
004016DB   .  8B4C24 10     mov ecx,dword ptr ss:[esp+0x10]
004016DF   .  68 678F4300   push 无壳无花.00438F67                       ;  PUSH NULL
004016E4   .  51            push ecx                                 ;  push Name
004016E5   .  E8 E1DB0100   call <无壳无花.strcmp>                       ;  吧Name与空字符串比较,确定Name是否为空
004016EA   .  83C4 08       add esp,0x8
004016ED   .  85C0          test eax,eax
004016EF   .  0F95C0        setne al
004016F2   .  84C0          test al,al
004016F4   .  74 5F         je short 无壳无花.00401755                   ;  为空的话跳向失败
004016F6   .  8B5424 0C     mov edx,dword ptr ss:[esp+0xC]           ;  取Pass的长度
004016FA   .  837A F4 14    cmp dword ptr ds:[edx-0xC],0x14          ;  与0x14比较,如果Pass的长度不够0x14,则跳向失败
004016FE   .  75 65         jnz short 无壳无花.00401765                  ;  Pass长度为 0x14
00401700   .  6A 00         push 0x0                                 ; /hTemplateFile = NULL
00401702   .  68 80000000   push 0x80                                ; |Attributes = NORMAL
00401707   .  6A 02         push 0x2                                 ; |Mode = CREATE_ALWAYS
00401709   .  6A 00         push 0x0                                 ; |pSecurity = NULL
0040170B   .  6A 02         push 0x2                                 ; |ShareMode = FILE_SHARE_WRITE
0040170D   .  68 00000040   push 0x40000000                          ; |Access = GENERIC_WRITE
00401712   .  68 D08B4300   push 无壳无花.00438BD0                       ; |c:\reg.ini
00401717   .  FF15 9C324300 call dword ptr ds:[<&KERNEL32.CreateFile>; \CreateFileA
0040171D   .  8BF8          mov edi,eax                              ;  下面就对文件C:\reg.ini开始写入注册信息。
0040171F   .  6A 00         push 0x0                                 ; /pOverlapped = NULL
00401721   .  8D4424 18     lea eax,dword ptr ss:[esp+0x18]          ; |
00401725   .  50            push eax                                 ; |pBytesWritten
00401726   .  8B4424 14     mov eax,dword ptr ss:[esp+0x14]          ; |
0040172A   .  8B48 F4       mov ecx,dword ptr ds:[eax-0xC]           ; |
0040172D   .  51            push ecx                                 ; |nBytesToWrite
0040172E   .  50            push eax                                 ; |Buffer
0040172F   .  57            push edi                                 ; |hFile
00401730   .  FF15 98324300 call dword ptr ds:[<&KERNEL32.WriteFile>>; \WriteFile
00401736   .  57            push edi                                 ; /hObject
00401737   .  FF15 94324300 call dword ptr ds:[<&KERNEL32.CloseHandl>; \CloseHandle
0040173D   .  6A 00         push 0x0
0040173F   .  6A 00         push 0x0
00401741   .  68 DC8B4300   push 无壳无花.00438BDC                       ;  验证通过,请重启软件!
00401746   .  8BCE          mov ecx,esi
00401748   .  E8 E3640000   call 无壳无花.00407C30                       ;  信息写入后退出程序
0040174D   .  6A 00         push 0x0                                 ; /ExitCode = 0x0
0040174F   .  FF15 90324300 call dword ptr ds:[<&KERNEL32.ExitProces>; \ExitProcess
00401755   >  6A 00         push 0x0                                 ;  验证失败则继续循环
00401757   .  6A 00         push 0x0
00401759   .  68 F48B4300   push 无壳无花.00438BF4                       ;  用户名和序列号不可为空!
0040175E   .  8BCE          mov ecx,esi
00401760   .  E8 CB640000   call 无壳无花.00407C30
00401765   >  C64424 20 00  mov byte ptr ss:[esp+0x20],0x0
0040176A   .  8B4424 10     mov eax,dword ptr ss:[esp+0x10]
           ...............;此处省略掉无关的代码
004017C0   .  83C4 18       add esp,0x18
004017C3   .  C3            retn


    这样注册的流程就一目了然了,
①首先,读取Name与Pass,把他们与Null比较,如果其中有一个为空,则提示失败
②接着把Pass的长度与0x14比较,如果不等,则继续要求用户重新输入
③最后把读取到的信息保存到文件c:\reg.ini里面,待重启程序后继续重新进行验证。
    于是,我们的目标也同样是非常明确的了。
①重启程序,并对CreateFileA之类的函数下断点。
②找到程序验证序列号的地方,并且找出他验证的方式
③爆破掉关键的地方,从而达到破解的目的。

    重启程序,对文件操作一类的函数下断点,然后F9运行。那么,自然的,程序就停下来了。。。。。。。才对的。但是神奇的一幕出现了,到注册框出现以前,程序并没有调用到对文件操作的函数!!!
    这下我可郁闷了,没办法,用程序监视一类的软件监视这个软件,果然,还是没有出现对reg.ini这个文件进行操作的记录。
    也就是说,这个程序压根就没有想过读取这一个文件!!!!!
    我哪个去,这又是为啥啊,的确是挺让人郁闷的,这让小菜该怎么办啊。

    实在是没有思路了,于是我就从程序初始化到程序界面出来为止跟了一下,发现了一个非常有趣的地方。

[Asm] 纯文本查看 复制代码
004012F0   .  56            push esi
004012F1   .  57            push edi
004012F2   .  8B7C24 0C     mov edi,dword ptr ss:[esp+0xC]           ;  初始化各项
004012F6   .  8BF1          mov esi,ecx
004012F8   .  8D46 78       lea eax,dword ptr ds:[esi+0x78]
004012FB   .  50            push eax
004012FC      68 EC030000   push 0x3EC
00401301   .  57            push edi
00401302   .  E8 33BE0000   call <无壳无花.CreateControl>                ;  注册button
00401307   .  8D8E D0000000 lea ecx,dword ptr ds:[esi+0xD0]
0040130D   .  51            push ecx
0040130E   .  68 EB030000   push 0x3EB
00401313   .  57            push edi
00401314   .  E8 21BE0000   call <无壳无花.CreateControl>                ;  Edit
00401319   .  8D96 24010000 lea edx,dword ptr ds:[esi+0x124]
0040131F   .  52            push edx
00401320   .  68 ED030000   push 0x3ED
00401325   .  57            push edi
00401326   .  E8 0FBE0000   call <无壳无花.CreateControl>                ;  注册button
0040132B   .  8D86 78010000 lea eax,dword ptr ds:[esi+0x178]
00401331   .  50            push eax
00401332   .  68 EE030000   push 0x3EE
00401337   .  57            push edi
00401338   .  E8 FDBD0000   call <无壳无花.CreateControl>                ;  Edit
0040133D   .  81C6 CC010000 add esi,0x1CC
00401343   .  56            push esi
00401344   .  6A 02         push 0x2
00401346   .  57            push edi
00401347   .  E8 EEBD0000   call <无壳无花.CreateControl>                ;  static
0040134C   .  5F            pop edi
0040134D   .  5E            pop esi
0040134E   .  C2 0400       retn 0x4



    这一段是程序初始化各个控件的地方。这倒是没有什么关系,不过认真想了一下,就会发现有特别的地方了!
    首先是两个Edit框,这倒是没有问题,一个用来输入Name,一个用来输入Pass。
    问题就在于它创建了两个 按钮 button。
    这不是很奇怪吗,为什么要创建两个呢?现在,我们来做一下假设,在MFC中,假如一个按钮button只能对应一个按钮事件,那么两个button不就对应了两个按钮事件吗?
    假如每一个按钮事件对应了一种验证方式,那么不就有两种不同的验证方式了吗?
    假如我们前面看到的验证方式是其中一种,那么另外一种是什么呢?话说回来,到底是谁规定了前面给出的验证方式就一定是正确的呢?如果前面那个是一个陷阱,那么不就表明另外一个按钮事件才是真正的验证地方吗?
    所以,基于这样一个想法,我就来寻找一种激活另外一个按钮的按钮事件的方法。

    寻找的方法有很多,我就不一一分析了。我说一下我的思路吧:
    程序肯定会有判断倒是是激活哪一个按钮的机制。有可能是时钟,不过这个程序并没有时钟,所以这个Pass。
    有可能是根据Name与Pass的数据来修改,所以我就对读取信息的相关函数下段了,就是前面我下过标签的Edit_GetText函数了,具体的位置在00409E6E,作用就是获取Edit框的文本数据了。
    断点下好后,输入Name,然后切换到Pass的输入时,OD里面停下来了。原来是根据Name_Edit的输入焦点消失的时候才会激活的事件。怪不得程序要使用WH_CBT钩子了。
    我们来看一下那个函数:


[Asm] 纯文本查看 复制代码
004017D0   .  6A FF         push -0x1                                ;  NameEdit焦点消失
         ...............;继续省略一堆数据
0040181E   .  8D4C24 08     lea ecx,dword ptr ss:[esp+0x8]
00401822   .  51            push ecx
00401823   .  8D8E 78010000 lea ecx,dword ptr ds:[esi+0x178]
00401829   .  C74424 18 000>mov dword ptr ss:[esp+0x18],0x0
00401831   .  E8 38860000   call <无壳无花.Edit_GetText>                 ;  GetName
00401836   .  8B5424 08     mov edx,dword ptr ss:[esp+0x8]
0040183A   .  52            push edx
0040183B   .  E8 E7D50100   call <无壳无花.strtoxl>                      ;  把Name(数字字符串)转换为数字
00401840   .  83C4 04       add esp,0x4
00401843   .  3D DE070000   cmp eax,0x7DE
00401848   .  75 17         jnz short 无壳无花.00401861                  ;  如果等于7DE(2014)则不会跳转
0040184A   .  6A 01         push 0x1
0040184C   .  8D8E 24010000 lea ecx,dword ptr ds:[esi+0x124]
00401852   .  E8 FFA40000   call <无壳无花.ShwoWindow>                   ;  使隐藏的按钮显示出来
00401857   .  6A 00         push 0x0
00401859   .  8D4E 78       lea ecx,dword ptr ds:[esi+0x78]
0040185C   .  E8 F5A40000   call <无壳无花.ShwoWindow>                   ;  并且隐藏原来的按钮
00401861   >  C74424 14 FFF>mov dword ptr ss:[esp+0x14],-0x1
00401869   .  8B4424 08     mov eax,dword ptr ss:[esp+0x8]
        .................;省略一堆代码
00401896   .  83C4 10       add esp,0x10
00401899   .  C3            retn



    很显然了,当NameEdit控件的焦点消失的时候,读取Name,并且判断Name是否为数字2014,如果是的话,就显示隐藏的按钮,并且隐藏原来的按钮。如果不是的话,就什么都不做。
    这不就是我一直在寻找的地方吗?赶快在Name中输入2014,然后切换代码吧,这样正确的注册按钮与正确的验证机制就会出来了。这样一来,输入完Pass后,点注册,就能来的正确的注册地方了。


[Asm] 纯文本查看 复制代码
004018A0   .  6A FF         push -0x1
           ........;看我省略一堆代码
004018F0   .  8D4C24 08     lea ecx,dword ptr ss:[esp+0x8]
004018F4   .  51            push ecx
004018F5   .  8D8E D0000000 lea ecx,dword ptr ds:[esi+0xD0]
004018FB   .  C74424 20 000>mov dword ptr ss:[esp+0x20],0x0
00401903   .  E8 66850000   call <无壳无花.Edit_GetText>                 ;  GetPass
00401908   .  8B4C24 08     mov ecx,dword ptr ss:[esp+0x8]
0040190C   .  8B41 F4       mov eax,dword ptr ds:[ecx-0xC]           ;  取得Pass的长度
0040190F   .  83F8 0A       cmp eax,0xA                              ;  用长度与0xa(10)比较
00401912   .  0F85 84000000 jnz 无壳无花.0040199C                        ;  不等于则跳向失败
00401918   .  51            push ecx
00401919   .  E8 09D50100   call <无壳无花.strtoxl>                      ;  把Pass(数字的Str)转换为整形数据
0040191E   .  83C4 04       add esp,0x4
00401921   .  3D 3F420F00   cmp eax,0xF423F                          ;  与0xF423F (999999)比较
00401926   .  7E 74         jle short 无壳无花.0040199C                  ;  比这个小的话就跳向失败
00401928   .  6A 00         push 0x0
0040192A   .  6A FF         push -0x1
0040192C   .  8BCE          mov ecx,esi
0040192E   .  E8 C3A20000   call <无壳无花.GetDlgItem>                   ;  获取图标控件的hwnd
00401933   .  8BC8          mov ecx,eax
00401935   .  E8 1CA40000   call <无壳无花.ShwoWindow>
0040193A   .  C74424 10 000>mov dword ptr ss:[esp+0x10],0x0
00401942   .  C74424 0C 044>mov dword ptr ss:[esp+0xC],无壳无花.00434D04 ;  0辕
0040194A   .  C64424 1C 01  mov byte ptr ss:[esp+0x1C],0x1
0040194F   .  E8 21B70000   call 无壳无花.0040D075
00401954   .  8B40 0C       mov eax,dword ptr ds:[eax+0xC]           ;  加载正确的图片
00401957   .  68 86000000   push 0x86                                ; /RsrcName = 134.
0040195C   .  50            push eax                                 ; |hInst
0040195D   .  FF15 70344300 call dword ptr ds:[<&USER32.LoadBitmapA>>; \LoadBitmapA
00401963   .  50            push eax
00401964   .  8D4C24 10     lea ecx,dword ptr ss:[esp+0x10]
00401968   .  E8 20CD0000   call 无壳无花.0040E68D
0040196D   .  8B5424 10     mov edx,dword ptr ss:[esp+0x10]
00401971   .  8B86 EC010000 mov eax,dword ptr ds:[esi+0x1EC]
00401977   .  52            push edx                                 ; /lParam
00401978   .  6A 00         push 0x0                                 ; |wParam = 0x0
0040197A   .  68 72010000   push 0x172                               ; |Message = STM_SETIMAGE
0040197F   .  50            push eax                                 ; |hWnd
00401980   .  FF15 5C344300 call dword ptr ds:[<&USER32.SendMessageA>; \SendMessageA
00401986   .  C64424 1C 00  mov byte ptr ss:[esp+0x1C],0x0
0040198B   .  8D4C24 0C     lea ecx,dword ptr ss:[esp+0xC]
0040198F   .  C74424 0C 044>mov dword ptr ss:[esp+0xC],无壳无花.00434D04 ;  0辕
00401997   .  E8 54010000   call 无壳无花.00401AF0
0040199C   >  C74424 1C FFF>mov dword ptr ss:[esp+0x1C],-0x1         ;  失败
        ........;不重要的代码就不贴了
004019D1   .  83C4 18       add esp,0x18
004019D4   .  C3            retn



      这样,真正的验证段又出现了。
      首先,获取Pass,然后用长度与0xA(10)比较。不等于的话就跳向失败。
      然后,把Pass的字符串数据转换为整形数据,并且与0xF423F(999999)比较,比他小的话就跳向失败。
      所以,输入1000000以上的10位数字就会成功的了,大家玩起吧。我就狠心一点,直接爆菊了。

2.jpg

版权声明:本文由F8LEFT原创与52pojie论坛,转载请保留以上信息

PS:很久没有玩过游戏了,手痒了,赶紧玩去了。各位如果觉得我写的文章有趣的话,请多多回复吧,不要老是潜水了啊。。。。。花费你们几分钟时间打几个字应该不过分吧?这篇破文我可是写了1个小时有多的的呵。

记录.doc

187.5 KB, 下载次数: 5, 下载积分: 吾爱币 -1 CB

破文记录

免费评分

参与人数 6热心值 +6 收起 理由
闹够了没有 + 1 谢谢@Thanks!
1094483658 + 1 才看懂呀,感谢大大
wssb999 + 1 分析完全正确 膜拜
凌云9 + 1 感谢分享破解教程
rain灿 + 1 感谢师父教会了我一切
灵光丶Fiycix + 1 你这么叼我刚知道!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

灵光丶Fiycix 发表于 2014-6-13 18:49
本帖最后由 qq516145704 于 2014-6-13 19:45 编辑

我不是这么分析的,但最后一样成功了

大概就是分析到有两个按钮.然后就用彗星小助手显示隐藏控件了.

点评

只要成功就好,层主能否把分析的大概思路发一下呢?  发表于 2014-6-13 18:50
万年的胡杨 发表于 2014-6-13 18:57
rain灿 发表于 2014-6-13 19:05
心断空 发表于 2014-6-13 19:30
我F8大大果然屌
lwj一辈子 发表于 2014-6-13 21:42
F8学编程去了,就是牛
wssb999 发表于 2014-6-14 08:34
师傅就是叼 两个按钮都看出了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-29 20:47

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表