中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 看雪学院专区 > CrackMe
newsearch之 CRACKME2的分析
作者:佚名 时间:2006-12-15 10:37 出处:pediy.com 责编:月夜寒箫
              摘要:newsearch之 CRACKME2的分析
【文章标题】: newsearch忽悠 CRACKME2的分析
【作    者】: laoqian[FCG]
【邮    箱】: -
【主    页】: 
www.fcgchina.com
【QQ    号】: -
【软件名称】: newsearch忽悠 CRACKME2
【大    小】: 44k
【下载地址】: 
http://bbs.pediy.com/attachment.php...tachmentid=3286
【加壳方式】: 无
【保护方式】: 算法
【编写语言】: VC,MFC42
【操作平台】: winxp
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
第一次在这个板块发文,呵呵!
【详细过程】
    最近newsearch一直在研究ecc,研究之余不忘了忽悠,忽悠了几个crackme,说是为了学习ecc而作,我们就来看看,首先说明我不懂ecc,而这个crackme只是有些类似想法而已。
  
  闲话少说,od打开crackme,我们搜索字符参考,只有几个看到"%C%c %c%c%c! ",我们过去,然后在望上面看到,下断点。
  
  疑问,为何在这里下断点,各位看官说为何在这里下呢?——因为我跟踪过他的crackme1,其中有出错提示,所以直接找到这里!
  这次就偷懒了,不过如果第一次跟踪,怎么设断点,不是本文的重点,就略过了,见谅!
  下面是分析:
  
