Как прочитать ROM-BIOS?

An Example of this unit is availabe as Demo Download.

////////////////////////////////////////////////////////////////////////////////

//

// BIOS Helper for Delphi

//

// BIOS related utilities for Win9x and WinNT(i386)

//

////////////////////////////////////////////////////////////////////////////////

//

// The Original Code is:

// BiosHelp.pas, released 2001-09-02.

//

// The Initial Developer of the Original Code is Nico Bendlin.

//

// Portions created by Nico Bendlin are

// Copyright (C) 2001-2003 Nico Bendlin. All Rights Reserved.

//

// Contributor(s):

// Nico Bendlin<nicode@gmx.net>

//

// The contents of this file are subject to the Mozilla Public License Version

// 1.1 (the "License"); you may not use this file except in compliance with the

// License. You may obtain a copy of the License at <a href="http://www.mozilla.org/MPL/

//

//" title="http://www.mozilla.org/MPL/

//

//">http://www.mozilla.org/MPL/

//

//</a> Software distributed under the License is distributed on an "AS IS" basis,

// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for

// the specific language governing rights and limitations under the License.

//

// Alternatively, the contents of this file may be used under the terms of

// either the GNU General Public License Version 2 or later (the "GPL"), or

// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),

// in which case the provisions of the GPL or the LGPL are applicable instead

// of those above. If you wish to allow use of your version of this file only

// under the terms of either the GPL or the LGPL, and not to allow others to

// use your version of this file under the terms of the MPL, indicate your

// decision by deleting the provisions above and replace them with the notice

// and other provisions required by the GPL or the LGPL. If you do not delete

// the provisions above, a recipient may use your version of this file under

// the terms of any one of the MPL, the GPL or the LGPL.

//

////////////////////////////////////////////////////////////////////////////////

//

// Revision:

//

// 2003-02-15 2.00 [NicoDE]

// - generic dump method completely rewritten

// - default range is now E000:0000-F000:FFFF

//

////////////////////////////////////////////////////////////////////////////////

{$IFDEF CONDITIONALEXPRESSIONS}

 {$DEFINE DELPHI6UP}

 {$IF NOT DEFINED(VER140)}

  {$DEFINE DELPHI7UP}

 {$IFEND}

{$ENDIF}

unit BiosHelp {$IFDEF DELPHI6UP} platform {$ENDIF};

{$MINENUMSIZE 4}

{$WEAKPACKAGEUNIT}

{$IFDEF DELPHI7UP}

 {$WARN UNSAFE_TYPE OFF}

 {$WARN UNSAFE_CODE OFF}

{$ENDIF}

interface

uses

 Windows;

const

 RomBiosDumpBase = $000E0000;

 RomBiosDumpEnd = $000FFFFF;

 RomBiosDumpSize = RomBiosDumpEnd - RomBiosDumpBase + 1;

type

 PRomBiosDump = ^TRomBiosDump;

 TRomBiosDump = array [RomBiosDumpBase..RomBiosDumpEnd] of Byte;

type

 TRomDumpMethod = (rdmAutomatic, // Autodetect OS type and use proper method

  rdmGeneric, // Use 16-bit EXE program to dump the BIOS

  rdmMemory, // Dump from process's address space (Win9x)

  rdmPhysical // Dump from physical memory object (WinNT)

  );

