CodeEngn Advance RCE L10 Write-Up
파일 링크: https://codeengn.com/challenges/
CodeEngn.com [코드엔진] - Challenges
코드엔진은 국내 리버스엔지니어링 정보공유를 위해 2007년 부터 리버스엔지니어링 컨퍼런스 및 비공개 워크숍을 현업 실무자들과 함께 운영하고 있습니다. 리버스엔지니어링이라는 하나의 큰 주제로 소프트웨어 보안에 대한 다양한 시각과 연구주제에 대한 정보공유를 추구하고 있으며, 상업적 이익 없이 작은 예산으로 운영하고 있어 큰 예산으로 운영하는 다른 컨퍼런스에 비해 여러 가지로 부족 할 수 있습니다.
codeengn.com
풀어보자.
파일을 실행하면 Nam
e, Serial을 입력한다. 실패 시 "Wront ~~" 문자열이 출력된다.
올리디버거로 분석해보니 코드가 너무 복잡해서 IDA를 이용했다. 메인 함수의 코드를 보면 check_serial 함수를 호출하고 반환 받은 값이 0이 아니면 성공하고 있다. 따라서 check_serial 함수를 분석해보자.
먼저 check_serial 함수의 리턴 값은 v15 변수인데, v15 변수는 v9 -> v26 변수에 의해 결정된다. v26 변수의 경우 v23 변수와 v22 변수의 차가 5를 초과하면 0으로 초기화된다.
즉, v23 변수와 v22 변수의 차가 5를 초과하면 실패 메시지가 출력되는 것이다. v23, v22 변수 값이 어떻게 초기화되는지 확인해보자.
v23, v22 변수는 stringFindSecond 함수의 반환 값으로 초기화되는데, stringFindSecond 함수의 인자는 2개가 전달되는 것을 확인할 수 있다. 그리고 for문에 의해 총 4번 반복된다.
stringFindSecond 함수의 주소는 0x00401406이다. 이제 올리디버거로 stringFindSecond 함수를 호출하는 부분을 살펴보자.
code 섹션에서 우클릭 - Search for - All commands... 기능을 클릭하고 어셈블리어 명령어를 입력하면 IDA에서 확인했듯이 2번 사용되고 있는 것을 확인할 수 있다. 두 곳 모두 브레이크 포인트를 설정하자.
올리디버거로 파일을 실행하고 Name 값으로 "1234", Serial 값으로 "ABCDEFGHIJKL" 문자열을 입력하였다. 0x00401406(stringFindSecond) 함수에 전달되는 첫 번재 인자는 "AJXGRFV6BKOW3Y9TM4S2ZU I70H5Q81PDECLNAJXGRFV6BKOW3Y9TM4S2ZU I70H5Q81PDECLNAJXGRFV6BKOW3Y9TM4S2ZU I70H5Q81PDECLN" 문자열이다.
두 번째 인자는 내가 입력한 Serial의 첫 번째 값이다.
함수가 호출되고 반환되는 값은 0x25인데, 이 값의 의미는 [사진 10]에서 확인할 수 있는 문자열 상에서 Serial 값과 일치하는 순서이다. 즉, 순서 상 37번째에 위치하는 것이다.
"AJXGRFV6BKOW3Y9TM4S2ZU I70H5Q81PDECLNAJXGRFV6BKOW3Y9TM4S2ZU I70H5Q81PDECLNAJXGRFV6BKOW3Y9TM4S2ZU I70H5Q81PDECLN" 문자열 맨 앞에 'A' 문자가 있어서 순서 상 0번째일 것 같은데 다른 문자들로 테스트 해본 결과 2번째로 조회되는 위치가 반환되는 것 같다.
이제 0x00401406(stringFindSecond) 함수가 두 번째로 호출되는 곳을 보면 전달되는 첫 번째 인자는 [사진 10]에서 확인한 문자열이다. 두 번째 인자는 내가 입력했던 Name의 첫 번째 값이다.
마찬가지로 함수가 반환하는 값은 '1' 문자가 위치한 순서이다.
[사진 13]에서 확인한 Serial 값의 위치는 0x25이고, Name 값의 위치는 0x43이다. 두 값의 차는 5를 초과하기 때문에 실패할 것이다. 따라서 두 값의 차가 5를 초과하지 않아야 하고 반환되는 두 값은 [사진 10]에서 확인한 문자열 상에서 두 번째로 위치한 순서이다.
예를 들면 위 사진에서 'D' 문자가 두 번째로 위치한 순서는 빨간색 박스이다. 그리고 두 번째로 위치한 'D' 문자의 앞뒤로 차가 5 이하인 문자는 '5', 'A'가 있다. '5' 문자는 두 번째로 위치하므로 빨간색 박스로, 'A' 문자는 세 번째로 위치하기 때문에 노란색 박스로 표시했다.
위와 같이 Name 값으로 "DDDD" 문자열을 입력하고 Serial 값으로 "555555555555" 문자열을 입력하면 성공하고, "AAAAAAAAAAAA" 문자열을 입력하면 실패하는 것을 확인할 수 있다.
따라서 코드엔진 문제에서 제시한 Serial "WWWCCCJJJRRR" 문자열에 맞게 적절한 Name 값을 찾아주면 되는데, "WWWCCCJJJRRR" Serial 값에 해당하는 여러 Name 값 중 0~9, a~z, A~Z 순서로 가장 빠른 문자열을 찾으면 된다.
Auth Key 값은 위 Name 값이다.