获取主板BIOS的信息 1、读取主板序列号 2、AWard Bios密码读取 3、读取BIOS信息 4、获取BIOS日期信息
========================================= 1、读取主板序列号
uses SHA1, Base64;
function GetHashedBiosInfo: string; var SHA1Context: TSHA1Context; SHA1Digest: TSHA1Digest; begin // Get the BIOS data SetString(Result, PChar(Ptr($F0000)), $10000); // Hash the string SHA1Init(SHA1Context); SHA1Update(SHA1Context, PChar(Result), Length(Result)); SHA1Final(SHA1Context, SHA1Digest); SetString(Result, PChar(@SHA1Digest), sizeof(SHA1Digest)); // Return the hash string encoded in printable characters Result := B64Encode(Result); end;
function GetBiosInfoAsText: string; var p, q: pchar; begin q := nil; p := PChar(Ptr($FE000)); repeat if q <> nil then begin if not (p^ in [#10, #13, #32..#126, #169, #184]) then begin if (p^ = #0) and (p - q >= 8) then begin Result := Result + TrimRight(String(q)) + #13#10; end; q := nil; end; end else if p^ in [#33..#126, #169, #184] then q := p; inc(p); until p > PChar(Ptr($FFFFF)); Result := TrimRight(Result); end;
procedure TForm1.FormCreate(Sender: TObject); begin Memo1.Lines.Text := GetBiosInfoAsText; end;
========================================== 2、AWard Bios密码读取(应该是jingtao的文章,但是ID没有记录) Unit AwardBiosPas; //Write by lovejingtao //http://www.138soft.com interface uses windows,SysUtils;
function My_GetBiosPassword:String; implementation
function CalcPossiblePassword(PasswordValue: WORD): string; var I: BYTE; C: CHAR; S: string[8];
begin I := 0; while PasswordValue <> 0 do begin Inc(I); if $263 > PasswordValue then begin if $80 > PasswordValue then S[I] := CHAR(PasswordValue) else if $B0 > PasswordValue then S[I] := CHAR(PasswordValue and $77) else if $11D > PasswordValue then S[I] := CHAR($30 or (PasswordValue and $0F)) else if $114 > PasswordValue then begin S[I] := CHAR($64 or (PasswordValue and $0F)); if '0' > S[I] then S[I] := CHAR(BYTE(S[I]) + 8); end else if $1C2 > PasswordValue then S[I] := CHAR($70 or (PasswordValue and $03)) else if $1E4 > PasswordValue then S[I] := CHAR($30 or (PasswordValue and $03)) else begin S[I] := CHAR($70 or (PasswordValue and $0F)); if 'z' < S[I] then S[I] := CHAR(BYTE(S[I]) - 8); end; end else S[I] := CHAR($30 or (PasswordValue and $3)); PasswordValue := (PasswordValue - BYTE(S[I])) shr 2; end;
S[0] := CHAR(I); PasswordValue := I shr 1; while PasswordValue < I do begin {this is to do because award starts calculating with the last letter}
C := S[BYTE(S[0]) - I + 1]; S[BYTE(S[0]) - I + 1] := S[I]; S[I] := C; Dec(I); end; CalcPossiblePassword := S; end;
function readcmos(off: byte): byte; var value: byte; begin asm xor ax, ax mov al, off out 70h, al in al, 71h mov value, al end; readcmos := value; end; function My_GetBiosPassword:String; var superpw, userpw: word; S:String; begin if Win32Platform <> VER_PLATFORM_WIN32_NT then //不是NT begin pchar(@superpw)[0] := char(readcmos($1C)); pchar(@superpw)[1] := char(readcmos($1D)); pchar(@userpw)[0] := char(readcmos($64)); pchar(@userpw)[1] := char(readcmos($65)); S:='超级用户密码为:'+CalcPossiblePassword(superpw)+#13+'用户密码为:'+CalcPossiblePassword(userpw); Result:=S; end else Result:='用户系统为NT,无法获取BISO密码!'; end; end.
========================================== 3、读取BIOS信息 {程序使用Windows 95/2000平台,自动检测系统类型,然后进行不同调用} uses BiosHelp;
procedure TForm1.Button1Click(Sender: TObject); var Dump: TRomBiosDump; i: Integer; begin ReadRomBios(Dump, rrbmAutomatic); for i := 1 to $000FFFFF - $000F0000 - 1 do Memo1.Lines.Add(IntToHex(Dump[i + $000FFFFF], 2)); end; (******************************************************************************* * * * 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.03, 2001-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..$000FFFFF] of 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 <> $FFFFFFFF) and (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, 0, 0); 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.
========================================== 4、获取BIOS日期信息
{--------------------------------------------------------------------------} {获取BIOS的日期信息,估计可能在2000下适用,但是可能需要获取权限} function GetBiosDate1: String; var Buffer: Array[0..8] Of Char; N: DWORD; begin ReadProcessMemory(GetCurrentProcess, Ptr($FFFF5), @Buffer, 8, N); Buffer[8] := #0; result := StrPas(Buffer) end;
function GetBiosDate2: String; begin result := string(pchar(ptr($FFFF5))); end;
|