吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2461|回复: 9
收起左侧

[原创] 练习笔记之160Crackme-007

[复制链接]
xiaoyu2032 发表于 2022-4-30 11:42
本帖最后由 xiaoyu2032 于 2022-4-30 11:50 编辑

160CM-007

1.爆破

  这道题和上一道类似,要求逆算法的,但不管他,先爆破一下试试,爽爽再说。
  从爆破的角度来看,这道题其实难度和上一道一样,Delphi编程(可以IDR反编译)、字符串未加密(可以字符串搜索)。先拖进IDR中看一下,可以发现图片实际有两个按钮控件,一个是register,一个是again,分别对应一个OnClick的事件,双击事件函数可以直接查看到函数对应的代码。
12.png
  IDR可以直接识别一些delphi的函数,但是OD识别不了,因为跟踪调试还是需要OD,因此需要在OD中对调用的函数设置一下标签,这样方便阅读理解代码。register对应的函数代码如下:

00442F28 >/.  55            push ebp                                 ;  reg_click
00442F29  |.  8BEC          mov ebp,esp
00442F2B  |.  83C4 F8       add esp,-0x8
00442F2E  |.  53            push ebx
00442F2F  |.  56            push esi
00442F30  |.  33C9          xor ecx,ecx
00442F32  |.  894D F8       mov [local.2],ecx
00442F35  |.  8BD8          mov ebx,eax
00442F37  |.  33C0          xor eax,eax
00442F39  |.  55            push ebp
00442F3A  |.  68 22304400   push aLoNg3x_.00443022
00442F3F  |.  64:FF30       push dword ptr fs:[eax]
00442F42  |.  64:8920       mov dword ptr fs:[eax],esp
00442F45  |.  8D55 F8       lea edx,[local.2]
00442F48  |.  8B83 DC020000 mov eax,dword ptr ds:[ebx+0x2DC]
00442F4E  |.  E8 ED02FEFF   call <aLoNg3x_.GetText>
00442F53  |.  8B45 F8       mov eax,[local.2]                        ;  comctl32.5D176109
00442F56  |.  8D55 FC       lea edx,[local.1]
00442F59  |.  E8 FAF9FBFF   call <aLoNg3x_.Str2Long>
00442F5E  |.  8BF0          mov esi,eax
00442F60  |.  837D FC 00    cmp [local.1],0x0
00442F64  |.  74 37         je short aLoNg3x_.00442F9D               ;  判断是否非数字
00442F66  |.  B8 38304400   mov eax,aLoNg3x_.00443038                ;  ASCII 59,"ou MUST insert a valid Long Integer Value in the Code Editor... Thank you :)"
00442F6B  |.  E8 00F6FFFF   call <aLoNg3x_.Showmessage>
00442F70  |.  8D55 F8       lea edx,[local.2]
00442F73  |.  8B83 DC020000 mov eax,dword ptr ds:[ebx+0x2DC]
00442F79  |.  E8 C202FEFF   call <aLoNg3x_.GetText>
00442F7E  |.  8B45 F8       mov eax,[local.2]                        ;  comctl32.5D176109
00442F81  |.  E8 06FBFFFF   call <aLoNg3x_.suanfa1>                  ;  算法函数1 计算edi
00442F86  |.  A3 30584400   mov dword ptr ds:[0x445830],eax
00442F8B  |.  BA 90304400   mov edx,aLoNg3x_.00443090                ;  UNICODE "0"
00442F90  |.  8B83 DC020000 mov eax,dword ptr ds:[ebx+0x2DC]
00442F96  |.  E8 D502FEFF   call <aLoNg3x_.SetText>
00442F9B  |.  EB 6F         jmp short aLoNg3x_.0044300C
00442F9D  |>  85F6          test esi,esi
00442F9F  |.  7E 5A         jle short aLoNg3x_.00442FFB
00442FA1  |.  8D55 F8       lea edx,[local.2]
00442FA4  |.  8B83 D8020000 mov eax,dword ptr ds:[ebx+0x2D8]
00442FAA  |.  E8 9102FEFF   call <aLoNg3x_.GetText>
00442FAF  |.  8B4D F8       mov ecx,[local.2]                        ;  comctl32.5D176109
00442FB2  |.  8BD6          mov edx,esi
00442FB4  |.  A1 30584400   mov eax,dword ptr ds:[0x445830]
00442FB9  |.  E8 EAF9FFFF   call <aLoNg3x_.suanfa2>                  ;  算法函数2
00442FBE  |.  84C0          test al,al
00442FC0  |.  74 30         je short <aLoNg3x_.Error2>               ;  判断是否正确
00442FC2  |.  33D2          xor edx,edx
00442FC4  |.  8B83 CC020000 mov eax,dword ptr ds:[ebx+0x2CC]
00442FCA  |.  E8 6101FEFF   call <aLoNg3x_.SetVisable>              ;设置可见属性
00442FCF  |.  B2 01         mov dl,0x1
00442FD1  |.  8B83 E8020000 mov eax,dword ptr ds:[ebx+0x2E8]
00442FD7  |.  E8 5401FEFF   call <aLoNg3x_.SetVisable>              ;设置可见属性
00442FDC  |.  33D2          xor edx,edx
00442FDE  |.  8B83 D8020000 mov eax,dword ptr ds:[ebx+0x2D8]
00442FE4  |.  8B08          mov ecx,dword ptr ds:[eax]
00442FE6  |.  FF51 60       call dword ptr ds:[ecx+0x60]             ;  SetEnable

  从上述代码可以看到有两处调用的SetVisable函数,用于设置控件的可见属性。我们可以看一下这段代码:

