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