물리 메모리 이미지를 분석하기 이전에 가장 먼저 수행되어져야 할 작업은 바로 메모리 이미지의 OS(Windows) 및 버젼을 판별하는 것입니다. 사실 OS의 버젼 자체가 중요한 것이 아니라, OS의 버젼에 따라 커널 분석 방법 및 객체의 구조체 형태가 다르기 때문에 가장 먼저 고려되어져야만 합니다.

아래는 윈도우즈 물리 메모리 이미지의 버젼을 판별하는 방법들입니다.


1. 문자열 검색을 이용한 방법

OS 종류를 판별하기 위해 문자열을 검색해볼 수 있습니다. 아래 예제는 일부 윈도우즈 버젼과 관련한 문자열을 나타냅니다.

Windows XP: 5.1.2600

2546060:5.1.2600.0 (xpclient.010817-1148)
2546134:InternalName
2546160:HCAppRes.dll
2546194:LegalCopyright
2546226: Microsoft Corporation. All rights reserved.
2546322:OriginalFilename
2546356:HCAppRes.dll

Windows 7: 6.1.7600.16385 (win7_rtm.090713-1255)

1335896:6.1.7600.16385 (win7_rtm.090713-1255)
1335978:InternalName
1336004:BlbEvents.dll
1336038:LegalCopyright
1336070: Microsoft Corporation. All rights reserved.

만약 메모리 이미지가 x86 혹은 x64인지 확인하기 위해서는 PROCESSOR_ARCHITECTUREPROCESSOR_ARCHITEW6432와 같은 환경변수를 이용하면 됩니다.

PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 37 Stepping 5, GenuineIntel

PROCESSOR_ARCHITECTURE=AMD64
PROCESSOR_IDENTIFIER=Intel64

PROCESSOR_ARCHITECTURE=x86
PROCESSOR_ARCHITEW6432=AMD64

보다 자세한 관련 내용은 여기를 참조 바랍니다.


2. _DBGKD_DEBUG_DATA_HEADER64 구조체를 이용한 방법

위의 문자열 검색을 이용한 방법은 분석자의 눈으로 보기에는 괜찮은 방법이긴하나, 물리 메모리 분석을 자동화하는 경우에는 적합치않아 보입니다. 아래는 WinDbg 설치 후 볼 수 있는 'wdbgext.h'에 정의되어있는 _DBGKD_DEBUG_DATA_HEADER64 구조체를 나타냅니다.

typedef struct _DBGKD_DEBUG_DATA_HEADER64 {
LIST_ENTRY64 List;
ULONG OwnerTag; //"KDBG"
ULONG Size; //Different for each OS
} DBGKD_DEBUG_DATA_HEADER64, *PDBGKD_DEBUG_DATA_HEADER64;

보시다시피 OwnerTag 필드는 반드시 'KDBG'라는 4바이트의 문자열이 나타나야 합니다. 만약 시스템이 x86 기반일 경우, LIST_ENTRY64 구조체는 절반만 사용되기 때문에 뒤의 8바이트가 NULL로 나타나야합니다. 즉, 아래의 값을 _DBGKD_DEBUG_DATA_HEADER64 구조체의 시그니쳐와 같이 사용할 수 있습니다.

\x00\x00\x00\x00\x00\x00\x00\x00KDBG

_DBGKD_DEBUG_DATA_HEADER64에는 버젼을 구분할 수 있는 특징이 존재합니다. 바로 Size 필드가 윈도우 커널 버젼에 따라 다르다는 점입니다.

OS Size
Windows 2000 \x08\x02
XP \x90\x02
W2K3 \x18\x03
Vista \x28\x03
W2K8 \x30\x03
Windows 7 \x40\x03

참고로 아래는 메모리 이미지가 x64 기반인 경우에 나타내는 패턴입니다.


'\x00\xf8\xff\xffKDBG'

위의 설명된 경우를 모두 조합하면 각 OS 버젼별, CPU 아키텍쳐 별 시그니쳐를 만들 수 있습니다.


3. _DBGKD_GET_VERSION64 구조체를 이용한 방법

아래는 Windows XP SP3에서의 _DBGKD_GET_VERSION64 구조체를 나타냅니다.

kd> dt nt!_DBGKD_GET_VERSION64 0x8054f2b8
+0x000 MajorVersion : 0xf
+0x002 MinorVersion : 0xa28
+0x004 ProtocolVersion : 6
+0x006 Flags : 3
+0x008 MachineType : 0x14c
+0x00a MaxPacketType : 0xc ''
+0x00b MaxStateChange : 0x3 ''
+0x00c MaxManipulate : 0x2d '-'
+0x00d Simulation : 0 ''
+0x00e Unused : [1] 0
+0x010 KernBase : 0xffffffff`804d9000
+0x018 PsLoadedModuleList : 0xffffffff`8055f720
+0x020 DebuggerDataList : 0xffffffff`80687ff4

특이한 점은 MajorVersion 필드는 항상 0xf를 나타내고 있으며, MinorVersion 필드에 마이너 버젼이 아닌, 빌드넘버를 표현하고 있습니다. (각 필드에 우리가 원하는 값이 있다면 좋겠지만)

하지만 다행스럽게도 빌드넘버는 각 커널 버젼마다 중복되지 않기 때문에 이를 이용하여 윈도우즈 버젼을 파악할 수 있습니다. 아래는 각 윈도우즈 버젼 별 빌드 넘버입니다.


Title Revison Build Number
/Version Level
Windows 2000 RTM  5.0.2195
Windows 2000 SP1  5.0.2195 SP 1
Windows 2000 SP2  5.0.2195 SP 2
Windows 2000 SP3  5.0.2195 SP 3
Windows 2000 SP4  5.0.2195 SP 4
Windows XP RTM  5.1.2600
Windows XP SP1  5.1.2600.1106
Windows XP SP2  5.1.2600.2180
Windows XP SP3  5.1.2600.5512
Windows Server 2003 RTM  5.2.3790
Windows Server 2003 SP1  5.2.3790.1180
Windows Server 2003 SP2  5.2.3790.3959
Windows Server 2003 R2 SP1  5.2.3790.1180
Windows Fundamentals SP3 5.1.2600.5512
Windows Vista RTM 6.0.6000.16386
Windows Vista SP1 6.0.6001.18000
Windows Vista SP2 6.0.6002.18005
Windows Home Server 5.2.4500
Windows Server 2008 RTM/SP1 6.0.6001.18000
Windows Server 2008 SP2  6.0.6002.18005
Windows 7 RTM  6.1.7600.16385
Windows Server 2008 R2 RTM  6.1.7600.16385

앞선 이미지에서의 MinorVersion 필드의 값이 0xa28, 즉 빌드넘버가 2600이기 때문에 Windows XP라는 것을 확인할 수 있습니다.


* 알림 : 이 글은 'JS's stuff' 블로그의 'Identifying Memory Images'를 참고 인용 및 일부 개인적인 지식을 요약 정리한 것입니다.





Leave a Reply