Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Проекция файла или как использовать native kernel32 функции ядра

Delphi , Синтаксис , Память и Указатели

Использование native kernel32 функций для получения проекции физической памяти

© 2006 Альберт Мамедов (MagDelphi)

В процессе написания программного обеспечения в ряде случаев возникает необходимость получения данных из физических ячеек памяти. Документации Delphi по данному вопросу, я найти не смог, поэтому хочу восполнить данный пробел.

Платформа WinNT(XP) не допускает возможность непосредственного доступа к памяти средствами Win32API. В этом случае программист должен или написать свой драйвер доступа к физической памяти или использовать native kernel32 функции ядра.

Рассмотрим второй вариант использующий объект "проекция файла" (file-mapping object), представляющем собой блок памяти(раздел) доступный двум и более процессам для совместного использования.

Совместное использование данных с помощью объекта "раздел" происходит следующим образом: Задав атрибуты с помощью функции

Code:

procedure InitializeObjectAttributes(InitializedAttributes : PNtObjectAttributes;
                                    pObjectName : PNtUnicodeString;
                                    const uAttributes : ULONG;
                                    const hRootDirectory : THandle;
                                    pSecurityDescriptor : PSECURITY_DESCRIPTOR);
begin
with InitializedAttributes^ do
begin
   Length := SizeOf(TNtObjectAttributes);
   ObjectName := pObjectName;
   Attributes := uAttributes;
   RootDirectory := hRootDirectory;
   SecurityDescriptor := pSecurityDescriptor;
   SecurityQualityOfService := nil;
end;
end;

 
 
которая фактически заполняет структуру NtObjectAttributes
Используем объект 'DevicePhysicalMemory' и преобразовав его в тип TNtUnicodeString;
RtlInitAnsiString(@AnsiPhysicalMemory, 'DevicePhysicalMemory');
RtlAnsiStringToUnicodeString(@UniPhysicalMemory, @AnsiPhysicalMemory, true);
InitializeObjectAttributes(@NtObjectAttributes, @UniPhysicalMemory, OBJ_KERNEL_HANDLE, 0, nil);

Получаем дескриптор секции вызывая функцию ядра
 

NtOpenSection(SectionHandle, SECTION_MAP_READ, @NtObjectAttributes);
Этим самым мы открываем объект 'DevicePhysicalMemory' для чтения отображенного участка физической памяти в процессе пользователя.
Отображение осуществляем с помощью функции NtMapViewOfSection возвращающей указатель на участок памяти процесса пользователя в который осуществляется отображение. Более подробную информацию можно найти в MicrosoftDDK.
Привожу несложный пример.

Code:
unit PhysMemWorks;
 
interface
 
uses windows;
 
type
 
NTSTATUS = LongInt;
PLARGE_INTEGER = ^LARGE_INTEGER;
TSectionInherit = (ViewNone,ViewShare,ViewUnmap);
SECTION_INHERIT = TSectionInherit;
 
PHYSICAL_ADDRESS = record
LowPart : DWORD ;
HighPart : DWORD;
end;
 
 
TNtAnsiString = packed record
Length : Word;
MaximumLength : Word;
Buffer : PChar;
end;
 
PNtAnsiString = ^TNtAnsiString;
ANSI_STRING = TNtAnsiString;
 
 
TNtUnicodeString = packed record
Length : Word;
MaximumLength : Word;
Buffer : PWideChar;
end;
 
UNICODE_STRING = TNtUnicodeString;
PNtUnicodeString = ^TNtUnicodeString;
 
 
TNtObjectAttributes = packed record
Length : ULONG;
RootDirectory : THandle;
ObjectName : PNtUnicodeString;
Attributes : ULONG;
SecurityDescriptor : Pointer;
SecurityQualityOfService : Pointer;
end;
 
OBJECT_ATTRIBUTES = TNtObjectAttributes;
PNtObjectAttributes = ^TNtObjectAttributes;
 
 
function OpenPhysicalMemory:dword;
 
function MapPhysicalMemory (hPhysMem:tHANDLE; pdwAddress:DWORD; pdwLength:DWORD; pdwBaseAddress:pDWORD):dword;
 
///////////
 
const DLL = 'ntdll.dll';
 
