코드엔진 Basic RCE L14번 문제를 풀어보았다.
실행 파일을 DIE에 올려보았다. UPX로 압축되어있다고 한다.
UPX 압축을 풀었다.
압축을 푼 파일을 IDA에 올리고, F5
를 눌러 디컴파일해보았다. 그리고 유의미해 보이는 sub_401025
함수에 들어가보았다.
또 win32api에서 중요한WndProc
함수인 sub_4011E2
함수 안에 들어가보았다.
중간 부분에서 do while 연산을 볼 수 있는데, 이곳에서는 byte_403037
에 어떠한 연산을 수행해서 새로운 v5
를 만든다.
특이한 점은 인덱스를 의미하는 v7
이 1부터 시작한다는 것인데, 입력받은 Name
이 dword_403038
이므로 Name
의 인덱스 0은 byte_403037
의 인덱스 1과 동일하다는 것이다.
즉, 여기서 byte_403037
은 Name
과 동일하게 보고 문제를 풀어도 된다.
sub_401383
에 들어가면 이러한 연산을 볼 수 있는데, sub_401383
라는 연산 후의 Name과 v5가 일치하는지를 확인한다.
동일하면 aGoodJobIWishYo
에 있는 캡션을 메세지박스에 출력하고, 동일하지 않으면 aYouHaveEnterAW
에 있는 캡션을 메세지박스에 출력한다.
각각의 캡션에는 아래와 같은 메세지가 들어가 있다. 결국 Good Job, I Wish You the Very Best
을 출력하려면 do while문 후의 v5
와 sub_401383(byte_401338)
이 같아야 한다. 이 둘을 각각 살펴보도록 하자.
아래의 디컴파일된 코드를 파이썬으로 바꾸면 다음과 같다.
name = "CodeEngn"
v5 = 0
for ch in name:
v5 += (ord(ch)>>1) + ord(ch)*ord(ch) - ord(ch)
print(v5)
v5
를 더해주지 않은 이유는 v5 +=
라는 식 자체에 자기 자신을 더해주고 있다는 뜻이 포함되기 때문이다.결과는 76193
가 나온다.
이제 76193
라는 값과 sub_401383(byte_401338)
를 비교해서 같으면 Good Job, I Wish You the Very Best
을 출력한다.
sub_401383
을 더블클릭해서 안으로 들어가보았다. 그러면 아래와 같은 코드가 보인다.
변수명을 다르게 바꿔보았다. 먼저 do while문 안에서 num = c - '0'
은 문자를 정수로 만들어주는 코드이다.
예를 들어, 아스키코드 '3'(51)에서 아스키코드 '0'(48)을 빼면 정수 3이 남는다.
이제 몇자리 수인지 알려주어야 한다. for 문으로 len-1부터 i까지 -1씩, 결국 0부터 len-1번 10을 곱한다. 그러면 12345가 있을 때 1은 1*1000, 2는 2*1000, 3은 3*100, 4는 4*10, 5는 5*0이 된다.
(이는 모두 아스키코드 '1', '2', '3', '4', '5'에서 각각 '0'을 빼서 정수 1, 2, 3, 4, 5가 되어 계산된 것이다.)
결과적으로 보기에는 76193
으로 답이 같지만, 이전에는 문자열이었다면 지금은 숫자라는 점에서 연산을 거치기 전과 다르다.
정답은 숫자 76193
이다!