中国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
llydd's crackme的逆向
作者:冲天剑 时间:2006-12-14 21:21 出处:pediy.com 责编:月夜寒箫
              摘要:llydd's crackme的逆向
下载地址:http://bbs.pediy.com/showthread.php?s=&threadid=33069
使用工具:OllyDbg,Resource Hacker


  分析资源的过程只是用Resource Hacker打开.exe文件,然后选择菜单项“操作--->保存所有资源”
就行了,没有什么技术问题,这里就不细说了。

  用OllyDbg打开.exe文件,停在入口点处。这是一个典型的VC++程序入口,不用PEID也可看出来,为
什么呢?这种入口往下看会依次出现GetVersion,GetCommandLine,GetStartupInfo和GetModuleHandle
这些API,其中GetModuleHandle返回的值是作为一个过程的实际参数,这个过程肯定就是WinMain。这就
是说,我们刚才看到的部分其实只是VC的初始化代码,而程序员可见的代码只有在WinMain被调用以后才
开始,在这之前的部分是不需要关心的。在这个例子中,WinMain的入口在地址0x401000处,而调用它的
语句在地址0x401319处。

  进入WinMain后发现这个过程只包含一个DialogBoxParam调用然后就返回了,典型的一个对话框做界
面的程序。根据DialogBoxParam的倒数第2个参数找到对话框的回调过程在地址0x401020处。

  接着进入对话框的回调过程中。一般而言,这个过程只是对派送给对话框的某些消息作出个性化的
响应,我们只需要知道它具体处理的是哪些消息。这个过程的第2个参数就是消息的代号,所以函数体中
肯定会根据第2个参数的值实现分支。不知什么原因,VC生成的机器代码在存取局部变量时不象通常那样
使用ebp而是直接用esp做指针,而switch..case结构也变了形。经过辨认,0x40104D处的指令所引用的
[esp+80]就是消息代码参数,而这个对话框一共处理3种消息:WM_DESTROY、WM_CLOSE和WM_COMMAND。而
WM_DESTROY、WM_CLOSE又是在同一个分支中处理的,其响应动作为用PostMessage在对话框的消息队列中
放入一条WM_QUIT消息。(笔者观点,结束对话框尽量用现成的API——EndDialog,而对话框消息循环是
已经被Windows封装的东西,能不去涉及最好)

  WM_COMMAND分支则较复杂些,其中涉及到界面上两个按钮被按下的事件,在地址0x401071处的指令
引用的[esp+84]是消息的(或者说是对话框过程的)wParam参数,通常这个参数的含义就是被按下按钮
的控件ID,这次就要查看刚保存的资源脚本了,经查验知0x3E9是“注册”按钮的ID,0x3ED则是
“关于”按钮的ID。于是很容易看到当“关于”按钮被按下时的动作是用MessageBox显示一条信息:

             "first crackme by llydd \^_^/"

  而当“注册”按钮被按下时,则调用GetDlgItemText到两个输入框中取得文本,这个函数的第二和
第三个参数分别是控件ID和文本缓冲区,根据第二个参数的数值以及资源脚本中的对应控件,就能知道
第三个参数所指向的缓冲区中是什么内容。在当前的情况下我们知道:

              esp+10 == szUserName
                            esp+44 == szSerial

取完文本后用strlen例程(这在汇编中是一个很常用的求字符串长的例程,但不知道为什么会出现在C语
言编译的代码中,而导入表中实际上也没有strlen这个函数)求它们的长度。如果其中某个字符串的长
度小于4或大于20,则分别用MessageBox显示下面的消息:

               "用户名至少4位最多20位"
                          "注册码至少4位最多20位"

并直接从对话框过程返回。只有这两个长度都在4到20之间才作进一步处理。

  首先将szUserName的各字符与szSerial的对应字符相xor。(如果szSerial不及szUserName长,则只
有前strlen(szSerial)个字符做了变换)然后szUserName逐字符与szSerial的中点字符,也就是

           szSerial [strlen (szSerial) / 2]

相xor,接下去是szUserName逐字符与这个中点字符减去'A'相xor,szUserName逐字符加上用户名长与序
列号长的总和,最后把szUserName与szSerial逐字符比较,如果相等,就用MessageBox显示下列信息:

              "注册成功"

根据以上描述,逆向出来的C语言代码如下:


