kgdiwss 发表于 2007-11-21 23:34:30

Artur Dend's CrackMe 2分析

//
// 作者:80王朝.∮明天去要饭
// 主页:http://www.80dnst.com
// 论坛:http://bbs.80dnst.com
// 适合:逆向分析初学者
//

       晚上学逆向的时候,拿了个以前分析过的程序再次进行分析,结果发现分析出来的结果不对,本来打算花点时间把整个程序详细分析一下的,可是时间不够,所以这里只挑算法分析过程来写,分析过程中产生的IDA文件和OllyDbg文件,以及注册机源码等都在附件中了,有兴趣的朋友可以下载去看看。      

.text:004010FC ; *************** S U B R O U T I N E ***************************************
.text:004010FC
.text:004010FC ; Attributes: bp-based frame
.text:004010FC
.text:004010FC ; int __stdcall ValidKey(HWND hWnd)
.text:004010FC ValidKey      proc near               ; CODE XREF: DialogFunc+7Bp
.text:004010FC
.text:004010FC hWnd            = dword ptr8
.text:004010FC
.text:004010FC               push    ebp
.text:004010FD               mov   ebp, esp
.text:004010FF               push    14h                ; nMaxCount,说明Name处最长只取20.
.text:00401101               push    offset String    ; lpString,保存Name值的指针
.text:00401106               push    0BB8h            ; nIDDlgItem,即Name处的文本框
.text:0040110B               push       ; hDlg
.text:0040110E               call    GetDlgItemTextA
.text:00401113               mov   esi, eax         ; 把取到的Name文本框的字符数保存到esi中
.text:00401115               lea   eax,
.text:00401117               cmp   esi, 5               ; 判断Name文本框中的字符个数是否大于等于5
.text:0040111A               jge   short loc_401134 ; 如果小于5,则提示至少输入5个字符.
.text:0040111C               push    40h               ; uType
.text:0040111E               push    offset Caption; "ArturDents CrackMe#2"
.text:00401123               push    offset Text       ; "Your name must be at least five charact"...
.text:00401128               push          ; hWnd
.text:0040112B               call    MessageBoxA
.text:00401130               xor   eax, eax
.text:00401132               jmp   short FuncLeave
.text:00401134 ; ---------------------------------------------------------------------------
.text:00401134
.text:00401134 loc_401134:                           ; CODE XREF: ValidKey+1Ej
.text:00401134               push    14h             ; nMaxCount
.text:00401136               push    offset szPWD    ; lpString
.text:0040113B               push    0BB9h         ; nIDDlgItem,还是取文本内容,这里估计是取密码的内容
.text:00401140               push          ; hDlg
.text:00401143               call    GetDlgItemTextA
.text:00401148               mov   eax, offset String ; eax指向Name值
.text:0040114D               mov   ebx, offset szPWD ; ebx指向密码
.text:00401152               mov   ecx, esi      ; ecx保存取到的用户名的个数,即相当于循环体中的i
.text:00401154
.text:00401154 loc_401154:                           ; CODE XREF: ValidKey+62j
.text:00401154               mov   dl,          ; 用户名一位位取出
.text:00401156               sub   dl, cl               ; 将取出的那一位 - 用户名的长度
.text:00401158               cmp   , dl         ; 将结果与密码相应位的值比较
.text:0040115A               jnz   short FuncLeave ; 不相等则跳出
.text:0040115C               inc   eax               ; eax加1,即取用户名时下标加1
.text:0040115D               inc   ebx                ; ebx加1
.text:0040115E               loop    loc_401154   ; ecx大于0时循环,直到用户名取完为止.
.text:0040115E                                                 ; 特别提醒:loop会使ecx的值减小.当cx的值不为0时才会循环.
.text:0040115E                                                 ; 因此可以得出算法:
.text:0040115E                                                 ; 1、从 name 中一位位取出用户名.
.text:0040115E                                                 ; 2、将 name - ecx
.text:0040115E                                                 ; 3、得到的值保存在 password
.text:0040115E                                                 ; 4、然后 ecx - 1
.text:00401160               push    40h               ; uType
.text:00401162               push    offset Caption; "ArturDents CrackMe#2"
.text:00401167               push    offset aYeahYouDidIt ; "Yeah, you did it!"
.text:0040116C               push          ; hWnd
.text:0040116F               call    MessageBoxA    ; 提示注册成功.
.text:00401174
.text:00401174 FuncLeave:                              ; CODE XREF: ValidKey+36j
.text:00401174                                       ; ValidKey+5Ej
.text:00401174               leave
.text:00401175               retn    4
.text:00401175 ValidKey      endp

      有了以上的分析过程,就可以得到算法如下:

      //取出用户名的每一位进行处理

      // 写法一:
      // 第一次分析的时候是这样写的,我也不清楚为什么这么写
      // for(int i = 0; i < nameLength; i++)
      // {
      //   tmp = name - (nameLength - i);
      //   serial = tmp;
      // }

      // 写法二:
      // 这一次分析的时候我是这样写的
      // 这样写是为了体现算法
      for(int i = 0; nameLength > 0; i++)
      {
       tmp = name - nameLength;
       serial = tmp;
       nameLength--;
      }

      printf("serial:%s\n\n", serial);

      另外还发现了另一篇分析这个 Crackme 的文章,也在附件中了,大家可以比对比对。
      如果发现有什么问题请到 80王朝论坛 告诉我,非常感谢!
      效果截图:

http://bbs.80dnst.com/80Dnst_Download/day_071121/20071121_9b04f498c85f0d5f921cIIPwdg3wjuR1.png

    注意:贴子复制过来后着色丢了,我也没时间再一个个着色,带着色的贴子在这:
    http://bbs.80dnst.com/thread-42-1-1.html

[ 本帖最后由 kgdiwss 于 2007-11-21 23:35 编辑 ]
页: [1]
查看完整版本: Artur Dend's CrackMe 2分析