[드림핵] rev-basic-1 풀이

비얌·2022년 11월 29일
2

어셈블리 게임

목록 보기
13/15

개요

저번 rev-basic-0 문제 풀이에 이어 rev-basic-1도 풀어보기로 했다.



rev-basic-1 풀이

1. 문제

문제는 아래와 같다. rev-basic-0과 마찬가지로 correct를 출력하는 입력값을 찾으면 된다.


2. Detect It Easy 사용

Detect It Easy라는 프로그램에 넣어보면, 이 파일이 PE64 파일이고 따로 압축은 되어있지 않다고 나온다. IDA64로 바로 열어보자.


3. IDA64 사용

(1) 전체적인 그래프 파악하기

IDA64에 해당 파일을 올려보았다. 그럼 이런 그래프가 나온다.

이 그래프만 해석해보면 어떤 input 값을 넣으면 Correct 혹은 Wrong을 출력한다는 것 같다.


(2) 디컴파일하기

F5 단축키를 눌러 디컴파일해보았다. 그럼 아래와 같은 코드가 나타난다.

sub_1400013E0 함수로 Input : 을 출력하고, sub_140001440 함수로 입력값을 받는 것 같다.

그리고 sub_140001000 함수에 입력값을 넣고 맞으면 Correct, 틀리면 Wrong을 출력한다.

sub_140001000함수가 중요해보이니 이 함수를 분석해보기로 했다.

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

(3) sub_140001000 함수 분석하기

sub_140001000 함수를 더블클릭해서 들어가보았다. 그럼 아래와 같은 코드가 뜬다.

입력값의 각 문자가 아래에 나오는 아스키코드와 일치해야하는 것 같다.

_BOOL8 __fastcall sub_140001000(_BYTE *a1)
{
  if ( *a1 != 67 )
    return 0i64;
  if ( a1[1] != 111 )
    return 0i64;
  if ( a1[2] != 109 )
    return 0i64;
  if ( a1[3] != 112 )
    return 0i64;
  if ( a1[4] != 97 )
    return 0i64;
  if ( a1[5] != 114 )
    return 0i64;
  if ( a1[6] != 51 )
    return 0i64;
  if ( a1[7] != 95 )
    return 0i64;
  if ( a1[8] != 116 )
    return 0i64;
  if ( a1[9] != 104 )
    return 0i64;
  if ( a1[10] != 101 )
    return 0i64;
  if ( a1[11] != 95 )
    return 0i64;
  if ( a1[12] != 99 )
    return 0i64;
  if ( a1[13] != 104 )
    return 0i64;
  if ( a1[14] != 52 )
    return 0i64;
  if ( a1[15] != 114 )
    return 0i64;
  if ( a1[16] != 97 )
    return 0i64;
  if ( a1[17] != 99 )
    return 0i64;
  if ( a1[18] != 116 )
    return 0i64;
  if ( a1[19] != 51 )
    return 0i64;
  if ( a1[20] == 114 )
    return a1[21] == 0;
  return 0i64;
}

이걸 모두 손으로 하나하나 하는 건 좋지 않은 방법인 것 같다. 어떻게 간편한 방법으로 답을 알 수 있을까?? 👉 모두... 그렇게 하나하나 푼 것 같다😂 그런 방법밖에 없나보다.



4. 다른 풀이 보기

하나하나 일일이 푸는 것 외에 다른 방법이 있을 것 같아 다른 풀이를 찾아보게 되었다. 일단 방법은 세가지 정도가 있는 것 같다.

(1) x64dbg 사용하여 풀기

일단 x64dbg에 해당 파일을 올려봤다.

그리고 input값을 입력하는 부분으로 가기 위해 문자열 검색을 했다.
(마우스 우클릭 - 다음을 찾기 - 모든 모듈 - 문자열 참조)

문자열 부분에 "Input : "가 보인다. 이부분을 더블클릭해서 들어가보자.

그럼 아래와 같이 뜨는데, Input 값을 넣고 Correct인지 Wrong인지 판별하는 흐름 사이에 call chall1.7FF7D9401000 이부분이 Input값을 판별하는 명령인 것을 짐작할 수 있다. 그래서 이곳에 단축키 F2를 눌러 브레이크포인트를 걸고, 이 안으로 들어가 보려고 한다.

실제로 값들을 어떠한 문자와 하나하나 비교한다! 이를 종합해보면 답은 Compar3_the_ch4ract3r라고 나온다.


(2) IDA 사용하여 풀기

이제 IDA를 사용해서 풀어보자. IDA를 사용해서 푸는 방법으로는 두가지가 있다.

1) 첫번째 방법

첫번째 방법은 조금 귀찮지만 일일이 아스키코드를 구하는 것보다는 덜 귀찮은 방법이다.

아래와 같이 아스키코드를 하나하나 뽑아 하나의 배열에 넣어준 후 이를 for문으로 순회하며 문자로 바꿔준다. (배열을 만드는 방법으로는 아스키코드를 뽑을 때 vscode에 모든 코드를 복붙하여 필요없는 부분을 지워서 사용하거나, 아니면 아예 IDA에서 해당 숫자만 뽑아오는 방법이 있다)

a = [67,111,109,112,97,114,51,95,116,104,101,95,99,104,52,114,97,99,116,51,114 ]

answer = ""
for i in a :
  answer += chr(i)

print(answer)

2) 두번째 방법

이건 스크립트를 짜서 푸는 건 아니지만, 단축키를 사용하여 푸는 방법이다. IDA의 기능을 새롭게 알게되어서 쓰려고 한다.

단축키 r을 누르면 숫자-문자의 아스키코드 변환 기능을 사용할 수 있다. 실제로 해보니, 아래와 같이 숫자가 문자로 변환된 것을 알 수 있다. 유용한 기능인 것 같다!



정답

정답이다!!



🐹 회고

아니.. 나는 진짜 IDAPython 스크립트로 푸는 방법이 있는 줄 알았다. 당연히 푸는 방법이 있을 거지만, 이렇게 인터넷에서 하나도 찾지 못할 줄은 몰랐다.. 너무 아쉽다.

그래도 단축키 r로 숫자-문자를 변환하는 기능을 알게되어 뿌듯했다!

그리고 스크립트로 못풀겠으면 코드를 복사해와서 vscode에 붙여넣은 후 원하는대로 수정하여 문제를 푸는 방법도 있다는 것을 알게되었다. 다음에는 더 좋은 방법이 있겠지? 하면서 문제 풀이를 중단하지 말고 어떻게든 답을 구한 후 풀이를 봐야겠다.

profile
🐹강화하고 싶은 기억을 기록하고 공유하자🐹

0개의 댓글