function RtlAnsiStringToUnicodeString( DestinationString : PNtUnicodeString; SourceString : PNtAnsiString;
AllocateDestinationString : Boolean ) : NTSTATUS; stdcall; external DLL name 'RtlAnsiStringToUnicodeString';
procedure RtlInitAnsiString( DestinationString : PNtAnsiString; SourceString : PChar ); stdcall; external DLL name 'RtlInitAnsiString';
 
function NtMapViewOfSection(SectionHandle : THandle;ProcessHandle : THandle; var BaseAddress : PDWORD;
ZeroBits : ULONG; CommitSize : ULONG; SectionOffset : PLARGE_INTEGER; ViewSize : DWORD;
InheritDisposition : SECTION_INHERIT;
AllocationType : ULONG; Protect : ULONG) : NTSTATUS; stdcall; external DLL name 'NtMapViewOfSection';
 
function NtUnmapViewOfSection(const ProcessHandle : THandle;
const BaseAddress : Pointer) : NTSTATUS; stdcall; external DLL name 'NtUnmapViewOfSection';
function NtOpenSection(out SectionHandle : THandle; const DesiredAccess : ACCESS_MASK;
ObjectAttributes : PNtObjectAttributes) : NTSTATUS; stdcall; external DLL name 'NtOpenSection';
 
implementation
 
const
OBJ_KERNEL_HANDLE = $0000200;
 
var
status: dword;
 
procedure InitializeObjectAttributes(InitializedAttributes : PNtObjectAttributes;
pObjectName : PNtUnicodeString; const uAttributes : ULONG; const hRootDirectory : THandle;
pSecurityDescriptor : PSECURITY_DESCRIPTOR);
begin
with InitializedAttributes^ do
begin
Length := SizeOf(TNtObjectAttributes);
ObjectName := pObjectName;
Attributes := uAttributes;
RootDirectory := hRootDirectory;
SecurityDescriptor := pSecurityDescriptor;
SecurityQualityOfService := nil;
end;
end;
 
 
function OpenPhysicalMemory:dword;
var
hPhysMem:dword;
UniPhysicalMemory : TNtUnicodeString;
AnsiPhysicalMemory :TNtAnsiString ;
oa :TNtObjectAttributes;
 
begin
RtlInitAnsiString(@AnsiPhysicalMemory, 'DevicePhysicalMemory');
status:= RtlAnsiStringToUnicodeString(@UniPhysicalMemory, @AnsiPhysicalMemory, true);
InitializeObjectAttributes(@oa, @UniPhysicalMemory, OBJ_KERNEL_HANDLE, 0, nil) ;
status:= NtOpenSection(hPhysMem, SECTION_MAP_READ, @oa);
if status <> 0 then result:= 0 else result:= hPhysMem;
end;
 
 
function MapPhysicalMemory (hPhysMem:tHANDLE; pdwAddress:DWORD; pdwLength:DWORD; pdwBaseAddress:pDWORD):dword;
var
SectionOffset: pLARGE_INTEGER;
begin
SectionOffset.HighPart := 0;
SectionOffset.LowPart:= pdwAddress;
NtMapViewOfSection(hPhysMem, 0, pdwBaseAddress, 0, 0, nil,0, ViewNone, 0, PAGE_READONLY);
result:=1;
end;
 
 
function UnmapPhysicalMemory (dwBaseAddress:DWORD):dword;
begin
NtUnmapViewOfSection(0, @dwBaseAddress);
result:=1;
end;
 
end.

Используя данный модуль получаем доступ к функциям ядра которые, в свою очередь, позволяют получить проекцию нужного участка памяти.

На форме разместим компонент StringGrid – для представления информации в табличном виде, Button, Label и Edit и пишем такой код.

Code:

unit Read_Mem;
 
interface
 
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Grids, ExtCtrls, PhysMemWorks;
 
type
TForm1 = class(TForm)
gridData: TStringGrid;
Label12: TLabel;
editAddr: TEdit;
btnRead: TButton;
Label2: TLabel;
procedure btnReadClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
end;
 
var
 
Form1: TForm1;
 
implementation
 
{$R *.DFM}
{$R WindowsXP.res}
 
 
type
XData = array[1..16] of Byte;
YData = array[1..16] of XData;
TPhysPointer =^YData;
 
