uses SHA1, Base64;
function GetHashedBIOSInfo: String;
var
Ctx: TSHA1Context;
Dig: TSHA1Digest;
begin
SetString(Result, PChar(Ptr($F0000)), $10000); // 讀取 F000:0000 - F000:FFFF
SHA1Init(Ctx);
SHA1Update(Ctx, PChar(Result), Length(Result));
SHA1Final(Ctx, Dig);
SetString(Result, PChar(@Dig), SizeOf(Dig));
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
Result := Result + TrimRight(String(Q)) + #13#10;
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;
unit AwardBIOS;
interface uses Windows, SysUtils;
function GetAwardBIOSPassword: String;
implementation
function CalcPossiblePassword(Value: Word): String;
var I: Byte; C: Char; S: String[8];
begin
I := 0;
while Value <> 0 do begin
Inc(I);
if Value < $263 then begin
if Value < $80 then S[I] := Char(Value)
else if Value < $B0 then S[I] := Char(Value and $77)
else if Value < $11D then S[I] := Char($30 or (Value and $0F))
else if Value < $114 then begin
S[I] := Char($64 or (Value and $0F));
if S[I] < '0' then S[I] := Char(Byte(S[I]) + 8);
end
else if Value < $1C2 then S[I] := Char($70 or (Value and $03))
else if Value < $1E4 then S[I] := Char($30 or (Value and $03))
else begin
S[I] := Char($70 or (Value and $0F));
if S[I] > 'z' then S[I] := Char(Byte(S[I]) - 8);
end;
end else
S[I] := Char($30 or (Value and $03));
Value := (Value - Byte(S[I])) shr 2;
end;
S[0] := Char(I);
Value := I shr 1;
while Value < I do begin
C := S[Byte(S[0]) - I + 1];
S[Byte(S[0]) - I + 1] := S[I];
S[I] := C;
Dec(I);
end;
Result := S;
end;
function ReadCMOS(Offset: Byte): Byte;
var V: Byte;
begin
asm
xor ax, ax
mov al, Offset
out 70h, al
in al, 71h
mov V, al
end;
Result := V;
end;
function GetAwardBIOSPassword: String;
var SuperPW, UserPW: Word;
begin
if Win32Platform <> VER_PLATFORM_WIN32_NT then 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));
Result := '超級用戶密碼: ' + CalcPossiblePassword(SuperPW) + #13#10 +
'用戶密碼: ' + CalcPossiblePassword(UserPW);
end else
Result := 'NT 系統無法讀取 CMOS 密碼';
end;
end.
unit BIOSHelp;
{ 完整單元碼略,核心 API: }
function ReadRomBIOS(var Dump: TRomBIOSDump; Method: TReadRomBIOSMethod; Timeout: DWord = INFINITE): Boolean;
{ Method: rrbmAutomatic(自動)、rrbmGeneric(16bit COM)、rrbmMemory(Win9x 記憶體)、rrbmPhysical(NT 物理記憶體) }
{ 輔助函數: GetRomBIOSString/DWord/Word/Byte/Buffer/LongLong }
end.
使用範例:
var Dump: TRomBIOSDump; I: Integer;
begin
ReadRomBIOS(Dump, rrbmAutomatic);
for I := 0 to High(Dump) do
Memo1.Lines.Add(IntToHex(Dump[I], 2));
end;
function GetBIOSDate1: String;
var Buf: array[0..8] of Char; N: DWord;
begin
ReadProcessMemory(GetCurrentProcess, Ptr($FFFF5), @Buf, 8, N);
Buf[8] := #0;
Result := StrPas(Buf);
end;
function GetBIOSDate2: String;
begin
Result := String(PChar(Ptr($FFFF5)));
end;
| 需求 | 推薦方案 | 平台限制 |
|---|---|---|
| 軟體授權綁定唯一硬體指紋 | 方案一 (SHA1 指紋) | 全平台 |
| 維修/管理需讀取 BIOS 設定密碼 | 方案二 (Award CMOS) | 僅 Win9x,非 NT |
| 完整 BIOS 程式碼分析/備份 | 方案三 (ROM 傾印) | 全平台 (自動選擇方法) |
| 快速取得 BIOS 發布日期 | 方案四 (日期字串) | Win9x/2K 推測適用,需權限 |