BIOS - pegando informacoes da bios

Top  Previous  Next

  Ein Beispiel zur Anwendung dieser Unit kann als Demo heruntergeladen werden. 

  An Example of this unit is availabe as Demo Download. 

} 

 

 

(******************************************************************************* 

*                                                                              * 

* BIOS Help - read ROM BIOS on Windows 95/98/SE/ME/NT/2K/XP                    * 

*                                                                              * 

* Copyright (C) 2001, Nico Bendlin (nico@bendlin.de)                           * 

*                                                                              * 

* Compiler: Delphi 4.03/5.01/6.00                                              * 

* Version: 1.032001-09-02                                                    * 

*                                                                              * 

*******************************************************************************) 

 

{ postum scriptum: sorry for the bad english, i wrote it in a hurry } 

 

unit BiosHelp; 

 

{$ALIGN ON} 

{$MINENUMSIZE 4} 

 

interface 

 

uses 

  Windows; 

 

type 

  PRomBiosDump = ^TRomBiosDump; 

  TRomBiosDump = array [$000F0000..$000FFFFFof Byte; 

 

type 

  TReadRomBiosMethod = ( 

    rrbmAutomatic, { Autodetect OS type and use proper method } 

    rrbmGeneric,   { Use 16-bit COM program to dump the BIOS  } 

    rrbmMemory,    { Read from memory (Win9x)                 } 

    rrbmPhysical   { Read from physical memory object (WinNT) } 

  ); 

 

function ReadRomBios(var Dump: TRomBiosDump; Method: TReadRomBiosMethod; 

  Timeout: DWORD = INFINITE): Boolean; 

 

function GetRomBiosBuffer(const Dump: TRomBiosDump; Address: Pointer; 

  var Buffer; BufferSize: Cardinal): Cardinal; 

function GetRomBiosString(const Dump: TRomBiosDump; Address: Pointer): string; 

function GetRomBiosLongLong(const Dump: TRomBiosDump; Address: Pointer): LONGLONG; 

function GetRomBiosDWord(const Dump: TRomBiosDump; Address: Pointer): DWORD; 

function GetRomBiosWord(const Dump: TRomBiosDump; Address: Pointer): Word; 

function GetRomBiosByte(const Dump: TRomBiosDump; Address: Pointer): Byte; 

 

implementation 

 

{############################################################################### 

#                                                                              # 

#                             GENERIC METHOD                                   # 

#                                                                              # 

# Create an temporary folder, save an 16bit COM program (RomDump.com) into it, # 

# execute program redirected to an file (Rom.dmp, RomDump.com simply dumps the # 

# memory range F000:0000-F000:FFFF to STDOUT), read dump file into the buffer, # 

# and finally cleanup all temporary files and directories.                     # 

#                                                                              # 

# (the function RomDumpCode is x86 specific, which i wrote to generate 16-bit  # 

#  code with the help of the 23-bit Delphi compiler, never try to execute the  # 

#  pseudo-code in your program! it will not work in 32-bit protected mode)     # 

#                                                                              # 

###############################################################################} 

 

{ *INTERNAL* - Pseudo 16-bit code } 

 

type 

  PRomDumpCodeInfo = ^TRomDumpCodeInfo; 

  TRomDumpCodeInfo = (rdciStart, rdciEnd, rdciSize); 

 

function _RomDumpCode(Info: TRomDumpCodeInfo): Pointer; 

var 

  CodeStart: Pointer; 

  CodeEnd: Pointer; 

begin 

  asm 

          JMP     @@End 

 

          { *BEGIN* 16-bit code  } 

          { -- never use it in your program! -- } 

          { COM which writes ROM-BIOS to StdOut } 

  @@Start: 

          { Dump F000:0000-F000:FFFE } 

          XOR     eDX, eDX  // DS = 0xF000   ; Data segment 

          MOV     DH, 0F0h 

          MOV     DS, eDX 

          XOR     eDX, eDX  // DX = 0x0000   ; Data offset 

          XOR     eCX, eCX  // CX = 0xFFFF   ; Data length 

          DEC     eCX 

          XOR     eBX, eBX  // BX = 0x0001   ; STDOUT (file handle) 

          INC     eBX 

          MOV     AH, 40h   // DosCall(0x40) ; INT21, DOS_WRITE_TO_HANDLE 

          INT     21h 

          JC      @@Exit    // On error exit ; AL = Error code 

          { Dump F000:FFFF } 

          XOR     eDX, eDX  // DS = 0xF000   ; Data segment 

          MOV     DH, 0F0h 

          MOV     DS, eDX 

          XOR     eDX, eDX  // DX = 0xFFFF   ; Data offset 

          DEC     eDX 

          XOR     eCX, eCX  // CX = 0x0001   ; Data length 

          INC     eCX 

          MOV     eBX, eCX  // BX = 0x0001   ; STDOUT (file handle) 

          MOV     AH, 40h   // DosCall(0x40) ; INT21, DOS_WRITE_TO_HANDLE 

          INT     21h 

          JC      @@Exit    // On error exit ; AL = Error code 

          MOV     AL, 0     // no error      ; AL = 0 

  @@Exit

          MOV     AH, 4Ch   // DosCall(0x4C) ; INT21, DOS_TERMINATE_EXE 

          INT     21h 

  @@End

          { *END* 16-bit code  } 

 

          MOV     CodeStart, OFFSET @@Start 

          MOV     CodeEnd, OFFSET @@End 

  end

  case Info of 

    rdciStart: 

      Result := CodeStart; 

    rdciEnd: 

      Result := CodeEnd; 

    rdciSize: 

      Result := Pointer(Cardinal(CodeEnd) - Cardinal(CodeStart)); 

  else 

    Result := nil; 

  end

end

 

{ *INTERNAL* - Save 16-bit code to file } 

 

function _RomDumpCodeToFile(const Filename: string): Boolean; 

var 

  ComFile: THandle; 

  Size: Cardinal; 

begin 

  Result := False; 

  ComFile := CreateFile(PChar(Filename), GENERIC_WRITE, FILE_SHARE_READ, nil, 

    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 

  if ComFile <> INVALID_HANDLE_VALUE then 

  try 

    Result := WriteFile(ComFile, _RomDumpCode(rdciStart)^, 

      Cardinal(_RomDumpCode(rdciSize)), Size, nil) and 

      (Size = Cardinal(_RomDumpCode(rdciSize))); 

    if not Result then 

      DeleteFile(PChar(Filename)); 

  finally 

    CloseHandle(ComFile); 

  end

end

 

{ *INTERNAL* - Execute 16-bit code redirected to file } 

 

function _RomDumpCodeExecute(const Com, Dmp: string; Timeout: DWORD): Boolean; 

var 

  ComSpec: string; 

  si: TStartupInfo; 

  pi: TProcessInformation; 

begin 

  Result := False; 

  SetLength(ComSpec, MAX_PATH); 

  SetLength(ComSpec, 

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

  if Length(ComSpec) > 0 then 

  begin 

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

    si.cb := SizeOf(TStartupInfo); 

    si.dwFlags := STARTF_USESHOWWINDOW; 

    si.wShowWindow := SW_HIDE; 

    if CreateProcess(nil, PChar(ComSpec + ' /C ' + Com + ' > ' + Dmp), 

      nil, nil, False, CREATE_NEW_CONSOLE or CREATE_NEW_PROCESS_GROUP, nil, 

      nil, si, pi) then 

    try 

      Result := WaitForSingleObject(pi.hProcess, Timeout) <> WAIT_TIMEOUT; 

    finally 

      CloseHandle(pi.hProcess); 

      CloseHandle(pi.hThread); 

    end

  end

end

 

function DirectoryExists(const Dir: string): Boolean; 

var 

  Attr: DWORD; 

begin 

  Attr := GetFileAttributes(PChar(Dir)); 

  Result := (Attr <> $FFFFFFFFand 

    (Attr and FILE_ATTRIBUTE_DIRECTORY = FILE_ATTRIBUTE_DIRECTORY); 

end

 

{ Get BIOS dump the generic way } 

 

function ReadRomBios16(var Buffer: TRomBiosDump; Timeout: DWORD): Boolean; 

const 

  TempSub = '~RomDmp'

  ComName = 'RomDump.com'

  DmpName = 'Rom.dmp'

var 

  TempPath: string; 

  TempDir: string; 

  TempIdx: Integer; 

  TempIdxStr: string; 

  ComFile: string; 

  DmpFile: string; 

  DmpHandle: THandle; 

  Written: DWORD; 

begin 

  Result := False; 

  SetLength(TempPath, MAX_PATH); 

  SetLength(TempPath, GetTempPath(MAX_PATH, PChar(@TempPath[1]))); 

  if Length(TempPath) > 0 then 

  begin 

    if (TempPath[Length(TempPath)] <> '\') then 

      TempPath := TempPath + '\'

    TempIdx := 0

    repeat 

      Inc(TempIdx); 

      Str(TempIdx, TempIdxStr); 

      TempDir := TempPath + TempSub + TempIdxStr; 

    until not DirectoryExists(TempDir); 

    if CreateDirectory(PChar(TempDir), nil) then 

    try 

      TempDir := TempDir + '\'

      ComFile := TempDir + ComName; 

      DmpFile := TempDir + DmpName; 

      if _RomDumpCodeToFile(ComFile) then 

      try 

        if _RomDumpCodeExecute(ComFile, DmpFile, Timeout) then 

        begin 

          DmpHandle := CreateFile(PChar(DmpFile), GENERIC_READ, 

            FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 00); 

          if DmpHandle <> INVALID_HANDLE_VALUE then 

          try 

            FillChar(Buffer, SizeOf(TRomBiosDump), 0); 

            Result := ReadFile(DmpHandle, Buffer, SizeOf(TRomBiosDump), 

              Written, nil) and (Written = SizeOf(TRomBiosDump)); 

          finally 

            CloseHandle(DmpHandle); 

          end

        end

      finally 

        DeleteFile(PChar(DmpFile)); 

        DeleteFile(PChar(ComFile)); 

      end

    finally 

      RemoveDirectory(PChar(TempDir)); 

    end

  end

end

 

{############################################################################### 

#                                                                              # 

#                           DIRECT METHOD (Win9x)                              # 

#                                                                              # 

# Due to the fact that Windows 95/98/ME maps the BIOS into every Win32 process # 

# for read access it is very simple to fill the buffer from memory.            # 

#                                                                              # 

###############################################################################} 

 

function ReadRomBios9x(var Buffer: TRomBiosDump): Boolean; 

begin 

  Result := False; 

  try 

    FillChar(Buffer, SizeOf(TRomBiosDump), 0); 

    Move(Pointer(Low(TRomBiosDump))^, Buffer, SizeOf(TRomBiosDump)); 

    Result := True; 

  except 

    // ignore exceptions 

  end 

end

 

{############################################################################### 

#                                                                              # 

#                       PHYSICAL MEMORY METHOD (WinNT)                         # 

#                                                                              # 

# On Windows NT the ROM BIOS is only available through the named kernel object # 

# '\Device\PhysicalMemory'. Because it is impossible to open kernel objects in # 

# user mode with standard Win32 API functions we make use of NT's nativeAPI in # 

# NtDll.dll ("NT-Layer") namely ZwOpenSection.                                 # 

#                                                                              # 

# (note: mostly there are two versions of every function ZwXxx and NtXxx. The  # 

#  only difference in kernel mode is that the NtXxx version works in conside-  # 

#  ration to security while ZwXxx not. But in user mode both work like NtXxx.) # 

#                                                                              # 

# At first the section is opened with ZwOpenSection. Normally we would proceed # 

# ZwMapViewOfSection, ZwUnmapViewOfSection, and NtClose. But the functions are # 

# more complex and there is no needing for it. With the handle (because we are # 

# in the "very simple" user mode =) we now use MapViewOfFile, UnmapViewOfFile, # 

# and CloseHandle to map an memory window (the ROM BIOS) into our process.     # 

#                                                                              # 

# Due to the fact that ZwOpenSection returns NT error-codes in case of failure # 

# we have to translate it to an Win32 error-code (RtlNtStatusToDosError).      # 

# All NT specific functions are dynamically loaded -- because the applications # 

# should start on Win9x systems =)                                             # 

#                                                                              # 

###############################################################################} 

 

{ For more information see Windows 2000/XP DDK  } 

{ It works on Windows NT 4.0 too, use NtDll.dll } 

 

type 

  NTSTATUS = Integer; 

 

const 

  STATUS_SUCCESS        = NTSTATUS(0); 

  STATUS_INVALID_HANDLE = NTSTATUS($C0000008); 

  STATUS_ACCESS_DENIED  = NTSTATUS($C0000022); 

 

type 

  PUnicodeString = ^TUnicodeString; 

  TUnicodeString = packed record 

    Length: Word; 

    MaximumLength: Word; 

    Buffer: PWideChar; 

  end

 

const 

  OBJ_INHERIT          = $00000002

  OBJ_PERMANENT        = $00000010

  OBJ_EXCLUSIVE        = $00000020

  OBJ_CASE_INSENSITIVE = $00000040

  OBJ_OPENIF           = $00000080

  OBJ_OPENLINK         = $00000100

  OBJ_KERNEL_HANDLE    = $00000200

  OBJ_VALID_ATTRIBUTES = $000003F2

 

type 

  PObjectAttributes = ^TObjectAttributes; 

  TObjectAttributes = record 

    Length: ULONG; 

    RootDirectory: THandle; 

    ObjectName: PUnicodeString; 

    Attributes: ULONG; 

    SecurityDescriptor: PSecurityDescriptor; 

    SecurityQualityOfService: PSecurityQualityOfService; 

  end

 

const 

  ObjectPhysicalMemoryDeviceName = '\Device\PhysicalMemory'

  ObjectPhysicalMemoryName: TUnicodeString = ( 

    Length: Length(ObjectPhysicalMemoryDeviceName) * 2

    MaximumLength: Length(ObjectPhysicalMemoryDeviceName) * 2 + 2

    Buffer: ObjectPhysicalMemoryDeviceName; 

  ); 

  ObjectPhysicalMemoryAccessMask: ACCESS_MASK = SECTION_MAP_READ; 

  ObjectPhysicalMemoryAttributes: TObjectAttributes =( 

    Length: SizeOf(TObjectAttributes); 

    RootDirectory: 0

    ObjectName: @ObjectPhysicalMemoryName; 

    Attributes: OBJ_CASE_INSENSITIVE; 

    SecurityDescriptor: nil; 

    SecurityQualityOfService: nil; 

  ); 

 

type 

  TFNZwOpenSection = function(out SectionHandle: THandle; 

    DesiredAccess: ACCESS_MASK; ObjectAttributes: PObjectAttributes): NTSTATUS; 

    stdcall; 

  TFNRtlNtStatusToDosError = function(Status: NTSTATUS): DWORD; stdcall; 

 

const 

  ntdll = 'ntdll.dll'

 

var 

  ZwOpenSection: TFNZwOpenSection; 

  RtlNtStatusToDosError: TFNRtlNtStatusToDosError; 

 

function ReadRomBiosNt(var Buffer: TRomBiosDump; Timeout: DWORD): Boolean; 

var 

  NtLayer: HMODULE; 

  Status: NTSTATUS; 

  Section: THandle; 

  View: Pointer; 

begin 

  Result := False; 

  NtLayer := GetModuleHandle(ntdll); 

  if NtLayer = 0 then 

    SetLastError(ERROR_CALL_NOT_IMPLEMENTED) 

  else 

  begin 

    if not Assigned(ZwOpenSection) then 

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

    if not Assigned(RtlNtStatusToDosError) then 

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

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

      SetLastError(ERROR_CALL_NOT_IMPLEMENTED) 

    else 

    begin 

      Status := ZwOpenSection(Section, ObjectPhysicalMemoryAccessMask, 

        @ObjectPhysicalMemoryAttributes); 

      case Status of 

        STATUS_SUCCESS: 

          try 

            View := MapViewOfFile(Section, ObjectPhysicalMemoryAccessMask, 0

              Low(TRomBiosDump), SizeOf(TRomBiosDump)); 

            if Assigned(View) then 

            try 

              FillChar(Buffer, SizeOf(TRomBiosDump), 0); 

              Move(View^, Buffer, SizeOf(TRomBiosDump)); 

              Result := True; 

            finally 

              UnmapViewOfFile(View); 

            end

          finally 

            CloseHandle(Section); 

          end

        STATUS_ACCESS_DENIED: 

          Result := ReadRomBios16(Buffer, Timeout); 

      else 

        SetLastError(RtlNtStatusToDosError(Status)) 

      end

    end

  end

end

 

{############################################################################### 

#                                                                              # 

#                               ReadRomBios                                    # 

#                                                                              # 

###############################################################################} 

 

function ReadRomBios(var Dump: TRomBiosDump; Method: TReadRomBiosMethod; 

  Timeout: DWORD = INFINITE): Boolean; 

begin 

  Result := False; 

  case Method of 

    rrbmAutomatic: 

      if (Integer(GetVersion) < 0) then 

      try 

        Result := ReadRomBios9x(Dump); 

      except 

        Result := ReadRomBios16(Dump, Timeout); 

      end 

      else 

        Result := ReadRomBiosNt(Dump, Timeout); 

    rrbmGeneric: 

      Result := ReadRomBios16(Dump, Timeout); 

    rrbmMemory: 

      Result := ReadRomBios9x(Dump); 

    rrbmPhysical: 

      Result := ReadRomBiosNt(Dump, Timeout); 

  else 

    SetLastError(ERROR_INVALID_PARAMETER); 

  end

end

 

{############################################################################### 

#                                                                              # 

#     Utilities to simplify the access to data as generic standard types       # 

#                                                                              # 

###############################################################################} 

 

function GetRomBiosBuffer(const Dump: TRomBiosDump; Address: Pointer; 

  var Buffer; BufferSize: Cardinal): Cardinal; 

begin 

  Result := 0

  if (Cardinal(Address) >= Low(TRomBiosDump)) and 

    (Cardinal(Address) <= High(TRomBiosDump)) then 

  begin 

    Result := BufferSize; 

    if (Cardinal(Address) + BufferSize > High(TRomBiosDump)) then 

      Result := High(TRomBiosDump) - Cardinal(Address) + 1

    Move(Dump[Cardinal(Address)], Buffer, Result); 

  end

end

 

function GetRomBiosString(const Dump: TRomBiosDump; Address: Pointer): string; 

begin 

  Result := ''

  if (Cardinal(Address) >= Low(TRomBiosDump)) and 

    (Cardinal(Address) <= High(TRomBiosDump)) then 

    Result := string(PChar(@Dump[Cardinal(Address)])); 

end

 

function GetRomBiosLongLong(const Dump: TRomBiosDump; Address: Pointer): LONGLONG; 

type 

  PLongLong = ^LONGLONG; 

begin 

  Result := 0

  if (Cardinal(Address) >= Low(TRomBiosDump)) and 

    (Cardinal(Address) <= High(TRomBiosDump) - SizeOf(LONGLONG) + 1) then 

    Result := PLongLong(@Dump[Cardinal(Address)])^; 

end

 

function GetRomBiosDWord(const Dump: TRomBiosDump; Address: Pointer): DWORD; 

begin 

  Result := 0

  if (Cardinal(Address) >= Low(TRomBiosDump)) and 

    (Cardinal(Address) <= High(TRomBiosDump) - SizeOf(DWORD) + 1) then 

    Result := PDWORD(@Dump[Cardinal(Address)])^; 

end

 

function GetRomBiosWord(const Dump: TRomBiosDump; Address: Pointer): Word; 

begin 

  Result := 0

  if (Cardinal(Address) >= Low(TRomBiosDump)) and 

    (Cardinal(Address) <= High(TRomBiosDump) - SizeOf(Word) + 1) then 

    Result := PWord(@Dump[Cardinal(Address)])^; 

end

 

function GetRomBiosByte(const Dump: TRomBiosDump; Address: Pointer): Byte; 

begin 

  Result := 0

  if (Cardinal(Address) >= Low(TRomBiosDump)) and 

    (Cardinal(Address) <= High(TRomBiosDump) - SizeOf(Byte) + 1) then 

    Result := PByte(@Dump[Cardinal(Address)])^; 

end

 

end