리버싱 학습

Simcurity·2023년 5월 6일
0

리버싱

목록 보기
1/9

안녕하세요 오늘부터 리버싱에 대해 학습해보겠습니다.
제가 학습할 책은 '리버싱 입문' (저자 : 조성문)입니다.

1. 프로그램 구조

윈도우에서 실행 가능한 파일 : PE(Portable Executable)파일 ---> exe, dll, ocx 등
PE파일의 구조 : 헤더 + 바디
헤더에는 프로그램을 실행하는데 필요한 기본정보와 파일을 메모리 어디에 저장할지에 대한 정보
바디에는 코드와 데이터가 들어있습니다.
프로그램 실행 시 운영체제에 있는 Loader(로더)는 PE헤더의 정보를 분석하여 PE바디에 있는 코드와 데이터를 메모리에 배치합니다.
이 때 배치되는 메모리는 다음과 같습니다.

code : 프로그램의 코드가 들어가는 코드 영역
data : 정적 변수와 전역 변수가 들어가는 데이터 영역
stack : 함수 호출 시 사용되는 매개 변수와 지역 변수가 저장되는 스택 영역
heap : 동적 메모리 할당에 사용되는 히프 영역

엔트리 포인트(Entry Point) : PE파일 실행이 시작되는 주소
프로그램의 명령을 실행하는 것은 CPU에 있는 제어장치와 연산장치입니다.
제어장치와 연산장치가 프로그램을 실행하려면 데이터는 모두 레지스터에 있어야 합니다.
그러므로, 메모리에 있는 데이터를 레지스터로 복사하는 과정이 필요합니다.

컨텍스트 스위칭(Context Switching)이란 CPU 사용이 끝나면 다른 프로그램에게 CPU 사용 권한을 넘겨주는데 자신이 사용하고 있던 모든 레지스터를 메모리 영역으로 복사해 놓는 것.

2. 레지스터

레지스터란 CPU에서 사용하는 고속의 기억장치입니다.
CPU는 연산을 위해 메모리에 있는 데이터를 CPU내부에 레지스터로 가지고 옵니다.
인텔 x86 CPU기준으로 범용 레지스터는 다음과 같습니다.

EAX(Extended Accumulator Register) : 곱셈과 나눗셈 명령에서 사용되고 함수의 반환 값을 저장합니다.
EBX(Extended Base Register) : ESI나 EDI와 결합해 인덱스에 사용됩니다.
ECX(Extended Counter Register) : 반복 명령어를 사용할 때 반복 카운터를 저장합니다.
EDX(Extended Data Index) : EAX와 같이 사용되며 부호 확장 명령 등에 활용됩니다.
ESI(Extednded Source Index) : 데이터 복사하거나 조작할 때 소스 데이터 주소가 저장됩니다.
EDI(Extended Destination Index) : 복사 작업을 할 때 목적지 주소가 저장됩니다.
보통 ESI레지스터가 가리키는 주소의 데이터가 복사됩니다.
EBP(Extended Base Pointer) : 하나의 스택 프레임의 시작 주소가 저장됩니다. 현재 사용되는 스택 프레임의 값으로 현재 함수가 끝나지 않는 이상 이 값은 변하지 않습니다.
ESP(Extended Stack Pointer) : 하나의 스택 프레임의 끝 지점 주소가 저장됩니다. push, pop 연산에 의해 값이 4바이트씩 변합니다.
EIP(Extended Instruction Pointer) : 다음에 실행할 명령어가 저장된 메모리 주소가 저장됩니다. 현재 명령어 실행 후 EIP 레지스터에 저장된 주소의 명령을 실행합니다.

RAX(64bit) -> EAX(32bit) -> AX(16bit) -> AH(high 8bit) -> AL(low 8bit)

3. 스택과 스택 프레임

3-1) 스택

스택은 자료구조 중 하나로 LIFO(Last In First Out) 방식입니다.
push연산으로 데이터를 집어 넣고 pop연산으로 데이터를 꺼냅니다.
그러므로 데이터가 한 방향으로만 쌓이게 됩니다.

PUSH를 하면 스택의 주소는 4바이트만큼 감소하면서 데이터가 스택으로 들어갑니다.
반대로 POP을 하면 스택의 주소는 4바이트만큼 증가하면서 데이터가 꺼내집니다.

스택은 주소가 감소하면 데이터가 쌓이는데 이유는 스택 구조위의 데이터는 시스템을 운영하는데 중요한 역할을 하는 데이터이기 때문에 접근하지 못하게하기위해 이러한 방식으로 설계된 것입니다.

3-2) 스택 프레임

스택 프레임이란 함수(서브루틴)가 가지는 자신만의 스택 영역입니다.
함수가 호출될 때 자신의 스택 프레임을 생성하고 함수 종료 시 복귀 주소로 돌아갈 때 스택 프레임은 소멸됩니다. (프롤로그 -> 에필로그)

  1. 함수 호출 시 복귀 주소를 스택에 PUSH
  2. 이전 함수의 EBP를 PUSH
  3. 호출 함수의 EBP에 POP

4. PE(Portable Executable)파일

보통 C언어, JAVA 등 고급언어를 이용해 코딩을 한다. 그러나 운영체제는 이러한 고급언어를 이해할 수 없습니다.
이를 이해하기 위해선 컴파일러를 통해 기계어 구조로 변경을 해주어야합니다.
그리고 로더를 통해 메모리로 이동시켜 이해합니다.

