Wargame/Lena’s Reversing for Newbies

Lena's Reversing for Newbie 14 Write-Up

0xe82de_ 2019. 8. 7. 00:10
728x90
728x90
728x90

파일 링크: https://tuts4you.com/e107_plugins/download/download.php?list.17

 

Downloads / Lenas Reversing for Newbies - Tuts 4 You

 

tuts4you.com

Tutorials Index: 14. More difficult schemes and an introduction to inline patching

사용도구: 올리디버거 2.01

 

Lena's Reversing for Newbie 14(이하 원본파일) 분석해보자.

 

[사진 1]

원본파일을 실행하면 위와 같이 Reg.Code를 입력할 수 있는 Shareware 창이 뜬다. "30 days left" 문자열을 보아 30일 동안 사용할 수 있는 프로그램같다. Enter Reg.Code 버튼을 클릭해보자.

 

 

[사진 2]

그러면 위와 같이 Name, Serial, Unlock Code 총 3개의 값을 입력할 수 있다.

 

 

[사진 3]

실패했을 때 "Please check Serial Number..." 문자열의 메시지 박스를 확인할 수 있다.

 

 

[사진 4]

Shareware 창을 종료하면 위와 같이 프로그램을 이용할 수 있다.

 

 

[사진 5]

올리디버거로 프로그램을 실행한 뒤, code 섹션에서 우클릭 - Search for - All referenced strings 기능을 클릭하면 위와 같이 사용되는 문자열들을 확인할 수 있다. "Please check Serial Number" 문자열을 검색해보자.

 

 

[사진 6]

그러면 위와 같이 0x00522390 주소에서 "Please check Serial Number..." 문자열이 사용되는 것을 알 수 있다.

 

 

해당 주소로 가보면 [EAX-8] 값과 0x8 값을 비교하여 [EAX-8] 값이 작으면 [사진 3]의 메시지 박스가 호출된다.

 

 

[사진 8]

0x00522388 주소에 브레이크 포인트를 설정하고 실행하면 [EAX-8] 값이 0x4라는 것을 알 수 있다. 따라서 0x0052239E 주소로 점프하지 않고 [사진 3]의 메시지 박스가 호출되는 것이다.

 

 

[사진 9]

따라서 위와 같이 JGE 명령어를 JB 명령어로 패치하여 [EAX-8] 값이 0x8 값보다 작으면 [사진 3]의 메시지 박스 함수를 호출하지 않도록 할 수 있다.

 

 

[사진 10]

그러면 위와 같은 새로운 내용의 메시지 박스가 뜬다. registration code가 유효하지 않다는 내용이다. 실수가 없는지 체크해보라고 한다.

 

 

[사진 11]

다시 code 섹션에서 우클릭 - Search for - All referenced strings 기능을 클릭하여 "The registration" 문자열을 검색해보자.

 

 

[사진 12]

그러면 0x004DC1D4 주소의 ""Thank you for your support ~~" 문자열이 보인다.

 

 

[사진 13]

0x004DC1B1 주소로 가면 [사진 10]의 메시지 박스 함수를 호출하는 코드와 성공했음을 알려주는 메시지 박스 함수를 호출하는 코드가 있다. 여기서 주의깊게 봐야하는 것은 EAX 레지스터의 값을 비교하여 계속 점프하고 있는 것이다. "Thank you for ~~" 문자열이 포함된 메시지 박스 함수가 호출되려면 EAX 레지스터의 값이 0x4 값이 되어야 한다.

따라서 EAX 레지스터의 값을 어디서 조작할 수 있는지 찾아봐야 한다. 0x004DC19D 주소가 어디서 점프되었는지 찾아보자.

 

 

[사진 14]

코드를 위로 올리다보면 EAX 레지스터의 값이 0x2 값이 아니면 0x004DC19D 주소로 점프한다. 0x004DC049 주소가 어디서 점프되었는지 찾아보자.

 

 

[사진 15]

마찬가지로 코드를 위로 올리다보면 EAX 레지스터의 값이 0x7 값이 아니면 0x004DC049 주소로 점프한다. 0x004DBDFE 주소가 어디서 점프되었는지 찾아보자.

 

 

[사진 16]

마지막이다. EAX 레지스터의 값이 0x1 값이 아니면 0x004DBDFE 주소로 점프한다. 그리고 0x004DBD9E 주소의 MOV EAX, DWORD PTR SS:[EBP+8] 명령어에 의해 EAX 레지스터의 값이 세팅된다.

 

 

[사진 17]

바로 윗 부분에 함수 프롤로그가 있는데 이 곳에 브레이크 포인트를 설정하고 디버깅해보자.

 

 

[사진 18]
[사진 19]