代码:
  004014A0   push -1   004014A2   push CrackMe4.00401B80          ;  SE handler installation   004014A7   mov eax,dword ptr fs:[0]   004014AD   push eax   004014AE   mov dword ptr fs:[0],esp   004014B5   sub esp,6C   004014B8   push ebx   004014B9   push ebp   004014BA   push esi   004014BB   push edi   004014BC   mov ebp,ecx   004014BE   push 1   004014C0   call <jmp.&MFC42.#6334>   004014C5   lea ecx,dword ptr ss:[esp+10]   004014C9   call <jmp.&MFC42.#540>   004014CE   mov esi,dword ptr ss:[ebp+60]   ;  Esi = 注册码   004014D1   mov edi,dword ptr ss:[ebp+68]   ;  Edi = 序列号   004014D4   xor ebx,ebx                     ;  ebx 清零   004014D6   lea ecx,dword ptr ss:[esp+1C]   004014DA   push ebx   004014DB   mov dword ptr ss:[esp+88],ebx   ;  ebx 零   004014E2   call CrackMe4.00401630   004014E7   cmp esi,edi                     ;  判断  注册码 序列号 是否相等   004014E9   mov byte ptr ss:[esp+84],1      ;  置 1   004014F1   je CrackMe4.004015B2            ;  注册码 序列号相等就玩完!   004014F7   mov eax,dword ptr ss:[ebp+64]   ;  eax=用户名   004014FA   cmp eax,edi                     ;  判断  用户名 序列号 是否相等   004014FC   mov dword ptr ss:[esp+18],eax   ;  eax=用户名   00401500   je CrackMe4.004015B2            ;  相等就玩完!   00401506   cmp esi,eax                     ;  判断  用户名 注册码 是否相等   00401508   je CrackMe4.004015B2            ;  相等就玩完!   0040150E   cmp esi,64                      ;  判断  注册码 是否小于100   00401511   jl CrackMe4.004015B2            ;  小于就玩完!   00401517   cmp edi,64   0040151A   jl CrackMe4.004015B2   00401520   cmp eax,64   00401523   jl CrackMe4.004015B2            ;  同理   00401529   lea eax,dword ptr ds:[esi+esi*4>;  eax=esi*5,[esi=注册码],传给eax   0040152C   lea eax,dword ptr ds:[eax+eax*4>;  eax=eax*5,传给eax,注意这里和上面!!!重点   0040152F   sub edi,eax                     ;  edi=edi-eax=序列号-eax   00401531   lea eax,dword ptr ds:[edi+edi*4>;  eax=edi*5,传给eax,注意这里和上面!   00401534   shl eax,1                       ;  逻辑左移1位,eax=eax*2   00401536   cmp eax,10                      ;  比较eax不能小于10H   00401539   mov dword ptr ss:[esp+14],eax   ;  eax复制   0040153D   jl short CrackMe4.004015B2      ;  小于就玩完!   0040153F   fld qword ptr ds:[402510]       ;  装入ST0 实数2,用上浮点了,嘿嘿,这里就是指数算法的关键   00401545   fild dword ptr ss:[esp+14]      ;  eax复制的值,装入ST0 整数   00401549   call <jmp.&MSVCRT._CIpow>       ;  pow(A,B),A的B次方函数   0040154E   fisub dword ptr ss:[esp+18]     ;  浮点减法,上面的结果减去用户名,存入ST0,看FPU寄存器   00401552   call <jmp.&MSVCRT._ftol>        ;  取整到eax   00401557   mov ecx,eax                     ;  ecx=eax   00401559   cdq                             ;  清零edx,准备除法   0040155A   idiv esi                        ;  整数除法,eax/esi,商存eax,余数存edx   0040155C   sub ecx,esi                     ;  Esi=注册码,验证正确应该相等,减法结果ecx=0,重点!有些迷惑后面的小手段!   0040155E   cmp eax,1                       ;  正确验证,eax应等于1   00401561   jnz short CrackMe4.0040159F     ;  不等跳就玩完!   00401563   lea edx,dword ptr ds:[ecx+64]   ;  用上了前面的ecx的值!ecx=0,则edx=64h,d   00401566   lea eax,dword ptr ds:[ecx+6F]   ;  ecx=0,则eax=6Fh,o   00401569   push edx                        ;  入栈   0040156A   push eax                        ;  入栈   0040156B   lea edx,dword ptr ds:[ecx+47]   ;  ecx=0,则edx=47h,G   0040156E   lea eax,dword ptr ds:[ecx+79]   ;  ecx=0,则eax=79h, y   00401571   push edx                        ;  入栈   00401572   add ecx,4D                      ;  ecx=0,则ecx=4Dh,M   00401575   push eax                        ;  入栈   00401576   push ecx                        ;  入栈   00401577   lea ecx,dword ptr ss:[esp+24]   ;  上面根据入栈顺序,我们出栈顺序得到ACSII码,看到“MyGod”呵呵   0040157B   push CrackMe4.00403020          ;  ASCII "%C%c %c%c%c! "   00401580   push ecx                        ;  上面就是我们下断点的依据!   00401581   call <jmp.&MFC42.#2818>         ;  这里就是动态生成成功提示的地方!   00401586   mov edx,dword ptr ss:[esp+2C]   0040158A   add esp,1C   0040158D   push ebx   0040158E   push ebx   0040158F   push edx                        ;  看到edx,就是“My God!”   00401590   call <jmp.&MFC42.#1200>         ;  成功窗口画面   00401595   push ebx   00401596   mov ecx,ebp   00401598   call <jmp.&MFC42.#6334>   0040159D   jmp short CrackMe4.004015BB   0040159F   lea ecx,dword ptr ss:[esp+1C]   004015A3   call <jmp.&MFC42.#2514>         ;  你被忽悠了!!——一张脸!   004015A8   push ebx   004015A9   mov ecx,ebp   004015AB   call <jmp.&MFC42.#6334>   004015B0   jmp short CrackMe4.004015BB   004015B2   lea ecx,dword ptr ss:[esp+1C]   004015B6   call <jmp.&MFC42.#2514>   004015BB   lea ecx,dword ptr ss:[esp+1C]   

  
  可以逆推做注册机了,呵呵我们假设:
  
  Name,用户名
  x,序列号
  y,注册码
  
  我们看
  0040153F   fld qword ptr ds:[402510]       ;  装入ST0 实数2,用上浮点了,嘿嘿,这里就是指数算法的关键
  00401545   fild dword ptr ss:[esp+14]      ;  eax复制的值,装入ST0 整数
  00401549   call <jmp.&MSVCRT._CIpow>       ;  pow(A,B),是的B次方函数,此处FPU看到A=2
  
  此处:2^B是一个关键,那么B是对少,往上看,
  00401529 -00401536中间计算了,我们总结得到B=10(x-25y)
  接下来看到对应关系:
  {2^[10(x-25y)]-Name}/y=1
  
  算法看清了,那么怎么逆向他呢,这个需要数学基础,我没有,只好自己瞎搞了!
  
  我设定:
  Name,用户名
  x,序列号
  y,注册码
  A,我们假设是整数变量,此处为=2,3,4....整数!
  
  把{2^[10(x-25y)]-Name}/y=1简单转化为:
  2^[10(x-25y)]=Name+y
  我设A=X-25Y,带入上式得
  
  2^[A*10]=Name+y
  再来:
  Y=2^[A*10]-Name
  X=25Y+A
  这就是简化后的算法了,A假设是整数变量,此处为=2,3,4....整数!
  
  程序中增加了一些检测用户名、序列号、注册码的判断,无非是避免一些极端情况的出现!
  
  X,Y,Name都是整数必须大于100,而确定A值,而且仅仅是要使Y大于100!可以看出一个用户名,如果不限定A可有无数解!
  本来到此为止了,可是在检验注册机时候,发现,用户名12345678的序列号、注册码的不能注册,奇怪!
  经过再次跟踪发现:
  因为eax等只能存储8位(16进制),lea命令就是传递地址(而不是地址存储数据,相当于复制),如果超出8位,高位就另存(或者说丢弃?),如当[eax*5]大于2^32时候,就去掉高位,只留下后面8位(16进制)参与计算,就是只保留余数!然后再*5,同理舍去高位。就是那个25Y,要在编程时候处理一下,5Y处理高位,再5y处理高位!!!后面也是同理,这个用汇编容易实现,高级语言就麻烦一点。

  这样A=3,4,5...也即能计算出序列号,4.5.6....以此类推!
  
X=25Y+A只是一种特殊情况,因此编写注册机时候,要根据上面作修改

X={5*{5*Y}}+A,其中{5*y}代表以上分析的结果,还是用汇编写注册机算了!

写注册机时候,应该注意到上面eax等寄存器的问题!
  
--------------------------------------------------------------------------------
【总结】
  这个crackme有点意思,据作者说,对于理解ecc有帮助,嘿嘿,等有时间去看看ecc算法!
  
  如果加上hash函数,再把算法复杂一些,这个注册机制就很难逆向!
  
  根据用户名,算法,确定A值,就可以唯一注册码了!

  还有,不是简单把下面ecx=0,就显示成功,而是经过转换,爆破就麻烦一些。
  0040155C   sub ecx,esi                     ;  Esi=注册码,验证正确应该相等,减法结果ecx=0,重点!有些迷惑
  后面的小手段!
  0040155E   cmp eax,1                       ;  正确验证,eax应等于1
  00401561   jnz short CrackMe4.0040159F     ;  不等跳就玩完!
  00401563   lea edx,dword ptr ds:[ecx+64]   ;  用上了前面的ecx的值!ecx=0,则edx=64h,d
  
  爆破点,就是让上面ecx=0 ,00401561这里不跳即可!
  
--------------------------------------------------------------------------------
【版权声明】: 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有