본문 바로가기

Learning/└◆Reversing

[참고]어셈블리 언어에 대해서

어셈블리(Assembly) 언어

 

 

 

 

1. 리버스 엔지니어링

 

(1) 리버스 엔지니어링(Reverse Engineering, Reversing)이란?

 

리버스 엔지니어링(Reverse Engineering)은 인조물로 부터 청사진을 얻는 것에서 유래되었다. 이진 코드로 되어 있는 실행 파일을 분석하려는 일련의 행위이다. 소프트웨어를 분석하고 동작을 해명해나가는 것을 리버스 엔지니어링이라 부른다. 이것은 멀웨어(Malware, 악성코드)에 한정하지 않고 일반적인 소프트웨어를 분석하는 것을 말하기 때문에, 컴퓨터 보안과 관계가 없는 곳에서도 사용된다.


 

(2) 리버스 엔지니어링의 종류

보안적 관점

  • 소프트웨어를 개발 후 개발된 제품에 대해 암호화 알고리즘과 관련된 보안의 평가

  • 해커들이 운영체제/애플리케이션의 취약점을 분석 후 바이러스 또는 악성코드를 제작하는데 사용

  • 백신업체에서 바이러스 또는 악성코드를 분석 후 백신을 만들기 위해 사용

  • 소프트웨어에서 사용된 암호화 알고리즘을 분석하기 위해 사용

 

개발적 관점

  • 소프트웨어 개발시 필요한 지식을 습득하기 위해 다른 소프트웨어를 분석하는데 사용

 

(3) 법률적 제제

  • 개인적인 필요에 의해서 프로그램을 수정하거나 변경할 수 있음.

  • 3자에게 정보를 제공하거나 유사 프로그램을 제작, 배포하는 행위는 위법

 

(4) 리버싱 분석 방법의 종류

정적 분석과 동적 분석

소프트웨어를 분석하는 방법에는 크게 정적 분석과 동적 분석으로 나눈다.

  • 정적분석: 대상 프로그램을 실행하지 않고 분석하는 방법이다. => 전체적으로 넓게 분석시 사용
    (실행전 캡처, 실행 된 다음 변화과정 캡처, 레지스트리 등 캡처 후 변화 비교)

  • 동적분석: 대상 프로그램을 실행하며 분석하는 방법이다. => 일부분을 집중적으로 분석시 사용
    (프로그램 자체 코드만 분석)

(5) 리버싱 관련 프로그램

리버싱 과정을 진행할 때 필수적으로 필요한 프로그램

  • 바이너리 에디터         --------> Stirling, BZ Editor(16진수를 ASCII코드로 보여준다.)

  • 계산기                  --------> 보조프로그램 > 계산기 (16진수를 10진수로)

  • 디스어셈블러            ----+---> OllyDbg/IDA/Immunity Debugger/WinDbg (기계어 -> 어셈블리어)

  • 디버거(Debugger)        ----+

 

디스어셈블러(Disassembler)

  • 디스어셈블러(Disassembler)는 기계어 01을 어셈블리 코드로 변환하는 툴이다.

 

디버거(Debuggers)

  • 프로그램을 실행모드에서 분석

  • Disassembler의 기능을 포함하고, 프로그램을 진행시켜가며 하나씩 분석하는 것

- User Mode(일반 응용 프로그램용) 

OllyDbg, IDA pro, Immunity Debugger

- Kernel Mode(하드웨어 관련 프로그램용) 

WinDbg, SoftICE

*IDA 상용툴 이라서 가장 보기좋다.

*가장 많이 사용하는 단순한 OllyDbg 기능은 부족하지만 프로그램이 가볍다.


각 디버거의 특징(윈도우에서 동작하는 대표적인 디버깅 프로그램)

OllyDbg

- 가장 일반적으로 사용되는 User Mode DebuggerGUI 환경 지원

- win32API를 가장 잘 표현

- 다운로드 : http://www.ollydbg.de

IDA Pro

- MFC로 만들어진 프로그램에서 주로 사용

- 지원 플랫폼(IA-32, IA64, AMD64)

