[Reversing] OllyDbg 사용법

(1) Hello World! 프로그램
아마도 모든 개발자가 처음 만들어보는 프로그램은 'Hello World!'일 것이다.
Hello World 프로젝트르 다음과 같이 열어 실행 시켜보도록 하자.


1-1. 디버거와 어셈블리 언어
-
개발 도구(Visual C++)를 이용해 소스 코드(HelloWorld.cpp)를 빌드하면, 실행 파일(HelloWorld.exe)이 생성
-
이 과정은 결국 사람이 이해하기 쉬운 소스 코드(HelloWorld.cpp)를 기계가 이해하기 쉬운 기계어(HelloWorld.exe)로 변환하는 것
-
이러한 기계어는 사람이 알아보기 어렵기 때문에 좀 더 편하게 보기 위해 디버거(Debugger) 유틸리티를 사용
-
디버거에 탑재된 디스어셈블러(Disassembler) 모듈은 이 기계어를 어셈블리(Assembly) 언어로 번역해서 보여줌
# 참고 내용
-
실행 파일을 생성하는 어떠한 프로그래밍 언어라도 빌드 과정을 거치면 모두 기계어로 변환 됨
-
디버거를 통해 어떤 실행 파일이라도 어셈블리 언어로 번역해서 볼 수 있기 때문에 리버서는 기본적으로 어셈블리 언어 지식 필요
-
어셈블리 언어만 잘 익혀 놓으면 실행 파일이 어떠한 프로그래밍 언어로 제작되었는지 상관없이 디버깅을 통한 코드 분석 가능
-
어셈블리 언어는 CPU에 종속되어 있음
-
즉, 일반 PC에서 많이 사용되는 Intel x86 계열 CPU와 모바일 제품에서 많이 사용되는 ARM 계열 CPU는 서로 어셈블리 명령어 형태가 다음
1-2. OllyDbg 사용

다운로드 사이트 : http://www.ollydbg.de/
OllyDbg v1.10
www.ollydbg.de
# 참고 내용
-
일반적으로 파일을 분석할 때, 소스 코드가 없이 실행 파일만 가지고 분석을 하므로 OllyDbg 같은 Win32 전문 디버거 사용
-
OllyDbg는 직관적 인터페이스와 강력한 확장 기능으로 무장한 Win32 디버거
-
무료로 제공되며, 가볍고 빠르기 대문에 많은 리버서들이 애용하는 디버거
-
다른 도구로는 Hex-Rays 사의 IDA-Pro 사용 추천 (최강의 유틸리티로 수 많은 기능 지원)
[표 1] OllyDbg 메인 화면 구성
Code Window | 기본적으로 disassembly code 표시하여 각종 comment, label을 보여주며, 코드를 분석하여 loop, jump 위치 등의 정보 표시 |
Register Window | CPU register 값을 실시간으로 표시하며 특정 register들은 수정 가능 |
Dump Window | 프로세스에서 원하는 memory 주소 위치를 Hex와 ASCII/유니코드 값으로 표시하고 수정 가능 |
Stack Window | ESP register가 가리키는 프로세스 stack memory를 실시간 표시하고 수정 가능 |
다음 [그림 4]와 [표 2]는 Code Window에 대한 설명이다.

