首页
社区
课程
招聘
[原创]RCTF-2024-TaskGo
发表于: 2024-5-29 17:41 5206

[原创]RCTF-2024-TaskGo

2024-5-29 17:41
5206

很久不打 CTF 比赛了,感觉现在的 Pwn 对代码审计和 Fuzz ,信息收集(相关的CVE)和逆向能力要求越来越高了。

main

main函数利用PostTask提交CtfMain()任务。

CtfMain

CtfMain函数内,利用GetName函数在g_player结构体内存储名字,保存在g_player[0]上,g_player[6]保存了money。然后通过PostTask跑MainStmt()函数。

MainStmt

这是程序的主菜单,功能如下:

(1) Rapidly advancing in the rapids.

子功能:1. Wooden Boat.; 2. Silver Boat.; 3. Golden Boat.

(2) Magic Castle.

子功能:1. Buy Magic Scroll.; 2. Drop Magic Scroll.; 3. Learning Magic Scroll.; 1337. Gods(需满足一定条件)

(3) Show Money.

(4) exit(0)

RapidAdvanceMenu

通过PostTask跑RapidAdvance::PickHandle()函数来进行选择处理,这里可以看出,v13+0x20是任务,v13+0x28保存了参数。将Repeat放进任务队列,Repeat又将MainStmt放进任务队列,这里存在潜在的条件竞争风险,因为money并不是原子数,可能存在竞争风险导致溢出。

接下来进入RapidAdvance::PickHandle()函数,输入 1 后,CheckMoney的返回值不等于 0 会调用 RapidAdvance::StartRA()。

StartRA

通过PostTask启动FiveStar,

进入FiveStart后,调试时发现其进入的时 v12<0 这个分支,将src[0]的内容复制给v7+0x28指向的地方。

CheckMoney

CheckMoney 调用了 sleep(1) 存在窗口时间,并且可以看到堆 money 的操作也并不是原子的,此时上面令起的Repeat任务早已开始运行了,我们此时可以利用这个等待时间购买其他东西,导致money整数溢出。

MagicCastleMenu

调用 MagicCastle::SwitchHandle(v16) 处理选择,然后令起任务MainStmt。

MagicCastle::SwitchHandle

可以看到一个隐藏后门 输入1337后,如果*(_BYTE *)(g_player + 0x1CLL) == 7会进入MagicHeld::Gods函数。

MagicHeld::Gods

根据上面的参数传递来看,参数this = v17[6] = v16 = *((_QWORD *)v12 + 4); // magic_cast;,根据提示,这里也存在条件竞争。

MagicCastle::BuyMS(this)

有三个选项,

MagicCastle::LearningMS(this)

这里发现可以改变g_player+0x1c的值,根据magic_cast的0x20的值做与运算,而我们正好可以利用 1, 2, 4 将其改为7,从而进入Gods函数,进行条件竞争的利用。

MagicCastle::DropMS

这里将0x30大小的magic_cast释放了,而在Gods函数里面我们会申请一个0x40大小的堆块,可以尝试利用条件竞争修改已经释放的Cast,将其保存的Log函数为BackDoor函数(题目给的一个用于读取文件的函数)或者system函数地址。Gods函数调用了v1(&g_player),如果名字为flag或cat flag,那麽就调用了BackDoor("flag")或者system("cat flag")。

但在调试中发现,Gods中申请的堆块与magic_cast并不是同一堆块且相隔很远,cyclic() 测距时,偏移为0x28,并且在cin结束后就已经读入到释放掉的magic_cast中原来Log的位置了,可能go在cin变长读取时在堆上申请了缓冲区。

