역분석 – 기계어를 분석한다 (Disassemblers)

기계어를 분석한다

디컴파일러(Dicompiler)와 디어셈블러(Disassemblers)는 쉽게 얘기하자면, 개발이 완료된 프로그램을 분석하기 쉬운 소스코드와 같은 상태로 되돌리는 것을 얘기한다.

우리는 흔히 편리한 자연어로 프로그램 코드를 작성하는데, 프로그램 실행을 위해 이를 CPU가 알 수 있는 기계어(이진수)로 컴파일해야 한다. 이때 컴파일하는 도구를 컴파일러라고 하며, 컴파일러별로 서로 다른 방식으로 기계어를 만들어 내게 된다.

이렇게 생성된 기계어는 사람이 판단하기에는 어렵기 때문에, 기계어와 가까운 어셈블리어/소스코드로 변환하여 분석을 진행하게 된다. 이때 사용자들에게 도움을 주는 도구가 바로 디어셈블러, 디컴파일러이다. 즉 디컴파일러와 디어셈블러는 어셈블리/소스코드상태로 되돌려 원활히 분석 할 수 있도록 도와주거나, 개발한 프로그램에 추가 개발이 필요한데 기존 소스를 잃어버렸을 때에도 유용하게 사용할 수 있다.

컴파일은 인간이 쉽게 작성할 수 있도록 고안된 Native 언어를 컴퓨터가 이해할 수 있는 기계어로 변환하는 작업이라고 할 수 있다. 그리고 그 기계어를 인간이 이해할 수 있는 저급 언어로 표현한 것이 어셈블리인 것이다. 즉 기계어 55는 어셈블리어 PUSH EBP를 뜻함을 디어셈블러가 표시해주는 형식이다. 이와 같이 패턴 매칭과 같은 방법으로 컴파일된 파일의 디컴파일, 디어셈블링을 진행하게 된다.

역분석 - 기계어를 분석한다 (Disassemblers)

[그림] 프로그램 코드와 기계어의 관계

 

그리고 동일한 프로그램이더라도 컴파일러에 따라 동일한 코드로 변환되지 않는다. 그럼 이 디컴파일러와 디어셈블러를 조금 세부적으로 나누어 보자. 아래와 같은 샘플 소스코드가 있다.

 

hello_vc.cpp, hello_bc.cpp
#include <stdio.h>

 

 

int main(void)

{

printf(“Hello, world\n”);

 

return 0;

}

[예제] Hello world 출력 프로그램

 

위 소스코드는 C배우게 되는 코드로 콘솔창에 “Hello, world”라는 문자를 출력해주는 프로그램이다.

이를 서로 다른 컴파일러로 컴파일 해보도록 하자.

위와 같은 코드를 볼랜드에서 제공하는 C++ 컴파일러로 컴파일했을 때와 마이크로소프트에서 제공하는 비주얼 스튜디오의 컴파일러로 컴파일했을 때 나타나는 기계어 코드는 다르다. 이렇듯 디컴파일러와 디어셈블러도 해당 바이너리 코드를 어떻게 해석하였느냐에 따라 서로 다른 결과로 보여주게 된다.

그럼 먼저 컴파일러의 차이를 알아보기 위해서 서로 다른 컴파일러 2개를 준비해 보자.

책에서는 무료 버전인 Borland C++ 컴파일러와 마이크로소프트 Visual C++ Express Edition을 다운로드 하여 설치하자.

Borland C++ 컴파일러 http://www.embarcadero.com/products/cbuilder/free-compiler 볼랜드사에서 무료로 제공하는 CLI기반의 C++ 컴파일러

마이크로소프트 Visual C++ Express Edition http://www.microsoft.com/visualstudio/en-us/products/2010-editions/express 마이크로소프트사에서 무료로 제공하는 CLI/GUI기반의 C++ 컴파일러

 

단 Borland C++의 경우 설치 디렉토리의 실행 파일이 있는 위치를 아래 그림처럼 시스템 환경 변수 Path에 추가해 주어야 한다.

[그림] 시스템 환경 변수 등록

 