[표 2] Code Window 역할
Address | 프로세스의 가상 메모리(Virtual Address : VA) 내의 주소 |
Instruction | IA32(또는 x86) CPU 명령어 |
Disassembled code | OP code를 보기 쉽게 어셈블리로 변환한 코드 |
comment | 디버거에서 추가한 주석(옵션에 따라 약간 다르게 보임), 빨간색 글씨 부분은 API 함수 이름 |
EP(Entry Point)
-
Windows 실행 파일(EXE, DLL, SYS 등)의 코드 시작점을 의미
-
프로그램이 실행될 때 CPU에 의해 가장 먼저 실행되는 코드 시작 위치
본격적인 디버깅을 하기 위해서 OllyDbg의 기본 명령어 사용법을 이해해야 한다.
[표 3] OllyDbg 기본 명령어(Code Window)
명령어 | 단축키 | 설명 |
Restart | [Ctrl] + [F2] | 다시 처음부터 디버깅 시작(디버깅을 당하는 프로세스를 종료 및 재실행) |
Step Into | [F7] | 하나의 OP code 실행(CALL 명령을 만나면, 그 함수 코드 내부로 따라 들어감 |
Step Over | [F8] | 하나의 OP code 실행(CALL 명령을 만나면, 따라 들어가지 않고 함수 자체를 실행 |
Execute till Return | [Ctrl] + [F9] | 함수 코드 내에서 RETN 명령어까지 실행(함수 탈출 목적) |
(2) 디버거 명령어
2-1. 디버거 동작 명령
추가적인 디버깅 명령어를 사용하는 방법은 다음과 같다.
[표 4] 디버거 동작 명령(Code Window)
명령어 | 단축키 | 설명 |
Go to | [Ctrl] + [G] | 원하는 주소로 이동(코드/메모리 확인 시 사용, 실행은 아님) |
Execute till Cursor | [F4] | cursor 위치까지 실행(디버깅하고 싶은 주소까지 바로 갈 수 있음) |
Comment | ; | Comment 추가 |
User-defined comment | 마우스 우측 메뉴 Search for - User-defined comment | 사용자가 입력한 comment 목록 보기 |
Label | : | Label 추가 |
User-defined label | 마우스 우측 메뉴 Search for- User-defined label | 사용자가 입력한 Label 목록 보기 |
Set/Reset BreakPoint | [F2] | BP 설정 / 해제 |
Run | [F9] | 실행(BP가 걸려있으면 그곳에서 실행 정지) |
Show the current EIP | * | 현재 EIP 위치를 보여줌 |
Show the previous Cursor | - | 직전 커서 위치를 다시 보여줌 |
Preview CALL/JMP address | [Enter] | 커서가 CALL / JMP 등의 명령어에 위치해 있다면, 해당 주소를 따라가서 보여줌 (실행되는 것이 아니며, 간단히 함수 내용 확인 시에 유용) |
All referenced text strings | 마우스 우측 메뉴 Search for - All referenced text strings | 코드에서 참조되는 문자열 보기 |
All intermodular calls | 마우스 우측 메뉴 Search for - All intermodular calls | 코드에서 호출되는 모든 API 함수 보기 |
Name in all modules | 마우스 우측 메뉴 Search for - Name in all modules | 모든 API 함수 보기 |
Edit data | Ctrl + [E] | 데이터 편집 |
Assemble | [Space] | 어셈블리 코드 작성 |
Copy to executable file | 마우스 메뉴 Copy to executable file | 파일의 복사본 생성(변경 사항 반영) |
다음은 Assembly에 대한 기초적인 명령어이다.
[표 5] Assembly 기초 명령어
명령어 | 설명 |
CALL XXXX | XXXX 주소의 함수 호출 |
JMP XXXX | XXXX 주소로 점프 |
PUSH XXXX | 스택에 XXXX 저장 |
RETN | 스택에 저장된 복귀 주소로 점프 |
다음은 리버싱과 관련된 중요한 용어들이다.
[표 6] 용어 정리
용어 | 설명 |
VA(Virtual Address) | 프로세스 가상 메모리 |
OP code(OPeration code) | CPU 명령어(바이트 code) |
PE(Portable Executable) | Windows 실행 파일(EXE, DLL, SYS 등) |
# Reference
'Reversing' 카테고리의 다른 글
[Reversing] Process Explorer (0) | 2020.03.26 |
---|---|
[Reversing] 스택 (0) | 2020.03.25 |
[Reversing] IA-32 Register (0) | 2020.03.25 |
[Reversing] 리틀 엔디언 표기법 (0) | 2020.03.24 |
[Reversing] 리버스 엔지니어링이란? (0) | 2020.01.04 |