v13 = g_main_thread_task_runner;
base::Location::Current((base::Location *)v19, "main", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 217);
v14 = operator new(0x30uLL);
base::internal::BindStateBase::BindStateBase(
  v14,
  base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(void)>,base::internal::BindState<false,true,false,void (*)(void)>,void ()(void)>::RunOnce,
  base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
*(_QWORD *)(v14 + 32) = CtfMain;
base::TaskRunner::PostTask(v13, v19, v14);
base::Location::Current((base::Location *)v19, "main", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 219);
base::RunLoop::Run((base::RunLoop *)v21, (const base::Location *)v19);
base::RunLoop::~RunLoop((base::RunLoop *)v21);
base::Thread::Options::~Options((base::Thread::Options *)v26);
base::Thread::~Thread((base::Thread *)v20);
v13 = g_main_thread_task_runner;
base::Location::Current((base::Location *)v19, "main", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 217);
v14 = operator new(0x30uLL);
base::internal::BindStateBase::BindStateBase(
  v14,
  base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(void)>,base::internal::BindState<false,true,false,void (*)(void)>,void ()(void)>::RunOnce,
  base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
*(_QWORD *)(v14 + 32) = CtfMain;
base::TaskRunner::PostTask(v13, v19, v14);
base::Location::Current((base::Location *)v19, "main", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 219);
base::RunLoop::Run((base::RunLoop *)v21, (const base::Location *)v19);
base::RunLoop::~RunLoop((base::RunLoop *)v21);
base::Thread::Options::~Options((base::Thread::Options *)v26);
base::Thread::~Thread((base::Thread *)v20);
__int64 CtfMain(void)
{
  [...]
  GetName();
  v3 = (__int128 *)g_player;
  *((_DWORD *)v3 + 6) = 10000; // money
  [...]
  v7 = g_main_thread_task_runner;
  base::Location::Current((base::Location *)v10, "CtfMain", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 178);
  v8 = operator new(0x30uLL);
  base::internal::BindStateBase::BindStateBase(
    v8,
    base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(void)>,base::internal::BindState<false,true,false,void (*)(void)>,void ()(void)>::RunOnce,
    base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
  *(_QWORD *)(v8 + 0x20) = MainStmt;
  return base::TaskRunner::PostTask(v7, v10, v8);
}
__int64 CtfMain(void)
{
  [...]
  GetName();
  v3 = (__int128 *)g_player;
  *((_DWORD *)v3 + 6) = 10000; // money
  [...]
  v7 = g_main_thread_task_runner;
  base::Location::Current((base::Location *)v10, "CtfMain", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 178);
  v8 = operator new(0x30uLL);
  base::internal::BindStateBase::BindStateBase(
    v8,
    base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(void)>,base::internal::BindState<false,true,false,void (*)(void)>,void ()(void)>::RunOnce,
    base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
  *(_QWORD *)(v8 + 0x20) = MainStmt;
  return base::TaskRunner::PostTask(v7, v10, v8);
}
v13 = operator new(0x30uLL);
base::internal::BindStateBase::BindStateBase(
  v13,
  base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(int),int &&>,base::internal::BindState<false,true,false,void (*)(int),int>,void ()(void)>::RunOnce,
  base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
*(_QWORD *)(v13 + 0x20) = RapidAdvance::PickHandle;
*(_DWORD *)(v13 + 0x28) = v18[0];
base::TaskRunner::PostTask(v12, v17, v13);
v14 = g_main_thread_task_runner;
base::Location::Current(
  (base::Location *)v17,
  "RapidAdvanceMenu",
  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc",
  110);
v15 = operator new(0x30uLL);
base::internal::BindStateBase::BindStateBase(
  v15,
  base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(void)>,base::internal::BindState<false,true,false,void (*)(void)>,void ()(void)>::RunOnce,
  base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
*(_QWORD *)(v15 + 32) = Repeat;
return base::TaskRunner::PostTask(v14, v17, v15);
v13 = operator new(0x30uLL);
base::internal::BindStateBase::BindStateBase(
  v13,
  base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(int),int &&>,base::internal::BindState<false,true,false,void (*)(int),int>,void ()(void)>::RunOnce,
  base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
*(_QWORD *)(v13 + 0x20) = RapidAdvance::PickHandle;
*(_DWORD *)(v13 + 0x28) = v18[0];
base::TaskRunner::PostTask(v12, v17, v13);
v14 = g_main_thread_task_runner;
base::Location::Current(
  (base::Location *)v17,
  "RapidAdvanceMenu",
  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc",
  110);
v15 = operator new(0x30uLL);
base::internal::BindStateBase::BindStateBase(
  v15,
  base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(void)>,base::internal::BindState<false,true,false,void (*)(void)>,void ()(void)>::RunOnce,
  base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
*(_QWORD *)(v15 + 32) = Repeat;
return base::TaskRunner::PostTask(v14, v17, v15);
__int64 __fastcall RapidAdvance::PickHandle(RapidAdvance *this)
{
  [...]
  v17[0] = result;
  if ( (_DWORD)this == 3 )
  {
    [...]
    v9 = (Player *)&g_player;
    v10 = 10000;
  }
  else
  {
    if ( (_DWORD)this != 2 )
    {
      if ( (_DWORD)this == 1 )
      {
        v5 = (Player *)&g_player;
        result = Player::CheckMoney(v5, 0x64u);
        if ( (_BYTE)result )
          return RapidAdvance::StartRA((RapidAdvance *)((char *)&qword_60 + 4));
      }
      return result;
    }
      [...]
      v9 = (Player *)&g_player;
      v10 = 1000;
    }
    else
    {
      v10 = 1000;
    }
  }
  result = Player::CheckMoney(v9, v10);
  if ( (_BYTE)result )
  {
    v14 = std::__Cr::__put_character_sequence<char,std::__Cr::char_traits<char>>(
            &std::__Cr::cout,
            "You finish the game. Hope your next visit.",
            42LL);
    [...]
    return std::__Cr::basic_ostream<char,std::__Cr::char_traits<char>>::flush(v14);
  }
  return result;
}
__int64 __fastcall RapidAdvance::PickHandle(RapidAdvance *this)
{
  [...]
  v17[0] = result;
  if ( (_DWORD)this == 3 )
  {
    [...]
    v9 = (Player *)&g_player;
    v10 = 10000;
  }
  else
  {
    if ( (_DWORD)this != 2 )
    {
      if ( (_DWORD)this == 1 )
      {
        v5 = (Player *)&g_player;
        result = Player::CheckMoney(v5, 0x64u);
        if ( (_BYTE)result )
          return RapidAdvance::StartRA((RapidAdvance *)((char *)&qword_60 + 4));
      }
      return result;
    }
      [...]
      v9 = (Player *)&g_player;
      v10 = 1000;
    }
    else
    {
      v10 = 1000;
    }
  }
  result = Player::CheckMoney(v9, v10);
  if ( (_BYTE)result )
  {
    v14 = std::__Cr::__put_character_sequence<char,std::__Cr::char_traits<char>>(
            &std::__Cr::cout,
            "You finish the game. Hope your next visit.",
            42LL);
    [...]
    return std::__Cr::basic_ostream<char,std::__Cr::char_traits<char>>::flush(v14);
  }
  return result;
}
__int64 __fastcall RapidAdvance::StartRA(RapidAdvance *this)
{
  if ( (_DWORD)this == 100 )
  {
    v1 = g_main_thread_task_runner;
    base::Location::Current((base::Location *)v7, "StartRA", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 276);
    v2 = operator new(0x30uLL);
    base::internal::BindStateBase::BindStateBase(
      v2,
      base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(void)>,base::internal::BindState<false,true,false,void (*)(void)>,void ()(void)>::RunOnce,
      base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
    *(_QWORD *)(v2 + 0x20) = FiveStar;
    base::TaskRunner::PostTask(v1, v7, v2);
  }
  v3 = std::__Cr::__put_character_sequence<char,std::__Cr::char_traits<char>>(
         &std::__Cr::cout,
         "You finish the game. Hope your next visit.",
         42LL);
  return 0LL;
}
__int64 __fastcall RapidAdvance::StartRA(RapidAdvance *this)
{
  if ( (_DWORD)this == 100 )
  {
    v1 = g_main_thread_task_runner;
    base::Location::Current((base::Location *)v7, "StartRA", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 276);
    v2 = operator new(0x30uLL);
    base::internal::BindStateBase::BindStateBase(
      v2,
      base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(void)>,base::internal::BindState<false,true,false,void (*)(void)>,void ()(void)>::RunOnce,
      base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
    *(_QWORD *)(v2 + 0x20) = FiveStar;
    base::TaskRunner::PostTask(v1, v7, v2);
  }
  v3 = std::__Cr::__put_character_sequence<char,std::__Cr::char_traits<char>>(
         &std::__Cr::cout,
         "You finish the game. Hope your next visit.",
         42LL);
  return 0LL;
}
__int64 FiveStar(void)
{
  *(_OWORD *)src = 0LL;
  v12 = 0LL;
  std::__Cr::operator>><char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>(&std::__Cr::cin, src);
  [...]
  v6 = g_io_thread_task_runner;
  base::Location::Current((base::Location *)v10, "FiveStar", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 270);
  v7 = operator new(0x40uLL);
  [...]
  *(_QWORD *)(v7 + 0x20) = NoteStar;
  v8 = (_OWORD *)(v7 + 0x28);                   // v8->v7+0x28
  if ( v12 < 0 )
  {
std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>::__init_copy_ctor_external(
      v8,
      src[0]);
  }
  else
  {
    *(_QWORD *)(v7 + 0x38) = v12;
    *v8 = *(_OWORD *)src;
  }
  result = base::TaskRunner::PostTask(v6, v10, v7);
  if ( v12 < 0 )
    return free(src[0]);
  return result;
}
__int64 FiveStar(void)
{
  *(_OWORD *)src = 0LL;
  v12 = 0LL;
  std::__Cr::operator>><char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>(&std::__Cr::cin, src);
  [...]
  v6 = g_io_thread_task_runner;
  base::Location::Current((base::Location *)v10, "FiveStar", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 270);
  v7 = operator new(0x40uLL);
  [...]
  *(_QWORD *)(v7 + 0x20) = NoteStar;
  v8 = (_OWORD *)(v7 + 0x28);                   // v8->v7+0x28
  if ( v12 < 0 )
  {
std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>::__init_copy_ctor_external(
      v8,
      src[0]);
  }
  else
  {
    *(_QWORD *)(v7 + 0x38) = v12;
    *v8 = *(_OWORD *)src;
  }
  result = base::TaskRunner::PostTask(v6, v10, v7);
  if ( v12 < 0 )
    return free(src[0]);
  return result;
}
bool __fastcall Player::CheckMoney(Player *this, unsigned int cost)
{
  v2 = (__int128 *)g_player;
  v3 = *((_DWORD *)v2 + 6);
  if ( v3 >= cost )
  {
    [...]
    sleep(1u); // 窗口时间,并且此时未更改money值
    v8 = (__int128 *)g_player;
    [...]
    v12 = *((_DWORD *)v8 + 6) - cost;
    v13 = (__int128 *)g_player;
    *((_DWORD *)v13 + 6) = v12;
    v14 = (__int128 *)g_player;
    v15 = std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>::insert(
            v22,
            0LL,
            "\n[!] OK, now you money is : ",
            28LL);
    if ( v25 < 0 )
    {
      free(v24);
      if ( v23 >= 0 )
        return v3 >= cost;
    }
    else if ( v23 >= 0 )
    {
      return v3 >= cost;
    }
    free(v22[0]);
    return v3 >= cost;
  }
  v9 = std::__Cr::__put_character_sequence<char,std::__Cr::char_traits<char>>(
         &std::__Cr::cout,
         "Don't have e enough money.",
         26LL);
  return v3 >= cost;
}
bool __fastcall Player::CheckMoney(Player *this, unsigned int cost)
{
  v2 = (__int128 *)g_player;
  v3 = *((_DWORD *)v2 + 6);
  if ( v3 >= cost )
  {
    [...]
    sleep(1u); // 窗口时间,并且此时未更改money值
    v8 = (__int128 *)g_player;
    [...]
    v12 = *((_DWORD *)v8 + 6) - cost;
    v13 = (__int128 *)g_player;
    *((_DWORD *)v13 + 6) = v12;
    v14 = (__int128 *)g_player;
    v15 = std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>::insert(
            v22,
            0LL,
            "\n[!] OK, now you money is : ",
            28LL);
    if ( v25 < 0 )
    {
      free(v24);
      if ( v23 >= 0 )
        return v3 >= cost;
    }
    else if ( v23 >= 0 )
    {
      return v3 >= cost;
    }
    free(v22[0]);
    return v3 >= cost;
  }
  v9 = std::__Cr::__put_character_sequence<char,std::__Cr::char_traits<char>>(
         &std::__Cr::cout,
         "Don't have e enough money.",
         26LL);
  return v3 >= cost;
}
__int64 MagicCastleMenu(void)
{
  [...]
  LODWORD(v16) = -1431655766;
  std::__Cr::basic_istream<char,std::__Cr::char_traits<char>>::operator>>(&std::__Cr::cin, &v16);
  [...]
  MagicCastle::SwitchHandle((MagicCastle *)(unsigned int)v16);
  v12 = g_main_thread_task_runner;
  base::Location::Current((base::Location *)v15, "Repeat", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 134);
  v13 = operator new(0x30uLL);
  base::internal::BindStateBase::BindStateBase(
    v13,
    base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(void)>,base::internal::BindState<false,true,false,void (*)(void)>,void ()(void)>::RunOnce,
    base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
  *(_QWORD *)(v13 + 0x20) = MainStmt;
  return base::TaskRunner::PostTask(v12, v15, v13);
}
__int64 MagicCastleMenu(void)
{
  [...]
  LODWORD(v16) = -1431655766;
  std::__Cr::basic_istream<char,std::__Cr::char_traits<char>>::operator>>(&std::__Cr::cin, &v16);
  [...]
  MagicCastle::SwitchHandle((MagicCastle *)(unsigned int)v16);
  v12 = g_main_thread_task_runner;
  base::Location::Current((base::Location *)v15, "Repeat", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ctf.cc", 134);
  v13 = operator new(0x30uLL);
  base::internal::BindStateBase::BindStateBase(
    v13,
    base::internal::Invoker<base::internal::FunctorTraits<void (*&&)(void)>,base::internal::BindState<false,true,false,void (*)(void)>,void ()(void)>::RunOnce,
    base::internal::BindState<false,true,false,void (*)(void)>::Destroy);
  *(_QWORD *)(v13 + 0x20) = MainStmt;
  return base::TaskRunner::PostTask(v12, v15, v13);
}
void __fastcall MagicCastle::SwitchHandle(MagicCastle *this)
{
  if ( (int)this <= 2 )
  {
    if ( (_DWORD)this == 1 )
    {
      if ( g_magiccastle <= 1uLL )
      {
        this = (MagicCastle *)&g_magiccastle;
        if ( (unsigned __int8)base::internal::NeedsLazyInstance((unsigned __int64 *)&g_magiccastle) )
        {
          this = (MagicCastle *)&g_magiccastle;
          base::internal::CompleteLazyInstance(&g_magiccastle, &unk_145068, 0LL);
        }
      }
      MagicCastle::BuyMS(this);
    }
    else if ( (_DWORD)this == 2 )
    {
      if ( g_magiccastle <= 1uLL )
      {
        this = (MagicCastle *)&g_magiccastle;
        if ( (unsigned __int8)base::internal::NeedsLazyInstance((unsigned __int64 *)&g_magiccastle) )
        {
          this = (MagicCastle *)&g_magiccastle;
          base::internal::CompleteLazyInstance(&g_magiccastle, &unk_145068, 0LL);
        }
      }
      MagicCastle::DropMS(this);
    }
    return;
  }
  if ( (_DWORD)this != 3 )
  {
    if ( (_DWORD)this != 1337 )
      return;
    v1 = (__int128 *)g_player;
    [...]
    v18[0] = *((_BYTE *)v1 + 0x1C);
    [...]
    v6 = (__int128 *)g_player;
    if ( g_player <= 1uLL )
    {
      if ( !(unsigned __int8)base::internal::NeedsLazyInstance((unsigned __int64 *)&g_player) )
      {
        [...]
        if ( (unsigned __int8)base::internal::NeedsLazyInstance((unsigned __int64 *)&g_player) )
        {
          [...]
LABEL_31:
          if ( *((_BYTE *)v7 + 0x1C) == 7 )
          {
LABEL_32:   // 根据提示来看,这里也存在条件竞争。
            v8 = std::__Cr::__put_character_sequence<char,std::__Cr::char_traits<char>>(
                   &std::__Cr::cout,
                   "\x1B[31m [!] The system is currently recording you name, Please wait 5s... \x1B[0m",
                   76LL);
            v11 = (void (__fastcall ***)(_QWORD, char *, _QWORD *, __int64))g_io_thread_task_runner;
            [...]
            v12 = (__int128 *)g_player;
            [...]
            v16 = *((_QWORD *)v12 + 4); // magic_cast
            [...]
            v17 = (_QWORD *)operator new(0x38uLL);
            [...]
            v17[4] = MagicHeld::Gods;
            v17[5] = 0LL;
            v17[6] = v16;
            (**v11)(v11, v18, v17, 3000000LL);
            return;
          }
          goto LABEL_41;
        }
        if ( *(_BYTE *)(g_player + 0x1CLL) == 7 )
          goto LABEL_32; // 如果条件成立进入调用Gods
LABEL_41:
        v13 = std::__Cr::__put_character_sequence<char,std::__Cr::char_traits<char>>(
                &std::__Cr::cout,
                "You are not qualified!",
                22LL);
        goto LABEL_42;
      }
    }
[...]
LABEL_19:
  if ( g_magiccastle <= 1uLL )
  {
    this = (MagicCastle *)&g_magiccastle;
    if ( (unsigned __int8)base::internal::NeedsLazyInstance((unsigned __int64 *)&g_magiccastle) )
    {
      this = (MagicCastle *)&g_magiccastle;
      base::internal::CompleteLazyInstance(&g_magiccastle, &unk_145068, 0LL);
    }
  }
  MagicCastle::LearningMS(this);
}
void __fastcall MagicCastle::SwitchHandle(MagicCastle *this)
{
  if ( (int)this <= 2 )
  {
    if ( (_DWORD)this == 1 )
    {
      if ( g_magiccastle <= 1uLL )
      {
        this = (MagicCastle *)&g_magiccastle;
        if ( (unsigned __int8)base::internal::NeedsLazyInstance((unsigned __int64 *)&g_magiccastle) )
        {
          this = (MagicCastle *)&g_magiccastle;
          base::internal::CompleteLazyInstance(&g_magiccastle, &unk_145068, 0LL);
        }
      }
      MagicCastle::BuyMS(this);
    }
    else if ( (_DWORD)this == 2 )
    {
      if ( g_magiccastle <= 1uLL )
      {
        this = (MagicCastle *)&g_magiccastle;
        if ( (unsigned __int8)base::internal::NeedsLazyInstance((unsigned __int64 *)&g_magiccastle) )
        {
          this = (MagicCastle *)&g_magiccastle;
          base::internal::CompleteLazyInstance(&g_magiccastle, &unk_145068, 0LL);
        }
      }
      MagicCastle::DropMS(this);
    }
    return;
  }
  if ( (_DWORD)this != 3 )
  {
    if ( (_DWORD)this != 1337 )
      return;
    v1 = (__int128 *)g_player;
    [...]
    v18[0] = *((_BYTE *)v1 + 0x1C);
    [...]
    v6 = (__int128 *)g_player;
    if ( g_player <= 1uLL )
    {
      if ( !(unsigned __int8)base::internal::NeedsLazyInstance((unsigned __int64 *)&g_player) )
      {
        [...]
        if ( (unsigned __int8)base::internal::NeedsLazyInstance((unsigned __int64 *)&g_player) )
        {
          [...]
LABEL_31:
          if ( *((_BYTE *)v7 + 0x1C) == 7 )
          {
LABEL_32:   // 根据提示来看,这里也存在条件竞争。
            v8 = std::__Cr::__put_character_sequence<char,std::__Cr::char_traits<char>>(
                   &std::__Cr::cout,

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 3
支持
分享
最新回复 (1)
游客
登录 | 注册 方可回帖
返回
//