阅读:1146回复:6
怎样写一个访问系统无力内存的driver?
Hi, 各位高手们:
小弟还是一个driver新手。小弟现在正在做一项任务,其中要在Windows下访问系统物理内存,包括读写物理内存。我想的话,这个工作只能通过driver来做了。小弟只大概知道一点如何访问IO,对于访问系统无力内存一点不是很清楚,只是知道首先要映射物理内存到系统线性地址空间。请问各位大虾们帮帮忙,能给小弟一点这方面的例子或资料吗?如果您曾经写过这样的driver,我希望您能慷慨的给小弟参考一下,谢谢! 非常希望能得到您的帮助。 |
|
沙发#
发布于:2003-09-23 22:36
9X 下可以调用_MapPhysToLinear把物理内存映射到线性地址。
2000下可以参考 http://www.sysinternals.com/files/physmem.zip |
|
板凳#
发布于:2003-09-23 23:13
//========================================================
// // Physmem // // Mark Russinovich // Systems Internals // http://www.sysinternals.com // // This program demonstrates how you can open and // map physical memory. This is essentially the NT // equivalent of the \\dev\\kmem device in UNIX. // //======================================================== #include <windows.h> #include <stdio.h> #include \"native.h\" // // Number of bytes to print per line // #define BYTESPERLINE 16 // // Lines to print before pause // #define LINESPERSCREEN 25 // // Functions in NTDLL that we dynamically locate // NTSTATUS (__stdcall *NtUnmapViewOfSection)( IN HANDLE ProcessHandle, IN PVOID BaseAddress ); NTSTATUS (__stdcall *NtOpenSection)( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSTATUS (__stdcall *NtMapViewOfSection)( IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG ZeroBits, IN ULONG CommitSize, IN OUT PLARGE_INTEGER SectionOffset, /* optional */ IN OUT PULONG ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect ); VOID (__stdcall *RtlInitUnicodeString)( IN OUT PUNICODE_STRING DestinationString, IN PCWSTR SourceString ); ULONG (__stdcall *RtlNtStatusToDosError) ( IN NTSTATUS Status ); //---------------------------------------------------------------------- // // PrintError // // Formats an error message for the last error // //---------------------------------------------------------------------- void PrintError( char *message, NTSTATUS status ) { char *errMsg; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, RtlNtStatusToDosError( status ), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &errMsg, 0, NULL ); printf(\"%s: %s\\n\", message, errMsg ); LocalFree( errMsg ); } //-------------------------------------------------------- // // UnmapPhysicalMemory // // Maps a view of a section. // //-------------------------------------------------------- VOID UnmapPhysicalMemory( DWORD Address ) { NTSTATUS status; status = NtUnmapViewOfSection( (HANDLE) -1, (PVOID) Address ); if( !NT_SUCCESS(status)) { PrintError(\"Unable to unmap view\", status ); } } //-------------------------------------------------------- // // MapPhysicalMemory // // Maps a view of a section. // //-------------------------------------------------------- BOOLEAN MapPhysicalMemory( HANDLE PhysicalMemory, PDWORD Address, PDWORD Length, PDWORD VirtualAddress ) { NTSTATUS ntStatus; PHYSICAL_ADDRESS viewBase; char error[256]; *VirtualAddress = 0; viewBase.QuadPart = (ULONGLONG) (*Address); ntStatus = NtMapViewOfSection (PhysicalMemory, (HANDLE) -1, (PVOID) VirtualAddress, 0L, *Length, &viewBase, Length, ViewShare, 0, PAGE_READONLY ); if( !NT_SUCCESS( ntStatus )) { sprintf( error, \"Could not map view of %X length %X\", *Address, *Length ); PrintError( error, ntStatus ); return FALSE; } *Address = viewBase.LowPart; return TRUE; } //-------------------------------------------------------- // // OpensPhysicalMemory // // This function opens the physical memory device. It // uses the native API since // //-------------------------------------------------------- HANDLE OpenPhysicalMemory() { NTSTATUS status; HANDLE physmem; UNICODE_STRING physmemString; OBJECT_ATTRIBUTES attributes; WCHAR physmemName[] = L\"\\\\device\\\\physicalmemory\"; RtlInitUnicodeString( &physmemString, physmemName ); InitializeObjectAttributes( &attributes, &physmemString, OBJ_CASE_INSENSITIVE, NULL, NULL ); status = NtOpenSection( &physmem, SECTION_MAP_READ, &attributes ); if( !NT_SUCCESS( status )) { PrintError( \"Could not open \\\\device\\\\physicalmemory\", status ); return NULL; } return physmem; } //-------------------------------------------------------- // // LocateNtdllEntryPoints // // Finds the entry points for all the functions we // need within NTDLL.DLL. // //-------------------------------------------------------- BOOLEAN LocateNtdllEntryPoints() { if( !(RtlInitUnicodeString = (void *) GetProcAddress( GetModuleHandle(\"ntdll.dll\"), \"RtlInitUnicodeString\" )) ) { return FALSE; } if( !(NtUnmapViewOfSection = (void *) GetProcAddress( GetModuleHandle(\"ntdll.dll\"), \"NtUnmapViewOfSection\" )) ) { return FALSE; } if( !(NtOpenSection = (void *) GetProcAddress( GetModuleHandle(\"ntdll.dll\"), \"NtOpenSection\" )) ) { return FALSE; } if( !(NtMapViewOfSection = (void *) GetProcAddress( GetModuleHandle(\"ntdll.dll\"), \"NtMapViewOfSection\" )) ) { return FALSE; } if( !(RtlNtStatusToDosError = (void *) GetProcAddress( GetModuleHandle(\"ntdll.dll\"), \"RtlNtStatusToDosError\" )) ) { return FALSE; } return TRUE; } //-------------------------------------------------------- // // Main // // This program drives the command loop // //-------------------------------------------------------- int main( int argc, char *argv[] ) { HANDLE physmem; DWORD vaddress, paddress, length; char input[256]; DWORD lines; char ch; DWORD i, j; printf(\"\\nPhysmem v1.0: physical memory viewer\\n\" \"By Mark Russinovich\\n\" \"Systems Internals - http://www.sysinternals.com\\n\\n\"); // // Load NTDLL entry points // if( !LocateNtdllEntryPoints() ) { printf(\"Unable to locate NTDLL entry points.\\n\\n\"); return -1; } // // Open physical memory // if( !(physmem = OpenPhysicalMemory())) { return -1; } // // Enter the command loop // printf(\"Enter values in hexadecimal. Enter \'q\' to quit.\\n\"); while( 1 ) { printf(\"\\nAddress: \" ); fflush( stdout ); gets( input ); if( input[0] == \'q\' || input[0] == \'Q\' ) break; sscanf( input, \"%x\", &paddress ); printf(\"Bytes: \"); fflush( stdout ); gets( input ); if( input[0] == \'q\' || input[0] == \'Q\' ) break; sscanf( input, \"%x\", &length ); // // Map it // if( !MapPhysicalMemory( physmem, &paddress, &length, &vaddress )) continue; // // Dump it // lines = 0; for( i = 0; i < length; i += BYTESPERLINE ) { printf(\"%08X: \", paddress + i ); for( j = 0; j < BYTESPERLINE; j++ ) { if( i+j == length ) break; if( j == BYTESPERLINE/2 ) printf(\"-\" ); printf(\"%02X \", *(PUCHAR) (vaddress + i +j )); } for( j = 0; j < BYTESPERLINE; j++ ) { if( i+j == length ) break; ch = *(PUCHAR) (vaddress + i +j ); if( __iscsym( ch ) || isalnum( ch ) || ch == \' \') { printf(\"%c\", ch); } else { printf(\".\" ); } } printf(\"\\n\"); if( lines++ == LINESPERSCREEN ) { printf(\"-- more -- (\'q\' to abort)\" ); fflush(stdout); ch = getchar(); if( ch == \'q\' || ch == \'Q\' ) { fflush( stdin ); break; } lines = 0; } } // // Unmap the view // UnmapPhysicalMemory( vaddress ); } // // Close physical memory section // CloseHandle( physmem ); return 0; } 很简单在NT下DEVICE下提供了PHYSICALMEMORY对象,也就是说你可以直接操纵物理地址,正常情况下ADM下可以读他,如果要写需要GETSECURITYINFO SETENTRIESINACL,SETSECURITYINFO,来增加ACL的可写属性 ,然后用ZWOPENSECTION打开这个对象,用MAPVIEWOFFILE影射进你的地址空间,就可以直接操纵物理地址了。 |
|
|
地板#
发布于:2003-09-24 10:40
Hi, wowocock:
非常感谢你的回复。小弟看了一下,还是有点模糊。在测试时我如果输入Address:400, Size:4 他就打出了好多数据,我想问一下,它这些数据是否就是对应的从物理内存0x400开始的一段物理内存数据呢?可是我用WinIO2.0里面的提供的bool _stdcall GetPhysLong(PBYTE pbPhysAddr, PDWORD pdwPhysVal)得到的数据好像与这个不同 |
|
地下室#
发布于:2003-09-24 12:01
没做过,不过读写物理内存2K/XP下很简单的,
可以直接操纵\\device\\physicalmemory 进行读,如果写的话需要ADM下通过GetSecurityInfo,SetEntriesInAcl,SetSecurityInfo来获得对该对象的写权限,网上有很多相关代码参考的. BTW在2003后MS加了限制不能直接操纵\\device\\physicalmemory ,郁闷...... |
|
|
5楼#
发布于:2003-09-24 12:22
没做过,不过读写物理内存2K/XP下很简单的, 真的!!!!! driver 也不能直接操作device\\physicalmemory 这个对象吗!! 那怎么写物理内存,在2003下? 苦! |
|
6楼#
发布于:2003-09-25 00:34
if you \"小弟只大概知道一点如何访问IO\" then it will be easy for you to do 读写物理内存:
1. write a driver, not hardware driver, 2. map the physical memory to system virtual address; 3. make a MDL and get user mode virtual address; 4. pass this user mode virtual address to application; 5. apllication use this user mode virtual address to R/W the physicall address mapped by driver; |
|