- 파일포맷(PE(Windows), ELF(Linux), XBE(X-Box)

- Runtime/MFC로 만든 프로그램에서 주로 사용

- 다운로드: http://www.hex-rays.com/products/ida/support/download.shtml

Immunity Debugger

- python과 친화성이 높으며 만약, pythonista라면 immunity debugger를 선택하는 것도 좋은 방법이다.

- 다운로드 : http://www.immunitysec.com/products-immdbg.shtml

WinDbg

- 운영체제를 개발하는 사람이 주로 사용

- Device Driver User Mode Native Application에서도 막강한 기능 사용

- 다중 프로세스 디버깅- 커널랜드(Kernel Land)에서 동작하는 프로그램이다. 따라서, 커널에서 동작하는 멀웨어를 분석하는 경우에는 필수적이다.

- 다운로드: http://msdn.microsoft.com/ko-kr/windows/hardware/hh852365

 

 

(6) 대표적인 리버스 엔지니어링 기술력을 경쟁하는 대회

 

세계에는 정부 시책 및 커뮤티니 이벤트의 일환으로 정보보안 기술의 향상을 추진하는 나라가 있다. CTF(Capture the Flag)를 시작으로, 리버스 엔지니어링 기술력을 경쟁하는 대회도 개최되고 있다.

 

(일본) SECCON CTF 

http://www.seccon.jp

(미국) DEFCON CTF

http://www.defcon.org/html/defcon-20/dc-20-ctf.html

(한국) CODEGATE

http://www.codegate.org

 

최근에는 그 수요가 늘어나 세계 각지에서 보안 콘테스트가 열리고 있다. 대부분은 예선을 온라인으로 치르고, 상위 10~20위 팀 정도가 결승전에 참가 자격을 얻는다


2. 어셈블리어(Assembley Language)


(1) 용어

 

CPU <-------> MEMORY <-------> DISK

                한글 프로세스      한글.exe

 

  • CPU(Central Processing Unit)

  • MEMORY

  • Register

 

스택(Stack)의 가장 위쪽 -> EBP (Base Point) 

스택(Stack)의 시작하는 부분 -> ESP(Start Point) 


CPU/MEM 구조 && 레지스터 참고 문서

ch02_8086 시스템에 대한 이해.pdf

 



(4) 레지스터(Register)

 

어셈블리 언어로 프로그램밍을 하기 위해서는 C/C++ 같은 고급 언어와는 달리 CPU 내부에 있는 레지스터에 대해서 잘 알고 있어야 한다. 레지스터는 CPU가 접근할 수 있는 메모리 주에서 가장 빠르게 동작하는 메모리로 CPU가 여러가지 연산등의 처리 하는 동안 임시적으로 데이터를 보관하는데 사용된다.

 

메인 메모리(일반적으로 RAM 이라고도 불린다.)는 바이트 단위의 번지 혹은 주소를 이용해서 접근할 위치를 구분하는데, 레지스터의 경우는 번지의 개념이 없고 모두 고유한 이름이 부여되어 있다.

 

(4-1) 레지스터(Register)?

  • 시스템을 제어하는 CPU에 존재하는 메모리

  • 실행 중인 명령어를 제어

  • 메모리 번지를 지정

  • 산술연산을 수행

(4-2) 레지스터의 종류

각각의 고유한 이름이 있고 이름을 통하여 레지스터를 참조

  • 세그먼트 레지스터(Segment Register)
    현재 32, 64비트 컴퓨터에 사용되지 않는다.

  • 범용 레지스터(General-Purpose Registers)
    일반적인 레지스터

  • 명령어 포인터 레지스터(Instruction Point Register, IP)
    다음 실행할 코드의 주소를 담는 레지스터

  • 포인터 레지스터(Pointer Register)
    스택 영역을 표시하기 위한 레지스터

  • 인덱스 레지스터(Index Register)
    문자열의 시작주소나 기타 다른 데이터들을 저장하기 위해 사용되는 레지스터

(4-3) 80x86 CPU 레지스터 종류

 

범용레지스터(General-Purpose Registers) 32bit만 표시

EAX(Accumulator, 누산기)

어큐물레이터(Accumulator): 모든 연산 명령에 사용되는 레지스터, 산술연산, 입출력, Translate 명령어, 주로 산술 연산에 사용(함수의 결과값 저장)

EBX(Base Register, 베이스 레지스터)

임의의 번지 지정에 사용되는 어드레스 레지스터, offset, 특정 주소 저장(주소 지정을 확대하기 위한 인덱스로 사용)

ECX(Count Register, 카운트 레지스터)

스트링 조작 명령이나 반복 루프의 계수기로 사용, 반복적으로 실행되는 특정 명령에 사용(루프의 반복 횟수나 좌우 방향 시프트 비트 수 기억)

EDX(Data Register, 데이터 레지스터)

산술연산, EAX와 함께 자주 사용, 일반 자료 저장(입출력 동작에 사용)

 

범용레지스터는 EAX, EBX, ECX, EDX 4개의 레지스터로 구성되며, 32비트 크기를 갖는다.

EAX는 누산기로 함수의 리턴값을 기억하는데 사용된다.

EDX는 연산시 Overflow된 결과를 저장하거나 나눗셈 연산시 나머지를 저장하는데 사용된다.



세그먼트 레지스터(Segment Registers)

CS(Code Segment Register)

DOS의 프로그램 코드 세그먼트의 시작 번지 저장, 이 번지에 명령어 포인터(IP) 레지스터 내의 옵션값을 더하면 실행을 위한 명령어의 번지가 된다. 실행될 기계 명령어가 저장된 메모리 주소 지정.


DS(Data Segment Register)

프로그램의 데이터 세그먼트 레지스터의 시작 번지를 기억, 프로그램에서 정의된 데이터, 상수, 작업 영역의 메모리 주소 지정.


SS(Stack Segment Register)

번지와 데이터를 임시로 저장할 목적으로 쓰이는 스택을 메모리에 구현, 스택 포인터 레지스터의 오프셋 값을 더하면 스택 내의 현재 워드를 가리키는 번지. 프로그램이 임시로 저장할 필요가 있거나 사용자의 피호출 서브 루팅이 사용할 데이터와 주소 포함.


ES(Extra Segment Register)

지정하기 위해 본 레지스터를 사용할 때 DI 레지스터와 연관

FS, GS286이후에 추가된 레지스터로서 보조 세그먼트 레지스터


포인터 레지스터(Pointer Register)

EBP(Base Pointer)

함수의 파라미터나 변수의 위치를 얻어오는데 간접적으로 사용(스택 메모리를 가리킴). 호출된 프로시저(Procedure)를 위한 스택 프레임 내의 고정 Reference point를 나타냄. 저장된 이전의 EBP 값을 SFP(Stack Function Flame Pointer)라고 함. SS 레지스터와 함께 사용되어 스택 내의 변수 값을 읽는 데 사용.

ESP(Stak Pointer)

스택(stack)의 맨 꼭대기를 가리키는데 사용,그러나 프로그램 안에서 수시로 변경되기 때문에 특정 기준 시점을 잡아 ESP값을 EBP에 저장하여 EBP를 기준으로 변수나 패러미터에 접근. SS 레지스터와 함께 사용되며, 스택의 가장 끝 주소를 가리킴.

EIP(Instruction Pointer)

현재 수행중인 코드를 가리킴. 다음 명령어의 오프셋(상대 위치 주소)를 저장하며 CS 레지스터와 합쳐져 다음에 수행될 명령의 주소 형성.

 

플래그 레지스터(Flag Register)

OF(Overflow Flag)

DF(Direction Flag)

SF(Sign Flag)

ZF(Zero Flag)

CF(Carry Flag)

TF(Trap Flag)

PF(Parity Flag)

AF(Auxiliary Flag)

IF(Interrupt Flag)

 

플래그 레지스터는 CPU 연산 시 발생하는 각 상황에 대한 것들로서 총 32비트로 이루어져 있으며, 이중 16비트만 사용

 

명령어 포인터 레지스터(Instruction Pointer Registers, IP)

SP(Stack Pointer) -> ESP

스택내의 현재 워드를 참조할 오프셋 값을 기억. 80386 이후의 프로세서는 확장 스택 포인터(ESP)

BP(Base Pointer) -> EBP

스택에 들어오고 나가는 데이터나 번지를 참조하는데 사용. 80386 이후의 프로세서는 확장 스택 포인터(ESP)

 

스택이란? LIFO(Last Input First Ouput)의 구조를 갖는것으로 여기서는 스택의 기능을 구현한 메모리 영역을 의미

 

BP란 이 스택의 시작 주소를 의미하며, SP는 현재 Stack에서 진행되고 있는 위치를 의미

 

인텍스 레지스터(Index Registers)

SI(Source Index)

스트링 조작에 사용, DS 레지스터와 연관 번지의 간접지정에 사용, 특히 스트링 명령에 있어서는 메모리 부터 레지스터로 데이터를 전송하기 위한 전송 측 번지의 지정


DI(Destination Index)

스트링 조작에 사용, ES 레지스터와 연관 번지의 간접번지에 사용, 특히 스트링 명령에 있어서는 레지스터로 부터 메모리에 데이터를 전송하기 위한 수신 측 번지를 지정할 때 사용

 

인덱스 레지스터는 주로 문자열의 시작 주소를 담아서 표현하는데 사용