0x004DBD9E 주소의 명령어가 실행되면 EAX 레지스터의 값은 0x3 값이 된다.

 

 

[사진 20]

따라서 0x004DC1B1 주소의 "The registration ~~" 문자열과 함께 [사진 10]의 메시지 박스 함수가 호출되는 것이다.

 

 

[사진 21]

"Thank you for ~~" 문자열을 포함하는 메시지 박스 함수를 호출하려면 EAX 레지스터의 값이 0x4 값이 되어야 한다.

그러나 위와 같이 0x004DBD9E 주소의 명령어를 MOV EAX, 4로 패치하면 0x004DBDA1 주소의 명령어 PUSH EBX와 0x004DBDA2 주소의 명령어 PUSH ESI 명령어가 지워진다.

따라서 인라인 패치를 해야 하는데 long 점프 명령어를 사용할 것이다. short 점프 명령어를 사용하면 공간을 2bytes 사용하여 명령어 크기를 줄일 수 있지만 점프 대상 주소가 80bytes 내에 있어야 한다. 즉, 80bytes 내에 빈 공간이 있어야 하는데 이 프로그램에서 80bytes 내에 빈 공간이 없다.

그래서 long 점프명령어를 사용해야 하는 것이다. 그런데, long 점프 명령어의 크기는 5bytes이기 때문에 0x004DBDA1 주소의 명령어 PUSH EBX와 0x004DBDA2 주소의 명령어 PUSH ESI 명령어가 지워진다.

따라서 인라인 패치를 하는 공간에 PUSH EBX, PUSH ESI 명령어도 입력해야 한다.

 

 

[사진 22]

PE 구조에 의해 반드시 잉여공간이 남을 수 밖에 없으므로 여유롭게 공간이 남아 있는 곳을 찾아 위와 같이 명령어를 입력해준다. 명령어의 시작 주소는 0x005F4FCB이다.

 

 

[사진 23]

그리고 0x004DBD9E 주소의 명령어를 JMP 0x005E4FCB 명령어로 패치한다. 0x004DBDA1 주소의 명령어 PUSH EBX와 0x004DBDA2 주소의 명령어 PUSH ESI 명령어가 지워진 것을 확인할 수 있다.

이렇게 패치하면 0x004DBD9E 주소에서 0x005E4FCB 주소로 점프한 후 EBX, ESI 레지스터의 값을 스택에 저장하고 EAX 레지스터의 값을 0x4 값으로 세팅한다. 그리고 0x004DBDA3 주소로 점프하여 프로그램이 잘 진행되도록 한다.

 

 

[사진 24]

따라서 EAX 레지스터의 값은 0x4 값이 되기 때문에 "Thank you for ~~" 문자열이 포함되어 성공했음을 알려주는 메시지 박스 함수가 호출된다. 모든 브레이크 포인트를 해제하고 실행해보자.

 

 

[사진 25]

위와 같은 메시지 박스를 확인할 수 있다. 하지만 문제가 있다. 프로그램이 동작하면서 [사진 17]의 함수 루틴을 계속 실행시키는데, 인라인 패치로 인해 EAX 레지스터의 값이 0x4 값으로 계속 고정된다. 즉, 계속 [사진 25]의 메시지 박스 함수가 호출되는 것이다.

 

 

[사진 26]

따라서 인라인 패치했던 명령어들을 위와 같이 바꿔준다. 추가된 내용은 EAX 레지스터의 값과 0xC 값을 비교하여 EAX 레지스터의 값이 0xC 값보다 크면 EAX 레지스터의 값을 0x4 값으로 세팅하지 않고 0x004DBDA3 주소로 점프하는 것이다.

 

 

[사진 27]

[사진 17]의 함수 프롤로그 부분을 다시 보면 0x004DBD8A 주소의 명령어 MOV EAX, DWORD PTR FS:[0] 명령어에 의해 EAX 레지스터 값이 우측의 0x0018FCD4 값처럼 계속 변경된다. 이렇게 패치하면 프로그램을 실행하면 Reg.Code를 입력하는 창이 뜨지 않고 바로 [사진 4]처럼 프로그램이 실행된다. 0x004DBD8A 주소의 명령어로 인해 EAX 레지스터의 값이 0xC 값보다 크기 때문에 [사진 25]의 메시지 박스 함수를 호출하지 않는 것이다.

사실 [사진 14], [사진 15]에서 EAX 레지스터의 값을 0x2, 0x7 값과 비교하여 점프하는데, 이 곳에서 최초 프로그램 실행 시 Reg.Code를 입력할 수 있는 [사진 1]의 메시지 박스 함수를 호출한다. 즉, [사진 26]처럼 패치하면 [사진 1]의 메시지 박스 함수도 호출하지 않고 프로그램이 실행되는 것이다.

728x90
728x90