Replace
Patching the compare instruction so any input is accepted, which reveals the stored password.
프로그램을 켜고 확인해보면, 입력을 받고 Check 버튼을 누르면 맞는지 아닌지를 확인하는 프로그램인 걸 알 수 있습니다. 이러한 방식의 문제는 그 패스워드가 플래그일 것이라는 걸 암시합니다. 일단 메인 함수와 문자열 찾기 방법을 통해 메인 코드에 진입합니다.
처음에는 00401071 의 점프문을 무조건적으로 참으로 만들어서 correct 문구를 띄워봅니다. 하지만 그 방식으로는 플래그를 알아낼 수 없다는 걸 깨달을 수 있습니다.
프로그램을 일단 실행시켜보고 12345 를 넣습니다. 실행을 시켜보면 다음과 같이 eax 값을 004084d0 에 저장하는데, 이 값은 16진수로 3039 입니다.
eax = 0x004084d0 = 0x3039
그 후 해당 함수로 이동하고 (40466F), 그곳에서 4084D0 의 값을 두 번 증가시킵니다.
eax = 0x3039 (12345)
0x004084d0 = 0x3039 + 2 = 0x303B
계속 실행시켜보면 해당 부분에서 또 연산이 있습니다 (ret 때문에). eax 는 1 증가시키고 004084d0 의 값은 601605c7 만큼 증가시킵니다.
eax = 0x3039 + 1 = 0x303a
0x004084d0 = 0x3039 + 2 + 0x601605c7
또 순서대로 해당 부분을 다시 거치면서 다시 한번 4084D0 의 값을 증가시킵니다.
eax = 0x303a
0x004084d0 = 0x3039 + 2 + 0x601605c7 + 1
이후 eax 값을 초기화하고 404690 으로 분기가 된다.
404690 주소에서는 4084D0 의 값을 DWORD 크기만큼 eax 에 저장한다 (60163604 임). 이후 404689 를 호출하여 INC 를 통해 2를 더해서 60165CA 로 만들어 4084D0 에 저장한다. 호출된 주소는 처음의 오류가 발생했던 지점이다.
40466F 에서 발생하는 오류는 결국 eax 에 정상적인 주소가 들어가지 못하였기에 생긴 오류이다. 따라서 정상적으로 작동을 한다면, eax 에 NOP 이 들어갈 것이다.
오류가 발생한 이후 스택 상태를 확인하였다. 스택 상태를 보니, 404672 에서 return 이 될 때 리턴할 주소는 4046AE 주소였다. 4046AE 주소로 정상적으로 복귀했을 경우, 해당 위치 이후의 코드가 실행되면서 eax 값이 1만큼 증가하게 된다.
이후 다시 40466F 주소를 호출하게 되는데, 이 부분은 eax 에 들어 있는 값을 주소처럼 사용하여 특정 값을 메모리에 저장하는 루틴으로 보인다. 앞서 발생했던 오류의 원인은 eax 에 정상적인 주소가 들어가지 못한 상태에서 해당 루틴이 실행되었기 때문이며, 정상적으로 동작하는 경우 eax 에는 유효한 주소가 들어가게 된다. 이때 해당 주소에 NOP(0x90) 이 저장되도록 설계된 것으로 보이며, 이러한 NOP 저장이 정상적으로 수행되면 함수는 ret 을 통해 다시 호출 지점으로 복귀하게 된다.
이후 실행 흐름을 따라가다 보면 4046BE 주소에서 pop eax 명령이 실행되는 것을 확인할 수 있는데, 이 명령은 eax 값을 사용하기 위한 목적이라기보다는 스택에 남아 있는 값을 정리하기 위한 용도로 사용된 것으로 보인다. 실제로 스택을 확인해보면 이전 단계에서 남아 있던 40469F 주소가 스택에 존재하고 있었고, 이 값이 pop eax 를 통해 제거되면서 스택 상태가 정상화된다.
스택 정리가 완료된 이후에는 4046C4 주소에 위치한 점프문을 통해 실행 흐름이 401071 주소로 분기된다. 이 401071 주소는 처음에 강제로 분기시켜 Correct 문구를 출력했던 위치로, 정상적인 조건을 만족했을 경우에만 도달할 수 있는 루틴이다. 즉, 앞선 연산과 스택 정리 과정이 모두 정상적으로 수행되었을 때에만 최종적으로 Correct 가 출력되는 구조임을 알 수 있다.
내부 연산 과정을 추적해보면 입력값에 2를 더하고, 0x601605C7 을 더한 뒤 다시 1과 1을 더하는 과정을 거치며, 이 최종 결과가 0x00401071 이 되어야만 분기 조건을 만족하게 된다. 이걸 식으로 표현하면:
x + 2 + 0x601605C7 + 1 + 1 = 0x00401071
x = 0xA02A0AA6
= 2687109798 (10진수)
실제로 해당 값을 입력하면 Correct 문구가 출력되는 것을 확인할 수 있었고, 결과적으로 이 값이 플래그다.





