crazy 攻防世界

工具

DIE+IDA

思路展开

1.查壳和位数

无壳,64位

2.IDA启动

代码看着很乱,有很多很长的命令,解决办法:依据英文意思去猜测。
找关键变量的方法:从后往前找,看flag和输入关系。复杂代码本质应该是简洁的,这样才叫出题。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rax
  __int64 v4; // rax
  __int64 v5; // rax
  __int64 v6; // rax
  __int64 v7; // rax
  __int64 v8; // rax
  __int64 v9; // rax
  __int64 v10; // rax
  __int64 v11; // rax
  __int64 v12; // rax
  __int64 v13; // rax
  __int64 v14; // rax
  __int64 v15; // rax
  __int64 v16; // rax
  char input; // [rsp+10h] [rbp-130h]
  char v19; // [rsp+30h] [rbp-110h]
  char v20; // [rsp+50h] [rbp-F0h]
  char v21; // [rsp+70h] [rbp-D0h]
  char temp; // [rsp+90h] [rbp-B0h]
  char temp_2; // [rsp+B0h] [rbp-90h]
  unsigned __int64 v24; // [rsp+128h] [rbp-18h]

  v24 = __readfsqword(0x28u);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&input, argv, envp);
  std::operator>><char,std::char_traits<char>,std::allocator<char>>(&std::cin, &input);
  v3 = std::operator<<<std::char_traits<char>>(&std::cout, "-------------------------------------------");
  std::ostream::operator<<(v3, &std::endl<char,std::char_traits<char>>);
  v4 = std::operator<<<std::char_traits<char>>(&std::cout, "Quote from people's champ");
  std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
  v5 = std::operator<<<std::char_traits<char>>(&std::cout, "-------------------------------------------");
  std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
  v6 = std::operator<<<std::char_traits<char>>(
         &std::cout,
         "*My goal was never to be the loudest or the craziest. It was to be the most entertaining.");
  std::ostream::operator<<(v6, &std::endl<char,std::char_traits<char>>);
  v7 = std::operator<<<std::char_traits<char>>(&std::cout, "*Wrestling was like stand-up comedy for me.");
  std::ostream::operator<<(v7, &std::endl<char,std::char_traits<char>>);
  v8 = std::operator<<<std::char_traits<char>>(
         &std::cout,
         "*I like to use the hard times in the past to motivate me today.");
  std::ostream::operator<<(v8, &std::endl<char,std::char_traits<char>>);
  v9 = std::operator<<<std::char_traits<char>>(&std::cout, "-------------------------------------------");
  std::ostream::operator<<(v9, &std::endl<char,std::char_traits<char>>);
  HighTemplar::HighTemplar((DarkTemplar *)&temp_2, (__int64)&input);
  v10 = std::operator<<<std::char_traits<char>>(&std::cout, "Checking....");
  std::ostream::operator<<(v10, &std::endl<char,std::char_traits<char>>);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(
    (__int64)&v19,
    (__int64)&input);
  func1((__int64)&v20, (__int64)&v19);
  func2((__int64)&v21, (__int64)&v20);
  func3((__int64)&v21, 0);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v21);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v20);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v19);
  HighTemplar::calculate((HighTemplar *)&temp_2);
  if ( (unsigned int)HighTemplar::getSerial((HighTemplar *)&temp_2) == 0 )
  {
    v11 = std::operator<<<std::char_traits<char>>(&std::cout, "/////////////////////////////////");
    std::ostream::operator<<(v11, &std::endl<char,std::char_traits<char>>);
    v12 = std::operator<<<std::char_traits<char>>(&std::cout, "Do not be angry. Happy Hacking :)");
    std::ostream::operator<<(v12, &std::endl<char,std::char_traits<char>>);
    v13 = std::operator<<<std::char_traits<char>>(&std::cout, "/////////////////////////////////");
    std::ostream::operator<<(v13, &std::endl<char,std::char_traits<char>>);
    ZN11HighTemplar7getFlagB5cxx11Ev((__int64)&temp, (__int64)&temp_2);
    v14 = std::operator<<<std::char_traits<char>>(&std::cout, "flag{");
    v15 = std::operator<<<char,std::char_traits<char>,std::allocator<char>>(v14, &temp);
    v16 = std::operator<<<std::char_traits<char>>(v15, "}");
    std::ostream::operator<<(v16, &std::endl<char,std::char_traits<char>>);
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&temp);
  }
  HighTemplar::~HighTemplar((HighTemplar *)&temp_2);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&input);
  return 0;
}

代码从下往上(从结果找输入)找到四句关键语句,代表的是四个处理函数,这四个函数将输入如何一步步变成flag,往下看
0x04ZN11HighTemplar7getFlagB5cxx11Ev((__int64)&temp, (__int64)&temp_2);
0x03if ( (unsigned int)HighTemplar::getSerial((HighTemplar *)&temp_2) == 0 )
0x02HighTemplar::calculate((HighTemplar *)&temp_2);
0x01HighTemplar::HighTemplar((DarkTemplar *)&temp_2, (__int64)&input);

这时从上往下看,缕清输入经历了什么。

