📄 physmem.c
字号:
//========================================================
//
// 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
);
NTSTATUS (__stdcall *ZwOpenSection)(
PHANDLE SectionHandle,
DWORD DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes
);
/*
typedef NTSTATUS (WINAPI *ZwOpenSectionProc)
(
PHANDLE SectionHandle,
DWORD DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes
);
*/
typedef NTSTATUS (WINAPI *ZwMapViewOfSectionProc)
(
HANDLE SectionHandle,
HANDLE ProcessHandle,
PVOID *BaseAddress,
ULONG ZeroBits,
ULONG CommitSize,
PLARGE_INTEGER SectionOffset,
PULONG ViewSize,
SECTION_INHERIT InheritDisposition,
ULONG AllocationType,
ULONG Protect
);
typedef NTSTATUS (WINAPI *ZwUnmapViewOfSectionProc)
(
HANDLE ProcessHandle,
PVOID BaseAddress
);
typedef VOID (WINAPI *RtlInitUnicodeStringProc)
(
IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString
);
//----------------------------------------------------------------------
//
// 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 );
//PAGE_READWRITE);
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,zwstatus;
HANDLE physmem;
UNICODE_STRING physmemString;
OBJECT_ATTRIBUTES attributes;
WCHAR physmemName[] = L"\\device\\physicalmemory";
RtlInitUnicodeString( &physmemString, physmemName );
InitializeObjectAttributes( &attributes, &physmemString,
OBJ_CASE_INSENSITIVE/*OBJ_VALID_ATTRIBUTES*/, NULL, NULL );
status = NtOpenSection( &physmem, SECTION_MAP_READ/*|SECTION_MAP_WRITE*/, &attributes );
//zwstatus = ZwOpenSection( &physmem, /*SECTION_MAP_READ|*/SECTION_MAP_WRITE, &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()
{
char *pTemp;
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;
}
if( !(ZwOpenSection = (void *) GetProcAddress( GetModuleHandle("ntdll.dll"),
"ZwOpenSection" )) ) {
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;
}
/*
typedef LONG NTSTATUS;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef enum _SECTION_INHERIT
{
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT, *PSECTION_INHERIT;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
// Interesting functions in NTDLL
typedef NTSTATUS (WINAPI *ZwOpenSectionProc)
(
PHANDLE SectionHandle,
DWORD DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes
);
typedef NTSTATUS (WINAPI *ZwMapViewOfSectionProc)
(
HANDLE SectionHandle,
HANDLE ProcessHandle,
PVOID *BaseAddress,
ULONG ZeroBits,
ULONG CommitSize,
PLARGE_INTEGER SectionOffset,
PULONG ViewSize,
SECTION_INHERIT InheritDisposition,
ULONG AllocationType,
ULONG Protect
);
typedef NTSTATUS (WINAPI *ZwUnmapViewOfSectionProc)
(
HANDLE ProcessHandle,
PVOID BaseAddress
);
typedef VOID (WINAPI *RtlInitUnicodeStringProc)
(
IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString
);
// Global variables
static HMODULE hModule = NULL;
static HANDLE hPhysicalMemory = NULL;
static ZwOpenSectionProc ZwOpenSection;
static ZwMapViewOfSectionProc ZwMapViewOfSection;
static ZwUnmapViewOfSectionProc ZwUnmapViewOfSection;
static RtlInitUnicodeStringProc RtlInitUnicodeString;
// initialize
BOOL InitPhysicalMemory()
{
if (!(hModule = LoadLibrary("ntdll.dll")))
{
return FALSE;
}
// 以下从NTDLL获取我们需要的几个函数指针
if (!(ZwOpenSection = (ZwOpenSectionProc)GetProcAddress(hModule, "ZwOpenSection")))
{
return FALSE;
}
if (!(ZwMapViewOfSection = (ZwMapViewOfSectionProc)GetProcAddress(hModule, "ZwMapViewOfSection")))
{
return FALSE;
}
if (!(ZwUnmapViewOfSection = (ZwUnmapViewOfSectionProc)GetProcAddress(hModule, "ZwUnmapViewOfSection")))
{
return FALSE;
}
if (!(RtlInitUnicodeString = (RtlInitUnicodeStringProc)GetProcAddress(hModule, "RtlInitUnicodeString")))
{
return FALSE;
}
// 以下打开内核对象
WCHAR PhysicalMemoryName[] = L"\\Device\\PhysicalMemory";
UNICODE_STRING PhysicalMemoryString;
OBJECT_ATTRIBUTES attributes;
RtlInitUnicodeString(&PhysicalMemoryString, PhysicalMemoryName);
InitializeObjectAttributes(&attributes, &PhysicalMemoryString, 0, NULL, NULL);
NTSTATUS status = ZwOpenSection(&hPhysicalMemory, SECTION_MAP_READ, &attributes );
return (status >= 0);
}
// terminate -- free handles
void ExitPhysicalMemory()
{
if (hPhysicalMemory != NULL)
{
CloseHandle(hPhysicalMemory);
}
if (hModule != NULL)
{
FreeLibrary(hModule);
}
}
BOOL ReadPhysicalMemory(PVOID buffer, DWORD address, DWORD length)
{
DWORD outlen; // 输出长度,根据内存分页大小可能大于要求的长度
PVOID vaddress; // 映射的虚地址
NTSTATUS status; // NTDLL函数返回的状态
LARGE_INTEGER base; // 物理内存地址
vaddress = 0;
outlen = length;
base.QuadPart = (ULONGLONG)(address);
// 映射物理内存地址到当前进程的虚地址空间
status = ZwMapViewOfSection(hPhysicalMemory,
(HANDLE) -1,
(PVOID *)&vaddress,
0,
length,
&base,
&outlen,
ViewShare,
0,
PAGE_READONLY);
if (status < 0)
{
return FALSE;
}
// 当前进程的虚地址空间中,复制数据到输出缓冲区
memmove(buffer, vaddress, length);
// 完成访问,取消地址映射
status = ZwUnmapViewOfSection((HANDLE)-1, (PVOID)vaddress);
return (status >= 0);
}
// 一个测试函数,从物理地址0xfe000开始,读取4096个字节
// 对于Award BIOS,可以从这段数据找到序列号等信息
BOOL test()
{
UCHAR buf[4096];
if (!InitPhysicalMemory())
{
return FALSE;
}
if (!ReadPhysicalMemory(buf, 0xfe000, 4096))
{
// ... 成功读取了指定数据
ExitPhysicalMemory();
return FALSE;
}
ExitPhysicalMemory();
return TRUE;
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -