Приветствую Вас Прохожий | Получать RSS-новости | Главная | Регистрация | Вход |
Меню сайта

Форма входа

Категория каталога
Разное [78]

Новое на сайте
Новые файлы


Случайные программы


Новые статьи

Как грамотно установить ...
Скрытые возможности MS S...
Как подобрать спутниково...
Пять советов по диагност...
Куда пропадает свободное...

Последние новости

«Спорту» осталось недолг...
Eutelsat W7. 36E Радуга-...
Astra 1H. 19.2E
Профилактика на спутнике...
Радуга-Интернет на Eutel...

Облако тегов


Друзья сайта
Дискуссионный клуб
Шаблоны для uCoz, скрипты для uCoz  Желтые страницы по спутниковому и кабельному ТВ


Для проживающих в городе Иваново:

Ремонт и настройка вашего компьютера
Установка программ
Защита. Удаление вирусов

Оцифровка видео и аудио материалов с возможностью компьютерного монтажа

Создание небольших сайтов, персональных страничек

Монтаж и настройка спутникового Интернета
и телевидения...

и прочие компьютерные услуги...

По всем вопросам обращаться по тел. 89605108897


Счетчики
Были сегодня:



Статистика

Онлайн всего: 7
Гостей: 7
Пользователей: 0

Главная » Статьи » Разное » Разное

Использование 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).

delphiplus
Альберт Мамедов

Категория: Разное | Добавил: Himik (03.06.2009)
Просмотров: 1102 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Copyright Himik © 2024