buu-reverse-CrackRTF

核心知识点

本题因为是hash类型的加密,因此无法用动态调试的方法获得答案(hash不可逆,只能暴力枚举)

用到以下几个额外的必须知识点:

password1

使用了wincrpyto库,经过查询是sha1加密,加密后要和6E32D0943418C2C33385BC35A1470250DD8923A9一致

wincrpytoAPI的加密类型:https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id

因为只有六位数字因此进行爆破即可,有两种方法:

  • 用python 的hashlib进行爆破(用其他语言类似)
  • 直接用网站查

但是很多网站查不到,使用hashlib进行爆破

import hashlib

# sha1的结果默认是小写表示的
goal = '6E32D0943418C2C33385BC35A1470250DD8923A9'.lower()

for i in range(100000,1000000):
    s = str(i)+"@DBApp"
    sha = hashlib.sha1(s.encode()) # 转成bytes类型
    cnt = sha.hexdigest() # hexdigest获取hash值
    if goal == cnt:
        print(str(i)) # 123321

password2

关键代码分析

关键代码(本质上最外层是两个判断,这是第二个,第一个是hash判断,复杂度太高,爆破几乎没可能),资源文件使用resource_hacker打开找到AAA文件

大致含义就是把 输入的字符串每一位与AAA文件的对应位进行异或操作,结果保存到资源指针

// ipstring是输入的第二个字符串 a2是资源文件 a3是资源字节大小
unsigned int __cdecl sub_401420(LPCSTR lpString, int a2, int a3)
{
  unsigned int result; // eax
  unsigned int i; // [esp+4Ch] [ebp-Ch]
  unsigned int v5; // [esp+54h] [ebp-4h]

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

其中lpString组成(_main()中调用的):password2 + password1 + @DBApp

之后在写入dbapp.rtf文件

char __cdecl sub_4014D0(LPCSTR lpString)
{
  LPCVOID lpBuffer; // [esp+50h] [ebp-1Ch]
  DWORD NumberOfBytesWritten; // [esp+58h] [ebp-14h]
  DWORD nNumberOfBytesToWrite; // [esp+5Ch] [ebp-10h]
  HGLOBAL hResData; // [esp+60h] [ebp-Ch]
  HRSRC hResInfo; // [esp+64h] [ebp-8h]
  HANDLE hFile; // [esp+68h] [ebp-4h]

  hFile = 0;
  hResData = 0;
  nNumberOfBytesToWrite = 0;
  NumberOfBytesWritten = 0;
  hResInfo = FindResourceA(0, (LPCSTR)0x65, "AAA");
  if ( !hResInfo )
    return 0;
  nNumberOfBytesToWrite = SizeofResource(0, hResInfo);
  hResData = LoadResource(0, hResInfo);
  if ( !hResData )
    return 0;
  lpBuffer = LockResource(hResData);
  sub_401005(lpString, (int)lpBuffer, nNumberOfBytesToWrite);
  hFile = CreateFileA("dbapp.rtf", 0x10000000u, 0, 0, 2u, 0x80u, 0); //看这里
  if ( hFile == (HANDLE)-1 )
    return 0;
  if ( !WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, &NumberOfBytesWritten, 0) ) //看这里
    return 0;
  CloseHandle(hFile);
  return 1;
}

思路分析

来仔细考虑一下这个异或内容怎么反向得到password1:

  • lpString:password2 + password1 + @DBApp
  • a2:AAA文件的内容可以使用resource_hack得到
  • result:最后的结果要保存成rtf文件,而rtf文件前六位是固定的{\rtf1

已知二三条的数据,可以反向异或得到password2

即可 result = ipstring ^ a2 => result ^ a2 == ipstring ^ a2 ^ a2 == ipstring

因此 ipstring = result ^a2

注册机

ipstring = ''
a2       = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
result   = "{\\rtf1"

for i in range(len(a2)):
    x = ord(result[i]) ^ a2[i]
    ipstring += chr(x)
print(ipstring) # ~!3a@0

得到flag

根据IDA分析_main()->sub_40100F()的内容

可以知道最后把一个内容保存进了dbapp.rtf文件,而题目提示有说flag就在一个rtf文件中。

因此运行原程序,依次输入两段password

  • 123321
  • ~!3a@0

打开生成的dbapp.rtf文件答案赫然在列flag为:flag{N0_M0re_Free_Bugs}

image.png

Last modification:March 4, 2021
如果觉得我的文章对你有用,请随意赞赏。咖啡(12RMB)进度+100%,一块巧克力(1RMB)进度+6%。
(赞赏请备注你的名称哦!后台记录中来自理工小菜狗)