CodeEngn Basic RCE L17 Write-Up
파일 링크: https://codeengn.com/challenges/
CodeEngn.com [코드엔진] - Challenges
코드엔진은 국내 리버스엔지니어링 정보공유를 위해 2007년 부터 리버스엔지니어링 컨퍼런스 및 비공개 워크숍을 현업 실무자들과 함께 운영하고 있습니다. 리버스엔지니어링이라는 하나의 큰 주제로 소프트웨어 보안에 대한 다양한 시각과 연구주제에 대한 정보공유를 추구하고 있으며, 상업적 이익 없이 작은 예산으로 운영하고 있어 큰 예산으로 운영하는 다른 컨퍼런스에 비해 여러 가지로 부족 할 수 있습니다.
codeengn.com
풀어보자.
파일을 실행하고 Name, Key 값을 입력하면 위와 같다. 코드엔진 문제에서 Name이 한 자리라고 하는데, 한 자리만 입력하면 문자를 더 입력하라고 한다. 이 부분부터 패치해야 한다.
code 섹션에서 우클릭 - Search for - All referenced strings 기능을 클릭하면 위와 같이 사용되는 문자열들을 확인할 수 있다. "Please Enter More Chars..." 문자열이 사용되는 곳을 살펴보자.
위와 같이 Name 값의 길이가 3 이상인지 검사한다.
JGE 명령어를 JMP 명령어로 패치하면 Name 값의 길이에 상관 없이 점프한다.
패치된 파일을 실행하고 Name 값에 'a' 문자를 입력하고 실행하면 Name 값이 틀렸기 때문에 아무 창도 뜨지 않는다.
루틴 아랫 부분을 살펴보면 "Well done!" 문자열이 사용되고 있다. 0x0045BB9B 주소의 CALL 명령어로 0x0045B850 함수가 호출된 후 "66EE-3EEC-2A139188-8B4F-79E2" 문자열을 EDX 레지스터에 복사한다. 즉, 이 문자열이 내가 입력한 'a' Name 값으로 만들어진 Key일 것이다. 따라서 0x0045B850 함수를 살펴봐야 한다.
0x0045B850 함수 내부를 보며면 반복 루틴이 여러 개 존재한다. 이 중 첫 번째 루틴이 종료되면 EDX 레지스터에 0x66EE46F0 값이 저장되는데 상위 4bytes의 0x66EE 값은 [사진 8]에서 확인했던 문자열의 앞 부분이다. 이 루틴에서 Key의 네 자리가 만들어지는 것이다. 따라서 이 루틴이 끝나고 EDX 레지스터의 상위 4bytes 값이 0xBEDA 값이 되면 된다.
import hashlib
list = [\
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', \
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', \
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', \
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', \
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
for key in list:
esi = int(ord(key))
edx = 0
esi += edx
esi *= 0x772
edx = esi
edx *= esi
esi += edx
esi *= 0x474
esi += esi
edx = esi
password = hex(edx).upper()[2:][4:-4]
if password == "BEDA":
print("Name => %c" %(key))
print("Key => %s" %(hex(edx).upper()[2:][4:-4]))
print("md5 => %s" %(hashlib.md5(key.encode()).hexdigest()))
위와 같이 Python으로 대/소문자 알파벳과 숫자의 연산 결과 값이 "BEDA" 문자열과 같으면 key와 md5 값을 출력한다.
실행 결과는 위와 같다. Name 값은 'F' 문자이고 md5 값은 0x800618943025315f869e4e1f09471012이다.
'F' 문자를 Name에 입력하고 Key를 입력하면 성공한다.
Auth Key 값은 md5 값이다.