일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- hacking game
- System Hacking
- Gon
- got overwrite
- Wargame
- python
- ctf player
- WEB
- h4cking game
- reversing
- webhacking
- crypto
- 2022 Fall GoN Open Qual CTF
- cryptography
- 해킹
- webhacking.kr
- dreamhack
- writeup
- 워게임
- TeamH4C
- hacking
- CTF
- 웹해킹
- Buffer Overflow
- hack
- pwnable
- KAIST
- Wreckctf
- christmas ctf
- deayzl
- Today
- Total
deayzl's blog
[DiceCTF 2024] pain-plus-plus 본문
The binary consists of two functions; main and main[cold].
main:
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rax
char *v4; // rdi
char *v5; // rdx
char *v6; // rax
__int64 v7; // rsi
__int64 v8; // rcx
signed __int64 v9; // rbx
signed __int64 v10; // rax
size_t v11; // rdx
char *v12; // rsi
__int64 v13; // rbx
int v14; // ebp
char v15; // cl
int *v16; // rdi
__int64 v17; // rdx
__int64 v18; // rax
__int64 v19; // rsi
__int64 v20; // rax
signed __int64 v21; // rcx
_QWORD *v23; // [rsp+8h] [rbp-240h]
char v24; // [rsp+2Fh] [rbp-219h] BYREF
__int64 v25[4]; // [rsp+30h] [rbp-218h] BYREF
char *v26; // [rsp+50h] [rbp-1F8h] BYREF
__int64 length; // [rsp+58h] [rbp-1F0h]
char v28; // [rsp+60h] [rbp-1E8h] BYREF
char v29[8]; // [rsp+70h] [rbp-1D8h] BYREF
char v30[16]; // [rsp+78h] [rbp-1D0h] BYREF
__int64 v31; // [rsp+88h] [rbp-1C0h]
char v32[8]; // [rsp+A0h] [rbp-1A8h] BYREF
int v33; // [rsp+A8h] [rbp-1A0h] BYREF
__int64 v34; // [rsp+B0h] [rbp-198h]
int v35[2]; // [rsp+B8h] [rbp-190h]
int v36[2]; // [rsp+C0h] [rbp-188h]
__int64 v37; // [rsp+C8h] [rbp-180h]
int v38[94]; // [rsp+D0h] [rbp-178h] BYREF
std::__ostream_insert<char,std::char_traits<char>>(&std::cout, "Enter the flag: ", 16LL);
std::ostream::flush((std::ostream *)&std::cout);
v28 = 0;
v26 = &v28;
length = 0LL;
std::operator>><char>((__int64)&std::cin, (__int64)&v26);
v3 = length;
v4 = v26;
v5 = &v26[length];
if ( length >> 2 > 0 )
{
while ( 1 )
{
if ( *v4 == 10 )
goto continue;
if ( v4[1] == 10 )
{
++v4;
goto continue;
}
if ( v4[2] == 10 )
{
v4 += 2;
goto continue;
}
if ( v4[3] == 10 )
break;
v4 += 4;
if ( &v26[4 * (length >> 2)] == v4 )
goto break;
}
v4 += 3;
continue:
if ( v4 != v5 )
{
v6 = v4 + 1;
if ( v5 == v4 + 1 )
{
v5 = v4;
v3 = v4 - v26;
}
else
{
do
{
if ( *v6 != 10 )
*v4++ = *v6;
++v6;
}
while ( v5 != v6 );
v7 = (__int64)v26;
v8 = length;
v3 = v4 - v26;
if ( v5 != &v26[length] )
{
v9 = v5 - v4;
v10 = v5 - v26;
v11 = length - (v5 - v26);
if ( length != v10 && v9 )
{
v12 = &v26[v10];
if ( v11 == 1 )
*v4 = *v12;
else
memmove(v4, v12, v11);
v8 = length;
v7 = (__int64)v26;
}
length = v8 - v9;
*(_BYTE *)(v7 + v8 - v9) = 0;
LABEL_20:
qmemcpy(v38, &unk_50A0, 0x108uLL);
v23 = (_QWORD *)operator new(0x108uLL);
*v23 = *(_QWORD *)v38;
v23[32] = *(_QWORD *)&v38[64];
qmemcpy(
(void *)((unsigned __int64)(v23 + 1) & 0xFFFFFFFFFFFFFFF8LL),
(const void *)((char *)v38 - ((char *)v23 - ((unsigned __int64)(v23 + 1) & 0xFFFFFFFFFFFFFFF8LL))),
8LL * (((unsigned int)v23 - (((_DWORD)v23 + 8) & 0xFFFFFFF8) + 264) >> 3));
memset(v38, 0, 0x138uLL);
*(_QWORD *)v38 = 0x620000001DLL;
*(_QWORD *)&v38[2] = 0x640000001CLL;
*(_QWORD *)&v38[4] = 0x6D00000010LL;
*(_QWORD *)&v38[6] = 0x7D0000000ALL;
*(_QWORD *)&v38[8] = 0x360000000DLL;
*(_QWORD *)&v38[10] = 0x790000001FLL;
*(_QWORD *)&v38[12] = 0x7B0000001ELL;
*(_QWORD *)&v38[14] = 0x6900000007LL;
*(_QWORD *)&v38[16] = 0x6100000002LL;
*(_QWORD *)&v38[18] = 0x6600000001LL;
*(_QWORD *)&v38[20] = 0x3100000016LL;
*(_QWORD *)&v38[22] = 0x740000001ALL;
*(_QWORD *)&v38[24] = 0x3400000013LL;
*(_QWORD *)&v38[26] = 0x7100000025LL;
*(_QWORD *)&v38[28] = 0x3200000009LL;
*(_QWORD *)&v38[30] = 0x6800000003LL;
*(_QWORD *)&v38[32] = 0x6A00000024LL;
*(_QWORD *)&v38[34] = 0x7500000021LL;
*(_QWORD *)&v38[36] = 0x3300000008LL;
*(_QWORD *)&v38[38] = 0x3000000015LL;
*(_QWORD *)&v38[40] = 0x7A00000020LL;
*(_QWORD *)&v38[42] = 0x3800000026LL;
*(_QWORD *)&v38[44] = 0x7600000018LL;
*(_QWORD *)&v38[46] = 0x650000000CLL;
*(_QWORD *)&v38[48] = 0x7800000023LL;
*(_QWORD *)&v38[50] = 0x7200000006LL;
*(_QWORD *)&v38[52] = 0x350000000ELL;
*(_QWORD *)&v38[54] = 0x6B00000019LL;
*(_QWORD *)&v38[56] = 0x5F0000000FLL;
*(_QWORD *)&v38[58] = 0x7700000014LL;
*(_QWORD *)&v38[60] = 0x6F00000027LL;
v38[62] = 17;
LOBYTE(v38[63]) = 55;
v38[64] = 4;
LOBYTE(v38[65]) = 108;
v38[66] = 5;
LOBYTE(v38[67]) = 115;
v38[68] = 18;
LOBYTE(v38[69]) = 110;
v38[70] = 27;
LOBYTE(v38[71]) = 99;
v38[72] = 23;
LOBYTE(v38[73]) = 103;
v38[74] = 11;
LOBYTE(v38[75]) = 112;
v38[76] = 34;
LOBYTE(v38[77]) = 57;
std::map<int,char>::map(v29, v38, 39LL, v25, v32);
v13 = v31;
v33 = 0;
v34 = 0LL;
*(_QWORD *)v35 = &v33;
*(_QWORD *)v36 = &v33;
v37 = 0LL;
if ( (char *)v31 != v30 )
{
v14 = *(_DWORD *)(v31 + 32);
LABEL_34:
v19 = (__int64)&v33;
LABEL_31:
v25[0] = v13 + 36;
v19 = std::_Rb_tree<char,std::pair<char const,int>,std::_Select1st<std::pair<char const,int>>,std::less<char>,std::allocator<std::pair<char const,int>>>::_M_emplace_hint_unique<std::piecewise_construct_t const&,std::tuple<char const&>,std::tuple<>>(
v32,
v19,
&std::piecewise_construct,
v25,
&v24);
while ( 1 )
{
*(_DWORD *)(v19 + 36) = v14;
v20 = std::_Rb_tree_increment(v13);
v13 = v20;
if ( (char *)v20 == v30 )
break;
v19 = v34;
v14 = *(_DWORD *)(v20 + 32);
if ( !v34 )
goto LABEL_34;
v15 = *(_BYTE *)(v20 + 36);
v16 = &v33;
while ( 1 )
{
v17 = *(_QWORD *)(v19 + 16);
v18 = *(_QWORD *)(v19 + 24);
if ( v15 > *(char *)(v19 + 32) )
break;
LABEL_26:
if ( !v17 )
goto LABEL_29;
v16 = (int *)v19;
v19 = v17;
}
while ( v18 )
{
v19 = v18;
v17 = *(_QWORD *)(v18 + 16);
v18 = *(_QWORD *)(v18 + 24);
if ( v15 <= *(char *)(v19 + 32) )
goto LABEL_26;
}
v19 = (__int64)v16;
LABEL_29:
if ( (int *)v19 == &v33 || v15 < *(char *)(v19 + 32) )
goto LABEL_31;
}
}
main_cold();
}
v5 = v4;
}
}
LABEL_36:
length = v3;
*v5 = 0;
goto LABEL_20;
}
break:
v21 = v5 - v4;
if ( v5 - v4 != 2 )
{
if ( v21 != 3 )
{
if ( v21 != 1 )
goto LABEL_36;
goto LABEL_40;
}
if ( *v4 == 10 )
goto continue;
++v4;
}
if ( *v4 == 10 )
goto continue;
++v4;
LABEL_40:
if ( *v4 != 10 )
goto LABEL_36;
goto continue;
}
main[cold]:
// positive sp value has been detected, the output may be wrong!
void __fastcall __noreturn main_cold()
{
int v0; // r15d
void *exception; // rbp
_QWORD *v2; // rbx
int v3; // r8d
int v4; // r9d
__int64 v5; // rax
__int64 v6; // rdx
int *v7; // rcx
__int64 v8; // rdx
int *v9; // rcx
char *v10; // [rsp-240h] [rbp-240h]
__int64 v11; // [rsp-230h] [rbp-230h]
__int64 v12; // [rsp-198h] [rbp-198h]
__int64 v13; // [rsp-180h] [rbp-180h]
int v14; // [rsp-170h] [rbp-170h] BYREF
__int64 v15; // [rsp-168h] [rbp-168h]
int *v16; // [rsp-160h] [rbp-160h]
int *v17; // [rsp-158h] [rbp-158h]
__int64 v18; // [rsp-150h] [rbp-150h]
exception = __cxa_allocate_exception(0x58uLL);
v15 = 0LL;
v14 = 0;
v16 = &v14;
v17 = &v14;
v18 = 0LL;
if ( v12 )
{
v5 = std::_Rb_tree<char,std::pair<char const,int>,std::_Select1st<std::pair<char const,int>>,std::less<char>,std::allocator<std::pair<char const,int>>>::_M_copy<false,std::_Rb_tree<char,std::pair<char const,int>,std::_Select1st<std::pair<char const,int>>,std::less<char>,std::allocator<std::pair<char const,int>>>::_Alloc_node>();
v6 = v5;
do
{
v7 = (int *)v6;
v6 = *(_QWORD *)(v6 + 16);
}
while ( v6 );
v16 = v7;
v8 = v5;
do
{
v9 = (int *)v8;
v8 = *(_QWORD *)(v8 + 24);
}
while ( v8 );
v17 = v9;
v15 = v5;
v18 = v13;
}
v2 = (_QWORD *)operator new(0x108uLL);
*v2 = *(_QWORD *)v10;
v2[32] = *(_QWORD *)(v11 - 16);
qmemcpy(
(void *)((unsigned __int64)(v2 + 1) & 0xFFFFFFFFFFFFFFF8LL),
(const void *)(v10 - ((char *)v2 - ((unsigned __int64)(v2 + 1) & 0xFFFFFFFFFFFFFFF8LL))),
8LL * (((unsigned int)v2 - (((_DWORD)v2 + 8) & 0xFFFFFFF8) + 264) >> 3));
((void (__fastcall *)(_DWORD, int, _DWORD, int, int))exception_with_both::exception_with_both)(
(_DWORD)exception,
v0,
0,
v3,
v4);
operator delete(v2, 0x108uLL);
((void (__fastcall *)(__int64))std::_Rb_tree<char,std::pair<char const,int>,std::_Select1st<std::pair<char const,int>>,std::less<char>,std::allocator<std::pair<char const,int>>>::_M_erase)(v15);
__cxa_throw(
exception,
(struct type_info *)&`typeinfo for'exception_with_both,
exception_with_both::~exception_with_both);
}
It uses rbtree and the implementations are following;
1. rbtree initialization
2. compare input character with something
3. If some conditions are satisfied, pass input character to _M_emplace_hint_unique function
4. cmp and je, print out "wrong"
I don't know what these codes do specifically but I just did print out operands on following two compares.
(they looked quite important while debugging)
1. 5555555563f3 (cmp dl, byte ptr [rax + 0x20])
2. 555555556709 (cmp dl, byte ptr [rsi + 0x20])
The character "i" of "di" (prefix of flag, "dice{") passed but "A" (which is not part of flag) crashed the process.
From this result, I could figure out that the brute-force attack may be possible.
Then I worked on making gdb script.
from random import choice
import string
import gdb
chset = string.ascii_letters + string.digits + string.punctuation.replace('\'', '').replace('}', '') + '}'
ge = gdb.execute
ge('file pain-plus-plus')
ge('b *0x5555555563f3') # cmp dl, byte ptr [rax + 0x20]
ge('b *0x555555556709') # cmp dl, byte ptr [rsi + 0x20]
ge('b *0x555555556611') # correct
flag = 'dice{'
bDone = False
while True:
for ch in chset:
print('try:', ch)
input_str = flag + ch + '}'
ge(f'r <<< \'{input_str}\'')
dl = ''
while True:
try:
rip = int(gdb.parse_and_eval('$rip'))
if rip & 0xfff == 0x3f3:
dl = chr(gdb.parse_and_eval('$dl'))
rax = ge('x/c $rax + 0x20', to_string=True).split()[-1][1:-1]
print('cmp '+dl+' '+rax)
elif rip & 0xfff == 0x709:
dl = chr(gdb.parse_and_eval('$dl'))
rsi = ge('x/c $rsi + 0x20', to_string=True).split()[-1][1:-1]
print('cmp '+dl+' '+rsi)
elif rip & 0xfff == 0x611:
bDone = True
print('flag:', input_str)
break
ge('c')
except:
break
if bDone:
break
print('dl:', dl)
print('present str:',input_str)
if dl != ch and dl == '}':
flag += ch
break
if bDone:
break
exit()
# dice{would_you_like_to_try_the_windows_abi_next_time_685dfc4bc1a0}
'CTF writeup > Others' 카테고리의 다른 글
[2023 UMDCTF] You Want Me To Run What?? writeup (unintended) (0) | 2023.05.01 |
---|---|
[VishwaCTF] 0 | 1 writeup (0) | 2023.04.02 |