00442FC2  |.  33D2          xor edx,edx
00442FC4  |.  8B83 CC020000 mov eax,dword ptr ds:[ebx+0x2CC]
00442FCA  |.  E8 6101FEFF   call <aLoNg3x_.SetVisable>  

  代码第一行将edx清零,第二行将一个内存地址送如eax,第三行调用子函数。从这个地方可以很清楚的看出,第一行设置的是可见属性(0,隐藏;1,显示),第二行设置是是控件对应的ID。这就是一个典型的函数调用过程,call之前的代码都是为了将参数传递给子函数。
  因此爆破的话就是要控制程序执行流程进入到00442FC2地址,因此直接将je改成jmp跳转。

00442F64     /74 37         je short aLoNg3x_.00442F9D
改成:
00442F64     /EB 5C         jmp short aLoNg3x_.00442FC2

  改完以后运行,会发现register按钮隐藏了,另一个again按钮显示出来了。同样的办法进入到again Onclick函数里面,可以发现程序过程和register Onclick函数基本相同,因此同样做一下修改:

004430F6     /74 3A         je short aLoNg3x_.00443132
改成:
004430F6     /EB 63         jmp short aLoNg3x_.0044315B

  复制修改、保存,然后运行,依次点击register按钮和again按钮,按钮全部隐藏完毕。
09.png

2.算法分析

  通过前面的爆破分析,其实对于这个程序的结构已经比较了解了,在OD中将IDR识别的函数都进行标签标识后可以发现,仅剩两个函数没有识别出来(红框部分),应该对应为验证算法函数。
08.png
  运行程序,输入name和Code,F8跟踪,可以发现程序直接跳过00442F81,执行到00442FB9代码段,因此先分析一下函数4429A8。函数4429A8的主要算法代码如下图:
13.png
  在IDA中F5得到对应的伪代码如下:
06.png
  这个代码通常看起来有点一头雾水,因为我们不知道其中变量v4~v15到底代表什么内容,这时就需要F8单步跟踪一下程序运行过程,将变量根据实际含义修改一下名字,最终能得到如下图的代码:
07.png
  将代码复制到vs中,将其中不符合C语言语法的部分修改整理一下,就能得到下面的代码:

    i=0;
    if ( Length > 0 )
    {
      k = Length;
      j = 1;
      do
      {
        m =Length;
        if ( m >= 1 )
        {
          do
    {
     i=i+n*str1[m-- -1]*str1[j-1];
    }
          while ( m );
        }
        ++j;
        --k;
      }
      while ( k );
    }
    a = abs(i) % 666666;
    code = code % 80 + code/ 89 + 1;
    if ( a == code )
      result = 1;  
    else
      result = 0;

  其中有个参数n,对应汇编代码中edi地址中的参数,在F8跟踪时发现这个数值一直是0,将n=0代入计算算法中,发现无论输入什么字符串,计算出来的a值都是零,不可能等于code,无法通过算法验证。

00442A16  |.  0FAFD7        ||imul edx,edi

  因此,我们还需要找一下,程序哪里对这个n进行了赋值。我们往前查看一下代码,发现算法函数中,只有4429B7位置将eax赋值给了edi。
14.png
  再往前查,发现在进入算法调用前,在442FB4位置对eax进行了赋值,将地址445830的数值赋给了eax。
15.png
  那就先查一下什么地方对地址445830进行,在地址445830处[右键]-[查找参考]-[地址常量],可以查找到程序中所有涉及到这个地址常量的位置。
17.png
  如下图,一共找出不少位置,依次排查,我们可以发现442F86就在算法2稍微前面一点的位置,在算法1执行完成后就将eax赋值给445830。其他位置除again Onclick中也有一处外,都是将445830进行清零的操作。