PE 파일 종류
실행 계열 : EXE, SCR
라이브러리 계열 : DLL, OCX, CPL, DRV
드라이버 계열 : SYS, VXD
오브젝트 파일 계열 : DBJ

4-1) PE 파일 구조

PE 파일은 PE 헤더, 섹션 헤더, 섹션 데이터로 구성됩니다.
모든 윈도우 PE 파일은 공통으로 PE 헤더를 가지고 있습니다.

공통 헤더
IMAGE_DOS_HEADER
MS-DOS Stub Program
IMAGE_NT_HEADERS (Signature, IMAGE_FILE_HEADER, IMAGE_OPTIONAL_HEADER)

섹션 헤더는 각 PE 파일마다 최소 1개 이상 씩 있고 내용과 형태가 다릅니다.
마찬가지로 섹션 데이터 또한 PE 파일마다 최소 1개이상의 영역이 있고 내용과 형태가 다릅니다.

IMAGE_OPTIONAL_HEADER 구조체는 뒤에 중요한 역할을 하는 16개의 IMAGE_DATA_DIRECTORY가 따라옵니다.
중요한 것들을 살펴보겠습니다.

1. Image Base

Image Base는 메모리에 PE파일이 저장되는 시작 주소입니다. PE 파일에서 확인할 수 있는 RVA(Relative Virtual Address)는 메모리에 로딩되면서 Image Base와 합산된 주소 VA(Virtual Address)에 저장됩니다.

2. Address of Entry Point

프로그램 실행에 대한 제어권이 커널 영역에서 코드 영역으로 처음 넘어오는 주소인 엔트리 포인트를 가리킵니다.

3. Base of Code

코드 영역이 시작되는 주소(RVA)를 가리킵니다.

4-2) 주소 형식

1. pFile

PE 파일 내부에서의 오프셋 값을 의미합니다. PE 파일이 물리적으로 하드디스크에 저장되었을 때 의미 있는 값.

2. RVA (Relative Virtual Address)

PE 파일 메모리 로드 시 저장되는 상대 주소로 특정 값을 기준으로 얼마나 떨어져 있는지를 나타냅니다.

3. VA (Virtual Address)

가상 메모리상에서 저장되는 실제 주소를 나타냅니다.

4-3) IAT (Import Address Table)

윈도우에서는 DLL(Dynamic Linking Library)을 사용합니다. 과거에는 프로그램이 컴파일 시점에 필요한 모든 기능을 실행 파일 안에 넣었지만, 기술이 발전함에 따라 더 다양한 기능과 부피가 커져서 이러한 방식은 비효율적이 되었습니다. 그래서 DLL을 사용하게 되었고 PE파일에는 DLL의 사용을 지원하는 IAT 정보가 포함되어 있습니다.

IAT란 PE 파일 안에 어떤 라이브러리의 어떤 함수를 가져다 쓰는지 기록해 놓은 정보입니다.
PHP의 경우 require함수와 비슷하다고 보면 될 것 같습니다.
로더는 PE파일을 메모리에 로드할 때 IAT에 기록된 API이름을 참조해 실제 주소를 찾아 IAT안에 API를 가리키는 주소를 적어 놓습니다.
라이브러리 참조 시 IAT 내부에 있는 함수 주소를 사용합니다.

5. 정리

범용 레지스터 종류
EAX : 곱셈 나눗셈에서 사용, 함수의 반환 값 저장
EBX : ESI나 EDI와 결합해 인덱스에 사용
ECX : 반복 명령 사용 시 반복 카운터 저장
EDX : EAX와 같이 사용되고 부호 확장 명령 등에 활용
ESI : 데이터 복서하거나 조작 시 소스 데이터 주소 저장
EDI : 복사 작업 시 목적지 주소 저장
EBP : 현재 함수의 스택 프레임 포인터
ESP : 현재 연산 위치 push, pop에 의해 감소하거나 증가
EIP : 다음 명령의 주소 값을 저장해 놓

PE파일 구조 : PE헤더, 섹션 헤더, 섹션 데이터
PE헤더의 종류 : IMAGE_DOS_HEADER, MS-DOS Stub Program, IMAGE_NT_HEADER
IMAGE_NT_HEADER -----> Signature, IMAGE_FILE_HEADER, IMAGE_OPTIONAL_HEADER
IMAGE_OPTIONAL_HEADER ---> 따라오는 16가지의 디렉터리 중 중요 디렉터리
Image Base : RVA와 합산하여 VA를 만듬
Address of Entry Point : 제어권이 커널에서 코드로 넘어올 때의 주소 엔트리 포인트 가리킴
Base of Code : 코드 영역의 RVA를 가리킴

PE파일의 종류
실행 계열 : EXE, SCR
라이브러리 계열 : DLL, OCX, CPL, DRV
드라이브 계열 : SYS, VXD
오브젝트 파일 계열 : DBJ

주소 형식
pFile : 물리적으로 PE파일이 하드디스크에 저장 시 의미 있는 값으로 PE파일 내부에서의 오프셋 값
RVA : 특정 값에서 상대적 위치
VA : 가상 메모리 상에서 실제 위치

IAT(Import Address Table)이란 원래는 DLL을 안썻는데 기술 발전에 의해 DLL을 쓰게 됨
그래서 DLL을 참조한다는 것을 기록해 놓은 정보로 로더가 메모리에 로드할 때 해당 api이름을 주소로 변환시킴 라이브러리 참조 시 IAT 내부의 해당 주소 사용

0개의 댓글