콘텐츠로 건너뛰기

babycmp

문제 정보

플래그를 찾을 수 있겠나요?

문제 파일


분석

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;
  }
...
}
  1. FLAG 길이가 총 24바이트인지 확인한다.
  2. FLAG가 DH{으로 시작하는지 확인한다.
  3. FLAG가 }으로 마치는지 확인한다.
  4. 입력받은 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!}

태그:

답글 남기기