16.png
  稍微往前查看一下程序代码就可以发现,前面有一处判断输入的code是否是数字,如果不是数字,就弹窗提示对话框告诉你code必须输入数字,然后执行算法1,跳过算法2;是数字的话,就跳过算法1,执行算法2。呃,原来是这里放了个烟雾弹迷惑人的,想要正确完成注册的话需要先在code其余输入非数字字符串,通过算法1的验证后,再输入数字字符串,通过算法2的验证。
  同样的方法,通过IDA获得算法的伪代码后,稍加改造,就能得到对应的C代码如下:

 int Length2 = strlen(str2);
 n=0;
 i = 891;
    m =Length2 - 1;
    if ( m > 0 )
    {
      j = 1;
      do
      {
        i = i + str2[j-1]*(str2[j] % 17 + 1);
        ++j;
        --m;
      }
      while ( m );
    }
 printf("i=%d\n",i);
 n= abs(i % 29000);
 printf("n=%d\n",n);

  这样就能通过输入的注册码字符串计算得到n的大小。
  由于算法2中对注册码的校验中的计算过程是code = code % 80 + code/ 89 + 1,这里面用了除余,没办法直接反向求解,只能用穷举法了算一下。

 i=1;
 do
 {
  i++;
  code=i%80+i/89+1;
 }
 while (code!=a);

  最终完成的注册码计算算法如下:

#include "stdafx.h"
#include <Windows.h>
#include<stdio.h>

int _tmain(int argc, _TCHAR* argv[])
{
 char str1[30],str2[30];
 int i,j,k,m,n,a,result,code=0;
 printf("请输入用户名(长度5~10):");
    scanf_s("%s",str1,30);
 printf("请输入注册码字符(长度6以上):");
    scanf_s("%s",str2,30);
    int Length = strlen(str1);
 int Length2 = strlen(str2);
 n=0;
 i = 891;
    m =Length2 - 1;
    if ( m > 0 )
    {
      j = 1;
      do
      {
        i = i + str2[j-1]*(str2[j] % 17 + 1);
        ++j;
        --m;
      }
      while ( m );
    }
 printf("i=%d\n",i);
 n= abs(i % 29000);
 printf("n=%d\n",n);

 i=0;
    if ( Length > 0 )
    {
      k = Length;
      j = 1;
      do
      {
        m =Length;
        if ( m >= 1 )
        {
          do
    {
     i=i+n*str1[m-- -1]*str1[j-1];
    }
          while ( m );
        }
        ++j;
        --k;
      }
      while ( k );
    }
    a = abs(i) % 666666;
    code = code % 80 + code/ 89 + 1;
 printf("a=%d\n",a);
 printf("code=%d\n",code);
 /*
    if ( a == code )
  result = 1;  
    else
      result = 0;
   */
 i=1;
 do
 {
  i++;
  code=i%80+i/89+1;
 }
 while (code!=a);

 printf("用户名为:%s\n",str1);
 printf("注册码为:%d \n",i);
 system("pause");
 return 0;
}

  运行注册码程序,输入用户名和注册码字符,结果如下:
01.png
  运行aLoNg3x.2.exe程序,输入用户名abcde,注册码abcdef,注册。
02.png
  然后再输入注册码58674159,注册,注册按钮隐藏了。
03.png
  注册按钮隐藏了,但是又出来一个again按钮,同样分析again Onclick函数,可以发现程序流程和register Onclick函数一样,算法也一样,因此输入注册码abcdef,点击again按钮。
04.png
  再输入注册码58674159,点击again按钮,完成。
05.png

3.总结

  到目前为止,已经成功完成了几个算法题,想想之前都只敢四处改跳转爆破,一看算法就头大,还是很有成就感的。
  如果大家想试试算法,从这几个入手,感觉还是不错的,不会直接打击到没有信心。不理解的汇编命令,百度一下,不理解的delphi函数,百度一下,一回生,二回熟,渐渐的就不怕他们了。

附:百度一下“Delphi反汇编内部字符串处理函数/过程不完全列表”,基本上反汇编后常见的delphi函数的功能都能查到。

免费评分

参与人数 3吾爱币 +8 热心值 +3 收起 理由
Hmily + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
安德鲁儿 + 1 + 1 我很赞同!
Pengruirui + 1 热心回复!

查看全部评分

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

hackerbob 发表于 2022-4-30 13:28
不辍,很详细,连算法也逆出来了
fjsxzhz 发表于 2022-5-1 12:57
MC淡定 发表于 2022-5-1 17:27
JZSun 发表于 2022-5-1 21:35
赞赞赞赞
deepgo 发表于 2022-5-2 00:58
存下以后备用
Kow丶安慕希 发表于 2022-5-2 07:29
感动!谢谢分享。
wildbloom 发表于 2022-5-2 18:20
学习了逆向算法的思路
头像被屏蔽
白鱼啊 发表于 2022-6-17 19:08
提示: 作者被禁止或删除 内容自动屏蔽
 楼主| xiaoyu2032 发表于 2022-6-18 00:38
白鱼啊 发表于 2022-6-17 19:08
 IDR  这个工具在哪下载啊 没找到 方便分享出来吗

论坛爱盘里有的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-15 10:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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