0x01

HighTemplar::HighTemplar((DarkTemplar *)&temp_2, (__int64)&input);

unsigned __int64 __fastcall HighTemplar::HighTemplar(DarkTemplar *a1, __int64 a2)
{
  char v3; // [rsp+17h] [rbp-19h]
  unsigned __int64 v4; // [rsp+18h] [rbp-18h]

  v4 = __readfsqword(0x28u);
  DarkTemplar::DarkTemplar(a1);
  *(_QWORD *)a1 = &zfc1;
  *((_DWORD *)a1 + 3) = 0;
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string((__int64)a1 + 16, a2); //temp+16->输入
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string((__int64)a1 + 48, a2);//temp+48->输入
  std::allocator<char>::allocator(&v3, a2);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(
    (__int64)a1 + 80,
    (__int64)"327a6c4304ad5938eaf0efb6cc3e53dc",
    (__int64)&v3); //temp+80->"327a6c4304ad5938eaf0efb6cc3e53dc"
  std::allocator<char>::~allocator(&v3);
  return __readfsqword(0x28u) ^ v4;
}

三个赋值操作,两个位置赋值输入,一个位置赋值一串字符串

0x02

HighTemplar::calculate((HighTemplar *)&temp_2);

bool __fastcall HighTemplar::calculate(HighTemplar *this)
{
  __int64 v1; // rax
  _BYTE *v2; // rbx
  bool result; // al
  _BYTE *v4; // rbx
  int i; // [rsp+18h] [rbp-18h]
  int j; // [rsp+1Ch] [rbp-14h]

  if ( std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length((char *)this + 16) != 32 ) //输入的长度32
  {
    v1 = std::operator<<<std::char_traits<char>>(&std::cout, "Too short or too long");
    std::ostream::operator<<(v1, &std::endl<char,std::char_traits<char>>);
    exit(-1);
  }
  for ( i = 0;
        i <= (unsigned __int64)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length((char *)this + 16);
        ++i ) 
  {
    v2 = (_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](
                    (__int64)this + 16,
                    i);
    *v2 = (*(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[]((__int64)this + 16, i) ^ 0x50) + 23;} //(每个字符^0x50)+23
  for ( j = 0; ; ++j )
  {
    result = j <= (unsigned __int64)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length((char *)this + 16);
    if ( !result )
      break;
    v4=(_BYTE*)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](
                    (__int64)this + 16,
                    j);
    *v4 = (*(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[]((__int64)this + 16, j) ^ 0x13)+ 11;}  //(每个字符^0x13)+11
  return result;
}

检查字符长度,两个简单异或运算。

0x03

if ( (unsigned int)HighTemplar::getSerial((HighTemplar *)&temp_2) == 0 )
验证函数

__int64 __fastcall HighTemplar::getSerial(HighTemplar *this)
{
  char v1; // bl
  __int64 v2; // rax
  __int64 v3; // rax
  __int64 v4; // rax
  __int64 v5; // rax
  unsigned int i; // [rsp+1Ch] [rbp-14h]

  for ( i = 0;
        (signed int)i < (unsigned __int64)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length((char *)this + 16);
        ++i )
  {
    v1 = *(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](
                     (__int64)this + 80,
                     (signed int)i); //之前被复过值327a6c4304ad5938eaf0efb6cc3e53dc
    if ( v1 != *(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](
                           (__int64)this + 16,
                           (signed int)i) ) //输入
    {
      v4 = std::operator<<<std::char_traits<char>>(&std::cout, "You did not pass ");
      v5 = std::ostream::operator<<(v4, i);
      std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
      *((_DWORD *)this + 3) = 1;
      return *((unsigned int *)this + 3);
    }
    v2 = std::operator<<<std::char_traits<char>>(&std::cout, "Pass ");
    v3 = std::ostream::operator<<(v2, i);
    std::ostream::operator<<(v3, &std::endl<char,std::char_traits<char>>);
  }
  return *((unsigned int *)this + 3);
}
0x04

ZN11HighTemplar7getFlagB5cxx11Ev((__int64)&temp, (__int64)&temp_2);

扫描二维码关注公众号,回复: 10940750 查看本文章
__int64 __fastcall ZN11HighTemplar7getFlagB5cxx11Ev(__int64 a1, __int64 a2)
{
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(a1, a2 + 48);//取输入
  return a1;
}

整体思路:一开始数据被分为三部分,一部分赋值输入,后面带入算法;一部分赋值输入,最后作为flag输出;一部分赋值一个字符串,作为比较对象。

脚本

temp='327a6c4304ad5938eaf0efb6cc3e53dc'
flag=''
for i in range(len(temp)):
	n=ord(temp[i])
	flag+=chr((((n-11)^0x13)-23)^0x50)
print('flag{'+flag+'}')
//flag{tMx~qdstOs~crvtwb~aOba}qddtbrtcd}

Wrestling was like stand-up comedy for me.
:p

发布了44 篇原创文章 · 获赞 19 · 访问量 5177

猜你喜欢

转载自blog.csdn.net/weixin_45055269/article/details/105604356