Proneer | Security is a people problem...
WMI(Windows Management Instrumentation)는 네트워크에서 관리 정보를 공유하는 표준을 만들기 위한 업계의 발의인 WBEM(Web-Based Enterprise Management Initiative)를 Microsoft에서 구현한 것이다. 다시 말해, WMI는 Windows 환경에서 관리 정보(OS, 서비스, 응용프로그램 등)를 공유하기 위한 표준인 것이다.
WMI는 Windows NT 4.0 SP4에 처음 릴리즈 되었는데 이때는 15개의 WMI 공급자를 사용할 수 있었다. 이후 Windows 2000 에는 29개, Windows 2003 에서는 80개, 이후 Vista, Server 2008을 거치면서 100개의 공급자를 지원하고 있다. 이러한 공급자 하에서 관리 정보를 액세스하기 위해서는 관리 정보를 조작할 수 있는 "서버탐색기"라는 기능을 통해 가능하다.
서버탐색기를 통해 관리 정보를 획득하기 위해서는 미리 정의된 WMI 클래스를 이용하여 서버탐색기에 WQL(WMI Query Language) 질의를 통해 가능하다. WMI 클래스는 다음을 통해 확인 가능하다.
http://msdn.microsoft.com/en-us/library/aa394084(VS.85).aspx
WMI 클래스들 중 저장장치의 정보를 얻기 위한 클래스는 다음과 같다.
이외에도 Windows 환경에서 제공하는 다양한 정보(거의 모든 정보)를 WMI 클래스 질의를 통해 액세스가 가능하다. 또한 하나 이상의 클래스를 조합하여 질의가 가능하다. 다음은 앞서 살펴본 4개의 클래스를 이용하여 저장장치 정보를 액세스하게 만든 프로그램이다.
다음은 Win32_LogicalDisk 클래스와 Win32_DiskPartition 클래스의 연관된 정보를 액세스하는 예제 코드이다.
WMI (Windows Management Instrumentation)
WMI(Windows Management Instrumentation)는 네트워크에서 관리 정보를 공유하는 표준을 만들기 위한 업계의 발의인 WBEM(Web-Based Enterprise Management Initiative)를 Microsoft에서 구현한 것이다. 다시 말해, WMI는 Windows 환경에서 관리 정보(OS, 서비스, 응용프로그램 등)를 공유하기 위한 표준인 것이다.
WMI는 Windows NT 4.0 SP4에 처음 릴리즈 되었는데 이때는 15개의 WMI 공급자를 사용할 수 있었다. 이후 Windows 2000 에는 29개, Windows 2003 에서는 80개, 이후 Vista, Server 2008을 거치면서 100개의 공급자를 지원하고 있다. 이러한 공급자 하에서 관리 정보를 액세스하기 위해서는 관리 정보를 조작할 수 있는 "서버탐색기"라는 기능을 통해 가능하다.
서버탐색기를 통해 관리 정보를 획득하기 위해서는 미리 정의된 WMI 클래스를 이용하여 서버탐색기에 WQL(WMI Query Language) 질의를 통해 가능하다. WMI 클래스는 다음을 통해 확인 가능하다.
http://msdn.microsoft.com/en-us/library/aa394084(VS.85).aspx
WMI 클래스들 중 저장장치의 정보를 얻기 위한 클래스는 다음과 같다.
- Win32_PhysicalMedia
- Win32_DiskDrive
- Win32_DiskPartition
- Win32_LogicalDisk
이외에도 Windows 환경에서 제공하는 다양한 정보(거의 모든 정보)를 WMI 클래스 질의를 통해 액세스가 가능하다. 또한 하나 이상의 클래스를 조합하여 질의가 가능하다. 다음은 앞서 살펴본 4개의 클래스를 이용하여 저장장치 정보를 액세스하게 만든 프로그램이다.
다음은 Win32_LogicalDisk 클래스와 Win32_DiskPartition 클래스의 연관된 정보를 액세스하는 예제 코드이다.
//
// File Name : PartitionToDrive.h
//
#pragma once
#include "resource.h"
#define MAX_DRIVE_LETTER 256
#define RADIX 10
typedef struct tagDiskToPartition DISKTOPARTITION;
/*
* disk(e.i. \\PHSYICALDRIVE0 or SAMSUNG HD154C
* patition(e.i. C:, D: or E: ...)
*/
struct tagDiskToPartition
{
WCHAR szDiskDrive_Index[MAX_DRIVE_LETTER];
WCHAR szDiskDrive_DeviceID[MAX_DRIVE_LETTER];
WCHAR szDiskDrive_Model[MAX_DRIVE_LETTER];
WCHAR szDiskDrive_Size[MAX_DRIVE_LETTER];
WCHAR szLogicalDisk_DeviceID[MAX_DRIVE_LETTER];
WCHAR szLogicalDisk_Description[MAX_DRIVE_LETTER];
WCHAR szLogicalDisk_FileSystem[MAX_DRIVE_LETTER];
};
BOOL wmi_run();
BOOL wmi_get_PartitionToDrive(CList *listDiskToPartition);
BOOL wmi_close();
// // File Name : PartitionToDrive.cpp // #include "stdafx.h" #include "PartitionToDrive.h" #ifdef _DEBUG #define new DEBUG_NEW #endif #define _WIN32_DCOM #includeusing namespace std; #include #include #pragma comment(lib, "wbemuuid.lib") CWinApp theApp; using namespace std; IWbemLocator *pLoc = NULL; IWbemServices *pSvc = NULL; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { CList listDiskToPartition; wmi_run(); wmi_get_PartitionToDrive(&listDiskToPartition); system("pause"); wmi_close(); POSITION pos; DISKTOPARTITION sDiskToPartition; for (pos = listDiskToPartition.GetHeadPosition(); pos != NULL;) { sDiskToPartition = listDiskToPartition.GetNext(pos); if (wcscmp(sDiskToPartition.szDiskDrive_DeviceID, L"")) wcout << L"Disk DeviceID : " << sDiskToPartition.szDiskDrive_DeviceID << endl; if (wcscmp(sDiskToPartition.szDiskDrive_Index, L"")) wcout << L"Disk Index : " << sDiskToPartition.szDiskDrive_Index << endl; if (wcscmp(sDiskToPartition.szDiskDrive_Model, L"")) wcout << L"Disk Model : " << sDiskToPartition.szDiskDrive_Model << endl; if (wcscmp(sDiskToPartition.szDiskDrive_Size, L"")) wcout << L"Disk Size : " << sDiskToPartition.szDiskDrive_Size << endl; if (wcscmp(sDiskToPartition.szLogicalDisk_Description, L"")) { wcout.imbue( locale("korean") ); wcout << L"Partition Decription : " << sDiskToPartition.szLogicalDisk_Description << endl; } if (wcscmp(sDiskToPartition.szLogicalDisk_DeviceID, L"")) wcout << L"Partition DeviceID : " << sDiskToPartition.szLogicalDisk_DeviceID << endl; if (wcscmp(sDiskToPartition.szLogicalDisk_FileSystem, L"")) wcout << L"Partition FileSystem : " << sDiskToPartition.szLogicalDisk_FileSystem << endl; wcout << L"---------------------------------------" << endl; } listDiskToPartition.RemoveAll(); return 0; } //// Step 1-5 at:// http://msdn.microsoft.com/en-us/library/aa390423(VS.85).aspx BOOL wmi_run() { HRESULT hres; // Step 1: -------------------------------------------------- // Initialize COM. ------------------------------------------ hres = CoInitializeEx(0, COINIT_APARTMENTTHREADED); if (FAILED(hres)) { cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl; return 1; // Program has failed. } // Step 2: -------------------------------------------------- // Set general COM security levels -------------------------- // Note: If you are using Windows 2000, you need to specify - // the default authentication credentials for a user by using // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ---- // parameter of CoInitializeSecurity ------------------------ hres = CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); if (FAILED(hres)) { cout << "Failed to initialize security. Error code = 0x" << hex << hres << endl; CoUninitialize(); return 1; // Program has failed. } // Step 3: --------------------------------------------------- // Obtain the initial locator to WMI ------------------------- //IWbemLocator *pLoc = NULL; hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hres)) { cout << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << endl; CoUninitialize(); return 1; // Program has failed. } // Step 4: ----------------------------------------------------- // Connect to WMI through the IWbemLocator::ConnectServer method //IWbemServices *pSvc = NULL; // Connect to the root\cimv2 namespace with // the current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (e.g. Kerberos) 0, // Context object &pSvc // pointer to IWbemServices proxy ); if (FAILED(hres)) { cout << "Could not connect. Error code = 0x" << hex << hres << endl; pLoc->Release(); CoUninitialize(); return 1; // Program has failed. } cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl; // Step 5: -------------------------------------------------- // Set security levels on the proxy ------------------------- hres = CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { cout << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); return 1; // Program has failed. } return 0; } BOOL wmi_close() { // Cleanup // ======== pSvc->Release(); pLoc->Release(); CoUninitialize(); return 0; // Program successfully completed. } BOOL wmi_get_PartitionToDrive(CList *listDiskToPartition) { // Use the IWbemServices pointer to make requests of WMI. // Make requests here: HRESULT hres; IEnumWbemClassObject* pEnumerator = NULL; // logical disk 정보에 대한 쿼리 요청 hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM Win32_LogicalDisk"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (FAILED(hres)) { cout << "Query for processes failed. " << "Error code = 0x" << hex << hres << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); return FALSE; // Program has failed. } else { IWbemClassObject *pclsObj; ULONG uReturn = 0; while (pEnumerator) { DISKTOPARTITION sDiskToPartition; ::ZeroMemory(&sDiskToPartition, sizeof(sDiskToPartition)); hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if(0 == uReturn) break; // logical disk 쿼리 결과에서 원하는 정보 획득 VARIANT vtLogicalDisk_DeviceID, vtLogicalDisk_Description, vtLogicalDisk_FileSystem; hres = pclsObj->Get(_bstr_t(L"DeviceID"), 0, &vtLogicalDisk_DeviceID, 0, 0); hres = pclsObj->Get(_bstr_t(L"Description"), 0, &vtLogicalDisk_Description, 0, 0); hres = pclsObj->Get(_bstr_t(L"FileSystem"), 0, &vtLogicalDisk_FileSystem, 0, 0); // logical disk deviceID 와 연관된 Partition 정보를 가져오기 위한 쿼리 생성 wstring tmp = vtLogicalDisk_DeviceID.bstrVal; wstring wstrQuery = L"Associators of {Win32_LogicalDisk.DeviceID='"; wstrQuery += tmp; wstrQuery += L"'} where AssocClass=Win32_LogicalDiskToPartition"; // 해당 쿼리문으로 쿼리 IEnumWbemClassObject* pEnumerator1 = NULL; hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t( wstrQuery.c_str()), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator1 ); if ( FAILED(hres) ) { cout << "Query for processes failed. " << "Error code = 0x" << hex << hres << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); return FALSE; // Program has failed. } else { IWbemClassObject *pclsObj1; ULONG uReturn1 = 0; while( pEnumerator1 ) { hres = pEnumerator1->Next( WBEM_INFINITE, 1, &pclsObj1, &uReturn1 ); if(0 == uReturn1) { // logical disk 정보(C: or d: ...) 의 정보만 존재하는 경우 // 파티션이 나눠진 경우가 아니라 독립된 장치로 존재하는 경우(A:, CD-ROM or virtual CD-ROM) BOOL bFlag = FALSE; POSITION pos = NULL; DISKTOPARTITION tmpDiskToPartition; // 중복 제거를 위해 for (pos = listDiskToPartition->GetHeadPosition(); pos != NULL;) { tmpDiskToPartition = listDiskToPartition->GetNext(pos); if (!wcscmp(tmpDiskToPartition.szLogicalDisk_DeviceID, vtLogicalDisk_DeviceID.bstrVal)) { bFlag = TRUE; break; } } if (!bFlag) { // if vt == 1, 정보를 가져오지 못한 경우 if (vtLogicalDisk_DeviceID.vt != 1) wcscpy(sDiskToPartition.szLogicalDisk_DeviceID, vtLogicalDisk_DeviceID.bstrVal); if (vtLogicalDisk_Description.vt != 1) wcscpy(sDiskToPartition.szLogicalDisk_Description, vtLogicalDisk_Description.bstrVal); if (vtLogicalDisk_FileSystem.vt != 1) wcscpy(sDiskToPartition.szLogicalDisk_FileSystem, vtLogicalDisk_FileSystem.bstrVal); listDiskToPartition->AddTail(sDiskToPartition); } break; } // Partition 정보와 연관된 Disk Drive 정보를 가져오기 위한 쿼리 생성 VARIANT vtDiskPartition_DeviceID; hres = pclsObj1->Get( _bstr_t(L"DeviceID"), 0, &vtDiskPartition_DeviceID, 0, 0 ); wstring wstrQuery = L"Associators of {Win32_DiskPartition.DeviceID='"; wstrQuery += vtDiskPartition_DeviceID.bstrVal; wstrQuery += L"'} where AssocClass=Win32_DiskDriveToDiskPartition"; // 생성한 쿼리문으로 쿼리 IEnumWbemClassObject* pEnumerator2 = NULL; hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t(wstrQuery.c_str()), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator2 ); if ( FAILED(hres) ) { cout << "Query for processes failed. " << "Error code = 0x" << hex << hres << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); return FALSE; // Program has failed. } else { IWbemClassObject *pclsObj2; ULONG uReturn2 = 0; while( pEnumerator2 ) { hres = pEnumerator2->Next( WBEM_INFINITE, 1, &pclsObj2, &uReturn2 ); if(0 == uReturn2) { break; } // 쿼리 결과에서 원하는 정보 획득(disk drive) VARIANT vtDiskDrive_DeviceID, vtDiskDrive_Index, vtDiskDrive_Model, vtDiskDrive_Size; hres = pclsObj2->Get( _bstr_t(L"Index"), 0, &vtDiskDrive_Index, 0, 0 ); hres = pclsObj2->Get( _bstr_t(L"DeviceID"), 0, &vtDiskDrive_DeviceID, 0, 0 ); hres = pclsObj2->Get( _bstr_t(L"Model"), 0, &vtDiskDrive_Model, 0, 0 ); hres = pclsObj2->Get( _bstr_t(L"Size"), 0, &vtDiskDrive_Size, 0, 0 ); BOOL bFlag = FALSE; POSITION pos = NULL; DISKTOPARTITION tmpDiskToPartition; WCHAR szBuf[MAX_DRIVE_LETTER]; ZeroMemory(szBuf, sizeof(szBuf)); // 중복 제거를 위해 for (pos = listDiskToPartition->GetHeadPosition(); pos != NULL;) { tmpDiskToPartition = listDiskToPartition->GetNext(pos); if (!wcscmp(tmpDiskToPartition.szLogicalDisk_DeviceID, vtLogicalDisk_DeviceID.bstrVal)) { bFlag = TRUE; break; } } if (!bFlag) { if (vtDiskDrive_DeviceID.vt != 1) wcscpy(sDiskToPartition.szDiskDrive_DeviceID, vtDiskDrive_DeviceID.bstrVal); if (vtDiskDrive_DeviceID.vt != 1) { _itow(vtDiskDrive_Index.uintVal, szBuf, RADIX); wcscpy(sDiskToPartition.szDiskDrive_Index, szBuf); } if (vtDiskDrive_Model.vt != 1) wcscpy(sDiskToPartition.szDiskDrive_Model, vtDiskDrive_Model.bstrVal); if (vtDiskDrive_Size.vt != 1) wcscpy(sDiskToPartition.szDiskDrive_Size, vtDiskDrive_Size.bstrVal); if (vtLogicalDisk_DeviceID.vt != 1) wcscpy(sDiskToPartition.szLogicalDisk_DeviceID, vtLogicalDisk_DeviceID.bstrVal); if (vtLogicalDisk_Description.vt != 1) wcscpy(sDiskToPartition.szLogicalDisk_Description, vtLogicalDisk_Description.bstrVal); if (vtLogicalDisk_FileSystem.vt != 1) wcscpy(sDiskToPartition.szLogicalDisk_FileSystem, vtLogicalDisk_FileSystem.bstrVal); listDiskToPartition->AddTail(sDiskToPartition); } VariantClear( &vtDiskDrive_Index ); VariantClear( &vtDiskDrive_DeviceID ); VariantClear( &vtDiskDrive_Model ); VariantClear( &vtDiskDrive_Size ); } pclsObj1->Release(); } VariantClear( &vtDiskPartition_DeviceID ); pEnumerator2->Release(); } pclsObj->Release(); } VariantClear( &vtLogicalDisk_DeviceID ); VariantClear( &vtLogicalDisk_Description ); VariantClear( &vtLogicalDisk_FileSystem ); pEnumerator1->Release(); } } pEnumerator->Release(); return TRUE; }
'Storage Forensics' 카테고리의 다른 글
| Small Computer System Interface- Part 1 [presentation] (0) | 2010/05/27 |
|---|---|
| LVM (Logical Volume Manager) (2) | 2010/03/30 |
| WMI (Windows Management Instrumentation) (0) | 2009/11/23 |
| 컴퓨터 하드웨어 (3) - 구성 요소 (0) | 2009/11/16 |
| 컴퓨터 하드웨어 (2) - 저장장치 (0) | 2009/11/16 |
| 컴퓨터 하드웨어 (1) - 기억장치 (0) | 2009/11/16 |
WMIEx.exe
댓글을 달아 주세요