这是一场人类与超智能AI的“生死”较量
请立刻集结,搭乘SpaceX,前往AI控制空间站
智慧博弈 谁能问鼎
看雪·2023 KCTF 年度赛于9月1日中午12点正式开赛!比赛基本延续往届模式,设置了难度值、火力值和精致度积分。由此来引导竞赛的难度和趣味度,使其更具挑战性和吸引力,同时也为参赛选手提供了更加公平、有趣的竞赛平台。
*注意:签到题持续开放,整个比赛期间均可提交答案获得积分
今天中午12:00第三题《秘密计划》已截止答题,该题持续了48小时,共有6支战队成功提交flag,他们分别是:
想必还是有一点点难度的,接下来一起看下该题的设计思路和解析吧。
出题战队:嗷来吼
战队成员:yimingqpa
本题解析由看雪专家 GreatIchild 提供:
<SOUI alpha="255" appWnd="1" bigIcon="ICON_LOGO:32" height="300" margin="0,0,0,0" name="mainWindow" resizable="0" smallIcon="ICON_LOGO:16" translucent="1" width="600">
<root cache="1" ncskin="skin_bg_shadow" colorBkgnd="#e6e6faff">
<caption pos="0,0" size="600, 300" show="1" font="adding:0">
<caption pos="0,0" size="600,30" colorBkgnd="#3cb371ff">
<imgbtn pos="-40,4" size="27,22" tip="关闭" animate="1" skin="skin_bg_close" name="btn_close" />
<text pos="8,5" colorText="#ffffffff" font="face:微软雅黑,size:13">CTF 2023</text>
</caption>
<caption pos="1,30" size="598, 269" skin="skin_bg_main">
<img pos="201,10" size="196,196" skin="skin_img_logo" name="img_logo" />
<text pos="95,224" font="face:微软雅黑,size:14">FLAG:</text>
<edit pos="144,222" size="296, 24" colorBkgnd="#FFFFFF" cueText="请输入你的答案" colorText="#000000" font="face:微软雅黑,size:13" maxBuf="32" inset="4,2,4,2" skin="image_check_png" name="input_va" />
<imgbtn pos="456,218" size="80,32" tip="验证输入" animate="1" font="face:微软雅黑,size:14" skin="image_btn_png" name="check_va">验证</imgbtn>
</caption>
</caption>
</root>
</SOUI>
memset(v30, 0, 0x2DCu);
sub_A487A2(L"LAYOUT:XML_MAINWND");
*(_DWORD *)v30 = &main_dlg::`vftable';
*(_DWORD *)&v30[4] = &main_dlg::`vftable';
*(_OWORD *)&v30[0x2AC] = 0i64;
*(_DWORD *)&v30[0x28] = &main_dlg::`vftable';
*(_DWORD *)&v30[0x2C] = &main_dlg::`vftable';
*(_DWORD *)&v30[0x130] = &main_dlg::`vftable';
*(_DWORD *)&v30[0x2A8] = &simulation::`vftable';
*(_DWORD *)&v30[0x2BC] = 0;
*(_DWORD *)&v30[0x2C0] = 15;
v30[0x2AC] = 0;
*(_DWORD *)&v30[0x2C8] = 0;
*(_DWORD *)&v30[0x2CC] = 0;
*(_DWORD *)&v30[0x2D0] = 0;
*(_DWORD *)&v30[0x2C4] = 0;
*(_DWORD *)&v30[0x2D8] = 0;
*(_DWORD *)&v30[0x268] = 0;
*(_DWORD *)&v30[0x26C] = 0;
*(_DWORD *)&v30[0x270] = 0;
*(_OWORD *)&v30[0x274] = 0i64;
*(_DWORD *)&v30[0x2A4] = 0;
*(_OWORD *)&v30[0x284] = 0i64;
*(_OWORD *)&v30[0x294] = 0i64;
v13 = CreateTimerQueue();
*(_DWORD *)(this + 0x294) = v13;
if ( v13 )
{
CreateTimerQueueTimer((PHANDLE)(this + 0x298), v13, sub_407880, *(PVOID *)(this + 28), 500u, 2000u, 0);
CreateTimerQueueTimer((PHANDLE)(this + 0x29C), *(HANDLE *)(this + 0x294), sub_407900, 0, 600u, 2000u, 0);
CreateTimerQueueTimer((PHANDLE)(this + 0x2A0), *(HANDLE *)(this + 0x294), sub_4079D0, 0, 700u, 2000u, 0);
CreateTimerQueueTimer((PHANDLE)(this + 0x2A4), *(HANDLE *)(this + 0x294), sub_407A60, 0, 800u, 2000u, 0);
}
SetForegroundWindow(*(HWND *)(this + 28));
*(_DWORD *)(this + 0x270) = SetTimer(*(HWND *)(this + 28), 1u, 100u, TimerFunc);
void __stdcall sub_407A60(PVOID a1, BOOLEAN a2)
{
HANDLE v2; // eax
void *v3; // esi
v2 = CreateMutexW(0, 0, L"A2D972DA-0A03-41D4-906B-6EFF73D0C937");
v3 = v2;
if ( v2 )
{
SetHandleInformation(v2, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE);
CloseHandle(v3);
}
}
switch ( a3 )
{
case WM_CREATE:
*(_DWORD *)(this + 0x2D4) = 0;
break;
case WM_INITDIALOG:
*(_DWORD *)(this + 0x2D4) = 1;
*a6 = sub_405F10(this, v14, v16);
goto LABEL_9;
case WM_CLOSE:
*(_DWORD *)(this + 0x2D4) = 1;
sub_405E60(this);
break;
default:
goto LABEL_10;
}
switch ( a3 )
{
case 0x47A:
v15 = a5;
v13 = (WCHAR *)a4;
v12 = 0x47A;
goto LABEL_22;
case 0x47B:
v15 = a5;
v13 = (WCHAR *)a4;
v12 = 0x47B;
goto LABEL_22;
case 0x47D:
v15 = a5;
v13 = (WCHAR *)a4;
v12 = 0x47D;
goto LABEL_22;
case 0x47C:
v15 = a5;
v13 = (WCHAR *)a4;
v12 = 0x47C;
LABEL_22:
v17 = 1;
sub_4061D0(this, v12, v13, (int)v15); =
return msg != 0;
}
if ( a3 != 0x47E )
return 0;
v17 = 1;
sub_4061D0(this, 0x47E, (WCHAR *)a4, (int)a5); =
return msg != 0;
BOOL __thiscall sub_405AF0(int this, int a2)
{
int v2; // ebx
int v3; // eax
int v4; // eax
v2 = 0;
if ( (*(int (__stdcall **)(int))(*(_DWORD *)a2 + 24))(a2) == 10000 )
{
if ( (*(int (__stdcall **)(int))(*(_DWORD *)a2 + 88))(a2) )
{
v3 = wcscmp((const unsigned __int16 *)(*(int (__stdcall **)(int))(*(_DWORD *)a2 + 88))(a2), L"btn_close");
if ( v3 )
v3 = v3 < 0 ? -1 : 1;
if ( !v3 )
{
v2 = 1;
(*(void (__stdcall **)(int, _DWORD))(*(_DWORD *)a2 + 100))(a2, 0);
sub_405E60(this);
if ( !(*(int (__stdcall **)(int))(*(_DWORD *)a2 + 96))(a2) )
return 1;
}
}
if ( (*(int (__stdcall **)(int))(*(_DWORD *)a2 + 88))(a2) )
{
v4 = wcscmp((const unsigned __int16 *)(*(int (__stdcall **)(int))(*(_DWORD *)a2 + 88))(a2), L"check_va");
if ( v4 )
v4 = v4 < 0 ? -1 : 1;
if ( !v4 )
{
++v2;
(*(void (__stdcall **)(int, _DWORD))(*(_DWORD *)a2 + 100))(a2, 0);
sub_406490(this);
if ( !(*(int (__stdcall **)(int))(*(_DWORD *)a2 + 96))(a2) )
return 1;
}
}
}
if ( (*(int (__stdcall **)(int))(*(_DWORD *)a2 + 96))(a2) )
v2 += sub_A3FBD7(a2) != 0;
return v2 != 0;
}
void __thiscall sub_406490(int this)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v36 = this;
v1 = *(_DWORD *)(this + 0x26C);
if ( !v1 )
return;
v46 = 0;
input_ = 0i64;
(*(void (__thiscall **)(int, __int64 *, _DWORD))(*(_DWORD *)(v1 + 12) + 0x230))(v1 + 12, &input_, 0);
v48 = 0;
if ( SOUI::SStringW::empty(&input_) || SOUI::SStringW::size(&input_) != 32 )
goto LABEL_42;
v2 = SOUI::SStringW::size(&input_);
v3 = SOUI::SStringW::data(&input_, v2);
std::wstring::ctor(&w_input, v3);
v4 = __rdtsc();
srand(v4);
v5 = rand() % 32;
v6 = __rdtsc();
v40 = v5 + 4;
srand(v6);
v7 = rand() % (v5 + 4);
v8 = 0;
v9 = 0;
v10 = 0;
v38 = 0;
0; =
v9 = 0;
0; =
v42 = 0;
0; =
v41 = 0;
2; =
v41 = 0;
if ( v40 <= 0 )
goto LABEL_29;
do
{
if ( v41 == v7 )
{
...
}
else
{
...
}
vector_pair_WCHAR_ptr_int__::push_back(&v47, v9, v14);
v10 = v47.end_of_storage;
v9 = v47.finish;
v42 = v47.end_of_storage;
LABEL_27:
++v41;
}
while ( v41 < v40 );
v8 = v47.start;
v39 = v47.start;
LABEL_29:
v29 = v8;
if ( v8 != v9 )
{
v30 = v36;
do
{
(__stdcall **)(int, int, WCHAR *, int))(*(_DWORD *)v30 + 176))(v30, 0x47A, v29->first, v29->second);
++v29;
}
while ( v29 != v9 );
v10 = v42;
v8 = v39;
}
if ( param1 )
{
if ( !*param1 )
{
j_j_j_free(param1);
return ;
}
sha256_digest(&v18, param1, param2);
v24 = 0;
v7 = (char *)&v18;
if ( v18.cap >= 0x10 )
v7 = v18.data.lstr;
sub_406D20(&v19, v7);
LOBYTE(v24) = 1;
if ( v19.size )
{
v8 = (char *)&v19;
if ( v19.cap >= 0x10 )
v8 = v19.data.lstr;
(*(void (__thiscall **)(int, char *, size_t, int))(*(_DWORD *)(this + 0x2A8) + 8))(
this + 0x2A8,
v8,
v19.size,
*(_DWORD *)(this + 0x1C));
(*(void (__thiscall **)(int))(*(_DWORD *)(this + 0x2A8) + 12))(this + 0x2A8);
}
else
{
(*(void (__stdcall **)(int, int, int, int))(*(_DWORD *)this + 176))(this, 0x47D, 0, 0);
}
// std::string dtor
}
void __thiscall sub_40CF10(simulation *this, char *data, size_t Size, HWND handle)
{
std::string *v5; // ecx
char *v6; // esi
if ( data && Size && handle )
{
this->handle = handle;
v5 = &this->encrypted;
this->encrypted.size = 0;
v6 = (char *)v5;
if ( v5->cap >= 0x10 )
v6 = v5->data.lstr;
*v6 = 0;
std::string::assign(v5, data, Size);
}
}
BOOL __thiscall sub_40CF60(simulation *this)
{
BOOL result; // eax
if ( this->handle )
{
if ( this->encrypted.size )
result = QueueUserWorkItem((LPTHREAD_START_ROUTINE)sub_40CF80, this, 0);
}
return result;
}
DWORD __stdcall sub_40CF80(simulation *this)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
if ( !this )
return 0;
(*(void (__thiscall **)(simulation *))this->vtable)(this);
void __thiscall sub_40D6A0(simulation *this)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v1 = this->strs.finish;
v2 = &this->strs;
v3 = this->strs.start;
if ( v3 != v1 )
{
std::string::array_dtor(v3, v1);
v1 = v2->start;
v2->finish = v2->start;
}
if ( v1 == v2->end_of_storage )
{
std::vector_std::string_::grow_cap_push(v2, v1, "F33FC7A6-5A29-44E7-921E-1A3E9D88B648");
}
else
{
v1->data = 0i64;
v1->size = 0;
v1->cap = 0;
std::string::ctor(v1, "F33FC7A6-5A29-44E7-921E-1A3E9D88B648", 0x24u);
++v2->finish;
}
// push 7 more strings
// ...
_i = 0;
_size = v2->finish - v2->start;
do
{
// exchange 2 random elments in vector
// ...
++_i;
}
while ( _i < 15 );
}
extracted.size = 0;
extracted.data = 0i64;
extracted.cap = 15;
extracted.data.sstr[0] = 0;
v55 = 0;
strs_iter = this->strs.start;
ptr = this->strs.finish;
if ( strs_iter != ptr )
{
while ( 1 )
{
v2 = strs_iter->cap < 16;
v3 = (char *)strs_iter;
v47 = 0;
if ( !v2 )
v3 = strs_iter->data.lstr;
v4 = sub_40DA90(&v54, &v47, v3);
if ( &extracted != v4 )
{
// std::string::dtor(&extracted);
extracted = *v4;
v4->size = 0;
v4->cap = 15;
v4->data.sstr[0] = 0;
}
if ( v54.cap >= 0x10 )
{
v6 = v54.data.lstr;
if ( v54.cap + 1 >= 0x1000 )
{
v6 = (char *)*((_DWORD *)v54.data.lstr - 1);
if ( (unsigned int)(v54.data.lstr - v6 - 4) > 0x1F )
goto LABEL_76;
}
j_j_j_j_j_free(v6);
}
if ( v47 )
break;
if ( ++strs_iter == ptr )
goto LABEL_17;
}
if ( extracted.size )
{
(*((void (__thiscall **)(simulation *, std::string *))this->vtable + 1))(this, &decrypted);
LOBYTE(v55) = 1;
if ( !decrypted.size )
{
SendMessageW(this->handle, 0x47Du, 0, 0);
LABEL_68:
// std::string::dtor(&decrypted);
goto LABEL_18;
}
v47 = 0;
ptr = VirtualAlloc(0, 0xA00000u, 0x3000u, PAGE_EXECUTE_READWRITE); // MEM_COMMIT | MEM_RESERVE
uc_open(1, 0, &uc); // UC_ARCH_ARM, UC_MODE_ARM
uc_ctl(uc, 0x44000007u, 17); // (UC_CTL_IO_WRITE, 1, UC_CTL_CPU_MODEL), UC_CPU_ARM_CORTEX_A15
tohex = std::string::tohex(&decrypted);
uc_mem_map_ptr(uc, 0i64, 0xA00000u, 7u, ptr); // rwx
uc_mem_write(uc, 0x43000ui64, extracted_data, extracted_size);
uc_mem_write(uc, 0x4033ui64, tohex.data, tohex.size);
if ( uc_emu_start(uc, 0x43000ui64, v20 + 0x43000, 0i64, 0) )
{
v22 = (void (__stdcall *)(HWND, UINT, WPARAM, LPARAM))SendMessageW;
}
else
{
memset(bytes, 0, 0x20);
uc_mem_read(uc, 0x14390ui64, bytes, 0x20u);
v22 = (void (__stdcall *)(HWND, UINT, WPARAM, LPARAM))SendMessageW;
v47 = 1;
SendMessageW(this->handle, 0x47Eu, (WPARAM)bytes, 0);
}
uc_mem_unmap(uc, 0i64, 0xA00000u);
uc_close(uc);
v24 = this->handle;
if ( v47 )
{
v22(v24, 0x47Bu, 0, 0);
}
else
{
v22(v24, 0x47Du, 0, 0);
}
*(_OWORD *)(this + 0x274) = *(_OWORD *)param1;
*(_OWORD *)(this + 0x284) = *((_OWORD *)param1 + 1);
if ( *(_BYTE *)(this + 0x28C) )
MessageBoxW(*(HWND *)(this + 28), L"验证成功!", L"提示", 0);
else
(*(void (__stdcall **)(int, int, _DWORD, _DWORD))(*(_DWORD *)this + 176))(this, 0x47D, 0, 0);
return sub_AE4396((unsigned int)&v25 ^ v20);
void sub_43000()
{
int v0; // r1
char *v1; // r0
const char *v2; // r2
int v3; // r5
int v4; // r3
int v5; // r4
v0 = 12;
while ( 2 )
{
v1 = input;
v2 = "4fc82b26aecb47d2868c4efbe3581732a3e7cbcc6c2efb32062c08170a05eeb8";
v3 = 0;
--v0;
do
{
v4 = *(_DWORD *)v1;
v5 = *(_DWORD *)v2;
if ( ++v3 >= 16 )
{
if ( "4fc82b26aecb47d2868c4efbe3581732a3e7cbcc6c2efb32062c08170a05eeb8" == "6749dae311865d64db83d5ae75bac3c9e36b3"
"aa6f24caba655d9682f7f071023" )
{
MEMORY[0x14390] = 1;
MEMORY[0x143A8] = 1;
}
return;
}
v1 += 4;
v2 += 4;
}
while ( v4 == v5 );
if ( v0 )
continue;
break;
}
}
在这个充满变数的赛场上,没有人能够预料到最终的结局。有时,优势的领先可能只是一时的,一瞬间的失误就足以颠覆一切。而那些一直默默努力、不断突破自我的人,往往会在最后关头迎头赶上,成为最耀眼的存在。
谁能保持领先优势?谁能迎头赶上?谁又能突出重围成为黑马?
球分享
球点赞
球在看
点击阅读原文进入比赛
原文始发于微信公众号(看雪学苑):看雪2023 KCTF年度赛 | 第三题设计思路及解析