[드림핵] 워게임 rev-basic-4 풀이

SCY·2023년 1월 4일
0

dreamhack

목록 보기
5/12

안녕하세요. 해킹하는 개발자가 되고 싶은 컴공 대학생입니다.
정보 보안 분야에 관심이 많아 드림핵으로 리버스 엔지니어링 학습 중입니다.
드림핵 사이트의 워게임 rev-basic-4 문제 풀이 진행하겠습니다.

문제

https://dreamhack.io/wargame/challenges/18/

풀이

프로그램 실행

문제 유형을 파악하기 위해 Windows의 PowerShell을 이용하여 프로그램을 실행시켜줍니다. 아래와 같이 임의의 문자열을 입력하면 'Wrong'이 출력됩니다.
이를 통해 오답 시 'Wrong', 정답 시 'Correct'가 출력됨을 예측할 수 있습니다.
image

IDA 실행

main 함수를 디컴파일합니다. (단축키 F5)

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[256]; // [rsp+20h] [rbp-118h] BYREF

  memset(v4, 0, sizeof(v4));
  sub_1400011C0("Input : ", argv, envp);
  sub_140001220("%256s", v4);
  if ( (unsigned int)sub_140001000((__int64)v4) )
    puts("Correct");
  else
    puts("Wrong");
  return 0;
}

sub_140001000 함수를 더블클릭하여 함수의 내용을 확인합니다.

__int64 __fastcall sub_140001000(__int64 a1)
{
  int i; // [rsp+0h] [rbp-18h]

  for ( i = 0; (unsigned __int64)i < 0x1C; ++i )
  {
    if ( ((unsigned __int8)(16 * *(_BYTE *)(a1 + i)) | ((int)*(unsigned __int8 *)(a1 + i) >> 4)) != byte_140003000[i] )
      return 0i64;
  }
  return 1i64;
}

해결 과정

(16 * a1[i]) | (a1[i] >> 4) == byte_140003000[i]

를 만족하는 a1을 찾아야 합니다.

(a1[i] << 4) | (a1[i] >> 4) == byte_140003000[i]

16을 곱하는 것은 4비트 왼쪽 시프트하는 것과 같으므로 위와 같이 변경합니다.

a1[0]을 예시로 위 연산을 진행해보겠습니다.

a1[0] = 0010 0100 (0x24)
a1[0] << 4 = 0100 0000 (0x4)
a1[0] >> 4 = 0000 0010 (0x2)
(a1[i] << 4) | (a1[i] >> 4) → 0100 0010 (0x42)

즉, a1[0]의 앞뒤 위치가 바뀝니다.
그렇다면 byte_140003000[i]의 앞뒤 위치를 바꾼 수가 a1[i]가 됩니다.

byte_140003000는 IDA에서 더블클릭하여 정보를 확인할 수 있습니다.
이를 바탕으로 코드를 작성합니다.

tmp = [0x24, 0x27, 0x13, 0xC6, 0xC6, 0x13, 0x16, 0xE6, 0x47, 0xF5, 0x26, 0x96, 0x47, 0xF5, 0x46, 0x27, 0x13, 0x26, 0x26, 0xC6, 0x56, 0xF5, 0xC3, 0xC3, 0xF5, 0xE3, 0xE3]

for i in range(len(tmp)) :
    print(chr((tmp[i]<<4 | tmp[i]>>4) % (16 * 16)), end='')

%(16 * 16)으로 함수 sub_140001000의 (_BYTE *)를 적용했습니다.
이는 16진수의 바이트만 사용하는 것으로 & 0xFF를 적용해주어도 무관합니다.

이 코드로 출력되는 문자열이 정답이 됩니다.

정답

Br1ll1antbit_dr1bble<<_>>

profile
성장 중독 | 서버, 데이터, 정보 보안을 공부합니다.

0개의 댓글