procedure TForm1.btnReadClick(Sender: TObject);
var
i, j: longint;
nAddr: int64;//
s1, s2: String;
b: Byte;
ch: Char;
arrayMemory :pbytearray;
PointMemory:pointer;
hmemory:dword;
xhex: integer;
yhex: integer;
ofsetHex: integer;
begin
with gridData do
begin
ColWidths[0] := Canvas.TextWidth(IntToHex(0, 9));
ColWidths[1] := Canvas.TextWidth(Cells[1, 0]);
end;
nAddr := StrToInt('$' + editAddr.Text);
label2.Caption:=inttostr(nAddr div 1024 )+ ' kб';
hmemory:=OpenPhysicalMemory;
PointMemory:=MapViewOfFile(hmemory, FILE_MAP_READ, 0, nAddr, $2000); //размер секции 8 кб
arrayMemory :=PointMemory;
xhex:= nAddr and $0f;
yhex:=(nAddr and $00f0) div 16;
ofsetHex:= ((nAddr and $0f00) div 16);
if yhex = 0 then yhex:=0;
if PointMemory <> nil then
begin
for i:=1 to 16 do
begin
gridData.Cells[0,i] := IntToHex(nAddr,8);
s1 := '';
s2 := '';
for j:=1 to 16 do
begin
b := arrayMemory^[((i+ofsetHex+yhex-1)*16)+(j+xhex-1)];
s1 := s1 + IntToHex(b, 2) + ' ';
if b >= $20 then ch := Char(b) else ch:='.';
s2 := s2 + ch;
end;
gridData.Cells[1,i] := s1;
gridData.Cells[2,i] := s2;
nAddr := nAddr + 16;
end;
 
with gridData do
begin
ColWidths[2] := Canvas.TextWidth(Cells[2, 1] + ' ');
end;
 
end else MessageDlg('Этот участок памяти' +^M+' недоступен!!!' , mtWarning, [mbOK], 0);
 
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
begin
with gridData do
begin
Cells[0,0]:=' ADDR';
Cells[1,0]:='';
for i := 0 to 15 do
Cells[1,0] := Cells[1,0] + IntToHex(i, 2) + ' ';
Cells[2,0]:=' ASCII';
end;
end;
end.

Готово! У нас есть приложение позволяющее просматривать физическую память. Наберите, например, в поле адреса 000FFF00 , нажмие "Read" и в ячейках начиная с FFFF5 прочитайте дату прошивки BIOS Вашей материнской платы.

Используя данные функции Вы легко получаете возможность просмотра всего объёма физической памяти, за исключением системных адресов операционной системы.

Copyright© 2006 Альберт Мамедов (MagDelphi) Специально для Delphi Plus

Статья обсуждает использование natives функций kernel32 в Delphi для получения проекции физической памяти. Автор предлагает пример кода, демонстрирующий, как открыть секцию физической памяти, отобразить ее в адресном пространстве процесса и прочитать данные из нее.

Статья начинается с объяснения, что прямой доступ к физической памяти не возможен под Windows NT (XP) из-за ограничений безопасности. Вместо этого автор рекомендует использовать объект "проекционный файл", который представляет собой блок памяти, который может быть общим для нескольких процессов.

Пример кода, предоставленный в статье, включает функции открытия и отображения физической памяти, а также пример приложения на основе формы, позволяющего пользователям прочитать данные из физической памяти. Приложение использует компонент StringGrid для отображения прочитанных данных в табличном формате.

Некоторые важные точки из статьи:

  • Автор использует функцию NtOpenSection для открытия секции физической памяти.
  • Функция NtMapViewOfSection используется для отображения секции физической памяти в адресном пространстве процесса.
  • Функции RtlAnsiStringToUnicodeString и RtlInitAnsiString используются для конвертации между строками ANSI и Unicode.
  • Функция InitializeObjectAttributes используется для инициализации структуры атрибутов объекта.
  • Приложение использует компонент TStringGrid для отображения прочитанных данных в табличном формате.

В целом, статья предоставляет полный пример использования natives функций kernel32 в Delphi для доступа к физической памяти. Однако важно отметить, что доступ к физической памяти может быть сложным и потенциально опасным операцией, и необходимо проявлять осторожность при работе с ней.

получение данных из физических ячеек памяти с помощью объекта "проекция файла" и функций ядра Windows.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Память и Указатели ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 11:33:16/0.0065879821777344/1