======================================================

#include   <windows.h>

#define    DLG_MAIN       101
#define    ID_REG         1001      //“注册”按钮的ID
#define    EDT_NAME       1003      //用户名输入框的ID
#define    EDT_SERIAL     1004      //序列号输入框的ID
#define    ID_ABOUT       1005      //“关于”按钮的ID

BOOL CALLBACK ProcDlgMain (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)

{
  char         loc_szUserName[52], loc_szSerial[52];
  int          loc_nLenOfName, loc_nLenOfSerial;
    int          loc_i, loc_k;

  switch (uMsg)
  {
  case WM_COMMAND:
    switch (LOWORD(wParam))
    {
    case ID_REG:         //“注册”按钮被按下

        GetDlgItemText (hDlg, EDT_NAME, loc_szUserName, 50);
      loc_nLenOfName = strlen (loc_szUserName);
      if (loc_nLenOfName < 4 || loc_nLenOfName > 20)
      {
        MessageBox (NULL, "用户名至少4位最多20位", "", MB_OK);
        return FALSE;
      }
      
      GetDlgItemText (hDlg, EDT_SERIAL, loc_szSerial, 50);
      loc_nLenOfSerial = strlen (loc_szSerial);
      if (loc_nLenOfSerial < 4 || loc_nLenOfSerial > 20)
      {
        MessageBox (NULL, "注册码至少4位最多20位", "", MB_OK);
        return FALSE;
      }
      
      loc_k = (loc_nLenOfName < loc_nLenOfSerial)? loc_nLenOfName: loc_nLenOfSerial;  //取较小者
      for (loc_i = 0; loc_i < loc_k; loc_i ++)
      {
        loc_szUserName [loc_i] = loc_szUserName [loc_i] ^ loc_szSerial [loc_i];       
        //用户名逐字符与序列号对应字符相xor
      }

      for (loc_i = 0; loc_i < loc_nLenOfName; loc_i ++)
      {
        loc_szUserName [loc_i] = loc_szUserName [loc_i] ^ loc_szSerial [loc_nLenOfSerial / 2]; 
        //再逐字符与序列号中点字符相xor
      }

      for (loc_i = 0; loc_i < loc_nLenOfName; loc_i ++)
      {
        loc_szUserName [loc_i] = loc_szUserName [loc_i] ^ (loc_szSerial [loc_nLenOfSerial / 2] - 'A'); 
        //再逐字符与序列号中点字符减'A'相xor
      }

      for (loc_i = 0; loc_i < loc_nLenOfName; loc_i ++)
      {
                loc_szUserName [loc_i] = loc_szUserName [loc_i] + (char) (loc_nLenOfName + loc_nLenOfSerial); 
        //再逐字符加上用户名长度与序列号长度的和
      }

      if (strcmp (loc_szUserName, loc_szSerial) == 0)
      {
        MessageBox (NULL, "注册成功", "", MB_OK);
      }
      break;
    
    case ID_about :

      MessageBox (NULL, "first crackme by llydd \^_^/", "", MB_OK);
    
    }
    break;
  case WM_DESTROY:
  case WM_CLOSE:
    PostMessage (hDlg, WM_QUIT, 0, 0);     //个人觉得这种方法不好
  }
    return FALSE;
}


int WINAPI WinMain (HINSTANCE hCurrInstance,
                    HINSTANCE hPrevInstance,
            LPSTR     lpszCmdLine,
            int       nCmdShow
           )
          
{
  DialogBoxParam (hCurrInstance, DLG_MAIN, NULL, &ProcDlgMain, NULL);
  return 0;
}

======================================================



资源脚本如下:

======================================================
101 DIALOGEX 0, 0, 162, 91
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "crackme BY llydd"
LANGUAGE LANG_CHINESE, 0x2
FONT 10, "System"
{
   CONTROL "crackme", 1001, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 23, 63, 50, 21 
   CONTROL "用户名", -1, STATIC, SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 14, 14, 25, 16 
   CONTROL "", 1003, EDIT, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 46, 11, 92, 17 
   CONTROL "注册码", -1, STATIC, SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 15, 37, 27, 10 
   CONTROL "", 1004, EDIT, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 46, 32, 92, 17 
   CONTROL "关于", 1005, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 109, 64, 30, 20 
}

======================================================



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