Lena's Reversing for Newbie 15 Write-Up
파일 링크: https://tuts4you.com/e107_plugins/download/download.php?list.17
Downloads / Lenas Reversing for Newbies - Tuts 4 You
tuts4you.com
Tutorials Index: 15. How to study behaviour in the code, continued inlining using a pointer
사용도구: 올리디버거 2.01
Lena's Reversing for Newbie 15(이하 원본파일) 분석해보자.
원본파일을 실행하면 Nag 창이 뜬다.
위와 같이 Register, Exit 버튼이 있고 Register 버튼을 클릭한다면 종료 시 Nag 창이 없어진다고 한다.
Help - About 기능을 실행하면 위와 같은 메시지 박스를 볼 수 있다.
Register 버튼을 클릭하지 않고 Exit 버튼을 클릭하면 위와 같은 Nag 창을 확인할 수 있다. Nag 창을 모두 없애면 된다.
먼저 올리디버거로 원본파일을 실행하고 첫 번째 Nag 창이 뜨면 상단 메뉴의 Debug - Pause 기능을 클릭하거나 (F12) 단축키로 프로세스를 중지시킨다. 그리고 (Alt+K) 단축키로 콜 스택을 살펴보자. 콜 스택에 대한 설명은 다음 링크를 참고하면 된다.
참고 링크: https://ko.wikipedia.org/wiki/%EC%BD%9C_%EC%8A%A4%ED%83%9D
콜 스택 - 위키백과, 우리 모두의 백과사전
위키백과, 우리 모두의 백과사전. 상향 축적 스택의 콜 스택 레이아웃. 콜 스택(call stack) 이란 컴퓨터 프로그램에서 현재 실행 중인 서브루틴에 관한 정보를 저장하는 스택 자료구조이다. 또한 실행 스택(execution stack), 제어 스택 (control stack), 런 타임 스택 (run-time) 스택 혹은 기계 스택 (machine stack) 이라고도 하며, 그냥 줄여서 스택 (the stack) 이라고도 한다. 소프트웨어 프로그램
ko.wikipedia.org
콜 스택을 보면 MFC42.#5718 Procedure에서 첫 번째 Nag 창의 흔적을 찾을 수 있다.
해당 주소는 0x6974FA24인데 이 루틴에 브레이크 포인트를 설정하고 실행해보자.
스택을 보면 리턴 주소로 0x6976198E 주소가 저장되어 있다.
0x6976198E 주소 직전의 명령어 CALL #5718에 의해 0x6974FA24 주소로 점프한 것임을 알 수 있다.
마찬가지로 스택을 보면 리턴 주소로 0x0042039F 주소가 저장되어 있다.
0x0042039F 주소 직전의 명령어 CALL <JMP.&MFC42.#2514>에 의해 0x69761989 주소가 포함된 루틴으로 점프한 것임을 알 수 있다.
0x0042039A 주소로 가기 전에 0x00420377 주소에서 EAX 레지스터를 TEST 연산하여 EAX 레지스터의 값이 0x0 값이라면 0x004203BA 주소로 점프한다.
0x00420377 주소에 브레이크 포인트를 설정하고 실행 후 TEST 연산을 수행하면 EAX 레지스터의 값이 0x1 값임을 알 수 있다. 따라서 0x004203BA 주소로 점프하지 않고 0x0042039A 주소의 CALL <JMP.&MFC42.#2514> 명령어가 수행되는 것이다.
0x0042039A 주소에만 브레이크 포인트를 설정하고 프로그램을 실행 ~ 종료까지 해보면 첫 번째 Nag 창, 프로그램 메인 화면, 두 번째 Nag 창이 실행될 때 모두 0x0042039A 주소의 CALL <JMP.&MFC42.#2514> 명령어를 수행한다.
위와 같이 EAX 레지스터의 값이 0x0이 아닐 때 0x004203BA 주소로 점프하면 Nag 창을 제거할 수 있지만 프로그램 메인 화면도 실행되지 않는다. 따라서 다른 방법으로 0x0042039A 주소의 명령어가 수행되기 전에 같은 루틴 내의 코드를 패치하거나 해야 한다.
하지만 보다시피 NOP 명령어가 없기 때문에 인라인 패치를 통해 여유 공간에 코드와 참조 변수를 작성하여 Nag 창을 없애보겠다.
(Alt+m) 단축키를 통해 메모리 맵을 볼 수 있는데, 인라인 패치를 위해 명령어를 작성할 코드 영역과 첫 번째 Nag, 프로그램 메인 화면, 두 번째 Nag 창이 실행 될때 참조할 변수가 저장될 데이터 영역을 선정해야 한다.
위와 같이 0x00401000 주소부터 읽기, 실행 권한이 있는 코드 영역이고 0x00442000 주소부터 읽기, 쓰기 권한이 있는 데이터 영역이다.
여유 공간으로 코드영역은 0x00437F80 주소, 데이터 영역은 0x00446D30 주소로 선정했다. 먼저 인라인 패치를 진행하기 전에 위 주소들에 하드웨어 브레이크 포인트를 설정하고 프로그램을 실행해봐야 한다.
왜냐하면 프로그램 실행 전에는 0x0 값으로 저장되어 있지만 프로그램이 동작하면서 사용될 수 있는 영역일 수도 있기 때문이다. 그렇다면 오류가 발생할 것이다.
실행하고 문제가 없으면 하드웨어 브레이크 포인트는 해제한다.
먼저 TEST 연산 후 0x00420379 주소의 명령어를 인라인 패치에 사용할 코드 영역인 0x00437F80 주소로 점프하도록 패치한다. 그리고 프로그램 메인 화면을 실행하려면 0x0042039A 주소로 이동해야 하므로 인라인 패치된 명령어를 수행하고 리턴될 주소는 0x0042037F이다.
첫 번째 Nag 창, 프로그램 메인 화면, 두 번째 Nag 창이 실행될 때마다 0x00420377 주소의 TEST 연산을 수행하므로 인라인 패치된 명령어는 총 3번 수행된다.
인라인 패치에 사용되는 명령어는 위와 같다. 각 명령어에 대한 설명은 다음과 같다.
1. 0x00437F80 / ADD BYTE PTR DS:[446D30],AL
인라인 패치에 사용되는 0x00446D30 주소의 데이터 영역에 AL 레지스터의 값을 더한다. 최초의 데이터 영역 0x00446D30 주소의 값은 0x0 값이기 때문에 첫 번째 Nag 창을 실행할 때의 데이터 영역은 ADD 연산 후 0x1 값이 된다.
2. 0x00437F86 / CMP DWORD PTR DS:[446D30],2
데이터 영역 0x00446D30 주소의 값과 0x2 값을 비교한다. 프로그램 메인 화면이 실행되고 두 번째 인라인 패치된 명령어가 수행되면 두 값은 같아질 것이다.
3. 0x00437F8D / JNE 004203BA
두 값이 같지 않다면 0x004203BA 주소로 점프한다. 즉, 첫 번째 인라인 패치된 명령어를 수행할 때와 세 번째 인라인 패치된 명령어를 수행할 때의 데이터 영역의 값은 각각 0x1, 0x3이다. 따라서 이 때는 0x00437F8D 주소로 점프하고 Nag 창은 보이지 않을 것이다.
4. 0x00437F93 / LEA ECX,[ESP+4C]
이 명령어는 프로그램 메인 화면이 수행될 때 실행된다. [사진 16]에서 0x00420397 주소의 명령어를 패치하면서 5bytes 크기를 사용했고, 그 결과 0x0042037B 주소까지 사용하는 것이다. 따라서 0x0042037B 주소의 원본 명령어인 LEA ECX, [ESP+4C[ 명령어가 지워졌으므로 인라인 패치를 통해 실행시키는 것이다.
5. 0x00437F97 / JMP 0042037F
이 명령어도 프로그램 메인 화면이 수행될 때 실행되는 곳이다. [사진 16]에서 명령어의 패치 결과 다음 주소인 0x0042037F 주소로 점프한다.
그리고 프로그램을 실행하면 첫 번째 Nag 창과 두 번째 Nag 창은 실행되지 않고 프로그램 메인 화면만 확인할 수 있다.
'Wargame > Lena’s Reversing for Newbies' 카테고리의 다른 글
Lena's Reversing for Newbie 17 Write-Up (0) | 2019.08.08 |
---|---|
Lena's Reversing for Newbie 16 Write-Up (0) | 2019.08.08 |
Lena's Reversing for Newbie 14 Write-Up (0) | 2019.08.07 |
Lena's Reversing for Newbie 13 Write-Up (0) | 2019.08.06 |
Lena's Reversing for Newbie 12 Write-Up (0) | 2019.08.06 |