首页 > 其他分享 >CrackRTF 1

CrackRTF 1

时间:2023-05-05 13:44:34浏览次数:43  
标签:Des sub CrackRTF Destination 密码 Str String1

查壳

先运行看看是个啥:

要我们输入密码(1),估计还有密码(2),随便输了就直接给你退出,先不管密码(2)是否存在遇到了再说。

32位,进IDA找主函数:

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  DWORD v3; // eax
  DWORD v4; // eax
  char Str[260]; // [esp+4Ch] [ebp-310h] BYREF
  int v7; // [esp+150h] [ebp-20Ch]
  char String1[260]; // [esp+154h] [ebp-208h] BYREF
  char Destination[260]; // [esp+258h] [ebp-104h] BYREF

  memset(Destination, 0, sizeof(Destination));
  memset(String1, 0, sizeof(String1));
  v7 = 0;
  printf("pls input the first passwd(1): ");
  scanf("%s", Destination);
  if ( strlen(Destination) != 6 )
  {
    printf("Must be 6 characters!\n");
    ExitProcess(0);
  }
  v7 = atoi(Destination);
  if ( v7 < 100000 )
    ExitProcess(0);
  strcat(Destination, "@DBApp");
  v3 = strlen(Destination);
  sub_40100A((BYTE *)Destination, v3, String1);
  if ( !_strcmpi(String1, "6E32D0943418C2C33385BC35A1470250DD8923A9") )
  {
    printf("continue...\n\n");
    printf("pls input the first passwd(2): ");
    memset(Str, 0, sizeof(Str));
    scanf("%s", Str);
    if ( strlen(Str) != 6 )
    {
      printf("Must be 6 characters!\n");
      ExitProcess(0);
    }
    strcat(Str, Destination);
    memset(String1, 0, sizeof(String1));
    v4 = strlen(Str);
    sub_401019((BYTE *)Str, v4, String1);
    if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", String1) )
    {
      if ( !(unsigned __int8)sub_40100F(Str) )
      {
        printf("Error!!\n");
        ExitProcess(0);
      }
      printf("bye ~~\n");
    }
  }
  return 0;
}

得到一个挺长的函数,老思想,先找正确的输出的判断:

是将“27019e688a4e62a649fd99cadaafdb4e”与String1对比,才有可能输出成功,那么我们来找Stirng1,先看它内存里有东西吗

空的,那么去找相关的赋值或者方法:这里要从头开始看,不然容易漏掉加密过程。

首先是memset方法,初始化空间嘛,不用理,往下看我们能看到sub_40100A方法调用了String1和Des,看起来有点像将Des的值给String1,不要感觉,我们去追求的是实际,那么我们去找Des:

可以知道Des是由我们来输入的,而且一定是6位数或者6个字符,接着往下看:

v7将我们输入的6个字符转化成了数字,并要求不能小于100000,否则退出,那么可以知道我们输入的Des范围一定是100000 ~ 999999(看到范围,第一个想干嘛,肯定是爆破昂(我知道你很急,但你先别急,我们接着看判断)):

是说将Des字符串上加上“@DBApp”后经过sub_40100A方法(出现了第一次涉及String1的方法)加密成一段密文后与"6E32D0943418C2C33385BC35A1470250DD8923A9"比较,正确则出现输入第二段密码的字样,跟进方法看看:

一堆看不懂的函数,查呗:(发现一个加密算法Hash标志)

可以知道这是Hash加密算法,这里不介绍了,0x8004表示具体加密形式:SHA1,可以自己去查:上脚本:

import hashlib

ad = '@DBApp'
Des = '6E32D0943418C2C33385BC35A1470250DD8923A9'.lower()
for i in range(100000, 1000000):
    ans = str(i) + ad
    end = hashlib.sha1(ans.encode('utf-8')).hexdigest()
    if end == Des:
        print(i)
        break

这里注意:为什么要进行一个小写的转化呢,因为hash加密后的密文一般都是小写的。

可以得到第一个密码123321,确认一下:

继续:

又读入一个长度为6的字符串,作为第二个密码:看判断:

将Des接入输入的密码后边,进入sub_401019方法加密后与"27019e688a4e62a649fd99cadaafdb4e"比较:看方法:

sub_401019:发现与上边差不多相同:(又是Hash)但是仔细观看,会发现参数的不同 0x8003u --> md5加密

我们又知道了加密后的文本,直接解密呗:

https://www.somd5.com/

得到一个字符串:"~!3a@0123321@DBApp"仔细一看?完整密码?直接过了 密码(2):~!3a@0

输入后得到一个文件dbapp.rtf打开后直接得到Flag{N0_M0re_Free_Bugs}可以收工了。

在做第二次判断的时候,我们发现内层里边里还有一个判断,是只针对Str来的,而Str就是密码(2),那么我们可以去看看这是个啥:

跟进sub_40100F方法:

发现似乎从"AAA"文件中拿东西,(https://blog.csdn.net/bygwys/article/details/124206536)参考文献。然后进入sub_401005解密,可能有人会问,从哪开始拿,拿几位? --> 一般文件都是从头开始拿,那么我们就从头开始拿就好了,那么拿几位呢?因为Str是六位嘛,那么我们拿六位出来解密:

跟进sub_401005方法:

发现是一个xor,那么问题又来来了,跟谁异或呢(在方法里面发现没有明确的东西异或),由于要生成.rtf文件,那么AAA中的数据跟什么异或一定得到"{\rtf1"(.rtf文件头的前六位(为什么是6位呢,因为密码就6位昂))这个呢:(异或的特性不就来了嘛)

Des = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
Des2 = '{\\rtf1'
pas = ''
for i in range(len(Des)):
    pas += chr(Des[i % len(Des)] ^ ord(Des2[i]))
print(pas)

得到密码:~!3a@0。

无论哪种都可以走到终点,但是多一个方法和思路都是很好的。

标签:Des,sub,CrackRTF,Destination,密码,Str,String1
From: https://www.cnblogs.com/TFOREVERY/p/17373878.html

相关文章

  • Buuctf CrackRTF
    BuuctfCrackRTF 查壳发现无壳,直接反汇编    可以看出,程序要我们输入6个字符.由atoi函数(字符串转换为整型数字)和v7需要大于100000得到输入的必须是六个数字......