00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #define LIBSMBIOS_SOURCE
00020 #include "MemoryImpl.h"
00021 #include "miniddk.h"
00022
00023
00024 #include "smbios/message.h"
00025
00026 using namespace std;
00027
00028 namespace memory
00029 {
00030 MemoryFactoryImpl::MemoryFactoryImpl()
00031 {
00032 setParameter("memFile", "\\Device\\PhysicalMemory");
00033 }
00034
00035
00036
00037 NtOpenSectionPtr NtOpenSection = NULL;
00038 NtClosePtr NtClose = NULL;
00039 NtMapViewOfSectionPtr NtMapViewOfSection = NULL;
00040 NtUnmapViewOfSectionPtr NtUnmapViewOfSection = NULL;
00041 RtlInitUnicodeStringPtr RtlInitUnicodeString = NULL;
00042 ZwSystemDebugControlPtr ZwSystemDebugControl = NULL;
00043
00044 EnumSystemFirmwareTablesPtr EnumSystemFirmwareTables = NULL;
00045 GetSystemFirmwareTablePtr GetSystemFirmwareTable = NULL;
00046 u8 * CBlockBuffer = NULL;
00047 u8 * EBlockBuffer = NULL;
00048 int reopenHint = 1;
00049
00050 int LoadNtdllFuncs(void)
00051 {
00052 HMODULE hNtdll;
00053 HMODULE hKerneldll;
00054
00055 hNtdll = GetModuleHandle(L"ntdll.dll");
00056 hKerneldll = GetModuleHandle( L"kernel32.dll" );
00057 if (!(hNtdll && hKerneldll))
00058 return FALSE;
00059
00060
00061 NtOpenSection = (NtOpenSectionPtr) GetProcAddress(hNtdll, "NtOpenSection");
00062 NtClose = (NtClosePtr) GetProcAddress(hNtdll, "NtClose");
00063 NtMapViewOfSection = (NtMapViewOfSectionPtr) GetProcAddress(hNtdll, "NtMapViewOfSection");
00064 NtUnmapViewOfSection = (NtUnmapViewOfSectionPtr) GetProcAddress(hNtdll, "NtUnmapViewOfSection");
00065 RtlInitUnicodeString = (RtlInitUnicodeStringPtr) GetProcAddress(hNtdll, "RtlInitUnicodeString");
00066 ZwSystemDebugControl = (ZwSystemDebugControlPtr) GetProcAddress(hNtdll, "ZwSystemDebugControl");
00067
00068
00069
00070 EnumSystemFirmwareTables = (EnumSystemFirmwareTablesPtr) GetProcAddress(hKerneldll, "EnumSystemFirmwareTables");
00071 GetSystemFirmwareTable = (GetSystemFirmwareTablePtr) GetProcAddress(hKerneldll, "GetSystemFirmwareTable");
00072
00073 return TRUE;
00074 }
00075
00076
00077
00078
00079 HANDLE OpenMemAccess(void)
00080 {
00081 UNICODE_STRING usDevmem;
00082 OBJECT_ATTRIBUTES oaAttrs;
00083 NTSTATUS status;
00084 HANDLE hPhysMem = NULL;
00085
00086 RtlInitUnicodeString(&usDevmem, L"\\device\\physicalmemory");
00087 InitializeObjectAttributes(&oaAttrs, &usDevmem, OBJ_CASE_INSENSITIVE, NULL, NULL);
00088 status = NtOpenSection(&hPhysMem, SECTION_MAP_READ, &oaAttrs);
00089
00090 if (!NT_SUCCESS(status))
00091 {
00092 hPhysMem = NULL;
00093 }
00094
00095 return hPhysMem;
00096 }
00097
00098 int CloseMemAccess(HANDLE hPhysMem)
00099 {
00100 NTSTATUS status;
00101
00102 status = NtClose(hPhysMem);
00103
00104 if (!NT_SUCCESS(status))
00105 {
00106 return FALSE;
00107 }
00108
00109 return TRUE;
00110 }
00111
00112 int MapMem(HANDLE hPhysMem, PVOID pBaseAddr, PDWORD pPhysAddr, PDWORD pSize)
00113 {
00114 NTSTATUS status;
00115 PHYSICAL_ADDRESS paAddr;
00116
00117 * (DWORD *) pBaseAddr = (DWORD) NULL;
00118 paAddr.HighPart = 0;
00119 paAddr.LowPart = *pPhysAddr;
00120 status = NtMapViewOfSection(hPhysMem, NtCurrentProcess(), (PVOID *) pBaseAddr, 0L,
00121 *pSize, &paAddr, pSize, ViewShare, 0, PAGE_READONLY);
00122
00123 if (!NT_SUCCESS(status))
00124 {
00125 hPhysMem = NULL;
00126 return FALSE;
00127 }
00128
00129 *pPhysAddr = paAddr.LowPart;
00130 return TRUE;
00131 }
00132
00133 int UnMapMem(PVOID pBaseAddr)
00134 {
00135 NTSTATUS status;
00136
00137 status = NtUnmapViewOfSection(NtCurrentProcess(), pBaseAddr);
00138
00139 if (!NT_SUCCESS(status))
00140 {
00141 return FALSE;
00142 }
00143
00144 return TRUE;
00145 }
00146
00147 static BOOL setPrivilege(LPCTSTR privilegeName, BOOL enable)
00148 {
00149 HANDLE hToken;
00150 HANDLE hCurrentProcess;
00151 DWORD err;
00152 TOKEN_PRIVILEGES tkprivs;
00153
00154
00155 hCurrentProcess = GetCurrentProcess();
00156 if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
00157 {
00158
00159 LookupPrivilegeValue(NULL, privilegeName, &tkprivs.Privileges[0].Luid);
00160 tkprivs.PrivilegeCount = 1;
00161 tkprivs.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
00162
00163
00164 AdjustTokenPrivileges(hToken, FALSE, &tkprivs, 0, (PTOKEN_PRIVILEGES)NULL, NULL);
00165 }
00166
00167 err = GetLastError();
00168
00169 return err == ERROR_SUCCESS;
00170 }
00171
00172 void readPhysicalMemoryMap( HANDLE hPhysMem, u8 *buffer, u64 offset, unsigned int length)
00173 {
00174 unsigned int totalBytes = 0;
00175 unsigned int originalSize = length;
00176 unsigned int pageSize = length;
00177
00178 if(!hPhysMem)
00179 {
00180 throw AccessErrorImpl( _("Handle to physical memory was not set or could not be opened.") );
00181 }
00182
00183 if(0 == buffer)
00184 {
00185 throw AccessErrorImpl( _("Error accessing buffer.") );
00186 }
00187
00188 while(totalBytes != originalSize )
00189 {
00190 DWORD BaseAddr;
00191 DWORD PhysAddr = static_cast<DWORD>(offset);
00192
00193
00194
00195
00196 if (!MapMem(hPhysMem, (PVOID) &BaseAddr, &PhysAddr, reinterpret_cast<PDWORD>(&pageSize)))
00197 {
00198 throw AccessErrorImpl( _("Error mapping physical memory.") );
00199 }
00200
00201
00202 unsigned int index = static_cast<DWORD>(offset) - PhysAddr;
00203
00204
00205
00206 while( index < pageSize && totalBytes != originalSize)
00207 {
00208 u64 tmp = BaseAddr + index;
00209 buffer[totalBytes] = *reinterpret_cast<u8 *>(tmp);
00210 index++;
00211 totalBytes++;
00212 }
00213
00214 u64 tmp = BaseAddr;
00215 if (!UnMapMem(reinterpret_cast<PVOID>(tmp)))
00216 {
00217 throw AccessErrorImpl( _("Error unmapping physical memory."));
00218 }
00219
00220
00221
00222
00223 offset = PhysAddr + index;
00224 pageSize = originalSize-totalBytes;
00225 }
00226 }
00227
00228 void readPhysicalMemoryDebugSysctl( u8 *buffer, u64 offset, unsigned int length)
00229 {
00230 MEM_STRUCT mem;
00231 NTSTATUS status;
00232 ULONG bytesReturned;
00233
00234 memset(&mem, 0, sizeof(mem));
00235 mem.Addr = (DWORD)offset;
00236 mem.pBuf = buffer;
00237 mem.NumBytes = (DWORD)length;
00238
00239 status = ZwSystemDebugControl(DebugSysReadPhysicalMemory,
00240 &mem,
00241 sizeof(mem),
00242 0,
00243 0,
00244 &bytesReturned);
00245 if (! NT_SUCCESS(status) )
00246 {
00247 throw AccessErrorImpl( _("Could not use Debug Sysctl to read physical memory."));
00248 }
00249 }
00250
00251
00252
00253
00254 void enumSystemFirmwareTables( u8 *buffer, u64 offset, unsigned int length)
00255 {
00256
00257
00258 if( offset >= 0xC0000 && offset < 0xDFFFF && CBlockBuffer != NULL )
00259 {
00260 memset( buffer, 0, length );
00261 memcpy( buffer, &CBlockBuffer[(DWORD)offset - 0xC0000], length );
00262 return;
00263 }
00264
00265
00266
00267 if( offset >= 0xE0000 && offset < 0xFFFFF && EBlockBuffer != NULL )
00268 {
00269 memset( buffer, 0, length );
00270 memcpy( buffer, &EBlockBuffer[(DWORD)offset - 0xE0000], length );
00271 return;
00272 }
00273
00274 DWORD iSignature = 0x46000000 | 0x00490000 | 0x00005200 | 0x0000004D ;
00275
00276
00277 unsigned int iBufferSizeNeeded = EnumSystemFirmwareTables( iSignature, NULL, 0 );
00278 if( iBufferSizeNeeded > 0 )
00279 {
00280 DWORD * FirmwareTableEnumBuffer = new DWORD[iBufferSizeNeeded];
00281 ULONG i=0;
00282 for( i = 0; i < iBufferSizeNeeded; i++ )
00283 {
00284 FirmwareTableEnumBuffer[i] = 0;
00285 }
00286
00287 EnumSystemFirmwareTables( iSignature, FirmwareTableEnumBuffer, iBufferSizeNeeded );
00288 DWORD FirmwareTableNameToUse = 0;
00289 for( i = 0; i < iBufferSizeNeeded; i++ )
00290 {
00291 if( FirmwareTableEnumBuffer[i] > 0 && FirmwareTableEnumBuffer[i] <= offset && offset <= FirmwareTableEnumBuffer[i] + 128 * 1024 )
00292 {
00293 FirmwareTableNameToUse = FirmwareTableEnumBuffer[i];
00294 }
00295 }
00296 delete [] FirmwareTableEnumBuffer;
00297
00298 if( FirmwareTableNameToUse == 0 )
00299 {
00300 throw AccessErrorImpl( _("Could not locate a table which can be used.") );
00301 }
00302
00303
00304 iBufferSizeNeeded = GetSystemFirmwareTable( iSignature, FirmwareTableNameToUse, NULL, 0 );
00305 if( iBufferSizeNeeded > 0 )
00306 {
00307 u8 * MemoryAtRequestedOffSet = NULL;
00308 MemoryAtRequestedOffSet = new u8[iBufferSizeNeeded];
00309 if( MemoryAtRequestedOffSet != NULL )
00310 {
00311 memset( MemoryAtRequestedOffSet, 0, iBufferSizeNeeded );
00312 memset( buffer, 0, length );
00313 GetSystemFirmwareTable( iSignature, FirmwareTableNameToUse, MemoryAtRequestedOffSet, iBufferSizeNeeded );
00314 memcpy( buffer, &MemoryAtRequestedOffSet[(DWORD)offset - FirmwareTableNameToUse], length );
00315 if( FirmwareTableNameToUse == 0xC0000 )
00316 {
00317 CBlockBuffer = MemoryAtRequestedOffSet;
00318 }
00319 else
00320 if( FirmwareTableNameToUse == 0xE0000 )
00321 {
00322 EBlockBuffer = MemoryAtRequestedOffSet;
00323 }
00324 else
00325 {
00326 delete MemoryAtRequestedOffSet;
00327 }
00328 }
00329 else
00330 {
00331 throw AccessErrorImpl( _("Failed to allocate memory for Firmware table.") );
00332 }
00333 }
00334 else
00335 {
00336 throw AccessErrorImpl( _("GetSystemFirmwareTable returned 0 for table length.") );
00337 }
00338 }
00339 else
00340 {
00341 throw AccessErrorImpl( _("EnumSystemFirmwareTables returned 0 for table size.") );
00342 }
00343 }
00344
00345
00346 MemoryOsSpecific::MemoryOsSpecific( const string )
00347 : IMemory()
00348 {
00349 HANDLE hPhysMem = NULL;
00350
00351 if (!LoadNtdllFuncs())
00352 {
00353
00354
00355 throw AccessErrorImpl( _("Could not load ntdll functions!") );
00356 }
00357
00358
00359
00360 setPrivilege(SE_DEBUG_NAME, 1);
00361
00362 hPhysMem = OpenMemAccess();
00363
00364 osData = static_cast<HANDLE *>(hPhysMem);
00365 }
00366
00367 MemoryOsSpecific::~MemoryOsSpecific()
00368 {
00369 HANDLE hPhysMem = static_cast<HANDLE>(osData);
00370
00371
00372 if(hPhysMem)
00373 {
00374 CloseMemAccess(hPhysMem);
00375 }
00376
00377 delete CBlockBuffer;
00378 CBlockBuffer = NULL;
00379
00380 delete EBlockBuffer;
00381 EBlockBuffer = NULL;
00382 }
00383
00384 void MemoryOsSpecific::fillBuffer( u8 *buffer, u64 offset, unsigned int length) const
00385 {
00386
00387 if( EnumSystemFirmwareTables && GetSystemFirmwareTable )
00388 {
00389
00390
00391
00392
00393 enumSystemFirmwareTables( buffer, offset, length );
00394 }
00395 else
00396 {
00397 HANDLE hPhysMem = static_cast<HANDLE>(osData);
00398 if(hPhysMem)
00399 {
00400 readPhysicalMemoryMap( hPhysMem, buffer, offset, length );
00401 }
00402 else
00403 {
00404 readPhysicalMemoryDebugSysctl( buffer, offset, length );
00405 }
00406 }
00407 }
00408
00409 u8 MemoryOsSpecific::getByte( u64 offset ) const
00410 {
00411 u8 value = 0;
00412 fillBuffer(&value, offset, 1);
00413 return value;
00414 }
00415
00416 void MemoryOsSpecific::putByte( u64 , u8 ) const
00417 {
00418 throw smbios::NotImplementedImpl( _("writing to physical memory is not implemented on Windows yet.") );
00419 }
00420
00421
00422
00423 int MemoryOsSpecific::incReopenHint()
00424 {
00425 return ++reopenHint;
00426 }
00427 int MemoryOsSpecific::decReopenHint()
00428 {
00429 return --reopenHint;
00430 }
00431 }