tmxklab

[HackCTF/reversing] Static 본문

War Game/HackCTF

[HackCTF/reversing] Static

tmxk4221 2021. 1. 14. 17:28

 

1. 문제


1) mitigation 확인

 

2) 문제 확인

  • 환경변수 team_name=bi0s를 설정하고 파라미터를 주면 됨

 

3) 코드흐름 파악

3-1) main

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  const char *s1; // [rsp+20h] [rbp-10h]

  s1 = getenv("team_name");
  if ( s1 && !strncmp(s1, "bi0s", 4uLL) )
  {
    if ( a1 == 2 )
    {
      if ( (unsigned int)sub_87C(s1, a2[1]) == 1 )
        sub_830(a2[1]);
      else
        printf("Better luck next time!");
    }
    else
    {
      printf("usage: chall <input>");
    }
  }
  else
  {
    printf("Nope.");
  }
  return 0LL;
}
  • 파라미터 한 개를 줬을 때 sub_87C()를 호출하고 조건문이 맞으면 sub_830()을 호출한다.

 

3-2) sub_87C()

__int64 __fastcall sub_87C(char *a1, const char *a2)
{
  size_t v3; // rbx
  char v4; // dl
  size_t v5; // rax
  char *v6; // [rsp+8h] [rbp-68h]
  char v7[32]; // [rsp+10h] [rbp-60h]
  __int64 v8; // [rsp+30h] [rbp-40h]
  int v9; // [rsp+48h] [rbp-28h]
  int v10; // [rsp+50h] [rbp-20h]
  int v11; // [rsp+54h] [rbp-1Ch]
  int v12; // [rsp+58h] [rbp-18h]
  int i; // [rsp+5Ch] [rbp-14h]

  v6 = a1;
  v12 = 0;
  v11 = 0;
  strcpy((char *)&v8, "1617181926381617919194");
  if ( strlen(a2) != 22 )
    return 0LL;
  for ( i = 0; ; ++i )
  {
    v3 = i;
    if ( v3 >= strlen(v6) )
      break;
    v12 += v6[i];
  }
  v9 = 0;
  v12 /= 30;
  while ( v11 != 22 )
  {
    if ( v11 & 1 )
      v4 = a2[v11] - 4;
    else
      v4 = a2[v11] + 4;
    v7[v11] = v4;
    v7[v11] ^= v12;
    ++v11;
  }
  v10 = 0;
  for ( i = strlen(v7) - 1; i >= 0; --i )
  {
    v5 = strlen(v7);
    if ( v7[v5 - i - 1] != *((_BYTE *)&v8 + i) )
      return 0LL;
  }
  return 1LL;
}
  • 먼저, 리턴 값이 참이 되기 위해 첫 번째 if문과 마지막 if문을 피해야 한다.
  • 접근 방법에서 단계별로 참이 되기 위해 어떻게 구성해야되는지 살펴보자

 

3-3) sub_830()

int __fastcall sub_830(__int64 a1)
{
  return printf("HackCTF{%s}", a1);
}
  • a1을 받고 플래그 값을 출력한다.
  • 여기서 a1은 바이너리를 실행할 때 인자 값으로 들어가는 것이다.

 

즉, sub_87C()에서 리턴 값이 1이 되도록 인자 값을 세팅하게 되면 그게 플래그 값이 된다.

 

2. 접근 방법


 

  • copy_number변수에 "1617181926381617919194"를 복사
  • 파라미터 길이가 22여야 한다.
  • for문에서 환경변수의 각 자리 수를 더해 sum_env에 넣는다.

 

  • v11과 1을 AND연산해서 참 또는 거짓일 경우 v4에 param[v11] ± 4를 넣는다.
  • 그리고 v7[v11]에 v4를 넣고 sum_env와 xor한고 v11을 증가시킨다.
  • 즉, v11이 0부터 21까지 돌면서
    • v11 홀수 : v7[v11] = (param[v11] - 4) xor sum_env
    • v11 짝수 : v7[v11] = (param[v11] - 4) xor sum_env

 

  • v7의 길이만큼 for문이 돌면서 copy_number와 비교
  • 이 때, v7의 인덱스는 0 ~ 21, copy_number는 거꾸로 1byte씩 비교한다.

 

그럼 이제 디버깅하면서 확인해보자

(참고로 파라미터는 "A"*22만큼 주고 실행하였다.)

  • env값을 모두 합한 값은 0x16e가 된다.

 

  • 그리고 최종적으로 sum_env에는 0xc가 저장됨

 

  • 첫 번째 인덱스에 들어 있는 "A"(0x41)값에 4를 더하고 0xc와 xor한 값인 0x49가 v7[0]에 들어가게 된다.

 

  • 그렇게 while문이 다 돌고 v7에 값이 세팅되면 다음 for문에서 copy_number와 v7와 값을 비교한다.

3. 문제 풀이


 

그럼 거꾸로 해보면 답이 나온다. xor한 값에 xor을 한 번더하면 그대로니깐

파이썬을 이용해서 구해보자

cp_num = "1617181926381617919194"[::-1]
new_list = []

idx = 0

for data in cp_num:
    if 1 == idx % 2:
        new_list.append(chr((ord(data) ^ 0xc) + 0x4))
    else:
        new_list.append(chr((ord(data) ^ 0xc) - 0x4))
    idx += 1

print("".join(new_list))

 

4. 몰랐던 내용


'War Game > HackCTF' 카테고리의 다른 글

[HackCTF/reversing] BabyMIPS  (0) 2021.01.14
[HackCTF/Pwnable] 훈폰정음  (0) 2020.08.27
[HackCTF/Pwnable] AdultFSB  (0) 2020.08.20
[HackCTF/Pwnable] Unexploitable #4  (0) 2020.08.15
[HackCTF/Pwnable] ChildFSB  (2) 2020.08.15
Comments