// ************************************************************************************************** // // CPU, HDD, MB 시리얼 넘버를 얻는 많은 방법중 // WMI 서비스를 이용하여 심플하게 받아오는 쉬운방법도 있지만 // 해당 서비스가 실행되고 있어야 하며 관리자권한 및 느리다는 단점이 있다. // // 아래 소스는 RRUZ.SMBIOS 라이브러리를 바탕으로 // System Management BIOS 통해 시스템 정보를 읽어 오는 방법이다. // // 혹자가 테스트 해 봤을때 불법 KMS로 인증받은 OS는 똑 같은 시리얼이 나온다. // // 2024.12.19 by 0GO2 // // ************************************************************************************************** unit GO2.SMBios; interface uses Winapi.Windows, Winapi.IpHlpApi, Winapi.IpTypes, System.SysUtils; function GetCPUSerialNumber: string; function GetMainboardSerialNumber: string; function GetHDDSerialNumber: string; function GetNetworkAdapterSerialNumber(IncludeWireless: Boolean = False): string; function GetHardwareInformation: string; implementation uses RRUZ.SMBIOS; function GetCPUSerialNumber: string; var SMBios: TSMBios; ProcessorInfo: TProcessorInformation; begin Result := ''; SMBios := TSMBios.Create; try // ProcessorInfo 정보 가져오기 for ProcessorInfo in SMBios.ProcessorInfo do begin // ProcessorID를 16진수 문자열로 변환 Result := IntToHex(ProcessorInfo.RAWProcessorInformation^.ProcessorID, 16); // 첫 번째 프로세서 정보만 가져오고 종료 Break; end; finally SMBios.Free; end; end; function GetMainboardSerialNumber: string; var SMBios: TSMBios; BaseBoardInfo: TBaseBoardInformation; begin Result := ''; SMBios := TSMBios.Create; try for BaseBoardInfo in SMBios.BaseBoardInfo do begin Result := BaseBoardInfo.SerialNumberStr; Break; end; finally SMBios.Free; end; end; function GetHDDSerialNumber: string; var Drive: string; SerialNumber: array[0..255] of Char; VolumeSerialNumber: DWORD; MaxComponentLength: DWORD; FileSystemFlags: DWORD; begin Drive := 'C:\'; if GetVolumeInformation(PChar(Drive), nil, 0, @VolumeSerialNumber, MaxComponentLength, FileSystemFlags, nil, 0) then begin Result := IntToHex(VolumeSerialNumber, 8); end else Result := ''; end; function GetNetworkAdapterSerialNumber(IncludeWireless: Boolean = False): string; const MIB_IF_TYPE_ETHERNET = 6; // 유선 이더넷 IF_TYPE_IEEE80211 = 71; // 무선 네트워크 var AdapterInfo: PIP_ADAPTER_INFO; LongSize: ULONG; Status: DWORD; Adapter: PIP_ADAPTER_INFO; begin Result := ''; LongSize := 0; GetAdaptersInfo(nil, LongSize); if LongSize = 0 then Exit; GetMem(AdapterInfo, LongSize); try Status := GetAdaptersInfo(AdapterInfo, LongSize); if Status = ERROR_SUCCESS then begin Adapter := AdapterInfo; while Adapter <> nil do begin // 이더넷 또는 무선 어댑터 확인 if (Adapter^.Type_ = MIB_IF_TYPE_ETHERNET) or (IncludeWireless and (Adapter^.Type_ = IF_TYPE_IEEE80211)) then begin Result := Format('%.2x%.2x%.2x%.2x%.2x%.2x', [Adapter^.Address[0], Adapter^.Address[1], Adapter^.Address[2], Adapter^.Address[3], Adapter^.Address[4], Adapter^.Address[5]]); Break; end; Adapter := Adapter^.Next; end; end; finally FreeMem(AdapterInfo); end; end; function GetHardwareInformation: string; var SMBios: TSMBios; BaseBoardInfo: TBaseBoardInformation; ProcessorInfo: TProcessorInformation; begin Result := ''; SMBios := TSMBios.Create; try // CPU 정보 for ProcessorInfo in SMBios.ProcessorInfo do begin Result := Result + 'CPU Information:' + #13#10; // SerialNumberStr는 SMBIOS Type 4의 Serial Number 필드를 읽어오는데, // 대부분의 CPU는 이 필드를 지원하지 않아 'Unknown'으로 표시된다. Result := Result + ' Serial Number: ' + IntToHex(ProcessorInfo.RAWProcessorInformation^.ProcessorID, 16) + #13#10; Result := Result + ' Manufacturer: ' + ProcessorInfo.ProcessorManufacturerStr + #13#10; Result := Result + ' Version: ' + ProcessorInfo.ProcessorVersionStr + #13#10; Break; end; // 메인보드 정보 for BaseBoardInfo in SMBios.BaseBoardInfo do begin Result := Result + #13#10 + 'Mainboard Information:' + #13#10; Result := Result + ' Serial Number: ' + BaseBoardInfo.SerialNumberStr + #13#10; Result := Result + ' Manufacturer: ' + BaseBoardInfo.ManufacturerStr + #13#10; Result := Result + ' Product: ' + BaseBoardInfo.ProductStr + #13#10; Break; end; // HDD 정보 Result := Result + #13#10 + 'HDD Information:' + #13#10; Result := Result + ' Serial Number: ' + GetHDDSerialNumber + #13#10; // 네트워크 어댑터 정보 Result := Result + #13#10 + 'Network Adapter Information:' + #13#10; Result := Result + ' MAC Address (Wired): ' + GetNetworkAdapterSerialNumber + #13#10; Result := Result + ' MAC Address (All): ' + GetNetworkAdapterSerialNumber(True); finally SMBios.Free; end; end; end.