Reverse Engineering

  • Reverse Engineering: 만들어진 제품, 도구를 분해해서 분석 or 재조합
    • 대상: 컴퓨터
    • 언어: 소프트웨어공학의 발전에 따라 하이레벨 언어(C, C++, 자바 등)을 사용

3.2 사례

리버싱으로 할 수 있는 일

  1. 컴퓨터 원리와 구조 이해

    -> 리버싱을 위해선 프로그램이 컴퓨터의 CPU, 레지스터, 메모리, 운영체제 등을 어떻게 사용해 실행되는지 알아야 함

  2. 프로그램 유지보수

    -> 실무에서 사용 중에 발견되는 버그를 리버스로 쉽게 찾기 가능

    -> 소스 코드가 없는 프로그램도 간단한 버그나 수정사항에 대해서 리버싱으로 유지 보수 가능

  3. 개발에 활용

    ex) 1982년 IBM

    ​ -> 리버싱을 통해 IBM의 바이오스를 철저히 분석

  4. 보안점검 및 취약점

    -> 소스 코드가 없는 프로그램의 버그를 정확히 알기 위해선 리버싱이 필요

    -> 프로그램에서 취약한 알고리즘을 사용하거나 주요 정보를 평문으로 저장하고 있는 경우 등을 찾아냄으로써 리버싱으로 보안점검

  5. 악성코드 분석

    -> 악성코드는 소스 코드 없이 실행 파일만 배포되므로, 리버싱 기술로 악성코드를 분석해야함

3.3 환경 구축

  • Visual Studio Express 설치

    p. 137 ~ 144 참고

  • 올리디버거 설치

    p. 144~ 147 참고

  • 계산기

    -> 리버싱할 때 진수 변환을 많이 하므로 윈도우 계산기 사용

3.4 기초 지식

※ 여기서 설명하는 리버싱이 전제하는 모든 프로세서는 대부분의 컴퓨터에서 사용하는 IA-32(intel Architecture, 32-bit)(=x 86 - 32)임

1. 중앙연산 처리 장치

  • CPU

    • 역할: 외부로부터 명령어를 입력받아 해석하고 연산해서 실행
  • 저장장치

    • 레지스터: 임시 기억 장치로, 제일 먼저 각종 정보 저장
    • 메모리(= RAM): 주기억 장치로, 레지스터만으로는 저장할 수 없는 많은 양의 정보를 저장 * RAM( Random-Access Memory ): 전원이 공급되지 않으면 저장된 정보가 지워지는 휘발성 메모리 * 하드디스크: 전원이 공급되지 않아도 저장된 정보를 계속 유지하는 비휘발성 메모리

    CPU에 더 가까운 저장장치: 레지스터> 메모리> 하드디스크

    속도 빠름 & 용량 작음: 레지스터> 메모리 > 하드디스크 image

2. 레지스터

  • 종류:

    8개의 32비트 범용 레지스터(General Register)6개의 16비트 세그먼트 레지스터(Segment Register), 32비트 EGLAGS 레지스터(Program status and control Register), 32비트 EIP(Extended Instruction Pointer) 레지스터가 있음

    image

  • 범용 레지스터: 16비트나 8비트로 나뉨

    image

    • 가장 많이 사용되는 용도의 레지스터

      (다른 용도로도 사용가능함)

      EAX(Extended Accumulatorregister) 함수의 리턴값을 저장하거나 산술 연산에 사용
      EBX(Extended Base Register) 특정 주소를 지정
      ECX(Extended Counter Register) 반복적인 명령어 수행시 횟수 저장
      EDX(Extended Data Register) 큰 수의 곱셈, 나눗셈 등의 연산 시 EAX 레지스터와 함께 사용
      ESI(Extended Source Index) 문자열 복사, 비교시 소스 문자열 주소 저장
      EDI(Extended Destination Index) 문자열 복사, 비교 시 목적지 문자열 주소 저장
      ESP(Extended Stack Pointer) 명령어 수행 시 스택의 위치 저장
      EBP(Extended Base Pointer) 함수 인자, 스택 변수에 접근
  • 세그먼트 레지스터: 메모리에 저장되어 있는 특정 세그먼트

    CS 레지스터 코드 세그먼트
    SS 레지스터 스택 세그먼트
    DS, ES, FS, GS 레지스터 데이터 세그먼트
    EFLAGS 레지스터 프로그램의 현재 상태나 분기문의 조건 검사에 사용되는 플래그를 모은 것
    EIP 레지스터 CPU가 다음에 수행해야 할 명령어를 담은 메모리 주소 저장

