1. 패킹(packing)
- PE 파일을 압축 푸는 과정 없이 바로 프로그램 실행 가능한 형태로 파일을 압축 시키는 것
[종류]
Compressor
- 파일의 크기를 줄이는 것이 목적
- 배포 쉽게 하고, 악성코드 실행 속도를 빠르게 하는 용도로 사용
- UPX, FSG가 대표적
Protectors
- 실행파일을 보호하는 것이 목적 (압축+보호)
- 크기는 증가할 수 있음
- 언패킹, 코드 분석, 난독화 어려움
언패킹: 패킹된 소스코드를 보기 위해 암호화나 압축을 푸는 행위
Exeinfo PE : 패킹 여부를 확인할 수 있는 프로그램
notepad.exe 파일을 확인해봤을 때 이와 같이 Not packed, 패킹되지 않은 것을 알 수 있다.
upx를 이용하여 notepad.exe파일 패킹을 진행했다. upx 파일에 패킹하려는 파일을 복사해야 한다.
upx: notepad.exe: CantPackException: GUARD_CF enabled PE files are not supported (use --force to disable)
이와 같은 오류가 발생했다.
해당 파일이 Control Flow Guard (CFG) 기능을 활성화하고 있기 때문이다.
이 기능은 Windows에서 보안 강화를 위해 사용하는 것으로, 주로 버퍼 오버플로 같은 공격을 방지하는 데 사용된다.
제한을 무시하고 패킹하는 --force 옵션을 추가하여 패킹하였다.
패킹된 파일은 기존 파일에 덮어쓰는 방식으로 저장된다.
패킹된 notepad.exe 파일을 올려보면 upx로 패킹되음을 알 수 있다.
언패킹은 -d 옵션을 붙이면 된다.
2. 문자열 확인
문자열 확인은 분석대상 파일 내부에 존재하는 string 값을 확인하는 것이다.
Bintext라는 프로그램을 이용하여 확인했다.
find를 통해서 원하는 문자열을 찾을 수 있다.
dll 파일, API 함수 등을 확인할 수 있다.
dll(Dynamic Link Library)파일: 동적링크라고 하며, 실행 파일에서 해당 라이브러리의 기능을 사용 시에만, 라이브러리 파일을 참조하여 특정 기능을 호출한다.
- dll 파일의 기능을 확인하여 분석 대상 파일이 어떤 기능을 수행하는지 유추해볼 수 있다.
API(Application Programming Interface): 운영체제가 응용 프로그램을 위해 제공하는 함수의 집합을 말한다.
- API 함수를 확인하면 해당 파일의 행위를 파악하는데 용이하다.
3. PE 구조 분석
PE(Portable Excutable) 파일: PE 포맷에 따라 윈도우 운영체제 상에서 실행할 수 있는 프로그램
- PE 파일 헤더에는 실행파일을 실행하기 위한 각종 정보들이 기록되어 있다.
- PE 파일을 실행하게 되면, PE 정보부터 읽어들여 바이너리를 메모리에 올리기 위한 데이터 설정 작업을 하게 된다.
[PE 파일 구조를 분석하는 이유]
- 파일이 실행되기 위한 모든 정보를 PE 구조 분석을 통해 확인할 수 있다.
- 분석 대상 파일이 사용하는 API 함수나 파일이 로딩되는 메모리 주소를 파악할 수 있다.
[PE 파일 종류]
- 실행 파일 계열 : exe, scr
- 라이브러리 계열 : dll, ocx, cpl, drv
- 드라이버 계열 : sys, vxd
- 오브젝트 파일 계열 : obj
오브젝트 파일을 제외한 대부분의 확장자 파일은 실행이 가능하다고 볼 수 있음
NULL Padding: 처리상의 효율성을 위해 특정 단위로 간격을 맞추며 빈공간을 채우는 것
Offset : 파일의 첫 바이트부터의 거리
VA(Virtual Address) : 프로세스 가상 메모리의 절대 주소
RVA(Relative Virtual Address) : 기준(ImageBase)으로부터의 상대주소
RVA + ImageBase = VA
PE Header에는 많은 정보들이 RVA형태로 존재한다.
- PE 파일이 가상 메모리의 특정 위치에 로딩될 때 해당 위치에 다른 PE파일이 로딩되어 있을 수 있으므로 Relocation 과정을 통해 빈 공간에 로딩되어야 한다.
- VA(절대주소)로 되어있다면 정상적인 액세스가 이뤄지지 않지만 RVA(상대주소)로 되어있다면 Relocation이 발생해도 ImageBase에 대한 상대주소는 변하지 않기 때문에 문제 없이 액세스가 가능하다.
[PE Header 종류]
DOS header
- DOS 파일에 대한 호환성을 위하여 만든다.
- 구조체로는 'IMAGE_DOS_HEADER'가 존재한다.
- 매직넘버를 표현하는 'e_magic'등을 포함하고 있다.
e_magic : DOS signature(매직넘버)로 PE파일을 나타내는 첫 2바이트, MZ(5A4D로 고정 값)
각 파일은 고유의 signature(매직넘버)를 가진다.
DOS stub
- DOS 환경에서 실행되는 코드를 가진 영역
- 코드와 데이터의 혼합으로 이루어져 있으며, DOS stub가 없어도 파일 실행에는 문제가 없다.
NT header
- 파일 실행에 필요한 정보가 저장되어 있다.
- DOS header 중 e_lfanew에 저장된 주소 값이 이 부분을 가리킨다.
- DOS 파일에 대한 호환성을 위하여 만든다.
-Signature, File Header, Optional Header로 구성되어 있다.
e_lfanew : IMAGE_NT_HEADER의 시작 Offset 값을 가진다.
- e_flanew에 설정된 주소를 확인하면 PE로 시작하는 것을 확인할 수 있으며, 한번 더 시작점을 알려준다.
Section header
- 각 Secition의 헤더들이 존재하며, Section들은 메타데이터를 저장하고 메모리에 로드될 때 필요한 정보를 포함하고 있다.
- 섹션의 크기, 시작 주소, Offset, 속성 등을 담고 있다.
PE Body에는 실제 세션들이 존재, 유형별로 파일에 필요한 정보를 담고 있다.
[Section 유형]
유형 | 종류 | 설명 |
Code | .text | 프로그램 실행 코드를 담고 있는 Section |
DOS stub | .data | 읽고 쓰기가 가능한 데이터로 초기화된 전역 및 정적 변수 등이 위치함 |
.rdata | 읽기 전용 데이터로 무낮열 상수, 상수형 변수 등이 위치함 | |
.bss | 초기화되지 않은 전역변수를 담고 있는 Section | |
Import API | .idata | 임포트할 DLL과 API 함수 등에 대한 정보를 담고 있음 |
.didat | Delay-loading import DLL에 대한 정보를 담고 있음 | |
Export API | .edata | Export할 API 정보를 담고 있으며, 주로 DLL에서 사용함 |
Resource | .rsrc | 리소스에 관련된 데이터를 담고 있는 섹션으로 아이콘 커서 등의 정보를 담고 있음 |
재배치 정보 | .reloc | 기본 재배치 정보를 담고 있는 Section |
TLS | .tls | 스레드 지역 저장소 |
Debugging | .debug$p | 미리 컴파일된 헤더 사용 시에만 사용 |
PEview 프로그램을 이용하여 notepad.exe.파일의 PE 구조를 살펴보았다.
SECTION.text 위로는 PE header이고 SECTION.text부터 PE Body이다.
[PE 구조 데이터 종류 확인]
MSDN 사이트 통해 확인 또는 Visual Studio 통해 확인이 가능하다.
후자의 방법으로 확인했다.
Visual studio에서 c언어 소스파일 생성 -> #include<winnt.h> 입력 -> 우클릭 -> 문서로 이동 클릭
을 하면 64bit 기반 PE 파일 구조체를 확인할 수 있다.
[IMAGE_DOS_HEADER]
e_magic
- Signature 데이터, 파일의 시그니처 값을 담고 있다.
- 매직코드나 헤더 시그니처라고 부르기도 한다.
- PE파일의 구조를 나타낸다.
- 대표적으로 실행파일.exe은 4D5A(MZ)
notepad.exe Data값이 5A4D라고 되어 있는데 리틀 엔디안으로 표기된 것이라 4D5A 값을 가진다.
즉 .exe파일이다.
e_lfanew
- IMAGE_NT_HEADERS 의 시작 주소를 저장하는 데이터
[MS_DOS Stub Program]
- DOS 환경에서 실행되었을 때 실행할 내용을 저장하는 데이터
[IMAGE_NT_HEADERS]
- IMAGE_NT_HEADERS 값이 제대로 세팅되어 있지 않으면 파일이 정상적으로 실행되지 않는다.
- Signature, FileHeader, OptionalHeader 3가지 항목을 포함하고 있다.
구조체 | 설명 |
Signature | ASCII 코드로 PE라는 문자열을 나타내며 PE구조 파일이라는 것을 알림 |
FileHeader | 동작하는 CPU, 섹션의 개수, 타임스탬프 등의 정보를 저장 |
OptionalHeader | 파일 실행에 필요한 주요 정보를 저장 |
Signature
notepad.exe Signature를 보면 Data 값이 4550이다.
이 또한 리틀 엔디안으로 역수로 취하면 50 45이며 PE 파일의 헥사값이 50 45이다.
따라서 notepad.exe 파일이 PE 파일임을 알 수 있다.
FileHeader
- 파일의 개략적인 속성에 대한 7가지 데이터가 존재
Machine - 파일이 동작하는 CPU 종류에 대한 넘버가 포함되어 있다.
데이터 | 설명 |
Machine | 파일이 동작하는 CPU 종류에 대한 넘버가 포함되어 있음 |
Bumber of Sections | 파일이 가진 섹션의 개수 |
Time Date Stamp | 파일이 생성된 날짜, 변조가 가능하므로 무조건 신뢰 x |
Pointer to Symbol Table | COFF 심볼 파일의 오프셋 값을 저장 -> 심볼테이블 사용 X, 모두 0 값으로 설정되어야함 |
Number of Symbols | 심볼 테이블에 있는 엔트리 개수 저장 -> 심볼테이블 사용 X, 모두 0 값으로 설정되어야함 |
Size of Optional Header | Option Header의 크기를 저장하는 곳으로 운영체제에 따라 차이가 있다. 32Bit PE 파일-> 0xE0 / 64Bit PE 파일 -> 0xF0 / 오브젝트(OBJ) 파일 -> 0x00 |
Characteristics | 현재 파일의 형식을 알 수 있는 데이터가 포함되어 있음 Characteristics 안에 저장되어 있는 값은 Bit OR 연산을 수행하여 저장됨 |
COFF(Common Object File Format): 공동 개체 일로 Windows NT 실행 파일 (이미지) 파일 및 개체 파일에 대한 특수 서식을 말한다.
notepad.exe 머신값은 86 64로 머신 넘버값 매칭해보면 AMD64임을 알 수 있다.
OptionalHeader
- 파일에 관한 중요한 정보들을 저장하는 영역으로 파일 실행에 있어 필수적인 값들
항목 | 설명 |
Magic | 구조체의 Bit 단위, 32Bit 구조체는 0x10B, 64Bit는 0x20B |
Size Of Code | 코드 영역 (.text Section)의 크기 |
Address of Entry Point | 프로그램이 시작되는코드의 주소를 RVA 값으로 저장 |
Base of Code | 코드 영역이 시작되는 상대 주소(RVA) |
Image Base | PE 파일이 메모리에 로드되는 시작 주소 |
Section Alignment | 메모리에서 섹션의 최소 단위 |
File Alignment | 파일에서 섹션의 최소 단위 |
Size of Image | PE 파일이 메모리에 로딩될 때의 전체 크기 |
Size of Header | 모든 헤더의 크기 |
Sub system | 1(System Driver), 2(GUI), 3(CUI) |
Number of RvaAndSizes | Data Directory의 구조체 멤버의 개수 |
Data Dirctory | PE파일의 중요 역할을 하는 개체의 위치,크기 |
[SECTION HEADER}
- 각각의 세션에 대한 정보 포함 -> 파일 Section 수와 동일하게 구성되어 있음
<중요 멤버>
항목 | 설명 |
VirtualSize | 메모리에서 섹션이 차지하는 크기 |
VirtualAddress | 메모리에서 섹션의 시작 주소(RVA) |
Size of RawData | 파일에서 섹션이 차지하는 크기 |
Pointer to Raw Data | 파일에서 섹션의 시작 위치 |
Characteristicss | 섹션의 특징 (bit OR 연산 수행값) |