본문 바로가기

Security

[Reversing.kr] Replace

[주의] 해당 글에는 풀이 및 정답이 적혀있습니다.

스스로 해결하고 싶으신 분들은 문제를 해결한 후, 이 페이지를 참고하셨으면 합니다 : )

 

"Replace" 프로그램 실행

프로그램을 실행해보면 숫자만 입력할 수 있는 박스와 Check라는 버튼이 있습니다. 내부 루틴을 통해 맞는 숫자인지 검사하는 프로그램 같아 보입니다.

"Replace" 프로그램 Entry Point

"Replace" 프로그램을 분석해보기 위해 디버거에 올리면 다음과 같이 바로 EP를 확인할 수 있습니다. 하나씩 실행하며 분석해보면 "CALL 0x401000" 명령이 있는데 따라가면 DialogBoxParamA 함수를 호출하는 것 같습니다. 그 아래에도 여러 코드가 있는데 살펴보니 GetDlgItemInt, SetDlgItemTextA 함수가 존재하고 SetDlgItemTextA 함수에서는 "Wrong" 인 문자열을 "Correct!"로 설정합니다.

GetDlgItemInt, SetDlgItemTextA 함수 코드

GetDlgItemInt 함수에서는 말그대로 입력한 숫자를 가져오는 것으로 생각되어 브레이크 포인트를 설정하고 임의의 값을 입력했습니다. 함수 리턴값은 EAX에 저장되고 이 값을 DS:[0x4084D0]에 저장합니다. 그리고 "CALL 0x40466F"를 호출합니다.

CALL 0x40466F 이후

"CALL 0x40467A"를 호출하고, 0x40467A에서는 [0x406016]에 0x619060EB를 저장합니다. 이때, 0x406016은 코드 영역이어서 아래와 같이 "JMP ...", "NOP", "POPAD"가 저장됩니다.

[0x406016]에 0x619060EB 복사

이후에 "CALL 0x404689"를 하고 이 코드에서는 아까 입력값을 저장했던 [0x4084D0]을 1 증가하고 RETN 합니다. 함수가 종료되고 다음 인스트럭션도 0x404689이므로 한 번 더 1 증가합니다. 증가하고 리턴하면, 0x404674의 "0xDB 0x81"로 보이는 곳으로 EIP가 이동합니다. 실행해보면 아래와 같이 디버거가 분석하여 어셈블리어가 나옵니다.

디버거가 분석한 코드

이 과정을 실행하면서 [0x4084D0]에 저장했던 값에 임의의 값이 더해지는 것을 확인했다. 위의 명령어를 실행하고 한 번 더, CALL 0x404689를 해서 아까와 마찬가지로 [0x4084D0]에 2가 증가하고 리턴을 하면 아까 처음에 호출했던 "CALL 0x40466F" 다음인 0x40106A로 EIP가 옵니다.

XOR EAX, EAX를 실행하고, 0x404690으로 점프합니다. 계속 따라가보면 저희가 입력한 값에 임의의 값이 더해진 값을 EAX에 저장하고 CALL 0x404689([0x4084D] 값 2 증가하는 함수)를 실행하고, [0x40466F]에 0xC39000C6을 저장합니다. 그리고 저장한 값의 위치인 0x40466F를 호출합니다.

CALL 0x404690 호출

0x40466F 주소로 가보니 [EAX]에 0x90을 저장합니다. 이때, EAX에는 (입력한 값+임의의값)이 저장되어 있었고 가리킬 수 없는 값 일 때는 Access violation이 발생해서 에러가 나는 경우도 발생했습니다.

0xc39000c6이 저장된 [0x40466f]

일단 EAX에 0x4084D8로 설정하고 쭉쭉 실행하다보면 Correct로 바꿔주는 SetDlgItemTextA 전에 "JMP 0x401084"가 있습니다. 이때문에 우리가 원하는 함수를 호출할 수 없었습니다. 그래서 생각해낸 아이디어는 0x40466F에서 우리가 컨트롤 가능한 값(=EAX)에 0x90을 저장하므로 이를 이용해서 "JMP 0x401084"가 있는 0x401071 주소를 0x90으로 설정하면 문제를 해결할 수 있다고 생각했습니다. (이후에 더 디버깅해보면 총 2번 0x90으로 덮어써서 0x401071과 0x401073을 덮었습니다.)

EAX를 조정하기위해 최종적으로 [0x4084D0]에 어떤 값이 저장되는지 확인했더니 "입력한 값" + 0x601605CB 인 것을 확인했습니다. 우리는 EAX를 0x401071이 되길 원하므로 "입력된 값" + 0x601605CB = 0x401071을 만족하는 값을 찾으면 됩니다. 어처피 8번째 자리 다음은 무시될 것이므로 0x100401071 - 0x601605CB = 0xA02A0AA6(=2687109798) 계산을 통해 구했습니다. 

2687109798을 입력하면 "Correct!"가 나오고 문제를 해결할 수 있었습니다.

'Security' 카테고리의 다른 글

KakaoTalk Hooking  (0) 2021.05.22
[Reversing.kr] ImagePrc  (0) 2021.04.06
[Reversing.kr] Easy Unpack  (0) 2021.03.28
[Dice CTF 2021] flippidy  (0) 2021.03.01
[Dice CTF 2021] babyrop  (0) 2021.02.23