ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [리버싱 핵심원리 study] 2장 Hello World! 리버싱
    Reverse Engineering 2020. 11. 22. 03:32

    처음 프로그래밍 언어를 배웠을 때, 아마도 가장 먼저 Hello World!를 출력해보는 프로그램을 작성할 것이다. 마찬가지로 리버싱에서도  Hello World! 프로그램을 분석해보는 방식으로 시작한다. (코드 작성은 Microsoft Visual C++ 2010 Express을 기준으로 하였다.)

    1. 프로그램 작성

    먼저 다음과 같은 코드를 작성하여 Hello World! 문구를 출력하는 프로그램을 만들어보자.

     

    #include "windows.h"
    #include "tchar.h"
    
    int _tmain(int argc, TCHAR *argv[]) {
    	MessageBox(NULL, L"Hello World!", L"www.reversecore.com", MB_OK);
        
        return 0;
    }

    (HelloWorld.cpp)

     

    Release 모드에서 빌드(Debug 모드로 빌드할 시 프로그램에 Debugging 정보가 포함되어 프로그램 내용이 길어지고 복잡해진다.)를 하게 되면 .exe 파일이 생성될 것이다. 클릭하여서 실행해보자.

     

    HelloWorld.exe

    위와 같이 Hello World!라는 문구를 출력하는 메시지 박스가 출력되는 것을 확인할 수 있다. 이제 위 exe 파일을 디버거를 이용해 그 구조를 살펴보겠다.

     

    2. Ollydbg를 이용한 분석(1)

    Ollydbg를 처음 실행하면 다음과 같다.

    Ollydbg 실행화면

    여기서 File->Open(F3)를 이용해 HelloWorld.exe파일을 열어보자.

    HelloWorld.exe를 연 직후

    무언가 굉장히 복잡해 보이지만 크게 4가지 영역으로 나뉘는 것을 확인할 수 있다. 파란 펜으로 표기한 것과 같이 1번 영역은 프로그램의 어셈블리 코드를 나타낸다. 2번 영역은 코드의 진행 시점에서의 register value 및 flag value를 나타낸다. 3번 영역은 Dump 영역으로, data의 ASCII값을 확인할 수 있다. 4번 영역은 stack 영역으로 현재 esp, ebp가 어디에 위치하고 있는지 알 수 있다.

     

     

    EP(entry point)에서 하나하나 코드를 실행시키면서 프로그램 내부 구조를 파악할 수 있는데, 생각했던 것 만큼 내부 구조가 단순하지는 않다. 각 컴파일러마다 추가적으로 붙게 되는 Stub Code 등이 있으며, 언뜻 보기에는 무의미해 보이는 assembly 연산도 존재한다. 우선 코드를 하나씩 실행시키기 위해 사용되는 기본적인 기능들로는 다음과 같은 것들이 있다.

    기능(단축키)

    설명

    Debug->Restart (Ctrl+F2)

    프로그램을 처음부터 restart 한다.

    Debug->Step into (F7)

    코드를 하나 실행시킨다.

    Debug->Step over (F8)

    코드를 하나 실행시킨다.(함수 내부로 들어가지 않음)

    Debug->Run (F9)

    프로그램을 bp까지 실행한다.

     

     

    앞서 말했듯이, 프로그램에 앞에 Stub Code가 붙어있으므로, 우리가 원하는 main 함수를 찾아낼 때 까지 위와 같은 기능을 이용한다. 물론 다른 방법들도 존재하지만, 처음에는 위와 같은 방법이 익숙해지도록 하는 것이 좋다. 코드를 실행시키다보면 다음과 같은 코드를 볼 수 있을 것이다.

    HelloWorld.exe의 main내부

    이 부분이 우리가 원하는 main 함수의 내부임을 알 수 있다.

     

    3. Ollydbg를 이용한 분석(2)

    언제나 항상 main 함수가 나올 때까지 F7, F8을 연타할 수는 없는 노릇이다. 사실 여러 다른 방법이 있는데 HelloWorld 프로그램의 경우 다음과 같은 방법으로 main 함수를 찾아낼 수 있다.

     

    (1) 문자열 검색

    HelloWorld 프로그램에서는 HelloWorld! 라는 문자열을 출력한다. 이에 착안하여 프로그램 내부에서 사용되는 문자열을 검색하면 보다 쉽게 main 함수를 찾을 수 있을 것이다. code창에서 마우스 우클릭->Search for->All referenced text strings를 선택하면 다음과 같은 화면이 나온다.

    문자열 기반의 main 함수 찾기

     

    (2) API 검색

    MessageBox API를 이용한 다는 점에 착안하여 어디서 호출되는지를 찾아볼 수도 있다. 마우스 우클릭->Search for->Name in all modules를 통해 프로그램에 사용된 모든 API 호출 목록을 찾아볼 수 있다. 아래 첨부사진과 같이 00FE100E 주소에서 MessageBoxW가 호출됨을 알 수 있다.

    API 기반의 main 함수 찾기

    위에서 제시한 방법이외에도 다양한 방법으로 원하는 곳의 주소를 찾을 수 있다. 상황에 따라 적절한 방법을 이용하여 원하는 위치로 이동하는 것에 익숙해질 수 있도록 해야한다.

     

    4. "Hello World!" 문자열 패치

    이제 본격적으로 Hello World 프로그램의 내용물을 바꿔보도록 하겠다. 책에서 제시한 대로 아래와 같은 두 가지 방법을 생각해 볼 수 있다.

     

    (1) 문자열 변경

    HelloWorld.exe main

    위 코드를 보면 알 수 있듯이, "Hello Word!"라는 문자열이 0FE211C라는 주소에 있음을 알 수 있다. Dump창에서 Ctrl+G를 통해 0FE211C로 이동해보면 다음과 같은 창을 확인할 수 있다.

    00FE211C의 dump

    원하는 영역만큼 드래그 하여 Ctrl+E(Edit)을 이용하여 내용을 다음과 같이 수정해보았다.

    00FE211C 수정

    F9를 통해 프로그램을 실행시켜보자.

    maple 19 out! 으로 패치

     

    (2) 다른 메모리에 문자열을 추가하고 해당 주소를 push하도록 변경

    위 첨부 사진에서 00FE213C영역에는 빈 공간이 있음을 알 수 있다. 여기에 변경하고 싶은 문자열을 추가하고 해당 문자열의 주소를 main 함수에서 push 하는 방식을 이용할 수도 있다.

    00FE213C에 문자열 추가
    PUSH 0FE213C로 변경

    F9를 통해 프로그램을 실행시켜보자.

    maple 20 in!으로 패치

    위와 같이 정상적으로 패치가 이뤄졌음을 확인할 수 있다.

    반응형

    댓글

Designed by Tistory.