function DumpRomBios(out Dump: TRomBiosDump;

 Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean;

function DumpRomBiosEx(RomBase: Pointer; RomSize: Cardinal; out Dump;

 Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean;

procedure ReadRomDumpBuffer(const Dump: TRomBiosDump; Addr: Pointer;

 var Buffer; Size: Cardinal);

procedure ReadRomDumpBufferEx(const Dump; Base, Addr: Pointer;

 var Buffer; Size: Cardinal);

function GetRomDumpAddr(const Dump: TRomBiosDump; Addr: Pointer): Pointer;

function GetRomDumpAddrEx(const Dump; Base, Addr: Pointer): Pointer;

implementation

////////////////////////////////////////////////////////////////////////////////

//

// DumpRomBios16 (rdmGeneric)

//

// Creates an 16-bit EXE program in TEMP and runs it redirected to an file.

//

// WARNING: One day 16-bit code will not run on future Windows.

// WARNING: You are dumping the BIOS inside the MS-DOS 'emulator'.

//

function _RomDumpCode(RomBase: Pointer; RomSize: Cardinal;

 out Code: Pointer; out Size: Cardinal): Boolean;

const

 BlockSize = $1000;

type  // ; RomDump (dumps mem to STDOUT)

 PRomDumpCode = ^TRomDumpCode; // ; BlockSize MUST be multiple of 10h.

 TRomDumpCode = packed record  //

  _header: TImageDosHeader; //

  _notice: array[0..$4F] of AnsiChar; // @@note: db 'RomDump 2.0', ...

  init: packed record  // @@init:

  _mov_44: array[0..2] of Byte; // mov ax, 4400h

  _mov_bx: array[0..2] of Byte; // mov bx, 0001h

  _dos_21: array[0..1] of Byte; // int 21h

  _jcf_18: array[0..1] of Byte; // jc @@code

  _and_dx: array[0..3] of Byte; // and dx, 0082h

  _cmp_dx: array[0..3] of Byte; // cmp dx, 0082h

  _jne_0E: array[0..1] of Byte; // jne @@code

  _psh_cs: Byte; // push cs

  _pop_ds: Byte; // push ds

  _mov_dx: array[0..2] of Byte; // mov dx, offset @@note

  _mov_09: array[0..1] of Byte; // mov ah, 09h

  _int_21: array[0..1] of Byte; // int 21h

  _mov_4C: array[0..2] of Byte; // mov ax, 4C01h

  _int_20: array[0..1] of Byte; // int 21h

  end; //

  code: packed record  // @@code:

  _mov_cx: Byte;

  BlockCount: Word; // mov cx, <BlockCount>

  _mov_dx: Byte;

  DatSegment: Word; // mov dx, <DatSegment>

  _jcx_1C: array[0..1] of Byte; // jcxz @@rest

  end; //

  loop: packed record  // @@loop:

  _psh_cx: Byte; // push cx

  _psh_dx: Byte; // push dx

  _mov_ds: array[0..1] of Byte; // mov ds, dx

  _mov_dx: Byte;

  DatOffset: Word; // mov dx, <DatOffset>

  _mov_cx: array[0..2] of Byte; // mov cx, <BlockSize>

  _mov_bx: array[0..2] of Byte; // mov bx, 0001h

  _mov_ax: array[0..2] of Byte; // mov ax, 4000h

  _int_21: array[0..1] of Byte; // int 21h

  _pop_dx: Byte; // pop dx

  _pop_cx: Byte; // pop cx

  _jcf_1C: array[0..1] of Byte; // jc @@exit

  _add_dx: array[0..3] of Byte; // add dx, <BlockSize/10h>

  _lop_E4: array[0..1] of Byte; // loop @@loop

  end; //

  rest: packed record  // @@rest:

  _mov_ds: array[0..1] of Byte; // mov ds, dx

  _mov_dx: Byte;

  DatOffset: Word; // mov dx, <DatOffset>

  _mov_cx: Byte;

  LenghtMod: Word; // mov cx, <LenghtMod>

  _mov_bx: array[0..2] of Byte; // mov bx, 0001h

  _mov_ax: array[0..2] of Byte; // mov ax, 4000h

  _jcx_06: array[0..1] of Byte; // jcxz @@exit

  _int_21: array[0..1] of Byte; // int 21h

  _jcf_02: array[0..1] of Byte; // jc @@exit

  _mov_al: array[0..1] of Byte; // mov al, 00h

  end; //

  Exit: packed record  // @@exit:

  _mov_ah: array[0..1] of Byte; // mov ah, 4Ch

  _int_21: array[0..1] of Byte; // int 21h

  end; //

 end;

const

 RomDumpCodeSize = SizeOf(TRomDumpCode) - SizeOf(TImageDosHeader);

 RomDumpCode: TRomDumpCode = (_header: (e_magic: IMAGE_DOS_SIGNATURE;

  e_cblp: Word(RomDumpCodeSize) and $1FF;

  e_cp: Word((RomDumpCodeSize - 1) shr 9) + 1;

  e_crlc: $0000;

  e_cparhdr: SizeOf(TImageDosHeader) shr 4;

  e_minalloc: $0000;

  e_maxalloc: $FFFF;

  e_ss: $0000;

  e_sp: $1000;

  e_csum: $0000;

  e_ip: SizeOf(RomDumpCode._notice);

  e_cs: $0000;

  e_lfarlc: SizeOf(TImageDosHeader);

  e_ovno: $0000;

  e_res: ($0000, $0000, $0000, $0000);

  e_oemid: $0000;

  e_oeminfo: $0000;

  e_res2: ($0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000,

  $0000, $0000);

  _lfanew: $00000000

  );

  _notice: #13#10 +

  'RomDump 2.0'#13#10 +

  'Copyright (c) 2003 Nico Bendlin'#13#10 +

  #13#10 +

  'Usage: RomDump > filename'#13#10 +

  #13#10'$';

  init: (_mov_44: ($B8, $00, $44);

  _mov_bx: ($BB, $01, $00);

  _dos_21: ($CD, $21);

  _jcf_18: ($72, $18);

  _and_dx: ($81, $E2, $82, $00);

  _cmp_dx: ($81, $FA, $82, $00);

  _jne_0E: ($75, $0E);

  _psh_cs: $0E;

  _pop_ds: $1F;

  _mov_dx: ($BA, $00, $00);

  _mov_09: ($B4, $09);

  _int_21: ($CD, $21);

  _mov_4C: ($B8, $01, $4C);

  _int_20: ($CD, $21);

  );

  code: (_mov_cx: $B9; BlockCount: $0010;

  _mov_dx: $BA; DatSegment: $F000;

  _jcx_1C: ($E3, $1C)

  );

  loop: (_psh_cx: $51;

  _psh_dx: $52;

  _mov_ds: ($8E, $DA);

  _mov_dx: $BA; DatOffset: $0000;

  _mov_cx: ($B9, Lo(BlockSize), Hi(BlockSize));

  _mov_bx: ($BB, $01, $00);

  _mov_ax: ($B8, $00, $40);

  _int_21: ($CD, $21);

  _pop_dx: $5A;

  _pop_cx: $59;

  _jcf_1C: ($72, $1C);

  _add_dx: ($81, $C2, Lo(BlockSize shr 4), Hi(BlockSize shr 4));

  _lop_E4: ($E2, $E4)

  );

  rest: (_mov_ds: ($8E, $DA);

  _mov_dx: $BA; DatOffset: $0000;

  _mov_cx: $B9; LenghtMod: $0000;

  _mov_bx: ($BB, $01, $00);

  _mov_ax: ($B8, $00, $40);

  _jcx_06: ($E3, $06);

  _int_21: ($CD, $21);

  _jcf_02: ($72, $02);

  _mov_al: ($B0, $00)

  );

  Exit: (_mov_ah: ($B4, $4C);

  _int_21: ($CD, $21)

  )

  );

begin

 Result := False;

 if (RomSize > 0) and (RomSize <= $100000) and

  (Cardinal(RomBase) < $100000) and

  (Cardinal(RomBase) + RomSize <= $100000) then

 begin

  Size := SizeOf(TRomDumpCode);

  Code := Pointer(LocalAlloc(LPTR, Size));

  if Code <> nil then

  try

  PRomDumpCode(Code)^ := RomDumpCode;

  with PRomDumpCode(Code)^ do

  begin

  code.BlockCount := Word(RomSize div BlockSize);

  code.DatSegment := Word(Cardinal(RomBase) shr 4);

  loop.DatOffset := Word(Cardinal(RomBase)) and $000F;

  rest.DatOffset := loop.DatOffset;

  rest.LenghtMod := Word(RomSize mod BlockSize);

  end;

  Result := True;

  except

  LocalFree(HLOCAL(Code));

  Code := nil;

  Size := 0;

  end;

 end;

end;

function _SaveRomDumpCodeToFile(RomBase: Pointer; RomSize: Cardinal;

 const FileName: string): Boolean;

var

 Code: Pointer;

 Size: Cardinal;

 Hand: THandle;

 Num: DWORD;

begin

 Result := False;

 if _RomDumpCode(RomBase, RomSize, Code, Size) then

  try

  Hand := CreateFile(PChar(FileName), GENERIC_WRITE, FILE_SHARE_READ, nil,

  CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

  if Hand <> INVALID_HANDLE_VALUE then

  try

  Result := WriteFile(Hand, Code^, Size, Num, nil) and (Num = Size);

  if not Result then

  DeleteFile(PChar(FileName));

  finally

  CloseHandle(Hand);

  end;

  finally

  LocalFree(HLOCAL(Code));

  end;

end;

function _ExecuteRomDumpCode(const Code, Dump: string; Timeout: DWORD): Boolean;

var

 ComSpec: string;

 StartInfo: TStartupInfo;

 ProcInfo: TProcessInformation;

 ErrorMode: Cardinal;

begin

 Result := False;

 SetLength(ComSpec, MAX_PATH + 1);

 SetLength(ComSpec,

  GetEnvironmentVariable('ComSpec', PChar(@ComSpec[1]), MAX_PATH));

 if Length(ComSpec) <= 0 then

  Exit;

 FillChar(StartInfo, SizeOf(TStartupInfo), 0);

 StartInfo.cb := SizeOf(TStartupInfo);

 StartInfo.dwFlags := STARTF_USESHOWWINDOW;

 StartInfo.wShowWindow := SW_HIDE;

 ErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS or SEM_NOGPFAULTERRORBOX or

  SEM_NOALIGNMENTFAULTEXCEPT or SEM_NOOPENFILEERRORBOX);

 try

  if CreateProcess(nil, PChar(ComSpec + ' /C ' + Code + ' > ' + Dump),

  nil, nil, False, HIGH_PRIORITY_CLASS, nil, nil, StartInfo, ProcInfo) then

  try

  Result :=

  (WaitForSingleObject(ProcInfo.hProcess, Timeout) <> WAIT_TIMEOUT);

  if not Result then

  TerminateProcess(ProcInfo.hProcess, STATUS_TIMEOUT);

  finally

  CloseHandle(ProcInfo.hThread);

  CloseHandle(ProcInfo.hProcess);

  end;

 finally

  SetErrorMode(ErrorMode);

 end;

end;

function DumpRomBios16(RomBase: Pointer; RomSize: Cardinal; var Dump;

 Timeout: DWORD): Boolean;

var

 Tmp: array [0..MAX_PATH] of Char;

 Dmp: array [0..MAX_PATH] of Char;

 Exe: array [0..MAX_PATH] of Char;

 Hnd: THandle;

 Num: DWORD;

begin

 Result := False;

 if GetTempPath(MAX_PATH, Tmp) > 0 then

  GetShortPathName(Tmp, Tmp, MAX_PATH)

 else

  lstrcpy(Tmp, '.');

 if GetTempFileName(Tmp, 'rom', 0, Dmp) > 0 then

  try

  lstrcpy(Exe, Dmp);

  lstrcat(Exe, '.exe'); // Win9x requires .EXE extention

  if _SaveRomDumpCodeToFile(RomBase, RomSize, Exe) then

  try

  if _ExecuteRomDumpCode(Exe, Dmp, Timeout) then

  begin

  Hnd := CreateFile(Dmp, GENERIC_READ, FILE_SHARE_READ or

  FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

  if Hnd <> INVALID_HANDLE_VALUE then

  try

  Result := ReadFile(Hnd, Dump, RomSize, Num, nil) and (Num = RomSize);

  finally

  CloseHandle(Hnd);

  end;

  end;

  finally

  DeleteFile(Exe);

  end;

  finally

  DeleteFile(Dmp);

  end;

end;

////////////////////////////////////////////////////////////////////////////////

//

// DumpRomBios9x (rdmMemory)

//

// Win9x maps the BIOS into every process - therefore it's directly accessed.

//

function DumpRomBios9x(RomBase: Pointer; RomSize: Cardinal; var Dump): Boolean;

begin

 Result := False;

 try

  Move(RomBase^, Dump, RomSize);

  Result := True;

 except

  // ignore exeptions

 end

end;

////////////////////////////////////////////////////////////////////////////////

//

// DumpRomBiosNt (rdmPhysical)

//

// On WinNT the BIOS is accessable through section '\Device\PhysicalMemory'.

// This object can only be opened by members of local 'Adminstrators' group.

// ZwOpenSection and RtlNtStatusToDosError are documented in newer MSDN/DDK.

//

type

 NTSTATUS = Integer;

 PUnicodeString = ^TUnicodeString;

 TUnicodeString = packed record

  Length: Word;

  MaximumLength: Word;

  Buffer: PWideChar;

 end;

 PObjectAttributes = ^TObjectAttributes;

 TObjectAttributes = record

  Length: ULONG;

  RootDirectory: THandle;

  ObjectName: PUnicodeString;

  Attributes: ULONG;

  SecurityDescriptor: PSecurityDescriptor;

  SecurityQualityOfService: PSecurityQualityOfService;

 end;

 TFNZwOpenSection = function(out Section: THandle; Access: ACCESS_MASK;

  Attributes: PObjectAttributes): NTSTATUS;

 stdcall;

 TFNRtlNtStatusToDosError = function(Status: NTSTATUS): DWORD;

 stdcall;

const

 PhysMemDevName = '\Device\PhysicalMemory';

 PhysMemName: TUnicodeString = (Length: Length(PhysMemDevName) * SizeOf(WideChar);

  MaximumLength: Length(PhysMemDevName) * SizeOf(WideChar) + SizeOf(WideChar);

  Buffer: PhysMemDevName;

  );

 PhysMemMask: ACCESS_MASK = SECTION_MAP_READ;

 PhysMemAttr: TObjectAttributes = (Length: SizeOf(TObjectAttributes);

  RootDirectory: 0;

  ObjectName: @PhysMemName;

  Attributes: $00000040; // OBJ_CASE_INSENSITIVE

  SecurityDescriptor: nil;

  SecurityQualityOfService: nil;

  );

var

 ZwOpenSection: TFNZwOpenSection;

 RtlNtStatusToDosError: TFNRtlNtStatusToDosError;

function DumpRomBiosNt(RomBase: Pointer; RomSize: Cardinal; var Dump): Boolean;

var

 HMod: HMODULE;

 Stat: NTSTATUS;

 Sect: THandle;

 View: Pointer;

begin

 Result := False;

 HMod := GetModuleHandle('ntdll.dll');

 if HMod = 0 then

  SetLastError(ERROR_CALL_NOT_IMPLEMENTED)

 else

 begin

  if not Assigned(ZwOpenSection) then

  ZwOpenSection := GetProcAddress(HMod, 'ZwOpenSection');

  if not Assigned(RtlNtStatusToDosError) then

  RtlNtStatusToDosError := GetProcAddress(HMod, 'RtlNtStatusToDosError');

  if not Assigned(ZwOpenSection) or not Assigned(RtlNtStatusToDosError) then

  SetLastError(ERROR_CALL_NOT_IMPLEMENTED)

  else

  begin

  Stat := ZwOpenSection(Sect, PhysMemMask, @PhysMemAttr);

  if Stat >= 0 then

  try

  View := MapViewOfFile(Sect, PhysMemMask, 0, Cardinal(RomBase), RomSize);

  if View <> nil then

  try

  Move(View^, Dump, RomSize);

  Result := True;

  finally

  UnmapViewOfFile(View);

  end;

  finally

  CloseHandle(Sect);

  end

  else

  SetLastError(RtlNtStatusToDosError(Stat));

  end;

 end;

end;

////////////////////////////////////////////////////////////////////////////////

//

// DumpRomBios(Ex)

//

// Public functions to call OS-dependent implementations.

//

function DumpRomBios(out Dump: TRomBiosDump;

 Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean;

begin

 Result := DumpRomBiosEx(Pointer(RomBiosDumpBase), RomBiosDumpSize, Dump,

  Method, Timeout);

end;

function DumpRomBiosEx(RomBase: Pointer; RomSize: Cardinal; out Dump;

 Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean;

begin

 Result := False;

 case Method of

  rdmAutomatic:

  if (GetVersion() and $80000000) <> 0 then

  Result := DumpRomBios9x(RomBase, RomSize, Dump)

  else

  begin

  Result := DumpRomBiosNt(RomBase, RomSize, Dump);

  if not Result then

  DumpRomBios16(RomBase, RomSize, Dump, DWORD(Timeout));

  end;

  rdmGeneric:

  Result := DumpRomBios16(RomBase, RomSize, Dump, DWORD(Timeout));

  rdmMemory:

  Result := DumpRomBios9x(RomBase, RomSize, Dump);

  rdmPhysical:

  Result := DumpRomBiosNt(RomBase, RomSize, Dump);

  else

  SetLastError(ERROR_INVALID_PARAMETER);

 end;

end;

////////////////////////////////////////////////////////////////////////////////

//

// ReadRomDumpBuffer(Ex) / GetRomDumpAddr(Ex)

//

// Utilities to simplify the access to dumps.

//

procedure ReadRomDumpBuffer(const Dump: TRomBiosDump; Addr: Pointer;

 var Buffer; Size: Cardinal);

begin

 Move(Dump[Cardinal(Addr)], Buffer, Size);

end;

procedure ReadRomDumpBufferEx(const Dump; Base, Addr: Pointer;

 var Buffer; Size: Cardinal);

begin

 Move(Pointer(Cardinal(@Dump) + Cardinal(Addr) - Cardinal(Base))^,

  Buffer, Size);

end;

function GetRomDumpAddr(const Dump: TRomBiosDump; Addr: Pointer): Pointer;

begin

 Result := @Dump[Cardinal(Addr)];

end;

function GetRomDumpAddrEx(const Dump; Base, Addr: Pointer): Pointer;

begin

 Result := Pointer(Cardinal(@Dump) + Cardinal(Addr) - Cardinal(Base));

end;

end.

Взято с сайта http://www.swissdelphicenter.ch/en/tipsindex.php

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...