1. Session, Window Station, 그리고 Desktop
Windows는 User Interface, GDI(Graphics Device Interface), 과 Kernel 이라는 3가지 큰 부류의 개체를 제공합니다. 이 중에서 User Interface 개체는 Windows Stations과 Desktops를 사용하여 관리됩니다.
그러면 Window Station은 무엇일까요? Window Station은 Clipboard, Atom Table, 그리고 한두개 이상의 Desktop 개체를 포함하고 있습니다. 그리고 이를 관리하게 됩니다. Windows Station이 생성될 때, 현재 호출 프로세스와 관련되며 현재 세션에 할당되게 됩니다.
Interactive Window Station, WinSta0은 User Interface 를 보여주거나 사용자 입력을 받는 유일한 Window Station입니다. 이것은 Interactive User의 Logon Session에 할당됩니다. 그리고 Keyboard, Mouse, 그리고 Display Device를 포함합니다. 그리고 모든 다른 Windows Station 들은 noninteractive 입니다. 이것은 즉, 다른 Windows Station 들은 User Interface를 보여주거나 사용자 입력을 받을 수 없다는 것을 의미합니다.
사용자가 Terminal Services를 제공하는 컴퓨터에 로그온할 때, 사용자를 위해 한 개의 Session을 제공하게 됩니다. 각 세션에는 세션만의 Interactive Window Station을 가지고 있습니다. 이렇게 생성된 세션은 고유한 Session ID를 가지게 됩니다. 이렇게 생성된 세션들은 Remote Desktop Client를 사용하여 사용자들이 로그온하기 때문에 이 Session 들을 Remote Desktop Session이라고 부릅니다. 이 세션에서 Interactive Window Station을 지원하는 유일한 Window Station 명은 WinSta0 입니다. 각 Window Station에는 Winlogon Desktop, Disconnect Desktop, 그리고 Default Desktop 이라는 3개의 Desktop이 있습니다.
![clip_image002[4] clip_image002[4]](http://blogs.msdn.com/blogfiles/coreinternals/WindowsLiveWriter/SessionWindowStationDesktop_CD2F/clip_image002%5B4%5D_thumb.jpg)
한 개의 Session에서 Interactive Window Station 으로 연결된 User를 Interactive User라고 부릅니다. Remote Desktop Connection client에서 Console Session 상에 있는 Interactive User 이외에 여려 Interactive User들이 있을 수 있습니다.
2. Window Station은 어떻게 생성하는가?
Window Station은 CreateWindowStation 함수를 호출하여 생성할 수 있습니다. MSDN에서 아래 경로를 참조하면 자세한 내용을 확인할 수 가 있습니다.
CreateWindowStation Function
http://msdn.microsoft.com/en-us/library/ms682496(VS.85).aspx
HWINSTA WINAPI CreateWindowStation(
__in_opt LPCTSTR lpwinsta,
DWORD dwFlags,
__in ACCESS_MASK dwDesiredAccess,
__in_opt LPSECURITY_ATTRIBUTES lpsa
);
CreateWindowStation 함수는 win32k.sys 드라이버에서 이와 연결된 함수를 호출하게 됩니다. 이 함수가 호출된 후 실제 WindowStation에 대한 인스턴스를 생성시킵니다. Window Station 인스턴스는 “WindowStation”이라는 TypeName을 가진 Kernel Object이기 때문에 생성될 때 ObCreateObject에 의해 생성이 되며 Nonpaged Pool에 할당이 됩니다. 이 내용은 Memory Dump에서 아래와 같이 확인할 수가 있습니다.
6: kd> !objects
808ac654 nt!ObpTypeDirectoryObject = e10008c0
HASH OBJ_TYPE Objects Handles Diff Type
00 : 8cd8e118 133 225 -92 Directory
01 : 8cd51380 1843 2055 -212 Mutant
01 : 8cd56ad0 1767 3675 -1908 Thread
03 : 8c928a28 0 0 0 FilterCommunicationPort
05 : 8cd2eca0 2 0 2 Controller
07 : 8cd50ad0 0 0 0 Profile
07 : 8cd51720 11458 11878 -420 Event
07 : 8cd8e2e8 31 0 31 Type
09 : 8cd50390 1818 795 1023 Section
09 : 8cd51550 0 0 0 EventPair
09 : 8cd56040 255 5 250 SymbolicLink
10 : 8cd50560 17 121 -104 Desktop
11 : 8cd50ca0 72 72 0 Timer
12 : 8cd2e560 12112 7328 4784 File
12 : 8cd50730 12 180 -168 WindowStation
16 : 8cd2e900 94 0 94 Driver
18 : 8cd82040 147 147 0 WmiGuid
18 : 8cd50900 1 89 -88 KeyedEvent
19 : 8cd2ead0 452 0 452 Device
19 : 8cd56e70 532 660 -128 Token
20 : 8cd55e70 0 0 0 DebugObject
21 : 8cd2e730 227 1292 -1065 IoCompletion
22 : 8cd56ca0 97 339 -242 Process
24 : 8cd2ee70 16 0 16 Adapter
26 : 8cd4f520 2775 2764 11 Key
28 : 8cd56900 2 2 0 Job
31 : 8cd2f4f0 3 3 0 WaitablePort
31 : 8cd2f6c0 941 928 13 Port
32 : 8cd50040 6 0 6 Callback
33 : 8c928bf8 0 0 0 FilterConnectionPort
34 : 8cd50e70 2700 2943 -243 Semaphore
아래 명령어를 사용하면 생성된 WindowStation의 상세한 내용을 확인할 수 있습니다. 아래에서 WindowStations 개체 아래에 있는 실제 생성된 WindowStation 들을 확인할 수가 있습니다. 그리고 Interactive Window Station인 WinSta0 을 확인할 수가 있습니다.
6: kd> !object \windows\WindowStations
Object: e1652530 Type: (8cd8e118) Directory
ObjectHeader: e1652518 (old version)
HandleCount: 0 PointerCount: 12
Directory Object: e16755b0 Name: WindowStations
Hash Address Type Name
---- ------- ---- ----
00 8c8a5f20 WindowStation Service-0x0-187ba$
01 8c38a088 WindowStation Service-0x0-3e4$
04 8c3f94f0 WindowStation Service-0x0-3e5$
08 8c763fa8 WindowStation Service-0x0-c4e36$
11 8c7de258 WindowStation Service-0x0-3e7$
15 8bfbce50 WindowStation __X78B95_89_IW
18 8c7b4508 WindowStation Service-0x0-2b5ac$
27 8c8b30e8 WindowStation WinSta0
28 8c068d28 WindowStation Service-0x0-be387$
31 8c47f6e0 WindowStation SAWinSta
35 8bef6b58 WindowStation Service-0x0-1b67c$
그러면 현재 WindowStation들이 있는 세션은 어떻게 확인할 수 있을까요? 아래와 같이 Session 명령어를 쓰면 쉽게 확인할 수가 있습니다.
6: kd> !session
Sesssions on machine: 3
Valid Sessions: 0 2 3
Using session CURRENT (0)
자! 그러면 WindowStation에 대해 자세하게 알아보겠습니다. WindowStation은 Win32k.sys 드라이버에서 _WINDOWSTATION 이라는 구조체를 사용하여 저장하게 됩니다. 이것을 사용하여 위에 Hash 27인 WinSta0를 한 번 살펴보도록 하겠습니다. 아래 내용을 보면 SessionId 가 0이고, Window Station이 Clipboard, AtomTable을 가진다고 설명하였는데, 그 내용을 확인할 수 있을 것입니다.
6: kd> dt win32k!WINDOWSTATION 8c8b30e8
+0x000 dwSessionId : 0
+0x004 rpwinstaNext : 0x8c7de258 tagWINDOWSTATION
+0x008 rpdeskList : 0x8c4182d0 tagDESKTOP
+0x00c pTerm : 0xbf9b6180 tagTERMINAL
+0x010 dwWSF_Flags : 0
+0x014 spklList : 0xbc064fb8 tagKL
+0x018 ptiClipLock : (null)
+0x01c ptiDrawingClipboard : (null)
+0x020 spwndClipOpen : (null)
+0x024 spwndClipViewer : (null)
+0x028 spwndClipOwner : (null)
+0x02c pClipBase : 0xbc56ea18 tagCLIP
+0x030 cNumClipFormats : 4
+0x034 iClipSerialNumber : 6
+0x038 iClipSequenceNumber : 0x1f
+0x03c pGlobalAtomTable : 0xe164f628
+0x040 luidEndSession : _LUID
+0x048 luidUser : _LUID
+0x050 psidUser : 0xbc376820
그리고, WinSta0가 가지고 있는 Desktop 목록이 rpdeskList에 저장되어 있습니다. 이 주소를 이용하여 Desktop 목록을 확인할 수가 있습니다. 또한 위 WinSta0 주소를 가지고 어디에 저장되어 있는지 아래와 같이 체크해 볼 수가 있습니다. 예상한 대로 Nonpaged Pool에 저장되어 있습니다.
6: kd> !pool 8c8b30e8 2
Pool page 8c8b30e8 region is Nonpaged pool
*8c8b30b0 size: 90 previous size: 10 (Allocated) *Wind (Protected)
Owning component : Unknown (update pooltag.txt)
3. Desktop은 어떻게 생성하는가?
WindowStation인스턴스인 WinSta0는 보통 3개의 Desktop을 가지고 있습니다: Default, Disconnect, Winlogon. 이러한 Desktop을 어떻게 생성하는지 알아보도록 하겠습니다. CreateDesktopEx 함수를 사용하면 새로운 Desktop을 생성하여 사용할 수가 있습니다. CreateDesktopEx의 함수 원형은 아래와 같습니다. 이 함수에는 Desktop Heap의 크기를 설정할 수가 있도록 되어 있습니다.
HDESK WINAPI CreateDesktopEx(
__in LPCTSTR lpszDesktop,
__reserved LPCTSTR lpszDevice,
__reserved LPDEVMODE pDevmode,
__in DWORD dwFlags,
__in ACCESS_MASK dwDesiredAccess,
__in_opt LPSECURITY_ATTRIBUTES lpsa,
__in ULONG ulHeapSize,
__reserved PVOID pvoid
);
CreateDesktopEx 함수는 Win32k.sys 드라이버에서 이와 연결된 함수를 호출하고 이 함수에서 Desktop을 생성하게 됩니다. 생성된 Desktop 정보는 Win32k.sys 드라이버에서 _DESKTOP 구조체를 사용하여 저장하고 이 정보는 Kernel Object로서 생성되게 됩니다. 따라서 !winde.objects 명령어를 사용하면 Desktop 개체의 개수를 확인할 수가 있습니다.
6: kd> !objects
808ac654 nt!ObpTypeDirectoryObject = e10008c0
HASH OBJ_TYPE Objects Handles Diff Type
00 : 8cd8e118 133 225 -92 Directory
01 : 8cd51380 1843 2055 -212 Mutant
01 : 8cd56ad0 1767 3675 -1908 Thread
03 : 8c928a28 0 0 0 FilterCommunicationPort
05 : 8cd2eca0 2 0 2 Controller
07 : 8cd50ad0 0 0 0 Profile
07 : 8cd51720 11458 11878 -420 Event
07 : 8cd8e2e8 31 0 31 Type
09 : 8cd50390 1818 795 1023 Section
09 : 8cd51550 0 0 0 EventPair
09 : 8cd56040 255 5 250 SymbolicLink
10 : 8cd50560 17 121 -104 Desktop
11 : 8cd50ca0 72 72 0 Timer
12 : 8cd2e560 12112 7328 4784 File
12 : 8cd50730 12 180 -168 WindowStation
16 : 8cd2e900 94 0 94 Driver
18 : 8cd82040 147 147 0 WmiGuid
18 : 8cd50900 1 89 -88 KeyedEvent
19 : 8cd2ead0 452 0 452 Device
19 : 8cd56e70 532 660 -128 Token
20 : 8cd55e70 0 0 0 DebugObject
21 : 8cd2e730 227 1292 -1065 IoCompletion
22 : 8cd56ca0 97 339 -242 Process
24 : 8cd2ee70 16 0 16 Adapter
26 : 8cd4f520 2775 2764 11 Key
28 : 8cd56900 2 2 0 Job
31 : 8cd2f4f0 3 3 0 WaitablePort
31 : 8cd2f6c0 941 928 13 Port
32 : 8cd50040 6 0 6 Callback
33 : 8c928bf8 0 0 0 FilterConnectionPort
34 : 8cd50e70 2700 2943 -243 Semaphore
Desktop Kernel Object가 생성된 후 Desktop이 사용할 Desktop Heap을 설정하게 됩니다. 첫 번째 Desktop인 Logon Desktop은 Small Heap (128K)를 사용하게 됩니다. 그리고 Disconnect Heap은 조금 더 작은 Heap(64K) 을 사용합니다. 그리고 Default Desktop은 아래의 레지스트리 경로에 설정된 값으로 설정됩니다. 기본값은 SharedSection에 있는 값입니다. SharedSection=1024,3072,512 값중에서 3072 입니다. 이 값의 단위는 KB(Kilobytes)이기 때문에 설정된 값은 3072K가 됩니다.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems\Windows
이 데이터에 대한 기본값은 아래와 같이 설정되어 있습니다.
%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,3072,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off MaxRequestThreads=16
그러면 SharedSection=1024,3072,512의 값의 의미를 좀 더 자세하게 살펴보도록 하겠습니다.
- 첫번째값(1024)는 모든 Desktop에 공통된 Shared Heap의 크기를 의미합니다. 이 값은 Desktop Heap의 사용량에 문제가 발생 경우 이를 위해서 수정되면 안됩니다. (단위는 Kilobytes)
- 두번째값(3072)는 Interactive Windows Station, WinSta0에 생성된 Disconnect와 Winlogon을 제외한 Default Desktop의 Heap Size를 의미합니다. (단위 Kilobytes)
- 세번째값(512)는 Noninteractive Window Station에서 생성된 Desktop에 필요한 Desktop Heap의 크기를 의미합니다. (단위 Kilobytes)
Desktop이 생성될 때 또 하나 아주 중요한 사실이 하나 있습니다. Section 생성 함수를 사용하여 설정한 Desktop Heap Size 만큼의 공간을 가진 Section Object를 생성합니다. 이 Section Object는 SessionSpace에 View를 Mapping하는 함수를 사용하여 생성되는 Session 의 Session Space에 Mapping이 되게 됩니다. 여기서 Mapping된 Session Space는 Session에 할당된 Session View의 크기를 이야기 합니다. 아래 레지스트리 키를 통해 Session에 할당된 View 크기를 설정할 수가 있습니다. 이 값은 16의 배수로 변경시켜야 합니다. 각 OS에 할당된 Session View의 크기는 아래와 같습니다.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management
SessionViewSize = 기본값 48, (0x30) (단위 Megabytes)
| OS | Size if no registry value configured | Default registry value |
| Windows 2000 * | 20 MB | None |
| Windows XP | 20 MB | 48 MB |
| Windows Server 2003 | 20 MB | 48 MB |
만일 위의 Desktop Heap의 기본 크기를 늘리게 되면 Session에서 생성할 수 있는 Desktop 수가 줄어들게 됩니다. 따라서 Desktop의 개수를 면밀히 조사하여 사용 개수를 파악한 후 Desktop Heap의 크기와 Session View 크기를 동시에 변경시키는 것을 권합니다. 예를 들어, SessionView의 크기가 48MB인 상태에서 Desktop Heap의 크기를 8192 KB로 증가 시킨 후 문제가 발생한다면 다시 SessionView의 크기를 16의 배수인 64 MB로 늘린 후 모니터링하여야 합니다.
I am going to describe how we can check PE stuffs on a file loaded on to a system in a memory dump file in this article. PE file format is the file format for Win32 Executables having extensions like .exe, .sys, .dll, etc. Here I put down on the short details of Portable Executables file format itself. PE file format is made up of IMAGE_DOS_HEADER, IMAGE_NT_HEADERS (IMAGE_FILE_HEADER, IMAGE_OPTIONAL_HEADER), IMAGE_SECTION_HEADERS, Sections. You can get the details on the structures of PE file format on Winnt.h. You will find further more about PE format on http://msdn.microsoft.com/en-us/library/ms809762.aspx.
How can we list the modules loaded in a memory dump file? We can use “lm n t” command to list the modules loaded on the dump file.
0:000> lm n t
start end module name
01000000 01014000 notepad notepad.exe Sat Feb 17 15:08:37 2007 (45D69BE5)
73070000 73097000 WINSPOOL WINSPOOL.DRV Sat Feb 17 23:01:47 2007 (45D70ACB)
762b0000 762f9000 comdlg32 comdlg32.dll Sat Feb 17 23:00:18 2007 (45D70A72)
76f50000 76f63000 Secur32 Secur32.dll Sat Feb 17 23:01:39 2007 (45D70AC3)
77380000 77411000 USER32 USER32.dll Fri Mar 02 15:38:46 2007 (45E7C676)
77420000 77523000 COMCTL32 COMCTL32.dll Sat Feb 17 22:58:29 2007 (45D70A05)
77ba0000 77bfa000 msvcrt msvcrt.dll Sat Feb 17 23:02:46 2007 (45D70B06)
77c00000 77c49000 GDI32 GDI32.dll Thu Oct 23 20:43:54 2008 (4900637A)
77c50000 77cef000 RPCRT4 RPCRT4.dll Wed Jul 11 19:38:05 2007 (4694B30D)
77da0000 77df2000 SHLWAPI SHLWAPI.dll Sat Feb 17 23:01:36 2007 (45D70AC0)
77e40000 77f42000 kernel32 kernel32.dll Thu Apr 19 01:25:36 2007 (46264680)
77f50000 77feb000 ADVAPI32 ADVAPI32.dll Sat Feb 17 22:59:02 2007 (45D70A26)
7c800000 7c8c0000 ntdll ntdll.dll Sat Feb 17 23:02:00 2007 (45D70AD8)
7c8d0000 7d0cf000 SHELL32 SHELL32.dll Wed Nov 07 22:49:28 2007 (4731C268)…
Here I will look into the PE on GDI32.dll listed above. We can use “!dh” to display the headers of the specified image as the followings.
0:000> !dh 77c00000
File Type: DLL
FILE HEADER VALUES
14C machine (i386)
4 number of sections
4900637A time date stamp Thu Oct 23 20:43:54 2008
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
210E characteristics
Executable
Line numbers stripped
Symbols stripped
32 bit word machine
DLL
OPTIONAL HEADER VALUES
10B magic #
7.10 linker version
42400 size of code
3400 size of initialized data
0 size of uninitialized data
80A5 address of entry point
1000 base of code
----- new -----
77c00000 image base
1000 section alignment
200 file alignment
3 subsystem (Windows CUI)
5.02 operating system version
5.02 image version
4.10 subsystem version
49000 size of image
400 size of headers
4AFCC checksum
00040000 size of stack reserve
00001000 size of stack commit
00100000 size of heap reserve
00001000 size of heap commit
1CB0 [ 3CD6] address [size] of Export Directory
42638 [ 64] address [size] of Import Directory
46000 [ 3D0] address [size] of Resource Directory
0 [ 0] address [size] of Exception Directory
0 [ 0] address [size] of Security Directory
47000 [ 18B0] address [size] of Base Relocation Directory
431EC [ 38] address [size] of Debug Directory
0 [ 0] address [size] of Description Directory
0 [ 0] address [size] of Special Directory
0 [ 0] address [size] of Thread Storage Directory
25C88 [ 40] address [size] of Load Configuration Directory
0 [ 0] address [size] of Bound Import Directory
1000 [ 204] address [size] of Import Address Table Directory
0 [ 0] address [size] of Delay Import Directory
0 [ 0] address [size] of COR20 Header Directory
0 [ 0] address [size] of Reserved Directory
SECTION HEADER #1
.text name
4224A virtual size
1000 virtual address
42400 size of raw data
400 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
(no align specified)
Execute Read
Debug Directories(2)
Type Size Address Pointer
cv 22 43228 42628 Format: RSDS, guid, 2, gdi32.pdb
( 10) 4 43224 42624
SECTION HEADER #2
.data name
1480 virtual size
44000 virtual address
1200 size of raw data
42800 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C0000040 flags
Initialized Data
(no align specified)
Read Write
SECTION HEADER #3
.rsrc name
3D0 virtual size
46000 virtual address
400 size of raw data
43A00 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40000040 flags
Initialized Data
(no align specified)
Read Only
SECTION HEADER #4
.reloc name
18B0 virtual size
47000 virtual address
1A00 size of raw data
43E00 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
42000040 flags
Initialized Data
Discardable
(no align specified)
Read Only
IMAGE_DOS_HEADER
Then how can we see the details listed above? We can start to check the PE stuff of GDI32.dll from its start address with IMAGE_DOS_HEADER. The start address of GDI32.dll is 77c00000.
0:000> dt IMAGE_DOS_HEADER 77c00000
ntdll!IMAGE_DOS_HEADER
+0x000 e_magic : 0x5a4d à MZ
+0x002 e_cblp : 0x90
+0x004 e_cp : 3
+0x006 e_crlc : 0
+0x008 e_cparhdr : 4
+0x00a e_minalloc : 0
+0x00c e_maxalloc : 0xffff
+0x00e e_ss : 0
+0x010 e_sp : 0xb8
+0x012 e_csum : 0
+0x014 e_ip : 0
+0x016 e_cs : 0
+0x018 e_lfarlc : 0x40
+0x01a e_ovno : 0
+0x01c e_res : [4] 0
+0x024 e_oemid : 0
+0x026 e_oeminfo : 0
+0x028 e_res2 : [10] 0
+0x03c e_lfanew : 232
The first two bytes of the specified image has 0x5a4d, which is “MZ”. We know that GDI32.dll file is a Win32 Executable from this one.
0: kd> dc b86a1000 L4
b86a1000 00905a4d 00000003 00000004 0000ffff MZ..............
and the first few hundred bytes of the typical PE file are taken up by the MS-DOS stub. This stub is a tiny program that prints out something to the effect of “This program cannot be run in MS-DOS mode”. So we can check if this file supports Win32
0: kd> ?? sizeof(IMAGE_DOS_HEADER)
unsigned int 0x40
0:000> dc 77c00000+0x40 L10
77c00040 0eba1f0e cd09b400 4c01b821 685421cd ........!..L.!Th
77c00050 70207369 72676f72 63206d61 6f6e6e61 is program canno
77c00060 65622074 6e757220 206e6920 20534f44 t be run in DOS
77c00070 65646f6d 0a0d0d2e 00000024 00000000 mode....$.......
IMAGE_NT_HEADERS
The e_lfanew in the MS-DOS stub header is a relative offset (or RVA, if you prefer) to the actual PE header. To get a pointer to the PE header in memory, we just add that field’s value to the image base as the following.
The Pointer of NT Header = the Start Address of DOSHeader + DosHeader->e_lfanew;
Based on this, we can see that the signature of PE NT Header. Please note that the numeric type of e_lfanew of DOSHeader is Decimal, not Hexadecimal. So here we must add 0n to use its value as Deciaml Type.
0:000> dc 77c00000+0n232 L1
77c000e8 00004550 PE..
Once we have a pointer to the main PE header, we can go further on NT Header. The main PE header is a structure of type IMAGE_HEADER_HEADERS, which is defined in WINNT.h. this structure is made up of a DWORD and two substructures and is laid out as follows :
0:000> dt IMAGE_NT_HEADERS 77c00000+0n232
ntdll!IMAGE_NT_HEADERS
+0x000 Signature : 0x4550 à PE\0\0
+0x004 FileHeader : _IMAGE_FILE_HEADER
+0x018 OptionalHeader : _IMAGE_OPTIONAL_HEADER
IMAGE_FILE_HEADER
Following the PE signature in the PE header is a structure of type IMAGE_FILE_HEADER, which contains the most basic information about the file. The fields of IMAGE_FILE_HEADER are show below :
0:000> dt IMAGE_FILE_HEADER 77c00000+0n232+4
ntdll!IMAGE_FILE_HEADER
+0x000 Machine : 0x14c
+0x002 NumberOfSections : 4
+0x004 TimeDateStamp : 0x4900637a
+0x008 PointerToSymbolTable : 0
+0x00c NumberOfSymbols : 0
+0x010 SizeOfOptionalHeader : 0xe0
+0x012 Characteristics : 0x210e
The value of machine field in IMAGE_FILE_HEADER is 0x14c, which is for Intel Intel 386. The number of sections are 8 from the second fields, NumberOfSections. We can check from TimeDateStamp when the linker produced this file as followings :
0:000> .formats 0x4900637a
Evaluate expression:
Hex: 4900637a
…
Time: Thu Oct 23 20:43:54 2008
The Characteristics of IMAGE_FILE_HEADER show us what kind of attributes the file can support. You can find more on the characteristics in the following website : http://msdn.microsoft.com/en-us/library/ms680313(VS.85).aspx .
0x210e : IMAGE_FILE_32BIT_MACHINE | à 32 bit word machine
IMAGE_FILE_EXECUTABLE_IMAGE | à Executable
IMAGE_FILE_LINE_NUMS_STRIPPED | à Line Numbers Stripped
IMAGE_FILE_LOCAL_SYMS_STRIPPED | à Symbols Stripped
IMAGE_FILE_DLL à DLL
So you will take notice of that the analysis result based on the file structures of PE format is the same as the first block of “!dh” command output listed as following :
File Type: DLL
FILE HEADER VALUES
14C machine (i386)
4 number of sections
4900637A time date stamp Thu Oct 23 20:43:54 2008
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
210E characteristics
Executable
Line numbers stripped
Symbols stripped
32 bit word machine
DLL
IMAGE_OPTIONAL_HEADER
The third part of the PE header is a structure of type IMAGE_OPTIONAL_HEADER. For PE files, this part certainly isn’t optional. We can know more details about the file through Image Optional Header : the state of the image file, the version number of the linker, the size of the code section, a pointer to the entry point function, relative to the image base address, the preferred address of the first byte of the image when it is loaded in memory, and so on. Please refer to more on its fields in http://msdn.microsoft.com/en-us/library/ms680339(vs.85).aspx
Then Where can we start to see the contents of optional header? Yes, we can find out the start offset of the image optional header from IMAGE_NT_HEADERS. Its start offset is +0x018 from the address of IMAGE_NT_HEADERS.
0:000> dt IMAGE_OPTIONAL_HEADER 77c00000+0n232+0x18
ntdll!IMAGE_OPTIONAL_HEADER
+0x000 Magic : 0x10b
+0x002 MajorLinkerVersion : 0x7 ''
+0x003 MinorLinkerVersion : 0xa ''
+0x004 SizeOfCode : 0x42400
+0x008 SizeOfInitializedData : 0x3400
+0x00c SizeOfUninitializedData : 0
+0x010 AddressOfEntryPoint : 0x80a5
+0x014 BaseOfCode : 0x1000
+0x018 BaseOfData : 0x41000
+0x01c ImageBase : 0x77c00000
+0x020 SectionAlignment : 0x1000
+0x024 FileAlignment : 0x200
+0x028 MajorOperatingSystemVersion : 5
+0x02a MinorOperatingSystemVersion : 2
+0x02c MajorImageVersion : 5
+0x02e MinorImageVersion : 2
+0x030 MajorSubsystemVersion : 4
+0x032 MinorSubsystemVersion : 0xa
+0x034 Win32VersionValue : 0
+0x038 SizeOfImage : 0x49000
+0x03c SizeOfHeaders : 0x400
+0x040 CheckSum : 0x4afcc
+0x044 Subsystem : 3
+0x046 DllCharacteristics : 0
+0x048 SizeOfStackReserve : 0x40000
+0x04c SizeOfStackCommit : 0x1000
+0x050 SizeOfHeapReserve : 0x100000
+0x054 SizeOfHeapCommit : 0x1000
+0x058 LoaderFlags : 0
+0x05c NumberOfRvaAndSizes : 0x10
+0x060 DataDirectory : [16] _IMAGE_DATA_DIRECTORY
The sum up of the Image Optional Header structure is as followings :
The state of the image file : Executable
Linker Version : 7.10
The size of code section(in bytes): 0x42400
A pointer to the entry point function: 0x80a5
A pointer to the beginning of the code section : 0x1000
A pointer to the beginning of the data section : 0x41000
The preferred address of the first byte of the image: 0x77c00000
The alignment of sections loaded in memory(in bytes): 0x1000 (4K)
The alignment of the raw data of sections in file: 0x200 (512)
The version number of the required OS : 5.02
The version number of the image : 5.02
The version number of the subsystem : 4.10
The size of the image (in bytes) : 0x49000
The combined size of the MS-DOS stub,PE,Section hdrs: 0x400
The image file checksum : 0x4afcc
The subsystem required to run this image : IMAGE_SUBSYSTEM_WINDOWS_CUI (3)
The number of bytes to reserve for the stack : 0x40000 (256K)
The number of bytes to commit for the stack : 0x1000 (4K)
The number of bytes to reserve for the local heap : 0x100000 (1MB)
The number of bytes to commit for the local heap : 0x1000 (4K)
The number of directory entries : 0x10 (16)
A pointer to the first IMAGE_DATA_DIRECTORY : Start Address of Optional header + 0x60
We can see that the code starts to run from “a pointer to the entry point function”. If you can have the private symbol of the file, you can see the following :
0:000> ln 77c00000+0x80a5
(77c080a5) GDI32!_DllMainCRTStartupForGS | (77c0812c) GDI32!NtGdiGetStockObject
Exact matches:
GDI32!_DllMainCRTStartupForGS (void *, unsigned long, void *)
0:000> uf 77c080a5 ß 77c00000+0x80a5
GDI32!_DllMainCRTStartupForGS:
37 77c080a5 8bff mov edi,edi
37 77c080a7 55 push ebp
37 77c080a8 8bec mov ebp,esp
43 77c080aa 837d0c01 cmp dword ptr [ebp+0Ch],1
43 77c080ae 750e jne GDI32!_DllMainCRTStartupForGS+0x19 (77c080be)
GDI32!_DllMainCRTStartupForGS+0xb:
45 77c080b0 ff7508 push dword ptr [ebp+8]
45 77c080b3 ff156c11c077 call dword ptr [GDI32!_imp__DisableThreadLibraryCalls (77c0116c)]
46 77c080b9 e88e020000 call GDI32!__security_init_cookie (77c0834c)
GDI32!_DllMainCRTStartupForGS+0x19:
49 77c080be 33c0 xor eax,eax
49 77c080c0 40 inc eax
50 77c080c1 5d pop ebp
50 77c080c2 c20c00 ret 0Ch
The Data Directory field contains Export Directory, Import Directory, Resource Directory, Exception Directory, Security Directory, Base Relocation Directory, Debug Directory, Description Directory, and so on. You can find more details on this at http://msdn.microsoft.com/en-us/library/ms680305(vs.85).aspx
Here I am going to see the imported functions from Import Directory among them. First I list all the image data directories as followings :
0:000> dt -a16 _IMAGE_DATA_DIRECTORY 77c00000+0n232+0x18+0x060
GDI32!_IMAGE_DATA_DIRECTORY
[0] @ 77c00160
---------------------------------------------
+0x000 VirtualAddress : 0x1cb0
+0x004 Size : 0x3cd6
[1] @ 77c00168 ß Import table address and size
---------------------------------------------
+0x000 VirtualAddress : 0x42638
+0x004 Size : 0x64
[2] @ 77c00170
---------------------------------------------
+0x000 VirtualAddress : 0x46000
+0x004 Size : 0x3d0
[3] @ 77c00178
---------------------------------------------
+0x000 VirtualAddress : 0
+0x004 Size : 0
[4] @ 77c00180
---------------------------------------------
+0x000 VirtualAddress : 0
+0x004 Size : 0
[5] @ 77c00188
---------------------------------------------
+0x000 VirtualAddress : 0x47000
+0x004 Size : 0x18b0
[6] @ 77c00190
---------------------------------------------
+0x000 VirtualAddress : 0x431ec
+0x004 Size : 0x38
[7] @ 77c00198
---------------------------------------------
+0x000 VirtualAddress : 0
+0x004 Size : 0
[8] @ 77c001a0
---------------------------------------------
+0x000 VirtualAddress : 0
+0x004 Size : 0
[9] @ 77c001a8
---------------------------------------------
+0x000 VirtualAddress : 0
+0x004 Size : 0
[10] @ 77c001b0
---------------------------------------------
+0x000 VirtualAddress : 0x25c88
+0x004 Size : 0x40
[11] @ 77c001b8
---------------------------------------------
+0x000 VirtualAddress : 0
+0x004 Size : 0
[12] @ 77c001c0
---------------------------------------------
+0x000 VirtualAddress : 0x1000
+0x004 Size : 0x204
[13] @ 77c001c8
---------------------------------------------
+0x000 VirtualAddress : 0
+0x004 Size : 0
[14] @ 77c001d0
---------------------------------------------
+0x000 VirtualAddress : 0
+0x004 Size : 0
[15] @ 77c001d8
---------------------------------------------
+0x000 VirtualAddress : 0
+0x004 Size : 0
Then we can get the contents of IMAGE_IMPORT_DESCRIPTOR at the address 77c00000+0x42638.
0:000> dt 77c00000+0x42638 IMAGE_IMPORT_DESCRIPTOR ß Import table address and size
GDI32!IMAGE_IMPORT_DESCRIPTOR
+0x000 Characteristics : 0x426d0
+0x000 OriginalFirstThunk : 0x426d0
+0x004 TimeDateStamp : 0
+0x008 ForwarderChain : 0
+0x00c Name : 0x4269c
+0x010 FirstThunk : 0x1000
0:000> da 77c00000+0x4269c ß Name
77c4269c "ntdll.dll"
0:000> dc 77c00000+0x426d0 ß OriginalFirstThunk
77c426d0 000428d4 000428e0 00042904 0004291c .(...(...)...)..
77c426e0 00042926 00042936 0004294a 00042954 &)..6)..J)..T)..
77c426f0 0004295e 0004296a 00042978 00042992 ^)..j)..x)...)..
77c42700 000429a4 000429ba 000429c6 000429d2 .)...)...)...)..
77c42710 000429ec 000429f6 00042a0e 00042a18 .)...)...*...*..
77c42720 00042a22 00042a3c 00042a58 00042a78 "*..<*..X*..x*..
77c42730 00042a94 00042aac 00042ab8 00042aca .*...*...*...*..
77c42740 00042ad4 00042ae6 00042b00 00042b0e .*...*...+...+..
0:000> dc 77c00000+0x1000 ß FirstThunk
77c01000 7c831983 7c8196ba 7c82b0be 7c81ba4a ...|...|...|J..|
77c01010 7c827ccf 7c81bdd9 7c82cfe2 7c82e828 .|.|...|...|(..|
77c01020 7c835757 7c82730f 7c82754f 7c826eaf WW.|.s.|Ou.|.n.|
77c01030 7c82727f 7c8394c5 7c8357d6 7c81c575 .r.|...|.W.|u..|
77c01040 7c82b47b 7c827cbf 7c81b2ed 7c82a57e {..|.|.|...|~..|
77c01050 7c82e383 7c837538 7c833d1d 7c82c988 ...|8u.|.=.|...|
77c01060 7c81a469 7c82733f 7c8276ff 7c826d1f i..|?s.|.v.|.m.|
77c01070 7c829fd6 7c82786f 7c82eb6e 7c82eb52 ...|ox.|n..|R..|
0:000> uf 7c831983
ntdll!_stricmp :
73 7c831983 8bff mov edi,edi
73 7c831985 55 push ebp
73 7c831986 8bec mov ebp,esp
105 7c831988 5d pop ebp
88 7c831989 55 push ebp
88 7c83198a 8bec mov ebp,esp
88 7c83198c 57 push edi
88 7c83198d 56 push esi
88 7c83198e 53 push ebx
95 7c83198f 8b750c mov esi,dword ptr [ebp+0Ch]
96 7c831992 8b7d08 mov edi,dword ptr [ebp+8]
98 7c831995 b0ff mov al,0FFh
98 7c831997 8bff mov edi,edi
Please refer to “Peering Inside the PE: A Tour of the Win32 Portable Executable File Format (http://msdn.microsoft.com/en-us/magazine/ms809762.aspx)” for the details of IMAGE_IMPORT_DESCRIPTOR.
WRAP UP
That is for the headers of PE files on the memory dump. I’ll continue to go over the remainder of portable executable files in the next article.