반응형
DOS Header
Microsoft 는 PE 파일 포멧을 만들때 당시에 널리 사용되던 DOS 파일에 대한 하위 호환성을 고려해서 만들었습니다.
그 결과로 PE header 의 제일 앞부분에는 기존 DOS EXE header 를 확장시킨 IMAGE_DOS_HEADER 구조체가 존재합니다.
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;
* 출처 : Microsoft 의 Visual C++ 에서 제공하는 winnt.h
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;
* 출처 : Microsoft 의 Visual C++ 에서 제공하는 winnt.h
<IMAGE_DOS_HEADER>
IMAGE_DOS_HEADER 구조체의 크기는 40h 입니다.
이 구조체에서 꼭 알아둬야 할 중요한 멤버는 e_magic 과 e_lfanew 입니다.
- e_magic : DOS signature (4D5A => ASCII 값 "MZ")
- e_lfanew : NT header 의 옵셋을 표시 (가변적인 값을 가짐)
모든 PE 파일은 시작 부분(e_magic)에 DOS signature ("MZ") 가 존재하고,
e_lfanew 값이 가리키는 위치에 NT header 구조체가 존재해야 합니다.
(NT header 구조체의 이름은 IMAGE_NT_HEADERS 이며 나중에 소개됩니다.)
* 'MZ' 는 Microsoft 에서 DOS 실행파일을 설계한 Mark Zbikowski 라는 사람의 이니셜입니다.
(출처 : http://en.wikipedia.org/wiki/Mark_Zbikowski)
notepad.exe 를 hex editor 로 열어서 IMAGE_DOS_HEADER 구조체를 확인해 보겠습니다.
과연 PE 스펙에 맞게 파일 시작 2 byte 는 4D5A 이며, e_lfanew 값은 000000E0 입니다. (E0000000 이 아닙니다.)
(참고 : Intel 계열 PC 는 자료를 역순으로 저장합니다. 이것을 Little Endian 표기법이라고 합니다.)
시험삼아 이 값들을 변경한 후 저장해서 실행해 보세요.
정상 실행되지 않을 것입니다. (PE 스펙에 따라서 더 이상 PE 파일이 아니거든요.)
DOS Stub
DOS Header 밑에는 DOS Stub 이 존재합니다.
DOS Stub 의 존재여부는 옵션이며 크기도 일정하지 않습니다.
(DOS Stub 은 없어도 파일 실행에는 문제가 없습니다.)
DOS Stub 은 코드와 데이타의 혼합으로 이루어져 있으며, 아래 그림에 notepad.exe 의 DOS Stub 이 나타나 있습니다.
위 그림에서 붉은색으로 표시된 부분은 16 bit 어셈블리 명령어 입니다.
32 bit 윈도우즈에서는 이쪽 명령어가 실행되지 않습니다. (PE 파일로 인식하기 때문에 아예 이쪽 코드를 무시하지요.)
DOS 환경에서 실행하거나, DOS 용 디버거 (debug.exe) 를 이용해서 실행할 수 있습니다.
(DOS EXE 파일로 인식합니다. 이들은 PE 파일 포멧을 모르니까요...)
콘솔 윈도우(cmd.exe)를 띄워서 아래와 같이 명령을 입력합니다.
C:\WINDOWS>debug notepad.exe
-u
0D1E:0000 0E PUSH CS
0D1E:0001 1F POP DS
0D1E:0002 BA0E00 MOV DX,000E ; DX = 0E : "This program cannot be run in DOS mode"
0D1E:0005 B409 MOV AH,09
0D1E:0007 CD21 INT 21 ; AH = 09 : WriteString()
-u
0D1E:0000 0E PUSH CS
0D1E:0001 1F POP DS
0D1E:0002 BA0E00 MOV DX,000E ; DX = 0E : "This program cannot be run in DOS mode"
0D1E:0005 B409 MOV AH,09
0D1E:0007 CD21 INT 21 ; AH = 09 : WriteString()
0D1E:0009 B8014C MOV AX,4C01
0D1E:000C CD21 INT 21 ; AX = 4C01 : Exit()
0D1E:000C CD21 INT 21 ; AX = 4C01 : Exit()
코드는 매우 간단합니다. 문자열을 출력하고 종료해버리지요.
즉, notepad.exe 는 32 bit 용 PE 파일이지만, MS-DOS 호환 모드를 가지고 있어서
DOS 환경에서 실행하면 "This program cannot be run in DOS mode" 문자열을 출력하고 종료합니다.
이 특성을 잘 이용하면 하나의 실행(EXE) 파일에 DOS 와 Windows 에서 모두 실행 가능한 파일을 만들 수도 있습니다.
실제로 세계적인 보안업체 McAfee 에서 무료로 배포했던 scan.exe 라는 파일이 이와 같은 특징을 가지고 있었습니다.
(DOS 환경에서는 16 bit DOS 용 코드가, Windows 환경에서는 32 bit Windows 코드가 각각 실행됨.)
앞에서 말씀드린대로 DOS Stub 은 옵션이기 때문에, 개발 도구에서 지원해 줘야 합니다.
(VB, VC++, Delphi 등은 DOS Stub 을 기본 지원합니다.)
(continue)
반응형
'study' 카테고리의 다른 글
DLL Injection - 다른 프로세스에 침투하기 (3) (10) | 2009.07.17 |
---|---|
DLL Injection - 다른 프로세스에 침투하기 (2) (117) | 2009.07.17 |
DLL Injection - 다른 프로세스에 침투하기 (1) (17) | 2009.07.06 |
PE(Portable Executable) File Format (8) - PE Header (16) | 2009.04.22 |
PE(Portable Executable) File Format (7) - PE Header (42) | 2009.04.18 |
PE(Portable Executable) File Format (6) - PE Header (62) | 2009.04.06 |
PE(Portable Executable) File Format (5) - PE Header (31) | 2009.04.03 |
PE(Portable Executable) File Format (4) - PE Header (25) | 2009.03.31 |
PE(Portable Executable) File Format (3) - PE Header (18) | 2009.03.29 |
PE(Portable Executable) File Format (1) - PE Header (56) | 2009.03.23 |