본문 바로가기

2. Reversing (리버싱)

[2024.04.06] 리버씽씽카 4주차 활동

https://www.youtube.com/playlist?list=PLY12b4RRLcSdsxgVvTW3mnNzMjVrd8JhO

 

리버싱 강의

리버싱에 대해 공부합시다.

www.youtube.com

위의 강의를 11-13강까지를 수강하여 학습한 다음 어려운 내용에 관해서 질의 응답하는 시간을 가졌다.


<11강 DOS stub>

▷DOS stub

-DOS header와 달리 DOS stub은 옵션이다.

-MS-Dos(마이크로소프트 사에서 만든 최초의 운영체제)에서만 실행되는 코드이므로 Window OS에서는 실행X

-이 특성을 잘 이용한다면 윈도우와 도스 두 개 다 실행 가능한 파일을 만들 수 있다.

치트엔진으로 파일 분석하기

DOS header에 있는 구조체의 첫 번째 맥락 'MZ'이다. 그러므로 문자열 MZ를 검색하여 빠르게 DOS header의 위치를 찾는다.

DOS stub의 hex값 발견

4D 5A 발견

밑줄 친 50 45 PE는 NT header의 첫번째 줄 시작 부분이다.

⇒ 그러므로 현재 이 파일에는 DOS stub이 없음을 확인할 수 있다.

 

※그렇다면 DOS stub이 있는 경우의 hex 값은 어떻게 될까?

노란색으로 밑줄친 부분이 DOS stub의 시작 값이다.


<12강 NT Header-FileHeader>

▷ NT Header

IMAGE_NT_HEADERS라는 구조체로 구성되어 있다.

typedef struct _IMAGE_NT_HEADERS {
  DWORD                   Signature;
  IMAGE_FILE_HEADER       FileHeader;
  IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

 

1. DWORD Signature;

-PE 값을 가짐

 

2.IMAGE_FILE_HEADER  FileHeader;

 

▶machine : CPU 호환칩의 고유한 번호를 저장

4C 01 → 01 4C(리틀 엔디언 방식)

(참고: 014C는 32bit intel 호환칩에서 사용되는 값)

 

▶numberofsections:

PE파일은 코드, 데이터, 리소스 등이 각각 섹션(부분)에 나누어 저장되는데 PE파일에서 생성 된 개수를 알려준다.

이 값은 무조건 0보다 커야 한다.

ex) NumberOfSections=1; 원래 Sections의 개수가 3개라면 오류 발생→ 섹션의 개수와 실제 섹션이 다르면 실행 X

 

▶SizeOfOptionalHeader:

IMAGE_OPTIONAL_HEADER32 OptionalHeader; 의 크기를 나타냄.

💡 C언어에서 구조체를 생성하면서 구조체의 크기를 이미 크기를 정한 상태로 생성하는데 굳이 SizeOfOptionalHeader를 생성해서 크기를 알려주는 이유는? 
→ 64bit를 사용 시 값이 달라지기 때문이다.

 

Characteristics :

파일 속성을 나타내는 값이다. 여기서 파일 속성이란 실행 가능한 형태(executable) 혹은 DLL 파일인지 정보를 저장한다.(Bit OR 형태로 저장)

  • *Characteristics 값이 없는 파일이 존재한다-obj, res.dll
  • 참고) TimeDateStamp는 파일이 빌드된 시간을 저장

<13강 NT Header - OptionalHeader>

typedef struct _IMAGE_NT_HEADERS {
  DWORD                   Signature;
  IMAGE_FILE_HEADER       FileHeader;
  IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

 

Optionalheader의 구조체는 IMAGE_OPTIONAL_HEADER32

typedef struct _IMAGE_OPTIONAL_HEADER {
WORD                 Magic;
BYTE                 MajorLinkerVersion;
BYTE                 MinorLinkerVersion;
DWORD                SizeOfCode;
DWORD                SizeOfInitializedData;
DWORD                SizeOfUninitializedData;
DWORD                AddressOfEntryPoint;
DWORD                BaseOfCode;
DWORD                BaseOfData;
DWORD                ImageBase;
DWORD                SectionAlignment;
DWORD                FileAlignment;
WORD                 MajorOperatingSystemVersion;
WORD                 MinorOperatingSystemVersion;
WORD                 MajorImageVersion;
WORD                 MinorImageVersion;
WORD                 MajorSubsystemVersion;
WORD                 MinorSubsystemVersion;
DWORD                Win32VersionValue;
DWORD                SizeOfImage;
DWORD                SizeOfHeaders;
DWORD                CheckSum;
WORD                 Subsystem;
WORD                 DllCharacteristics;
DWORD                SizeOfStackReserve;
DWORD                SizeOfStackCommit;
DWORD                SizeOfHeapReserve;
DWORD                SizeOfHeapCommit;
DWORD                LoaderFlags;
DWORD                NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

 

▶Magic

구조체의 크기를 나타낸다.

IMAGE_OPTIONAL_HEADER32 10B

IMAGE_OPTIONAL_HEADER64 20B

 

AddressOfEntryPoint

EP(Entry Point)의 RVA(상대주소) 값을 가지고 있다. 프로그램의 최초로 실행되는 코드에 시작주소로 매우 중요하다.

 

ImageBase

프로세스의 가상 메모리는 0~FFFFFF 범위이다.

(32bit) ImageBase는 위의 광활한 메모리에서 PE파일이 로드되는 시작주소를 나타낸다.

PE로더는 PE파일을 실행하기 위해 프로세스를 생성하고 파일을 메모리에 로드한 후 EIP[32bit](RIP[64bit]) Reg 값을 ImageBase+AddressOfEntryPoint를 Point값으로 세팅한다.

*EIP: CPU가 다음 실행할 명령어

*EIP: CPU가 다음 실행할 명령어

💡 로드 VS 매핑
매핑은 간단히 말해서 메모리에 파일을 적재하는 것 로드는 매핑을 실제로 하는 것

 

<Entry point와 ImageBase의 차이점>

ImageBase는 실행파일이 로드될 때 BaseAddress(기본주소)를 나타내는 값이다.

Entry point 실행파일이 시작될 때 실행되는 맨 처음 함수의 주소를 나타내는 값이다.

⇒ ImageBase와 Entry point는 모두 파일의 메모리에 로딩과 관련이 있지만 ImageBase는 실행파일의 기본주소를, Entry point는 실행파일 내의 시작 함수의 주소를 나타낸다.

*BaseAddress(기본주소): 기본주소에 오프셋을 더하면 절대주소를 획득 가능

 

▶SectionAlignment & FileAlignment

PE파일의 바디 부분은 섹션으로 나뉜다. 파일에서 섹션의 최소 단위를 나타내는 것이 FileAlignment이고 메모리에서 섹션의 최소 단위를 나타내는 것이 SectionAlignment이다.

 

▶ SizeOfImage

PE파일이 메모리에 로딩되었을 때 가상메모리 PE IMAGE가 차지하는 크기를 나타낸다. 일반적으로 파일의 크기와 메모리의 로딩된 파일의 크기는 다르다.

 

▶ SizeOfHeaders

PE파일의 전체 크기를 나타낸다.

 

▶ Subsystem

<sys>인지 dll or exe를 구별한다(=시스템 파일인지 아닌지를 구별)

 

▶NumberOfRvaAndSizes

IMAGE_OPTIONAL_HEADER32의 마지막 멤버인 DataDirectory의 배열의 개수를 나타낸다.

 

▶ DataDirectory

IMAGE_OPTIONAL_HEADER32의 배열