-
-
[原创]RCTF-2024-TaskGo
-
发表于: 2024-5-29 17:41 4728
-
很久不打 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,