3. 메모리 구조

  1. 코드 세그먼트

    : 컴퓨터가 수행할 수 있는 명령어들이 저장되어 있는 메모리

    -> 일반적인 프로그램에서 코드 세그먼트에 저장되어 있는 내용은 변경 X

    ​ ex) C언어 - 분기문, 반복문, 함수 호출 등

    -> but, 패킹(Packing), 가상머신(Virtual Machine)등이 적용된 프로그램에서는 내용 변경

  2. 스택 세그먼트

    : 현재 수행되고 있는 프로그램의 지역 변수와 함수 호출 인자를 저장하는 메모리 영역

    • 읽기 & 쓰기: PUSH & POP

    • 현재 스택 위치 : ESP 레지스터

  3. 데이터 세그먼트

    전역 변수와 힙(Heap)을 저장하는 메모리 영역

    • 힙(Heap): 프로그램 실행 도중에 할당, 해제하며 사용하는 동적 메모리 공간

      -> 필요한 만큼 메모리 할당하지만, 메모리에 한계가 있어 쓰지 않는 메모리는 직접 해제해야함

      스택(stack): 컴파일 단계에서 미리 프로그램이 사용할 메모리 크기 계산하여 변수의 배치가 이루어지는 정적 메모리

4. 어셈블리어 vs. C언어

  • 어셈블리어(Assembly Language)

    기계어 코드를 사람이 인식할 수 있도록 일대일(1:1) 대응시키는 컴퓨터의 로우 레벨 언어

    • 특징:
      • 프로세서에 따라 기계어가 달라지며, 기계어와 일대일 대응되는 어셈블리어도 달라짐
      • 프로세서마다 지원하는 명령어 종류와 개수는 제각각이며 레지스터 크기와 개수, 데이터형의 표현도 각각 다름
  • C언어

    프로세서가 다르더라도 같은 소스 코드를 해당 프로세서에서 컴파일해 사용할 수 있는 하이 레벨 언어

    -> 리눅스, 윈도우 등 거의 대부분의 운영체제도 C언어로 만들어짐

5. 컴파일, 디컴파일

  • 컴파일

    -> 바이너리 데이터로 이뤄진 실행파일 만들 때 거치는 과정

    • 과정:

      1. 컴파일러로 입력 파일을 어셈블리 파일로 만드는 컴파일 실행

      2. 어셈블리 파일은 다시 어셈블러에 의해 오브젝트 파일 생성

      3. 오브젝트 파일은 링커에 의해 각종 라이브러리 함수와 연결되어 최종 실행 파일 완성

      ※위 과정은 C 언어로 작성된 소스코드를 말함

      ​ -> 소스코드는 #Include, #define과 같은 지시자를 처리하는 전처리기과정 진행 & 컴파일러, 어셈블러, 링커를 거쳐 실행 파일 만듦

      image

  • 디컴파일

    -> 디버거 툴인 올리디버거로 실행파일의 기계어코드를 어셈블리어로 표현

6. 바이트 오더

  • 바이트 오더

    컴퓨터에서 데이터가 바이트 단위로 메모리에 저장된느 순서

    • 빅 인디안

      사람이 숫자를 쓰는 방식과 같이 큰 단위의 바이트가 앞에 옴

      -> 보기 편함

    • 리틀인디안

      작은 단위의 바이트가 앞에 옴

      -> 하위 바이트만 사용할 때 별도의 계산이 필요 없음

      -> 설계가 조금 더 단순해서 속도가 빠름

      (현재의 프로세서는 동시에 여러 바이트를 읽어들여 연산하는 구조이므로 두 방식에 차이 없음)

      -> IA-32에서 사용하는 방식

    image

7. 디버깅

  • 디버깅:

    컴퓨터 프로그램의 버그를 찾아서 제거하는 일련의 과정

    • 올리디버거로 디버깅하기

      • 코드 영역

        -> 주소, 기계어, 어셈블리어로 나누어짐

        -> 분석해야할 명령어의 어셈블리어 표시

      • 레지스터 영역

        -> 명령어 실행 시 실시간으로 변하는 레지스터 확인 가능

      • 덤프 영역

        -> 특정 메모리 위치의 값을 16진수(Hex), 아스키(ACII), 유니코드(UNICODE)로 표시

      • 스택 영역

        -> ESP 레지스터가 가리키는 스택 위치를 실시간으로 표시

    image