An Example of this unit is availabe as Demo Download.

 

Code:

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

//

//                            BIOS Helper for Delphi

//

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

//

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

//

//  The Original Code is:

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

//

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

//

//  Portions created by Nico Bendlin are

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

//

//  Contributor(s):

//   Nico Bendlin<Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.>

//

//  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 https://www.mozilla.org/MPL/

//

//  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:

//

//    2013-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.

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить