一周学习总结2_BUUCTF_re_CrackRTF

CrackRTF

通读了一下程序,大概是要通过两次输入,然后与给定的字符串进行比较来得到flag,思路比较清晰,但中间过程遇到了一些麻烦。
第一次输入的时候,输入经过atoi函数处理存在v4中

v4 = atoi((const char *)&pbData);

经查询后这是一个把字符串转换成整型的一个函数,全称是ascii to integer
接着是一个连接操作,然后就进入了一个函数处理,处理完后和给定的字符串进行比较
直接进入函数处理

 sub_40100A(&pbData, v0, &String1);

进入函数之后发现不知所云,但大概可以看出是对字符串进行了hash处理,之前只知道hash后会转成定长输出,具体不清楚,查了一下常见的hash算法。SHA-1是转成40位,MD5是转成32位。再一看比较的字符串长度,基本就可以确定是SHA-1了。
接下里就是编写脚本了,因为已经知道输入是个六位的整形,所以求解起来就方便多了,这里要注意hash转换后的散列是小写的,之前没有注意直接用的IDA里面复制的大写,然后一直解不出来,气死我了。

import hashlib
a = '@DBApp'
b = '6E32D0943418C2C33385BC35A1470250DD8923A9'
b = b.lower()
for i in range(100000, 999999):
    flag = str(i) + a
    sha1 = hashlib.sha1(flag.encode())
    x = sha1.hexdigest()
    if x == b:
        print(flag)

接着是第二次输入,看到熟悉的一长串字符我以为是故技重施,但仔细一想,不对劲,事情兵没有这么简单。
首先没有给任何提示,第一次是数字所以很好破解,但如果全字符的话那就很难搞了,所以应该是另外的解法。果然在第二个if函数内发现了了一个不明函数。

if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", &String1) )
    {
     
      if ( !sub_40100F(&String) )
      {
     
        printf("Error!!\n");
        ExitProcess(0);
      }
      printf("bye ~~\n");
    }

好的,进入这个函数,看到下面这串函数

 hResInfo = FindResourceA(0, (LPCSTR)0x65, "AAA");

不懂没关系,遇事不决,直接百度。
FindResourceA( )函数
根据文章提示下载Resource Hacker
把文件拖进去之后直接可以看到一个AAA命名的文件夹,这应该就是我们要找的那个一周学习总结2_BUUCTF_re_CrackRTF_第1张图片
接着是SizeofResource()函数
函数功能:该函数返回指定资源字节数大小。

LoadResource()函数
意思是装载指定资源到全局存储器。

LockResource()函数
是指锁定资源并得到资源在内存中的第一个字节的指针。

CreateFileA()函数
主要用于打开一个文件或者是IO设备,最常用于打开一个IO设备。
知道几个函数大概功能后,遇到了一个不知名函数,点进去查看

  v5 = lstrlenA(lpString);
  for ( i = 0; ; ++i )
  {
     
    result = i;
    if ( i >= a3 )
      break;
    *(_BYTE *)(i + a2) ^= lpString[i % v5];
  }

可以看出意思是把a2和lpString进行异或,刚才已经通过Resource Hacker来得到了一个文件,根据题目的六位长度提示,应该就是取其前六位就可以了,那问题来了,另外一个字符串哪里来,从前文已经找不到可用信息了,然后一直没想明白,后来看了大佬的博客。是说根据CreateFileA()函数可以看出是要建一个rtf文件,然后查找rtf文件头,取其前六位

 hFile = CreateFileA("dbapp.rtf", 0x10000000u, 0, 0, 2u, 0x80u, 0);

rtf文件
以下RTF代码:
{\rtf1\ansiHello!\parThis is some {\b bold} text.\par}
在文字处理软件中将显示为如下效果:
Hello!
This is some
bold
text.
反斜线符号(\)标志着RTF控制代码开始。代码\par表示开始新的一行,代码\b将文本以粗体显示。花括号{和}定义一个群组。上述例子中使用了一个群组来限制代码\b的作用范围。合法的RTF文档是一个以代码\rtf开始的群组
所以前六位也就刚好对应上了标识rtf文档开始的六位{\rtf1
编写脚本

s = "{\\rtf1"
a = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
flag = ""
for i in range(0, len(s)):
    x = ord(s[i]) ^ a[i]
    flag += chr(x)
print(flag)

然后打开程序输入两次得到的字符串
一周学习总结2_BUUCTF_re_CrackRTF_第2张图片
之后在你程序所对应的文件夹下就会生成一个rtf文档,打开即可得到flag
一周学习总结2_BUUCTF_re_CrackRTF_第3张图片

你可能感兴趣的:(一周学习总结2_BUUCTF_re_CrackRTF)