TIL(사전캠프)

리버싱1. 13 ~ 20(2024-06-20)

note994 2024. 6. 20. 15:16

1. Hello World! 프로그램

Hello World! 프로그램으로 첫 디버깅 실습을 한다.

 

먼저 실습예제의 코드는 이렇게 되어있다.

Hello World!.cpp

이 코드를 실행파일로 만든다. 실행파일을 만든다는 것은 사람이 이해하기 쉬운언어인 C언어(HelloWorld.cpp)를 컴퓨터가 이해하기 쉬운 언어인 기계어(HelloWorld.exe)로 변환하는 것이다. 기계어는 사람이 알아보기 어렵기 때문에 디버거(Debugger) 유틸리티를 사용한다. 디버거에 탑재된 디스어셈블러(Disassembler) 모듈은 이 기계어를 어셈블리(Assembly) 언어로 번역해서 보여준다.

 

* 어셈블리 언어는 CPU에 종속되어 있다. Intel x86 계열의 CPU와 ARM 계열의 CPU는 서로 어셈블리 명령어의 형태가 다르다.


1. 디버깅 목표

HellowWorld.exe 실행 파일을 디버깅하여 어셈블리 언어로 변환된 main() 함수를 찾아보겠다. 이 과정을 통해 기본적인 디버거의 사용법과 어셈블리 명령어에 대해 공부한다.

 

HelloWorld.exe 파일을 OllyDbg로 열어본다.

OllyDbg 기본화면

앞으로 우리가 계속 사용하게 될 OllyDbg의 실행화면이다. 번호순으로 설명하겠다.

 

(1) Code Window : disassembly code를 표시하여 각종 comment, label을 보여주며, 코드를 분석하여 loop, jump 위치 등의 정보를 표시한다.

(2) Register window : CPU register 값을 실시간으로 표시하며 특정 register들은 수정도 가능하다.

(3) Dump Window : 프로세스에서 원하는 memory 주소 위치를 Hex와 ASCII/유니코드 값으로 표시하고 수정도 가능하다.

(4) Stack Window : ESP register가 가리키는 프로세스 stack memory를 실시간으로 표시하고 수정도 가능하다.


2. EP

디버거가 멈춘 곳은 EP(EntryPoint) 코드로, HelloWorld.exe의 실행 시작 주소(004011A0)이다. EP는 프로그램이 실행될 때 CPU에 의해 가장 먼저 실행되는 코드 시작 위치라고 생각하면 된다.

디버거 시작위치 살펴보기

Address : 프로세스의 가상 메모리(Virtual Address:VA) 내의 주소

Instruction : IA32(또는 x86) CPU 명령어

Disassembled code : OP code를 보기 쉽게 어셈블리로 변환한 코드

comment : 디버거에서 추가한 주석

 

위 두 줄의 어셈블리 코드의 의미는 명확하다.

 

"40270C 주소의 함수를 호출(CALL)한 후 40104F 주소로 점프(JMP)하라"

 

계속 디버깅을 진행해본다. 목표는 main() 함수에서 MessageBox() 함수 호출을 확인하는 것이다.


3. 40270C 함수 따라가기

본격적인 디버깅을 위해 OllyDbg의 기본 명령어 사용법을 알아보겠다.

OllyDbg의 단축키들

EP 코드의 4011A0 주소에서 Step Into(F7) 명령을 사용하여 40270C 함수 안으로 따라갈 수 있다.

40270C 함수 내부

굉장히 복잡하지만 현재로서는 모두 이해할 필요가 없다. 위 화면 가장 오른쪽 부분은 OllyDbg에서 보여주는 주석(Comment)이다. 빨간색 글씨로 된 부분은 코드에서 호출되는 API 함수 이름이다.

 

호출되는 API 함수들만 살펴보자. 

 

원본 소스코드에서 사용된적이 없는 API들이 호출되고 있다. 이곳은 우리가 찾는 main() 함수가 아닐것이다. 

 

사실 이곳은 Visual C++에서 프로그램 실행을 위해 추가시킨 Visual C++ Stub Code이다. (각 컴파일러 종류와 버전별로 Stup Code 모양은 달라진다.) 지금은 신경 쓰지 말고 목표인 main()을 찾아 계속 진행한다.

 

4027A1 주소에 RETN 명령어가 있다. RETN은 함수의 끝에서 사용되며 이 함수가 호출된 원래 주소쪽으로 되돌아간다.

 

위 경우 리턴 주소가 4011A5이다. (2.EP 문단의 사진 참조)

 

RETN 명령어까지 Step over(F8) 하거나 Execute till Return(Ctrl+F9) 명령을 이용해 한 방에 가본다. 그리고 F7으로 실행하면 4011A5주소로 오게된다. (C언어에서 함수를 호출하고 리턴하면, 그 다음 명령어로 오는 것과 마찬가지이다.)


4. 40104F 점프문 따라가기

4011A5 주소의 'JMP 0040104F' 명령을 실행해서 40104F 주소로 가본다.

40104F 주소 도착

또 복잡한 코드가 나타났다. 이 코드 역시 Visual C++ Stub Code이다.

 

나같은 초보자는 이게 사용자 코드인지 Stub Code인지 알아보기 어렵다. 하지만 디버깅을 자주 해보면 Visual C++로 제작된 실행 파일들은 대개 위와 같은 형식으로 되어있다는걸 알게된다. Stub Code를 눈에 잘 익혀두면 나중에 이런 부분은 빨리 건너뛸 수 있다. Stub Code는 개발 도구에 따라 달라지며, 각 개발 도구끼리도 버전에 따라서 달라진다. 따라서 각종 개발도구로 생성된 파일을 많이 접해보면 좋다.