문제 정보
플래그를 찾을 수 있겠나요?
문제 파일
분석
sub_7FF7D3221C30
char __fastcall sub_7FF7D3221C30(void **a1) { ... v24[0] = '{HD'; if ( a1[2] != (void *)24 ) { ... } ... do { v7 = a1; if ( v5 >= 0x10 ) v7 = (void **)*a1; if ( *((_BYTE *)v7 + v6) != *((_BYTE *)v24 + v6) )// CHECKPOINT: DH{ goto LABEL_34; ++v4; ++v6; } ... if ( *((_BYTE *)v8 + 23) != '}' ) { ... } ... sub_7FF7D3221A10(v18, &v20, v12); v13 = &dword_7FF7D3228050; // [0x40007608, 0x800075f6... v14 = v18[0]; do { if ( *(_QWORD *)((char *)v13 + v18[0] - (void *)&dword_7FF7D3228050) != *(_QWORD *)v13 )// CHECKPOINT { if ( v18[0] ) { if ( (unsigned __int64)(4 * ((signed __int64)(v19 - (unsigned __int64)v18[0]) >> 2)) >= 0x1000 ) { v14 = (void *)*((_QWORD *)v18[0] - 1); if ( (unsigned __int64)(v18[0] - v14 - 8) > 0x1F ) goto LABEL_32; } operator delete(v14); *(_OWORD *)v18 = 0i64; v19 = 0i64; } LABEL_34: v2 = (unsigned __int64)a1[3]; v10 = v2 < 0x10; LABEL_35: if ( !v10 ) { v3 = *a1; goto LABEL_37; } LABEL_41: result = 0; goto LABEL_42; } v13 += 2; } ... }
- FLAG 길이가 총 24바이트인지 확인한다.
- FLAG가 DH{으로 시작하는지 확인한다.
- FLAG가 }으로 마치는지 확인한다.
- 입력받은 FLAG인 v20를 sub_7FF7D3221A10에서 수행시킨 v18을 가져오고 dword_7FF7D3228050에 있는 배열들을 하나씩 비교한다.
비교를 총 12번 하는데 서로 비교하는 값들은 8바이트(QWORD) 단위이다.
sub_7FF7D3221A10
_QWORD *__fastcall sub_7FF7D3221A10(_QWORD *a1, _QWORD *a2, __int64 a3) { ... v5 = a2[2];// v5=24 (strlen) ... strcpy(v16, "neko_hat"); v10 = 0; if ( a2[2] )// 24 { v11 = 0i64; do { v12 = a2; if ( a2[3] >= 16ui64 ) v12 = (_QWORD *)*a2; *(_DWORD *)(*a1 + 4 * v11) = *((char *)v12 + v11); *(_DWORD *)(*a1 + 4 * v11) = __ROR4__(*(_DWORD *)(*a1 + 4 * v11), 4); *(_DWORD *)(*a1 + 4 * v11) ^= v16[v10 % 8]; *(_DWORD *)(*a1 + 4 * v11) += v16[v10 % 4]; *(_DWORD *)(*a1 + 4 * v11) += 30000; ++v10; ++v11; } while ( (unsigned __int64)v10 < a2[2] ); // v10 < 24 (strlen) } ... return a1; }
FLAG가 “DH{….”으로 가정했을때, 한글자씩 아래와 같은 연산을 해서 4바이트씩 값을 지정한다.
파이썬3로 구현하면 다음과 같다.
def ROR(data, shift, size=32): shift %= size body = data >> shift remains = (data << (size - shift)) - (body << size) return (body + remains) FLAG = "DH{..." #(24bytes) for i in range(24): oneChar = FLAG[i] oneChar = ROR(oneChar, 4) oneChar = oneChar ^ ord(neko[i % 8]) oneChar = oneChar + ord(neko[i % 4]) oneChar += 30000 print(oneChar)
풀이
def ROR(data, shift, size=32): shift %= size body = data >> shift remains = (data << (size - shift)) - (body << size) return (body + remains) cmp_list = [0x40007608, 0x800075F6, 0xB0007607, 0x90007607,\ 0x000075FA, 0x50007604, 0xF00075FF, 0x40007616,\ 0x20007607, 0x300075FB, 0xF0007609, 0x30007608,\ 0xD00075F7, 0x00007604, 0xF00075FF, 0xF0007610,\ 0xD0007606, 0x100075F8, 0x50007603, 0x40007607,\ 0x300075FA, 0x20007604, 0x100075FE, 0xD0007612] neko = "neko_hat" FLAG = "" for i in range(24): for j in range(255): oneChar = j oneChar = ROR(oneChar, 4) oneChar = oneChar ^ ord(neko[i % 8]) oneChar = oneChar + ord(neko[i % 4]) oneChar += 30000 if(oneChar == cmp_list[i]): print(chr(j), end='')
역연산시키기 귀찮아서 0~255범위의 한글자를 브루트포싱해서 맞추는 식으로 풀었다.
PS C:\Users\Seo Hyun-gyu\Desktop\babycmp> python3 .\solve.py DH{y0u_4r3_cmp__ma5t3r!}
FLAG
DH{y0u_4r3_cmp__ma5t3r!}