저번 rev-basic-0 문제 풀이에 이어 rev-basic-1도 풀어보기로 했다.
문제는 아래와 같다. rev-basic-0과 마찬가지로 correct를 출력하는 입력값을 찾으면 된다.
Detect It Easy라는 프로그램에 넣어보면, 이 파일이 PE64 파일이고 따로 압축은 되어있지 않다고 나온다. IDA64로 바로 열어보자.
IDA64에 해당 파일을 올려보았다. 그럼 이런 그래프가 나온다.
이 그래프만 해석해보면 어떤 input 값을 넣으면 Correct 혹은 Wrong을 출력한다는 것 같다.
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;
}
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;
}
이걸 모두 손으로 하나하나 하는 건 좋지 않은 방법인 것 같다. 어떻게 간편한 방법으로 답을 알 수 있을까?? 👉 모두... 그렇게 하나하나 푼 것 같다😂 그런 방법밖에 없나보다.
하나하나 일일이 푸는 것 외에 다른 방법이 있을 것 같아 다른 풀이를 찾아보게 되었다. 일단 방법은 세가지 정도가 있는 것 같다.
일단 x64dbg에 해당 파일을 올려봤다.
그리고 input값을 입력하는 부분으로 가기 위해 문자열 검색을 했다.
(마우스 우클릭 - 다음을 찾기 - 모든 모듈 - 문자열 참조)
문자열 부분에 "Input : "가 보인다. 이부분을 더블클릭해서 들어가보자.
그럼 아래와 같이 뜨는데, Input 값을 넣고 Correct인지 Wrong인지 판별하는 흐름 사이에 call chall1.7FF7D9401000
이부분이 Input값을 판별하는 명령인 것을 짐작할 수 있다. 그래서 이곳에 단축키 F2를 눌러 브레이크포인트를 걸고, 이 안으로 들어가 보려고 한다.
실제로 값들을 어떠한 문자와 하나하나 비교한다! 이를 종합해보면 답은 Compar3_the_ch4ract3r
라고 나온다.
이제 IDA를 사용해서 풀어보자. IDA를 사용해서 푸는 방법으로는 두가지가 있다.
첫번째 방법은 조금 귀찮지만 일일이 아스키코드를 구하는 것보다는 덜 귀찮은 방법이다.
아래와 같이 아스키코드를 하나하나 뽑아 하나의 배열에 넣어준 후 이를 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)
이건 스크립트를 짜서 푸는 건 아니지만, 단축키를 사용하여 푸는 방법이다. IDA의 기능을 새롭게 알게되어서 쓰려고 한다.
단축키 r
을 누르면 숫자-문자의 아스키코드 변환 기능을 사용할 수 있다. 실제로 해보니, 아래와 같이 숫자가 문자로 변환된 것을 알 수 있다. 유용한 기능인 것 같다!
정답이다!!
아니.. 나는 진짜 IDAPython 스크립트로 푸는 방법이 있는 줄 알았다. 당연히 푸는 방법이 있을 거지만, 이렇게 인터넷에서 하나도 찾지 못할 줄은 몰랐다.. 너무 아쉽다.
그래도 단축키 r
로 숫자-문자를 변환하는 기능을 알게되어 뿌듯했다!
그리고 스크립트로 못풀겠으면 코드를 복사해와서 vscode에 붙여넣은 후 원하는대로 수정하여 문제를 푸는 방법도 있다는 것을 알게되었다. 다음에는 더 좋은 방법이 있겠지? 하면서 문제 풀이를 중단하지 말고 어떻게든 답을 구한 후 풀이를 봐야겠다.