Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Новости ИТ Программы Книги Games   Обои   Экспорт RSS E-Books
 
Поиск по сайту

TOP-10 программ
Symantec Norton Ghost 9.0
Partition Magic 8.0.2 Pro
Xilisoft 3GP Video Converter v3.1.7.0616b
Norton AntiVirus 2005
Xilisoft 3GP Video Converter v2.1.52.831b
Антивирус Касперского Personal 5.0.303 beta 2
RAR Password Cracker 4.12
ABBYY PDF Transformer v1.00.820
MP3 To Ringtone Gold v3.02
Mobtime Cell Phone Manager v5.3.1
 
Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
 
 

  Раздел: Компьютерная документация -> Программирование -> Delphi / Pascal

 

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

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

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

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

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

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 

Используем объект  '\Device\PhysicalMemory' и преобразовав его в  тип TNtUnicodeString;

RtlInitAnsiString(@AnsiPhysicalMemory, '\Device\PhysicalMemory');
RtlAnsiStringToUnicodeString(@UniPhysicalMemory, @AnsiPhysicalMemory, true);
InitializeObjectAttributes(@NtObjectAttributes, @UniPhysicalMemory, OBJ_KERNEL_HANDLE, 0, nil);

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

NtOpenSection(SectionHandle,  SECTION_MAP_READ, @NtObjectAttributes);
Этим самым мы открываем объект '\Device\PhysicalMemory' для чтения отображенного участка физической памяти в процессе пользователя.

Отображение осуществляем с помощью функции NtMapViewOfSection возвращающей указатель на участок памяти процесса пользователя в который осуществляется отображение. Более подробную информацию можно найти в MicrosoftDDK.

Привожу несложный пример.

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, '\Device\PhysicalMemory');
   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  и пишем такой код.

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 Вашей материнской платы.

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

В следующей статье используя эти методы получим данные о системе - структуры (SMBIOS).

Пример (176K) и его исходный код (4.26K).

Автор: Альберт Мамедов
Источник: magdelphi.boom.ru

Ссылки по теме
Алгоритмы Сортировки. Часть 1
Введение в Delphi 8
Работа с реестром в Delphi
Delphi и ресурсы компьютера
Советы начинающим программировать на Delphi
Структуры и базы данных, методы сортировки

Вся документация Pascal и Delphi

 

Компьютерная документация от А до Я - Главная

 
Популярные книги

Системное администрирование на 100 % (+CD)

Подробнее

Дизайн помещений и интерьеров в 3ds max 7 (+CD)

Подробнее

Самоучитель Macromedia Flash 5

Подробнее

 

 
Новости ИТ
01.12.2008  Buffalo выпустил миниатюрные USB-накопители
01.12.2008  VENTO TA-U1 - стильный корпус представлен Asus
01.12.2008  Fujitsu-Siemens выпускает в продажу внешний ускоритель для ноутбуков
01.12.2008  Оригинальные чехлы для ноутбуков от Choiix
01.12.2008  Опубликован код драйвера для беспроводных карт Atheros
01.12.2008  Лучший блог 2008
01.12.2008  Linux запустили на Apple iPhone
01.12.2008  LG KC780
01.12.2008  MSI дополнит линейку Wind-нетбуков двумя моделями
01.12.2008  Nikon D3X - 24,5 млн пикселей для профессионалов
01.12.2008  Киловаттник HIPER M1000 с КПД выше 85%
01.12.2008  AMD впервые снизила цены линейки Radeon HD 4800
01.12.2008  Чистильщики: Wise Registry Cleaner v.3.8.2
01.12.2008  Антивирусы: RemoveIT Pro v4 SE (30.11.2008)
01.12.2008  Корпус ASUS Vento TA-U1 можно поставить вместо новогодней ёлки
01.12.2008  Диагностика: PC Wizard 2008 v.1.871
01.12.2008  Диагностика: NextSensor v.2.7.6.0 Build 1130
01.12.2008  Тестовые приложения: PassMark BurnInTest v.6.0 Build 1000 Beta 15
01.12.2008  Неофициальные драйверы для модемов Motorola
01.12.2008  Драйверы и утилиты для сетевых хранилищ D-Link
 
Полезно

 
Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.
 
Rambler's Top100