문제 소개

설명을 보면 뉴비를 위한 뻔한 crackme 문제라고 한다. 바이러니의 checksum 비교를 위하여 hash 값을 비교해 본다.

 

hash 값은 동일하며, 맥에서 사용되는 Mach-0 파일임을 알 수 있다.

 

함수 분석

__int64 start()
{
  void *v0; // ST30_8
  __int64 result; // rax
  char v2; // [rsp+40h] [rbp-30h]
  __int64 v3; // [rsp+68h] [rbp-8h]

  v0 = calloc(0x29BuLL, 4uLL);
  scanf("%s", &v2);
  result = sub_100000DB0(sub_100000D00, sub_100000C80, sub_100000BA0, sub_100000C10, &v2, v0);
  if ( __stack_chk_guard == v3 )
    result = 0LL;
  return result;
}

ida 로 열어보면, start 함수에서는 v0 에 0x29B 만큼 calloc 해주고 v2 에 입력값을 받는다.

그 후 sub_100000DB0 함수에서 여러 인자들로 result 값을 만든다.

 

__int64 __fastcall sub_100000DB0(
  void (__fastcall *a1)(__int64, __int64),          // sub_100000D00
  unsigned int (__fastcall *a2)(__int64, void *),   // sub_100000C80
  unsigned int (__fastcall *a3)(__int64),           // sub_100000BA0
  unsigned int (__fastcall *a4)(__int64),           // sub_100000C10
  __int64 a5,                                       // scanf address
  __int64 a6)                                       // calloc(0x29BuLL, 4uLL)
{
  unsigned int (__fastcall *v6)(__int64);           // sub_100000BA0
  __int64 v7;                                       // scanf address
  __int64 v9;                                       // calloc(0x29BuLL, 4uLL)
  unsigned int (__fastcall *v10)(__int64);          // sub_100000C10

  v6 = a3;
  v10 = a4;
  v7 = a5;
  v9 = a6;
  a1(a6, a5);
  if ( v6(v7) && v10(v9) && a2(v9, &unk_100001040) )
    printf("Congratz - You have earned it!");
  else
    printf("%s", "You've got to do better");
  return 0LL;
} 

sub_100000DB0 함수로 들어가 보면, 인자들을 로컬변수에 넣고 그 값들을 이용하여 입력값이 올바른지 확인한다.

이를 요약하면 아래의 함수들로 정리할 수 있다.

  • al(a6,a5) => sub_100000D00(v0,&v2)
  • v6(v7) => sub_100000BA0(&v2)
  • v10(v9) => sub_100000C10(v0)
  • a2(v9, &unk_100001040) => sub_100000C80(v0,&unk_100001040)

 

__int64 __fastcall sub_100000D00(__int64 a1, const char *a2)
{
  __int64 result; // rax
  int j; // [rsp+0h] [rbp-20h]
  int i; // [rsp+4h] [rbp-1Ch]
  int v5; // [rsp+8h] [rbp-18h]
  int v6; // [rsp+Ch] [rbp-14h]

  v6 = strlen(a2);
  v5 = 0;
  for ( i = 0; i < v6; ++i )
  {
    for ( j = i + 1; j < v6; ++j )
      *(_DWORD *)(a1 + 4LL * v5++) = a2[j] + a2[i];
  }
  result = a1;
  *(_DWORD *)(a1 + 2668) = 0;
  return result;
}

sub_100000D00 함수에서는 a1 을 이용하여 a2 값을 생성한다.

 

_BOOL8 __fastcall sub_100000BA0(__int64 a1)
{
  signed int i; // [rsp+4h] [rbp-18h]
  int v3; // [rsp+8h] [rbp-14h]

  v3 = 0;
  for ( i = 0; i < 37; ++i )
    v3 += *(char *)(a1 + i);
  return v3 == 3504;
}

sub_100000BA0 함수에서는 a1의 배열 값들을 더해서 3504 가 맞으면 True 값을 리턴해준다.

 

_BOOL8 __fastcall sub_100000C10(__int64 a1)
{
  signed int i; // [rsp+4h] [rbp-18h]
  int v3; // [rsp+8h] [rbp-14h]

  v3 = 0;
  for ( i = 0; i < 667; ++i )
    v3 += *(_DWORD *)(a1 + 4LL * i);
  return v3 == 126144;
}

sub_100000C10 함수에서는 a1의 배열 값들을 더해서 126144 가 맞으면 True 값을 리턴해준다.

 

_BOOL8 __fastcall sub_100000C80(__int64 a1, __int64 a2)
{
  signed int v3; // [rsp+0h] [rbp-1Ch]

  v3 = 0;
  while ( v3 < 666 )
  {
    if ( *(_DWORD *)(a1 + 4LL * v3) == *(_DWORD *)(a2 + 4LL * v3) )
      ++v3;
  }
  return v3 >= 666;
}

마지막으로 sub_100000C80 함수에서는 a1의 값과 a2의 값이 같은지 확인하는데, 그 길이가 666인지 확인한다.

여기서 a1은 입력값을 기반으로 만든 배열로 a2의 길이가 길이가 666일 경우, a1의 길이가 37인 것을 알 수 있다.

 

위의 함수들을 정리해 보면

  • 입력값의 길이는 37
  • 입력값을 이용하여 만든 배열을 바이너리에 있는 값과 비교
  • 입력값의 문자열들의 총합은 3504

인 것을 알 수 있다.

이제 이를 구하는 간단한 파이썬 코드를 작성한다.

 

flag 구하기

with open('cliche_crackme','rb') as rb:
    rb.seek(0x1040)
    data = rb.read(666*4)
    for i in range(0x21,0x80):
        try:
            rev = chr(i)
            for j in range(0,len(data),4):
                rev += chr(data[j]-ord(rev[0+(len(rev)-1)//37]))
        except:
            a5,chk = rev[:37],0
            for j in range(len(a5)): chk += ord(a5[j])
            if chk == 3504: print('input :',a5)

플래그를 구할때는 거꾸로, 바이너리에서 데이터를 읽어오고 그 값에서 임의의 값을 빼서 문자열을 추측해 본다.

임의의 값을 기반으로 생성한 문자열의 값들을 합한 값이 3504 인지 확인하고, 맞을 경우 이를 출력해 주는 코드이다.

 

숫자, 대문자, 소문자를 거쳐 i로 시작하는 경우에만 그 문자열의 합이 3504이며 플래그를 확인할 수 있다.

'0x00 Reversing > 0x02 CTF' 카테고리의 다른 글

THC CTF 2018 :: Android Serial (with Z3 solver)  (0) 2019.10.13

+ Recent posts