설치 후 각 컴파일러를 실행하도록 하자.

Borland C++는 기본 디렉토리에 설치했다는 가정으로 명령 프롬프트창(Cmd.exe)에서 다음과 같이 실행하자.

 

C:\Borland\BCC55\Bin\bcc32.exe –v –IC:\Borland\BCC55\include –v –LC:\Borland\BCC55\lib –n c:\hello_bc.cpp

 

Visual C++역시 기본 디렉토리에 설치했다는 가정으로 명령 프롬프트창(Cmd.exe)에서 다음과 같이 실행하자.

 

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin>cl c:\hello_vc.cpp

 

컴파일이 완료되었다면 컴파일한 파일을 디버깅 프로그램인 Ollydbg로 프로그램 실행 코드의 바이너리 코드를 확인해 보면 동일한 결과를 출력하는 프로그램이지만 바이러니(기계어) 코드는 다른 것을 알 수 있다.

[그림] 빌드한 각 파일의 Entry Point의 코드, 코드 내용이 전혀 다르다

 

아래는 프로그램 시작 지점인 Entry Point(프로그램 실행 준비를 마치고 실행을 시작하는 위치)의 어셈블리 결과이다. 이 역시 컴파일러에 따라, 다음과 같이 전혀 다른 내용을 보인다.

 

// Boland C Entry point 어셈블리 코드

00401000 > $ /EB 10         JMP SHORT 00401012   ß Entry Point      ;  hello_bc.00401012

00401002     |66            DB 66                                    ;  CHAR ‘f’

00401003     |62            DB 62                                    ;  CHAR ‘b’

00401004     |3A            DB 3A                                    ;  CHAR ‘:’

00401005     |43            DB 43                                    ;  CHAR ‘C’

00401006     |2B            DB 2B                                    ;  CHAR ‘+’

00401007     |2B            DB 2B                                    ;  CHAR ‘+’

00401008     |48            DB 48                                    ;  CHAR ‘H’

00401009     |4F            DB 4F                                    ;  CHAR ‘O’

0040100A     |4F            DB 4F                                    ;  CHAR ‘O’

0040100B     |4B            DB 4B                                    ;  CHAR ‘K’

0040100C     |90            NOP

0040100D     |E9            DB E9

0040100E   . |1CA14000      DD hello_bc.___CPPdebugHook

00401012   > \A1 0FA14000   MOV EAX,DWORD PTR DS:[40A10F]

00401017   .  C1E0 02       SHL EAX,2

0040101A   .  A3 13A14000   MOV DWORD PTR DS:[40A113],EAX

…중략

// Visual C Entry point 어셈블리 코드

00401254 > $  E8 C7260000   CALL 00403920   ß Entry Point            ;  hello_vc.00403920

00401259   .^ E9 A4FEFFFF   JMP 00401102                             ;  hello_vc.00401102

0040125E  /$  B8 08C04000   MOV EAX,40C008

00401263  \.  C3            RETN

00401264   .  A1 C0EA4000   MOV EAX,DWORD PTR DS:[40EAC0]

00401269   .  56            PUSH ESI

0040126A   .  6A 14         PUSH 14

0040126C   .  5E            POP ESI

0040126D   .  85C0          TEST EAX,EAX

0040126F   .  75 07         JNZ SHORT 00401278                       ;  hello_vc.00401278

00401271   .  B8 00020000   MOV EAX,200

00401276   .  EB 06         JMP SHORT 0040127E                       ;  hello_vc.0040127E

00401278   >  3BC6          CMP EAX,ESI

0040127A   .  7D 07         JGE SHORT 00401283                       ;  hello_vc.00401283

0040127C   .  8BC6          MOV EAX,ESI

…중략

[실습] 컴파일러별 EP의 어셈블리 코드

 

이러한 차이는 역분석을 진행하는 디어셈블러에서도 나타난다. 따라서 역분석 전문가가 되기 위해서는 다양한 컴파일러를 통해 컴파일된 프로그램을 분석해 보아야 역분석을 원활히 진행할 수 있을 것이다

Facebook Comments

Leave A Reply

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.