首页
社区
课程
招聘
[原创]"易语言写的一个漂亮的creakme"破解分析
发表于: 2008-1-8 16:28 9473

[原创]"易语言写的一个漂亮的creakme"破解分析

2008-1-8 16:28
9473

【文章标题】: "易语言写的一个漂亮的creakme"破解分析
【文章作者】: netwind
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  1、去掉neg.
  od加载程序,bp MessageBoxA下断。f9运行,断下,取消断点,堆栈如下分布:
  0012F9F4   10062176  /CALL 到 MessageBoxA 来自 krnln.10062170
  0012F9F8   00000000  |hOwner = NULL
  0012F9FC   0040C0CF  |Text = "本关你要去掉我(*^__^*) 嘻嘻",A1,"",AD,"",A1,"",AD,""
  0012FA00   0040C0CB  |Title = "NAG"
  0012FA04   00002000  \Style = MB_OK|MB_TASKMODAL
  
  在代码窗口 右键 转到 10062170 ,也就是跳到call MessageBoxA的地方了
  1006216B   .  50            push    eax                              ; /Style
  1006216C   .  52            push    edx                              ; |Title
  1006216D   .  51            push    ecx                              ; |Text
  1006216E   .  6A 00         push    0                                ; |hOwner = NULL
  10062170   .  FF15 A0260C10 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
  10062176   .  5F            pop     edi
  
  这个就是neg窗口 开始想改下跳转 跳过去,但发现 这段代码 在creakme.exe 释放的一个库文件里
  并且api调用都是调用这里的,改库文件麻烦。
  我们在 call 下一行 pop edi 下断 f9运行弹出neg ,点确定, 然后单步 f8 几下子,
  程序流程就回到 creakme.exe本身的代码区域了,如下:
  00472368    68 04000080     push    80000004
  0047236D    6A 00           push    0
  0047236F    68 CBC04000     push    0040C0CB                         ; ASCII "NAG"
  00472374    68 01030080     push    80000301
  00472379    6A 00           push    0
  0047237B    68 00000000     push    0
  00472380    68 04000080     push    80000004
  00472385    6A 00           push    0
  00472387    68 CFC04000     push    0040C0CF
  0047238C    68 03000000     push    3
  00472391    BB 00030000     mov     ebx, 300
  00472396    E8 82040000     call    0047281D
  0047239B    83C4 28         add     esp, 28
  
  程序返回到了0047239b 很显然call 0047281d就是用来弹neg的,我们直接nop它 保存,第一关就过了。
  
  2、使按钮和输入框有效
  按钮和输入框由CreateWindowExA创建,其是否有效是由该函数的输入参数style的值决定。
  那么我们的思路就是在改函数创建button 和 edit 控件时 把输入参数给该掉,就可以了。
  cm调用的 代码都是在它释放的库文件里
  我们直接修改它的库文件。
  在程序开始部分简单跟几下 或者断WriteFileA你会发现 它释放如下文件
  C:\Documents and Settings\netwind\Local Settings\Temp\E_4\krnln.fnr
  
  程序调用的api都是在这个文件里的。
  我们直接od加载
  右键,查找所有模块间调用 找到CreateWindowExA,双击,有如下代码:
  100AE0D3  |.  FF50 5C       call    dword ptr [eax+5C]
  100AE0D6  |.  85C0          test    eax, eax
  100AE0D8      0F85 03BF0000 jnz     100B9FE1    //这个跳转 是我修改了的 //这里始终都跳,也可以写jmp,
  100AE0DE      90            nop
  100AE0DF      90            nop
  100AE0E0      90            nop
  100AE0E1      90            nop          //这里的指令执行不到,没用被我nop了
  100AE0E2      90            nop
  100AE0E3      90            nop
  100AE0E4      90            nop
  100AE0E5      90            nop
  100AE0E6      90            nop
  100AE0E7      90            nop
  100AE0E8  |>  57            push    edi
  100AE0E9  |.  56            push    esi
  100AE0EA  |.  E8 F8FEFFFF   call    100ADFE7
  100AE0EF  |.  FF75 D0       push    dword ptr [ebp-30]               ; /lParam
  100AE0F2  |.  FF75 D4       push    dword ptr [ebp-2C]               ; |hInst
  100AE0F5  |.  FF75 D8       push    dword ptr [ebp-28]               ; |hMenu
  100AE0F8  |.  FF75 DC       push    dword ptr [ebp-24]               ; |hParent
  100AE0FB  |.  FF75 E0       push    dword ptr [ebp-20]               ; |Height
  100AE0FE  |.  FF75 E4       push    dword ptr [ebp-1C]               ; |Width
  100AE101  |.  FF75 E8       push    dword ptr [ebp-18]               ; |Y
  100AE104  |.  FF75 EC       push    dword ptr [ebp-14]               ; |X
  100AE107  |.  FF75 F0       push    dword ptr [ebp-10]               ; |Style
  100AE10A  |.  FF75 F4       push    dword ptr [ebp-C]                ; |WindowName
  100AE10D  |.  FF75 F8       push    dword ptr [ebp-8]                ; |Class
  100AE110  |.  FF75 FC       push    dword ptr [ebp-4]                ; |ExtStyle
  100AE113  |.  FF15 58250C10 call    dword ptr [<&USER32.CreateWindow>; \CreateWindowExA
  
  
  push    dword ptr [ebp-10]               ; |Style  就是这个参数决定着button ,edit 是否激活的。
  我们就把上面来个跳转找 到一 空白区 加几条指令 判断Style 的值,换成我们想要的值然后再跳回来。
  这里是我加的 修改style参数的代码,空白空间不连续,我多来了几个跳转。
  100B9FE1      817D F0 002F0>cmp     dword ptr [ebp-10], 4C012F00    //这个就是原button 的style.
  100B9FE8      90            nop
  100B9FE9      74 17         je      short 100BA002          如果是这个4c012f00就去修改了它         
  100B9FEB      EB 55         jmp     short 100BA042          如果不是就继续往下判断是不是edit的stye.
  100B9FED      90            nop
  100B9FEE      90            nop
  100B9FEF      90            nop                                    
  。。。。。。。。。。
  100BA002      C745 F0 80008>mov     dword ptr [ebp-10], 50800080   //把button的style改为 50800080使有效
  100BA009    ^ E9 DA40FFFF   jmp     100AE0E8                       //改完后返回去
  。。。。。。。。。
  
  100BA042      817D F0 80080>cmp     dword ptr [ebp-10], 44010880    //到这判断是不是edit 的参数44010880
  100BA049      74 3A         je      short 100BA085                 //是就跳去修改
  100BA04B    ^ E9 9840FFFF   jmp     100AE0E8                      //不是就返回
  。。。。。。。。。。。。。。。。。。。。。
  100BA085      C745 F0 80000>mov     dword ptr [ebp-10], 44000080    //修改edit 的style参数为4400080
  100BA08C      74 4A         jmp      short 100BA0D8                 //改完后返回 这里空间不够,多跳了一下
  
  。。。。。。。。。。。。。
  100BA0D8    ^ E9 0B40FFFF   jmp     100AE0E8
  
  
  好了,修改完毕 保存 。
  
  这时 重新打开 cm 运行发现,还是没效果,其实cm每运行时 都重新释放那个库,所以,下面我们让它只生产一次。
  
  重加载cm bp WriteFile用上面类似方法断下,有如下代码:
  004013C7   .  8D85 68FDFFFF lea     eax, dword ptr [ebp-298]
  004013CD   .  50            push    eax
  004013CE   .  E8 FD1E0000   call    004032D0
  004013D3   . /E9 81000000   jmp     00401459   //这里又被我改了      
  004013D8     |90            nop
  004013D9     |90            nop
  004013DA     |90            nop
  004013DB     |90            nop
  004013DC   . |53            push    ebx                              ; /hTemplateFile
  004013DD   . |68 80000000   push    80                               ; |Attributes = NORMAL
  004013E2   . |6A 02         push    2                                ; |Mode = CREATE_ALWAYS
  004013E4   . |53            push    ebx                              ; |pSecurity
  004013E5   . |53            push    ebx                              ; |ShareMode
  004013E6   . |68 00000040   push    40000000                         ; |Access = GENERIC_WRITE
  004013EB   . |50            push    eax                              ; |FileName
  004013EC   . |FF15 20704000 call    dword ptr [<&KERNEL32.CreateFile>; \CreateFileA
  004013F2   . |83F8 FF       cmp     eax, -1
  004013F5   . |8945 08       mov     dword ptr [ebp+8], eax
  004013F8   . |74 17         je      short 00401411
  004013FA   . |8D4D D8       lea     ecx, dword ptr [ebp-28]
  004013FD   . |53            push    ebx                              ; /pOverlapped
  004013FE   . |51            push    ecx                              ; |pBytesWritten
  004013FF   . |57            push    edi                              ; |nBytesToWrite
  00401400   . |56            push    esi                              ; |Buffer
  00401401   . |50            push    eax                              ; |hFile
  00401402   . |FF15 0C704000 call    dword ptr [<&KERNEL32.WriteFile>>; \WriteFile
  00401408   . |FF75 08       push    dword ptr [ebp+8]                ; /hObject
  0040140B   . |FF15 08704000 call    dword ptr [<&KERNEL32.CloseHandl>; \CloseHandle
  00401411   > |03F7          add     esi, edi
  00401413   . |3B75 F4       cmp     esi, dword ptr [ebp-C]
  00401416   .^|0F82 51FFFFFF jb      0040136D
  0040141C   . |385D A4       cmp     byte ptr [ebp-5C], bl
  0040141F   . |75 0C         jnz     short 0040142D
  00401421   > |C745 FC 20814>mov     dword ptr [ebp-4], 00408120      ;  ASCII "Not found the kernel library!"
  00401428   . |E9 92000000   jmp     004014BF
  0040142D   > |8D85 6CFEFFFF lea     eax, dword ptr [ebp-194]
  00401433   . |50            push    eax
  00401434   . |8D85 68FDFFFF lea     eax, dword ptr [ebp-298]
  0040143A   . |50            push    eax
  0040143B   . |E8 801E0000   call    004032C0
  00401440   . |8D45 A4       lea     eax, dword ptr [ebp-5C]
  00401443   . |50            push    eax
  00401444   . |8D85 68FDFFFF lea     eax, dword ptr [ebp-298]
  0040144A   . |50            push    eax
  0040144B   . |E8 801E0000   call    004032D0
  00401450   . |83C4 10       add     esp, 10
  00401453   . |8D85 68FDFFFF lea     eax, dword ptr [ebp-298]
  00401459   > \50            push    eax                              ; /FileName
  0040145A   .  FF15 04704000 call    dword ptr [<&KERNEL32.LoadLibrar>; \LoadLibraryA
  你会发现每次他都生成一个库 再loadlibraryA,我们发现在004013CE   .  E8 FD1E0000   call    004032D0
  执行完后eax,保存的就是要生成库的路径,那么我们直接从这jmp 到loadlibrary的地方,就避免了他每次重生产那库了。
  修改完保存,再把上面修改好的库放到对应的目录
  再运行cm,就一切ok了。
  
  3、解密
  
  od加载我们修改好的,bp MessageBoxA 断下后 堆栈如下:
  0012F830   10062176  /CALL 到 MessageBoxA 来自 krnln.10062170
  0012F834   00000000  |hOwner = NULL
  0012F838   0040C18A  |Text = ""D7,"",A2,"",B2,"崧?,B4,"砦?
  0012F83C   0040C15A  |Title = "警",B8,"?
  0012F840   00002000  \Style = MB_OK|MB_TASKMODAL
  
  这里是是警告 ,提示错误,我们在内存窗口 看看40c15a的内容,在内存窗口右键转到40c15a
  内容如下:
  0040C15A  BE AF B8 E6 00 C7 EB CA E4 C8 EB D7 A2 B2 E1 C2  警告.请输入注册
  0040C16A  EB 00 00 00 00 00 00 54 9F 40 00 00 00 00 00 00  ?.....T烜......
  0040C17A  14 40 B9 A7 CF B2 00 D7 A2 B2 E1 B3 C9 B9 A6 00  @恭喜.注册成功.
  0040C18A  D7 A2 B2 E1 C2 EB B4 ED CE F3 00 38 00 00 00 53  注册码错误.8...S
  
  放了成功时的提示串和不成功时的串,很明显 注册码对时 就会把成功提示串压栈,我们找找看 哪里是否有 push 004c181
  指令 这个指令就是把成功提示压栈。
  我们在内存窗口搜索 二进制串81 c1 4c 00 找到地址00472778 放的这个串,我们在代码窗口 转到00472778 直接
  是敏感代码部分,附近有如下代码:
  00472651    E8 BDFEFFFF     call    00472513                         ; 把机器码读入到eax,符号到edx
  00472656    8945 F8         mov     dword ptr [ebp-8], eax
  00472659    8955 FC         mov     dword ptr [ebp-4], edx
  0047265C    68 01030080     push    80000301
  00472661    6A 00           push    0
  00472663    68 40E20100     push    1E240
  00472668    68 01030080     push    80000301
  0047266D    6A 00           push    0
  0047266F    FF75 F8         push    dword ptr [ebp-8]
  00472672    68 02000000     push    2
  00472677    BB CC000000     mov     ebx, 0CC
  0047267C    E8 9C010000     call    0047281D
  00472681    83C4 1C         add     esp, 1C
  00472684    99              cdq
  00472685    8945 F0         mov     dword ptr [ebp-10], eax          ; 机器码转为整数后 前4字节给eax
  00472688    8955 F4         mov     dword ptr [ebp-C], edx          //后4字节给edx
  0047268B    816D F0 F3220D0>sub     dword ptr [ebp-10], 0D22F3
  00472692    835D F4 00      sbb     dword ptr [ebp-C], 0
  00472696    8145 F0 CF07000>add     dword ptr [ebp-10], 7CF
  0047269D    8355 F4 00      adc     dword ptr [ebp-C], 0
  004726A1    DF6D F0         fild    qword ptr [ebp-10]               ; 写入到寄存器
  004726A4    DD5D E0         fstp    qword ptr [ebp-20]
  004726A7    DD45 E0         fld     qword ptr [ebp-20]                //把机器码 转浮点数放FPU寄存器
  004726AA    DC0D 6CC14000   fmul    qword ptr [40C16C]               // 把浮点数*2005.0000000
  004726B0    DD5D D8         fstp    qword ptr [ebp-28]               ; 放到后面变量里
  004726B3    DD45 D8         fld     qword ptr [ebp-28]               ; 读出来
  004726B6    E8 58FEFFFF     call    00472513       //这个call 相当与把运算过的机器码 变整数压栈后传给eax
  004726BB    8945 F0         mov     dword ptr [ebp-10], eax
  004726BE    8955 F4         mov     dword ptr [ebp-C], edx
  004726C1    DF6D F0         fild    qword ptr [ebp-10]
  004726C4    DD5D E0         fstp    qword ptr [ebp-20]
  004726C7    DD45 E0         fld     qword ptr [ebp-20]
  004726CA    DC35 74C14000   fdiv    qword ptr [40C174]                 //除以5.000000
  004726D0    DD5D D8         fstp    qword ptr [ebp-28]
  004726D3    DD45 D8         fld     qword ptr [ebp-28]
  004726D6    E8 38FEFFFF     call    00472513
  004726DB    8945 F0         mov     dword ptr [ebp-10], eax           //到这里运算完毕,运算后前4字节在eax里
  004726DE    8955 F4         mov     dword ptr [ebp-C], edx          //后4字节在edx里
  004726E1    6A FF           push    -1                              //这以下对注册码处理
  004726E3    6A 08           push    8                              //实际上就是把注册码变整数压栈了
  004726E5    68 07000116     push    16010007
  004726EA    68 01000152     push    52010001
  004726EF    E8 35010000     call    00472829
  004726F4    83C4 10         add     esp, 10
  004726F7    8945 E4         mov     dword ptr [ebp-1C], eax
  004726FA    68 04000080     push    80000004
  004726FF    6A 00           push    0
  00472701    8B45 E4         mov     eax, dword ptr [ebp-1C]
  00472704    85C0            test    eax, eax
  00472706    75 05           jnz     short 0047270D
  00472708    B8 59C14000     mov     eax, 0040C159
  0047270D    50              push    eax
  0047270E    68 01000000     push    1
  00472713    BB 64010000     mov     ebx, 164
  00472718    E8 00010000     call    0047281D
  0047271D    83C4 10         add     esp, 10
  00472720    8945 DC         mov     dword ptr [ebp-24], eax
  00472723    8955 E0         mov     dword ptr [ebp-20], edx
  00472726    8B5D E4         mov     ebx, dword ptr [ebp-1C]
  00472729    85DB            test    ebx, ebx
  0047272B    74 09           je      short 00472736
  0047272D    53              push    ebx
  0047272E    E8 F0000000     call    00472823
  00472733    83C4 04         add     esp, 4
  00472736    DD45 DC         fld     qword ptr [ebp-24]
  00472739    E8 D5FDFFFF     call    00472513
  0047273E    8945 E8         mov     dword ptr [ebp-18], eax
  00472741    8955 EC         mov     dword ptr [ebp-14], edx
  00472744    8B55 EC         mov     edx, dword ptr [ebp-14]
  00472747    8B45 E8         mov     eax, dword ptr [ebp-18]
  0047274A    3945 F0         cmp     dword ptr [ebp-10], eax           //这里注册码前4字节跟运算过后的机器码前4字节比较
  0047274D    75 03           jnz     short 00472752
  0047274F    3955 F4         cmp     dword ptr [ebp-C], edx            //后4字节比较
  00472752    0F85 3B000000   jnz     00472793
  00472758    68 04000080     push    80000004
  0047275D    6A 00           push    0
  0047275F    68 7CC14000     push    0040C17C
  00472764    68 01030080     push    80000301
  00472769    6A 00           push    0
  0047276B    68 00000000     push    0
  00472770    68 04000080     push    80000004
  00472775    6A 00           push    0
  00472777    68 81C14000     push    0040C181                           //如果相等就执行这里了,成功提示消息压栈
  0047277C    68 03000000     push    3
  00472781    BB 00030000     mov     ebx, 300
  00472786    E8 92000000     call    0047281D
  0047278B    83C4 28         add     esp, 28
  0047278E    E9 36000000     jmp     004727C9
  00472793    68 04000080     push    80000004
  00472798    6A 00           push    0
  0047279A    68 5AC14000     push    0040C15A
  0047279F    68 01030080     push    80000301
  004727A4    6A 00           push    0
  004727A6    68 00000000     push    0
  004727AB    68 04000080     push    80000004
  004727B0    6A 00           push    0
  004727B2    68 8AC14000     push    0040C18A               //不相等就会执行到这,错误警告消息压栈
  004727B7    68 03000000     push    3
  004727BC    BB 00030000     mov     ebx, 300
  004727C1    E8 57000000     call    0047281D
  
  
  注册算法简单,就是把机器码运算下 得到一个结果,如果注册码不是这个结果,就错了。
  我用c套汇编把代码 简单列出如下:
  #include <stdio.h>
  #include <windows.h>
  inline void key()  这个就是那个call ,call    00472513 就是把浮点数 变整数压栈 返回给eax
  {
          _asm{
                  push    ebp
                          mov     ebp, esp
                          sub     esp, 0xc
                          fistp   qword ptr [ebp-0xC]  //从寄存器读入浮点数到堆栈(这里是机器码)
                          mov     eax, dword ptr [ebp-0xC]
                          mov     edx, dword ptr [ebp-8]
                          mov     esp, ebp
                          pop     ebp
                         
                         
          }
  }
  void main()
  {
          long a;
          double b=-2141937092,c=2005,d=5;  //b为机器码
          _asm{
                  fld b
                          call key             //把机器码放到栈上,并传给eax
              xor eax,0x1e240
                          sub eax,0xd22f3
                          add eax,0x7cf               
                          mov     dword ptr [ebp-0x24], eax
                          mov     dword ptr [ebp-0x20], edx
                          fild    qword ptr [ebp-0x24]       //写入fpu寄存器
                          fmul    c
                          fdiv    d
                          fstp    qword ptr [ebp-0x34]  //读入栈
                          lea eax,dword ptr [ebp-0x34]
                          mov a,eax
          }
          memcpy(&b,(double *)a,8);
          printf("%0.0f\n",b);
  }
  
  我列的代码就是 把机器码的运算的过程 ,运算完了就得到注册码了。
  修改过的文件放附件里了.
--------------------------------------------------------------------------------
【经验总结】
  由于对浮点指令完全陌生,google的时间远比调试的时间长,汇编代码编写能力也差强人意,所以耗了n久时间,这个cm作
  者累坏我了,还是感谢作者,毕竟有些收获,希望作者最好把代码放出来。
  petnt大侠已经放出破文了,自己感觉分析的思路 不一样,就放出来交流。petnt大侠修改cm 远比我修改库文件的方法简单
  多了,当时我想过直接在库里找压栈参数的值 修改就完了,但没搜到,于是来了个麻烦的跳来跳去的方法 呵呵。
  有不对之处 望大家指导!
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2008年01月08日 16:23:02


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (11)
雪    币: 212
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
哈哈,学习了啊,修改库文件来达到破解目的。不过我觉得petnt大虾分析的都不错啊。
2008-1-8 16:43
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
3
呵呵,不知道作者的原意是让你跳来跳去的改呢?还是让我跋山涉水的找那个07和01?
反正完成作业了,帮你顶一下!
2008-1-8 16:48
0
雪    币: 14363
活跃值: (3930)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
4
是啊作业做完了,累啊
向两位大侠学习
2008-1-8 16:54
0
雪    币: 405
活跃值: (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
5
C语言的反汇编好啊~~~~
2008-1-9 15:11
0
雪    币: 297
活跃值: (26)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
6
赞一个~!厉害啊
2008-1-10 19:27
0
雪    币: 443
活跃值: (200)
能力值: ( LV9,RANK:1140 )
在线值:
发帖
回帖
粉丝
7
好文啊,学习一下先!
2008-1-11 14:59
0
雪    币: 242
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
真是高手。。。。
2008-1-20 11:12
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
不错,学习了。。
2008-1-21 17:20
0
雪    币: 106728
活跃值: (202444)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
10
Thanks again for sharing your efforts netwind!
2008-1-21 18:40
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
11
不错,殊途同归,也是思想火花的碰撞
2008-1-21 22:32
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
好文章 啊,来学习以下啊
2008-1-25 19:58
0
游客
登录 | 注册 方可回帖
返回