본문 바로가기
Reversing/드림핵

[Dreamhack] rev-basic-6

by L3m0n S0ju 2021. 7. 17.


 

문제에서 주어진 파일을 IDA Pro에 로드하면 아래와 같은 코드가 출력됩니다.

 


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_1400011B0("Input : ", argv, envp);
  sub_140001210("%256s", v4);
  if ( (unsigned int)sub_140001000(v4) )
    puts("Correct");
  else
    puts("Wrong");
  return 0;
}

 

문제의 핵심은 if문에 sub_140001000(v4)에 있습니다. 해당 함수로 이동하면 아래와 같은 코드가 출력됩니다.

 


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

  for ( i = 0; (unsigned __int64)i < 0x12; ++i )
  {
    if ( byte_140003020[*(unsigned __int8 *)(a1 + i)] != byte_140003000[i] )
      return 0i64;
  }
  return 1i64;
}

 

 

sub_140001000 함수 역시 핵심은 if 문에 있습니다.

 

 if ( byte_140003020[*(unsigned __int8 *)(a1 + i)] != byte_140003000[i] ) 

 

조금더 쉽게 바꾸면 byte_140003020을 str2, byte_140003000을 str1이라고 가정합니다.

 

str2[*(unsigned __int8 *)(a1 + i)] != str1[i]

 

a1 역시 함수에 인자로 들어오는 문자열이므로 str3이라고 가정합니다.

 

str2[str3[i]] != str1[i]

 

str1, str2가 가르키는 byte_140003000, byte_140003020을 IDA를 통해 살펴보면 아래와 같습니다. 아스키코드는 128을 넘지 않으므로 str2 값은 128개 까지만 가져오겠습니다.

 

str1 = [00 4D 51 50 EF FB C3 CF  92 45 4D CF F5 04 40 50
43 63 ]

 

 

str2 = [63 7C 77 7B F2 6B 6F C5  30 01 67 2B FE D7 AB 76
CA 82 C9 7D FA 59 47 F0  AD D4 A2 AF 9C A4 72 C0
B7 FD 93 26 36 3F F7 CC  34 A5 E5 F1 71 D8 31 15
04 C7 23 C3 18 96 05 9A  07 12 80 E2 EB 27 B2 75
09 83 2C 1A 1B 6E 5A A0  52 3B D6 B3 29 E3 2F 84
53 D1 00 ED 20 FC B1 5B  6A CB BE 39 4A 4C 58 CF
D0 EF AA FB 43 4D 33 85  45 F9 02 7F 50 3C 9F A8
51 A3 40 8F 92 9D 38 F5  BC B6 DA 21 10 FF F3 D2]


이제 문제는 간단합니다. 우리가 입력한 str3[i] 아스키코드 값을 str2에 대입하여 str1[i]와 같으면 조건을 만족합니다. 문제 해결 알고리즘은 아래와 같습니다.

 

 

#include<stdio.h>

int main(void)
{
    char str1[19] = { 0x00, 0x4D, 0x51, 0x50, 0xEF, 0xFB, 0xC3, 0xCF,  0x92, 0x45, 0x4D, 0xCF, 0xF5, 0x04, 0x40, 0x50,
    0x43, 0x63 };

    char str2[] =
    {
        0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,  0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
        0xCA ,0x82 ,0xC9 ,0x7D ,0xFA ,0x59 ,0x47 ,0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
        0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
        0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
        0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
        0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
        0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
        0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2
    };

    char str3[19] = {0}; // 나중에 쓰레기값이 안나오도록 19바이트 크기 배열 0으로 세팅
    for (int i = 0; i < 18; i++)
    {
        for (int j = 0; j < 128; j++) // j는 우리가 입력할 문자열 아스키코드 값
        {
            if (str2[j] == str1[i])
            {
                str3[i] = j;
                break;
            }
        }
    }
    printf("%s", str3);
    return 0;
}


플래그

'Reversing > 드림핵' 카테고리의 다른 글

[Dreamhack] rev-basic-8  (0) 2021.04.12
[Dreamhack] rev-basic-7  (0) 2021.03.30
[Dreamhack] rev-basic-5  (0) 2021.03.30
[Dreamhack] rev-basic-4  (0) 2021.03.30
[Dreamhack] rev-basic-3  (0) 2021.03.30

댓글