R136A1
[WEEK2] 어셈블리 명령어 / PE Header 본문
어셈블리 명령어
참고: 최은정교수님 윈도우즈보안과운영실습
1) 데이터 이동
값을 직접 레지스터로 대입
레지스터에서 레지스터로 옮기기
값을 직접 메모리로 대입하기
레지스터에서 메모리로 또는 그 반대로 옮기기
메모리에서 메모리로 옮기기
MOV: move operand1 <- operand2 값을 복사
MOV | EAX, EBX | // EBX 값을 EAX로 복사 |
EBP, ESP | // ESP 값을 EBP로 복사 | |
EAX, 42 | // 0x42를 EAX로 복사 | |
EAX, [4037C4] | // 메모리주소 4037C4에 있는 4바이트 값을 EAX로 복사 | |
EAX, [EBX] | // EBX가 명시한 메모리주소의 4바이트 값을 EAX로 복사 | |
EAX, [EBX+ESI*4] | // EBX+ESI*4 연산결과가 명시한 메모리 주소의 4바이트 값을 EAX로 복사 |
[메모리주소값]일 경우 그곳의 값,
메모리주소가 아닐 경우 [대괄호 안에 있는 값]이 명시한 곳(=메모리주소)에 있는 값을 가리킴
LEA: Load Effective Address, 주소값을 저장
- LEA EAX, [EBP+8] // EBP+8에 저장된 주소를 EAX에 저장
- MOV EAX, [EBP+8] // EBP+8가 명시한 메모리주소에 있는 값을 EAX에 복사
PUSH: 스택에 값을 저장 => 스택 4byte증가 == (현재 스택포인터) ESP 4byte 감소
// 스택에만 사용하는 opcode이므로 저장될 장소 operand 필요없음. 값 operand만
- PUSH EBP // 스택에 EBP 값을 push
- PUSH 5 // 스택에 5를 push
POP: 스택 끝에 저장된 값을 가져옴 => 스택 4byte감소 == (현재 스택포인터) ESP 4byte 증가
// 스택에만 사용하는 opcode이므로 가져올 장소 operand 필요없음. 저장될 operand만
POP EBP // 스택이 현재 가리키는 값(=끝 값)을 EBP에 저장
POP ECX // 스택이 현재 가리키는 값(=끝 값)을 ECX에 저장
2) 산술연산
명령 | 설명 | 사용예 |
ADD | 덧셈 | ADD ECX, 10 |
SUB | 뺄셈 | SUB ECX, 5 |
INC | operand 내용을 1 증가 | INC ECX |
DEC | operand 내용을 1 감소 | DEC ECX |
MUL/IMUL | EAX와 operand를 곱셈하여 EAX에 저장 | MUL EDX |
DIV/IDIV | EAX와 operand를 나누어 EAX에 저장 | DIV EDX |
NEG | operand 내용을 2의 보수(부호반전) | NEG EAX |
곱셈보다 덧셈이 빠르기 때문에 MUL 100 보다 ADD 100번 쓰는게 빠름
IMUL, IDIV는 부호가 있는 Integer 형태에서 사용됨
3) 비트연산
operand 2진수 형태로 연산한다
명령 | 설명 | 사용예 |
AND | 두 operand의 각 비트값을 AND 연산 (덧셈 느낌) (두 비트가 모두 1이면 1, 나머지는 0) |
|
OR | 두 operand의 각 비트값을 OR 연산 (곱셈 느낌) (두 비트가 하나라도 1이면 1, 나머지는 0) |
|
XOR | 두 operand의 각 비트값을 XOR 연산 (두 비트의 값이 같으면 0, 다르면 1) |
|
NOT | 비트 값을 반대 값(0→1, 1→0)으로 변경 | |
SHL | 왼쪽으로 쉬프트 연산, 최하위 비트는 0으로 채워지고, 기존 값은 CF 플래그 레지스터에 저장됨 |
|
SHR | 오른쪽으로 쉬프트 연산, 최하위 비트는 부호비트로 채워지고, 기존 값은 CF 플래그 레지스터에 저장됨 |
|
ROL/RCL | 왼쪽으로 쉬프트 연산, 최하위 비트는 최상위 비트로 채워짐 |
|
ROR/RCR | 오른쪽으로 쉬프트 연산, 최상위 비트는 최하위 비트로 채워짐 |
4) 제어
명령 | 설명 | 사용예 |
CMP | 두 operand 비교 (뺄셈 연산 후 플래그 설정) | CMP EAX, 0 (같으면 ZF 0set) |
TEST | 두 operand 비교 (AND 연산 후 플래그 설정) | TEST EAX, EAX (EAX가 0이면 ZF 1set) |
CALL | 해당되는 주소의 함수를 호출하여 수행 코드 위치로 옮김 |
CALL 00401990 (PUSH EIP, JMP 주소) |
INT | 오퍼랜드로 지정된 예외 처리 수행 - 중단점으로 디버그용 소프트웨어 트랩 - 오버플로우 상황 시 발생하는 트랩 - 하드웨어 디버그 트랩 |
INT 3 |
LEAVE | 함수에서 사용한 지역변수 스택을 비움 | LEAVE (서브루틴보다 C핵심 main에서...) |
RETN | 스택에 저장된 주소로 복귀 | RET |
NOP | 아무 동작도 수행하지 않음 (기계어코드 0x90) | NOP |
CMP, TEST는 주로 분기 명령어와 함께 쓰이며 NOP는 공격 코드를 삽입할 때 자주 쓰인다.
4) 분기
JMP: 무조건 EIP 주소값으로 점프
JE(Jump if Eqaul)
JNE(Jump if Not Equal)
JCC: CC(조건부코드) 값에 따라 해당 EIP 주소값으로 점프
E = Equal / Z = Zero / N = Not / L = Less / G = Greater
B = Bellow / A = Above / P, O, S = PF, OF, SF(플래그) / ECX = ECX(레지스터)
CC | 설명 | 플래그값 |
E/Z | 같은/0인 | ZF=1 |
NE/NZ | 다른/0이아닌 | ZF=0 |
L/NGE | 작은 (부호 있는 연산) | (SF^OF)=1 (SF != OF) |
G/NLE | 큰 (부호 있는 연산) | ((SF^OF) | ZF)=0 |
GE/NL | 크거나 같은 (부호 있는 연산) | (SF^OF)=0 |
LE/NG | 작거나 같은 (부호 있는 연산) | ((SF^OF) | ZF)=1 |
B/ANE | 작은 (부호 없는 연산) | CF=1 |
AE/NB | 크거나 같은 (부호 없는 연산) | CF=0 |
P/PE | PF가 1이면 (짝수) | PF=1 |
NP/PO | PF가 0이면 (홀수) | PF=0 |
O | OF가 1이면 | OF=1 |
S | SF가 1이면 | SF=1 |
ECXZ | ECX가 0이면 | ECX=0 |
5) 반복
REP: repeat, ECX 레지스터 지정횟수만큼 또는 ZF 플래그 조건에 맞을동안 반복
• REP : ECX가 0이 될 때까지 반복
• REPE, REPZ : ECX가 0이거나 ZF가 0일 때까지 반복
• REPNE, REPNZ : ECX가 0이 아니거나 ZF가 1일 때까지 반복
LOOP : LOOP 영역을 ECX 레지스터 지정 값만큼 반복
• LOOP 주소 : ECX 카운터 감소시키고, 카운터가 0이 아니면 주소로 이동함
• LOOPE 주소 : ECX 카운터 감소시키고, 카운터가 0이 아니고 ZF가 1 이면 주소로 이동함
• LOOPNE 주소 : ECX 카운터 감소시키고, 카운터가 0이 아니고 ZF가 0 이면 주소로 이동함
Stud_PE Editing을 사용하면 구조대로 이름이 뜸 + CFF_Explorer는 구조를 아예 분석해서 보여줌
PE 포맷
윈도우 운영 체제에서 사용되는, "실행 가능한 파일 형식"을 뜻함 (Linux에서는 ELF사용)
하나의 실행파일을 다양한 운영체제에서 실행할 수 있다는 의미로
"이식 가능한 실행파일" PE, Portable Executable 플랫폼에 독립적임
종류 | 확장자 |
실행파일 | exe |
드라이버 | sys, vxd |
라이브러리 | dll, ocx, cpl, drv |
오브젝트 | obj |
* exe는 직접적으로 실행 가능, obj를 제외한(?) 나머지 파일은 간접적으로 실행 가능
* 32비트 형태의 실행 파일 → PE or PE32
64비트 형태의 실행 파일 → PE+ or PE32+
윈도우 Loader가 "실행가능한 코드를 관리"하는 데 필요한 정보를 캡슐화한 데이터 구조체
PE를 구성하는 요소들은 각각 구조체의 형태를 갖고있음
※ 아래부터 쌓이는 형태임.
크게 Header 부분 / Section(=Body) 부분으로 나뉨
Section은 보통 4종류로 구성되어있음(Header에서 각 Section에 대한 정보를 포함)
섹션명 | 용도 |
.text | 코드, 실행, 읽기 속성을 지니며 컴파일 후의 결과가 이곳에 저장됩니다. 즉, 이 섹션은 실행되는 코드들이 들어가는 섹션 |
.data | 초기화, 읽기, 쓰기 속성을 지니며 초기화된 전역 변수를 가집니다. |
.rdata | 초기화, 읽기 속성을 지니며 문자열 상수나 const로 선언된 변수처럼 읽기만 가능한 읽기 전용 데이터 섹션 |
.bss | 비초기화, 읽기, 쓰기 속성을 지니며 초기화되지 않은 전역 변수의 섹션 |
.edata | 초기화, 읽기 속성을 지니며 EAT와 관련된 정보가 들어가 있는 섹션 |
.idata | 초기화, 읽기, 쓰기 속성을 지니며 IAT와 관련된 정보가 들어가 있는 섹션 |
.rsrc | 초기화, 읽기 속성을 지니며 리소스가 저장되는 섹션 |
각 섹션은 최소 1개 이상 존재하며 각 헤더 사이에는 정렬 규칙을 사용해 패딩 영역이 있음 (크기압축 대신 처리효율을 높임)
파일이 메모리에 적재된 후에는 헤더는 같은데 섹션의 크기 및 형태가 달라짐
파일은 offset, 메모리에서는 address로 통칭함.
PE파일 실행 과정
1) PE 파일 실행 명령
2) PE Header 정보를 메모리에 Mapping
- 실제 프로세스를 위한 메모리 할당
- 섹션 정보를 메모리에 복사
- Import 정보 처리
- 기준 재배치 처리
3) 실제 프로그램 코드로 분기
VA(Virtual Address): 가상 메모리 절대 구조
RVA(Relative Virtual Address): 가상 메모리 상대 주소
- PE파일이 메모리 상의 어떤 위치에 올라갈지 알 수 없음
- ImageBase라 불리는 기준점을 놓고, 그 곳으로부터 위치를 계산
- ImageBase가 바뀌더라도 정보 접근이 가능하도록 함
VA = ImageBase + RVA
PE파일 구조
PEview로 확인 가능
PE 헤더 (DOS Header ~ Section Table)
파일을 실행하는 데 있어 필요한 전반적인 정보들
ex) 파일을 실행할 때 맨 처음 시작해야 할 코드의 시작 부분에 대한 정보
프로그램이 구동 될 수 있는 플랫폼에 대한 정보
코드 및 데이터 영역의 위치와 크기, 운영체제, 초기 스택 크기 등
※ DWORD=4byte / WORD=2byte / LONG=4byte
1) DOS Header (4줄)
typedef struct _IMAGE_DOS_HEADER {
WORD e_magic; // 중요: DOS signature : 4D5A ("MZ")
WORD e_cblp;
WORD e_cp;
WORD e_crlc;
WORD e_cparhdr;
WORD e_minalloc;
WORD e_maxalloc;
WORD e_ss;
WORD e_sp;
WORD e_csum;
WORD e_ip;
WORD e_cs;
WORD e_lfarlc;
WORD e_ovno;
WORD e_res[4];
WORD e_oemid;
WORD e_oeminfo;
WORD e_res2[10];
LONG e_lfanew; // 중요: offset to NT header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
WORD 16+14 / LONG 1 =64 byte
1-1. e_magic: DOS signature, PE파일의 시그니처가 저장됨 맨 처음 2byte 고정 MZ (설계자 이름 Mark Zbikowski에서 따옴)
1-2. e_lfanew: NT Header의 시작 주소(=offset)를 저장함 맨 마지막 4byte, little endian
2) DOS Stub (e_lfanew값 주소 이전까지)
크기가 정해져있지 않음, DOS에서 돌아가는 16bit (=2 Byte) 어셈블리어로 작성되어 있음
32bit 이상 Windows에서는 실행되지 않고 무시되어 있든 없든 상관없음
*대부분 32bit로 프로그래밍된 프로그램이 16bit DOS mode에서 실행되었을 때
여기선 돌릴 수 없다는 text를 출력하는 용도로 사용함 (하위호환성)
3) NT Header (e_lfanew값 주소부터)
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; // PE Signature : fixed 50450000 ("PE"00)
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
3-1. Signature: NT code의 시작을 알림, PE파일임을 명시, 고정적으로 50 45 00 00 (ASCII PE00) 이 들어있음 맨 처음 4byte
3-2. FileHeader: 별도의 구조체(IMAGE_FILE_HEADER) - PE의 기본적인 내용 총 20 Byte
- 동작 가능한 cpu의 종류, 섹션의 개수, 빌드된 시간, OptionalHeader의 크기, 파일속성 ...
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
3-2-1. Machine: 동작 가능한 cpu의 종류를 상수로 담고 있음 2byte, little endian
#define IMAGE_FILE_MACHINE_(명칭) (값)
명칭 | 값 | 설명 |
UNKNOWN | 0 | |
I386 | 0x014c | Intel 386 |
R3000 | 0x0162 | MIPS little-endian, 0x160 big-endian |
R4000 | 0x0166 | MIPS little-endian |
R10000 | 0x0168 | MIPS little-endian |
WCEMIPSV2 | 0x0169 | MIPS little-endian WCE v2 |
ALPHA | 0x0184 | Alpha_AXP |
SH3 | 0x01a2 | SH3 little-endian |
SH3DSP | 0x01a3 | |
SH3E | 0x01a4 | SH3E little-endian |
SH4 | 0x01a6 | SH4 little-endian |
SH5 | 0x01a8 | SH5 |
ARM | 0x01c0 | ARM Little-Endian |
THUMB | 0x01c2 | |
AM33 | 0x01d3 | |
POWERPC | 0x01F0 | IBM PowerPC Little-Endian |
POWERPCFP | 0x01f1 | |
IA64 | 0x0200 | Intel 64 |
MIPS16 | 0x0266 | MIPS |
ALPHA64 | 0x0284 | ALPHA64 |
MIPSFPU | 0x0366 | MIPS |
MIPSFPU16 | 0x0466 | MIPS |
AXP64 | IMAGE_FILE_MACHINE_ALPHA64 | |
TRICORE | 0x0520 | Infineon |
CEF | 0x0cef | |
EBC | 0x0ebc | EFI Byte Code |
AMD64 | 0x8664 | AMD64 (K8) |
M32R | 0x9041 | M32R little-endian |
CEE | 0xc0ee |
3-2-2. NumberOfSections: 파일이 갖고있는 Section의 개수 2byte
3-2-3. TimeDateStamp: 파일이 빌드된 시간 *변조가능, 신뢰X / 10진수값으로 바꾼 뒤 표준시작으로 바꾸면 됨 4byte
+ PointerToSymbolTable 4byte
+ NumberOfSymbols 4byte
3-2-4. SizeOfOptionalHeader: 다음 멤버인 Optional Header의 크기 (보통 x32: 0xE0 / x64: 0xF0 / obj: 0x00) 2byte
3-2-5. Characteristics: 파일의 속성에 대한 정보 마지막 2byte, little endian
(rwx처럼 값 중첩해서 계산=비트 플래그 형식 사용, 2진수 형식으로 증가 ex. 0102면 EXECUTABLE_IMAGE &32bit 기반)
#define IMAGE_FILE_(명칭) (값)
명칭 | 값 | 설명 |
RELOCS_STRIPPED | 0x0001 | Relocation info stripped from file. |
EXECUTABLE_IMAGE | 0x0002 | File is executable (i.e. no unresolved externel references) |
LINE_NUMS_STRIPPED | 0x0004 | Line nunbers stripped from file |
LOCAL_SYMS_STRIPPED | 0x0008 | Local symbols stripped from file |
AGGRESIVE_WS_TRIM | 0x0010 | Agressively trim working set |
LARGE_ADDRESS_AWARE | 0x0020 | App can handle >2gb addresses |
BYTES_REVERSED_LO | 0x0080 | Bytes of machine word are reversed. |
32BIT_MACHINE | 0x0100 | 32 bit word machine. |
DEBUG_STRIPPED | 0x0200 | Debugging info stripped from file in .DBG file |
REMOfBLE_RUN_FROM_SWAP | 0x0400 | If Image is on removable media, copy and run from the swap file. |
NET_RUN_FROM_SWAP | 0x0800 | If Image is on Net, copy and run from the swap file. |
SYSTEM | 0x1000 | System File. |
DLL | 0x2000 | File is a DLL. |
UP_SYSTEM_ONLY | 0x4000 | File should only be run on a UP machine |
BYTES_REVERSED_HI | 0x8000 | Bytes of machine word are reversed. |
3-3. OptionalHeader: 구조체 (주로 주소 관련 내용, 31개의 필드, 가변적)
- 32/64구분자, EntryPoint주소, PE파일이 매핑되는 시작주소, 메모리의 섹션최소단위, 파일의 섹션최소단위, ...
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES
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;
3-3-1. Magic : 구조체의 비트에 따라... IMAGE_OPTIONAL_HEADER32 - 0x010B / 64 - 0x020B (2byte, little endian)
3-3-2. SizeOfCode: 코드 영역 전체의 크기 (=.text 섹션의 크기) 4byte
3-3-3. ImageBase : PE파일이 메모리에 로드될 때의 시작주소, RVA의 기준이 됨 4byte
EXE파일인 경우 0x400000번지 / DLL파일인 경우 0x10000000번지 //고정아님. 링커 옵션을 통해 지정 가능 + 이미 있는 경우 재배치 이루어짐)
(RVA: Relative Virtual Address, 상대 가상주소 ImageBase를 기준으로 어느만큼 떨어져있는지 나타냄_메모리주소
ImageBase가 0x400000 번지일 경우 .text섹션 RVA값이 0x3000이라면 실제로 .text 섹션이 메모리에 로드되는 위치는 0x403000)
3-3-4. AddressOfEntryPoint : EP; Entry Point (프로그램의 시작점) 주소를 가짐, RVA주소이므로 ImageBase(3-3-3)에 더해야 VA주소 4byte
3-3-5. BaseOfCode: 코드 영역이 시장되는 RVA주소
3-3-5. SectionAlignment : 메모리에서의 섹션의 최소단위 (즉, 메모리에서 섹션의 크기는 반드시 SectionAlignment의 배수 = 시작주소도 이 값 배수)
3-3-6. FileAlignment : 파일에서 섹션의 최소단위 (즉, 파일=저장공간에서 섹션의 크기는 반드시 FileAlignment의 배수 = 시작주소도 이 값 배수)
3-3-7. SizeOfimage : 파일이 메모리에 로딩되었을때 PE파일이 차지하는 크기
3-3-8. SizeOfHeader : PE 모든 헤더의 전체크기(DOS Header + DOS Stub + PE Header + Section Header)
즉, 파일의 시작점에서 SizeOfHeader만큼 떨어진 Offset에 첫번째 섹션이 존재하는 것
3-3-9. SubSystem : 파일을 실행하기위한 기본 환경
#define IMAGE_SUBSYSTEM_(명칭) (값)
명칭 | 값 | 설명 |
UNKNOWN | 0 | Unknown subsystem. |
NATIVE | 1 | Image doesn't require a subsystem. |
WINDOWS_GUI | 2 | Image runs in the Windows GUI subsystem. |
WINDOWS_CUI | 3 | Image runs in the Windows character subsystem |
OS2_CUI | 5 | image runs in the OS/2 character subsystem. |
POSIX_CUI | 7 | image runs in the Posix character subsystem. |
NATIVE_WINDOWS | 8 | image is a native Win9x driver. |
WINDOWS_CE_GUI | 9 | Image runs in the Windows CE subsystem. |
EFI_APPLICATION | 10 | |
EFI_BOOT_SERVICE_DRIVER | 11 | |
EFI_RUNTIME_DRIVER | 12 | |
EFI_ROM | 13 | |
XBOX | 14 | |
WINDOWS_BOOT_APPLICATION | 16 |
3-3-9. NumberOfRvaAndSizes : DataDirectory(3-3-10)구조체의 멤버변수로, 배열 크기를 정함
3-3-10. DataDirectory: PE파일에서 중요한 역할을 하는 개체들의 위치 및 크기
파일이 어떤 라이브러리를 제공하고, 필요한지를 정의한 테이블의 위치와 크기
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
#define IMAGE_DIRECTORY_ENTRY_(명칭) (값)
0 Export 8 GLOBALPTR
1 Import 9 TLS
2 RESOURCE 10 LOAD_CONFIG
3 EXCEPTION 11 BOUND_IMPORT
4 SECURITY 12 IAT
5 BASERELOC 13 DELAY_IMPORT
6 DEBUG 14 COM_DESCRIPTOR
7 COPYRIGHT 15 Reserved
IMAGE_OPTIONAL_HEADER의 DataDirectory 필드는 익스포트 디렉터리, 임포트 디렉터리, 리소스 디렉터리, 예외 디렉터리, 보안 디렉터리 영역 등에 접근할 수 있는 주소와 크기를 지니고 있는 배열로, IMAGE_DATA_DIRECTORY 구조체의 VirtualAddress를 통해 가상 주소를 알 수 있으며, Size를 통해 크기를 알 수 있습니다. 여기서 중요한 값은 EXPORT, IMPORT, RESOURCE, TLS, IAT인데 우선은 이것들을 잘 기억해두시기 바랍니다. 이부분에 대해서는 추후에 다시 설명하도록 하겠습니다.
IMAGE_OPTIONAL_HEADER의 DataDirectory 필드는 익스포트 디렉터리, 임포트 디렉터리, 리소스 디렉터리, 예외 디렉터리, 보안 디렉터리 영역 등에 접근할 수 있는 주소와 크기를 지니고 있는 배열로, IMAGE_DATA_DIRECTORY 구조체의 VirtualAddress를 통해 가상 주소를 알 수 있으며, Size를 통해 크기를 알 수 있습니다. 여기서 중요한 값은 EXPORT, IMPORT, RESOURCE, TLS, IAT인데 우선은 이것들을 잘 기억해두시기 바랍니다. 이부분에 대해서는 추후에 다시 설명하도록 하겠습니다.
4) Section Header (=Section Table)
Section에 대한 정보를 관리하는 구조체, Section의 속성을 정의
Section을 나누고, 각 Section들의 시작위치, 크기, 속성값 등 정함
.text .data. rdata Section 등에 대한 정보를 알 수 있음
Section마다 액세스 권한이 달라야 함 (프로그램의 안정성을 위하여)
ㄴCode: 실행, 읽기 권한
Data: 비실행, 읽기, 쓰기 권한
Resource: 비실행, 읽기 권한
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
4-0. Name 8byte
4-1. VirtualSize : 메모리에서의 Section의 크기 4byte
4-2. VirtualAddress : 메모리에서 Section이 시작되는 RVA 주소 4byte
4-3. SizeOfRawData : 파일에서 Section이 차지하는 크기 4byte
4-4. PointerToRawData : 파일에서 Section이 시작하는 위치 4byte → 검색 후 SizeOf(4-3) 값 단위로 Section임
4-5. Characteristics : 섹션의 속성. NT헤더의 Characteristics랑 같은 역할 및 형식. 조합하여 사용 4byte
#define IMAGE_SCN_(명칭) (값)
명칭 | 값 | 설명 |
CNT_CODE | 0x00000020 | Section contains code. |
CNT_INITIALIZED_DATA | 0x00000040 | Section contains initialized data. |
CNT_UNINITIALIZED_DATA | 0x00000080 | Section contains uninitialized data. |
MEM_EXECUTE | 0x20000000 | Section is executable. |
MEM_READ | 0x40000000 | Section is readable. |
MEM_WRITE | 0x80000000 | Section is writeable. |
blog.hexabrain.net/270 그 이후..IAT 부가 설명..
섹션
실제 프로그램을 구성하는 어셈블리 코드
소스코드 내에서 선언한 전역변수나 static변수 등
'SWING > [21-2] REVERSING' 카테고리의 다른 글
[WEEK5] LAB 6-3, LAB 6-4 실습 (0) | 2021.11.20 |
---|---|
[WEEK4] DLL Injection & Ejection (0) | 2021.11.13 |
[WEEK3] IAT, EAT(32bit) (0) | 2021.10.02 |
[WEEK2] 패킹 & 패커 UPX & x32dbg로 수동 언패킹 (0) | 2021.09.25 |
[WEEK1] 레지스터, 함수 호출규약(Calling Convention) (2) | 2021.09.11 |