Прочитать ROM-BIOS

Советы » BIOS » Прочитать ROM-BIOS

// An Example of this unit is availabe as Demo Download. 
// Ein Beispiel zur Anwendung dieser Unit kann als Demo heruntergeladen werden. 


//////////////////////////////////////////////////////////////////////////////// 
// 
//                            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 http://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: 
// 
//    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 'DevicePhysicalMemory'. // 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 = 'DevicePhysicalMemory'; 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

.

Другое по теме:

Категории

Статьи

Советы

Copyright © 2022 - All Rights Reserved - www.delphirus.com