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

SCY·2023년 1월 4일
0

dreamhack

목록 보기
6/12

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

문제

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

풀이

프로그램 실행

문제 유형을 파악하기 위해 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 < 0x18; ++i )
  {
    if ( *(unsigned __int8 *)(a1 + i + 1) + *(unsigned __int8 *)(a1 + i) != byte_140003000[i] )
      return 0i64;
  }
  return 1i64;
}

해결 과정

함수 sub_140001000의 if절을 확인해보면

a1[i + 1] + a1[i] == byte_140003000[i]

를 만족해야함을 확인할 수 있습니다.
byte_140003000는 IDA에서 더블클릭하여 정보를 확인할 수 있습니다.

a1[1] + a1[0] = byte_140003000[0] = 0xAD
a1[2] + a1[1] = byte_140003000[1] = 0xD8
a1[3] + a1[2] = byte_140003000[2] = 0xCB
...
a1[17] + a1[16] = byte_140003000[16] = 0x4C
a1[18] + a1[17] = byte_140003000[17] = 0x00

마지막 식을 통해 a1[18]과 a1[17]은 unsigned이므로 0임을 파악할 수 있습니다.

이를 바탕으로 코드를 작성합니다.

nums = [0xAD, 0xD8, 0xCB, 0xCB, 0x9D, 0x97, 0xCB, 0xC4, 0x92, 0xA1, 0xD2, 0xD7, 0xD2, 0xD6, 0xA8, 0xA5, 0xDC, 0xC7, 0xAD, 0xA3, 0xA1, 0x98, 0x4C, 0x00]

res = [0] * (len(nums)+1)
res[0x17] = 0
res[0x18] = 0

i = 0
for i in reversed(range(len(nums))) :
    res[i] = nums[i] - res[i + 1]

j = 0
for j in range(len(res)) :
    print(chr(res[j]), end='')

정답

All_l1fe_3nds_w1th_NULL


시행착오

a1[17]과 a1[18]이 0임을 깨닫지 못했을 때,
정답이 문자열이라는 가정 하에 아스키코드를 참조하여 코드를 작성했습니다.

j = 0
for j in range(33, 127) :
    i = 0
    n = 0
    res = []
    res.append(j)
    for i in range(len(nums)) :
        res.append(nums[i] - res[i])
    for n in range(len(res)) :
        print(chr(res[n]), end='')
    print()

a1[0]이 될 수 있는 문자를 하나씩 변경해가며 가능한 모든 문장을 확인했습니다.

위와 같이 출력되었고
이 중 가장 정답일 듯한 문장을 찾아냈습니다.
답은 찾았지만 부정확하여 옳은 방법은 아니라 생각됩니다.

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

0개의 댓글