mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[uefi] add detection and warning for revoked bootloaders
* Considering that alerting users to potential security breaches that may be exploited by boot media should also be performed by application that create them, we add detection for all the currently known revoked UEFI bootloaders, be it the ones from the official UEFI DBX as well as the ones from Windows' SkuSiPolicy.p7b, and warn the user when one such bootloader is detected on their source media. * Note that, to actually be revoked, the bootloaders flagged through SkuSiPolicy require the copying of the .p7b to the boot media, which we are currently not enacting but will perform in a subsequent commit. * Also fix a Coverity warning in hash.c.
This commit is contained in:
parent
c4b1b23832
commit
43764268de
8 changed files with 3168 additions and 17 deletions
|
@ -597,6 +597,12 @@ t MSG_337 "An additional file ('diskcopy.dll') must be downloaded from Microsoft
|
|||
"- Select 'Yes' to connect to the Internet and download it\n"
|
||||
"- Select 'No' to cancel the operation\n\n"
|
||||
"Note: The file will be downloaded in the application's directory and will be reused automatically if present."
|
||||
t MSG_338 "Revoked UEFI bootloader detected"
|
||||
t MSG_339 "Rufus detected that the ISO you have selected contains a UEFI bootloader that has been revoked and that will produce %s, on a fully up to date UEFI system with Secure Boot enabled.\n\n"
|
||||
"- If you obtained this ISO image from a non reputable source, you should consider the possibility that it may contain UEFI malware and avoid booting from it.\n"
|
||||
"- If you obtained it from a trusted source, you should try to locate a more up to date version, that will not produce this warning."
|
||||
t MSG_340 "a \"Security Violation\" screen"
|
||||
t MSG_341 "a Windows Recovery Screen (BSOD) with '%s'"
|
||||
# The following messages are for the Windows Store listing only and are not used by the application
|
||||
t MSG_900 "Rufus is a utility that helps format and create bootable USB flash drives, such as USB keys/pendrives, memory sticks, etc."
|
||||
t MSG_901 "Official site: %s"
|
||||
|
|
203
res/scripts/SspToBar.ps1
Normal file
203
res/scripts/SspToBar.ps1
Normal file
|
@ -0,0 +1,203 @@
|
|||
#
|
||||
# SspToBar.ps1 - SkuSiPolicy.p7b revoked PE256 hashes to C byte array converter
|
||||
# Copyright © 2023 Pete Batard <pete@akeo.ie>
|
||||
# Heavily derived from https://gist.github.com/mattifestation/92e545bf1ee5b68eeb71d254cec2f78e
|
||||
# Copyright © 2016-2019 Matthew Graeber with contributions by James Forshaw
|
||||
#
|
||||
# License: BSD 3-Clause
|
||||
#
|
||||
|
||||
# This script is generates the pe256ssp[] byte array from Rufus' db.h
|
||||
|
||||
#region Parameters
|
||||
[cmdletbinding()]
|
||||
param(
|
||||
# (Optional) The path to the .p7b to process
|
||||
[string]$BinaryFilePath = "SkuSiPolicyp.p7b"
|
||||
)
|
||||
#endregion
|
||||
|
||||
Add-Type -AssemblyName 'System.Security'
|
||||
|
||||
$BinPath = Resolve-Path $BinaryFilePath
|
||||
$GuidLength = 0x10
|
||||
$Pe256HashLength = 0x20
|
||||
$HeaderLengthMax = 0x44
|
||||
|
||||
# Helper function to read strings from the binary
|
||||
function Get-BinaryString {
|
||||
[OutputType('String')]
|
||||
param (
|
||||
[Parameter(Mandatory)]
|
||||
[IO.BinaryReader]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
$BinaryReader
|
||||
)
|
||||
|
||||
$StringLength = $BinaryReader.ReadUInt32()
|
||||
|
||||
if ($StringLength) {
|
||||
$PaddingBytes = 4 - $StringLength % 4 -band 3
|
||||
|
||||
$StringBytes = $BinaryReader.ReadBytes($StringLength)
|
||||
$null = $BinaryReader.ReadBytes($PaddingBytes)
|
||||
|
||||
[Text.Encoding]::Unicode.GetString($StringBytes)
|
||||
}
|
||||
|
||||
$null = $BinaryReader.ReadInt32()
|
||||
}
|
||||
|
||||
try {
|
||||
$CIPolicyBytes = [IO.File]::ReadAllBytes($BinPath.Path)
|
||||
|
||||
try {
|
||||
$ContentType = $null
|
||||
try {
|
||||
$ContentType = [Security.Cryptography.Pkcs.ContentInfo]::GetContentType($CIPolicyBytes)
|
||||
} catch { Write-Host "WTF!" }
|
||||
|
||||
# Check for PKCS#7 ASN.1 SignedData type
|
||||
if ($ContentType -and $ContentType.Value -eq '1.2.840.113549.1.7.2') {
|
||||
$Cms = New-Object System.Security.Cryptography.Pkcs.SignedCms
|
||||
$Cms.Decode($CIPolicyBytes)
|
||||
$CIPolicyBytes = $Cms.ContentInfo.Content
|
||||
if ($CIPolicyBytes[0] -eq 4) {
|
||||
$PolicySize = $CIPolicyBytes[1]
|
||||
$BaseIndex = 2
|
||||
if (($PolicySize -band 0x80) -eq 0x80) {
|
||||
$SizeCount = $PolicySize -band 0x7F
|
||||
$BaseIndex += $SizeCount
|
||||
$PolicySize = 0
|
||||
for ($i = 0; $i -lt $SizeCount; $i++) {
|
||||
$PolicySize = $PolicySize -shl 8
|
||||
$PolicySize = $PolicySize -bor $CIPolicyBytes[2 + $i]
|
||||
}
|
||||
}
|
||||
|
||||
$CIPolicyBytes = $CIPolicyBytes[$BaseIndex..($BaseIndex + $PolicySize - 1)]
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Output $_
|
||||
}
|
||||
|
||||
$MemoryStream = New-Object -TypeName IO.MemoryStream -ArgumentList @(,$CIPolicyBytes)
|
||||
$BinaryReader = New-Object -TypeName System.IO.BinaryReader -ArgumentList $MemoryStream, ([Text.Encoding]::Unicode)
|
||||
} catch {
|
||||
throw $_
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
$CIPolicyFormatVersion = $BinaryReader.ReadInt32()
|
||||
Write-Verbose "Detected CI Policy Format Version $CIPolicyFormatVersion"
|
||||
if ($CIPolicyFormatVersion -gt 7) {
|
||||
Write-Warning "CI Policy Format may be unsupported..."
|
||||
}
|
||||
|
||||
$PolicyTypeID = [Guid][Byte[]] $BinaryReader.ReadBytes($GuidLength)
|
||||
switch ($PolicyTypeID.Guid) {
|
||||
'a244370e-44c9-4c06-b551-f6016e563076' { Write-Verbose "Policy Type {$PolicyTypeID} => Enterprise Code Integrity Policy (SiPolicy.p7b or UpdateSiPolicy.p7b)" }
|
||||
'2a5a0136-f09f-498e-99cc-51099011157c' { Write-Verbose "Policy Type {$PolicyTypeID} => Windows Revoke Code Integrity Policy (RvkSiPolicy.p7b or UpdateRvkSiPolicy.p7b)" }
|
||||
'976d12c8-cb9f-4730-be52-54600843238e' { Write-Verbose "Policy Type {$PolicyTypeID} => SKU Code Integrity Policy (SkuSiPolicy.p7b or UpdateSkuSiPolicy.p7b)" }
|
||||
'5951a96a-e0b5-4d3d-8fb8-3e5b61030784' { Write-Verbose "Policy Type {$PolicyTypeID} => Windows Lockdown Code Integrity Policy (WinSiPolicy.p7b or UpdateWinSiPolicy.p7b)" }
|
||||
'4e61c68c-97f6-430b-9cd7-9b1004706770' { Write-Verbose "Policy Type {$PolicyTypeID} => Advanced Threat Protection Code Integrity Policy (ATPSiPolicy.p7b or UpdateATPSiPolicy.p7b)" }
|
||||
'd2bda982-ccf6-4344-ac5b-0b44427b6816' { Write-Verbose "Policy Type {$PolicyTypeID} => Driver Code Integrity Policy (DriverSiPolicy.p7b or UpdateDriverSiPolicy.p7b)" }
|
||||
default { Write-Warning "Policy Type {$PolicyTypeID} => Unknown Policy Type" }
|
||||
}
|
||||
|
||||
[Byte[]] $PlatformIDBytes = $BinaryReader.ReadBytes($GuidLength)
|
||||
$PlatformID = [Guid] $PlatformIDBytes
|
||||
Write-Verbose "PlatformID: {$PlatformID}"
|
||||
|
||||
$OptionFlags = $BinaryReader.ReadInt32()
|
||||
Write-Verbose "Policy Option Flags: 0x$($OptionFlags.ToString('X8'))"
|
||||
|
||||
if ($OptionFlags -band ([Int32]::MinValue) -ne [Int32]::MinValue) {
|
||||
throw "Invalid Policy Option Flags"
|
||||
return
|
||||
}
|
||||
if (($OptionFlags -band 0x40000000) -eq 0x40000000) {
|
||||
Write-Warning 'Policy Option Flags indicate that the CI Policy was built from supplemental policies.'
|
||||
}
|
||||
|
||||
$EKURuleEntryCount = $BinaryReader.ReadInt32()
|
||||
Write-Verbose "$EKURuleEntryCount EKU Rule(s)"
|
||||
|
||||
$FileRuleEntryCount = $BinaryReader.ReadInt32()
|
||||
Write-Verbose "$FileRuleEntryCount File Rule(s)"
|
||||
|
||||
$SignerRuleEntryCount = $BinaryReader.ReadInt32()
|
||||
Write-Verbose "$SignerRuleEntryCount Signer Rule(s)"
|
||||
|
||||
$SignerScenarioEntryCount = $BinaryReader.ReadInt32()
|
||||
Write-Verbose "$SignerScenarioEntryCount Signer Scenario(s)"
|
||||
|
||||
$Revis = $BinaryReader.ReadUInt16()
|
||||
$Build = $BinaryReader.ReadUInt16()
|
||||
$Minor = $BinaryReader.ReadUInt16()
|
||||
$Major = $BinaryReader.ReadUInt16()
|
||||
Write-Verbose "Version: $Major.$Minor.$Build.$Revis"
|
||||
|
||||
$HeaderLength = $BinaryReader.ReadInt32()
|
||||
if ($HeaderLength -ne ($HeaderLengthMax - 4)) {
|
||||
Write-Warning "$BinPath has an invalid header footer: 0x$($HeaderLength.ToString('x8'))"
|
||||
}
|
||||
|
||||
if ($EKURuleEntryCount) {
|
||||
Write-Verbose "Skipping EKU Rules..."
|
||||
for ($i = 0; $i -lt $EKURuleEntryCount; $i++) {
|
||||
$EkuValueLen = $BinaryReader.ReadUInt32()
|
||||
$PaddingBytes = 4 - $EkuValueLen % 4 -band 3
|
||||
$null = $BinaryReader.ReadBytes($EkuValueLen)
|
||||
$null = $BinaryReader.ReadBytes($PaddingBytes)
|
||||
}
|
||||
}
|
||||
|
||||
if ($FileRuleEntryCount) {
|
||||
Write-Verbose "Processing File Rules..."
|
||||
$HashArray = New-Object System.Collections.ArrayList
|
||||
|
||||
for ($i = 0; $i -lt $FileRuleEntryCount; $i++) {
|
||||
$FileRuleTypeValue = $BinaryReader.ReadInt32()
|
||||
|
||||
$FileName = Get-BinaryString -BinaryReader $BinaryReader
|
||||
$Revis = $BinaryReader.ReadUInt16()
|
||||
$Build = $BinaryReader.ReadUInt16()
|
||||
$Minor = $BinaryReader.ReadUInt16()
|
||||
$Major = $BinaryReader.ReadUInt16()
|
||||
|
||||
$HashLen = $BinaryReader.ReadUInt32()
|
||||
if ($HashLen) {
|
||||
$PaddingBytes = 4 - $HashLen % 4 -band 3
|
||||
$HashBytes = $BinaryReader.ReadBytes($HashLen)
|
||||
# We are only interested in the 'DENY' type (0) for PE256 hashes
|
||||
if (($FileRuleTypeValue -eq 0) -and ($HashLen -eq $Pe256HashLength)) {
|
||||
$HashString = ($HashBytes | ForEach-Object ToString x2) -join ''
|
||||
$HashArray.Add($HashString) | Out-Null
|
||||
}
|
||||
$null = $BinaryReader.ReadBytes($PaddingBytes)
|
||||
}
|
||||
}
|
||||
# Sort the array and remove duplicates
|
||||
$HashArray.Sort()
|
||||
$HashArray = $HashArray | Select-Object -Unique
|
||||
# Output as C array data
|
||||
foreach ($HashStr in $HashArray) {
|
||||
$HashChars = $HashStr.ToCharArray()
|
||||
$Line = "`t"
|
||||
for ($i = 0; $i -lt $Pe256HashLength; $i++) {
|
||||
$Line += "0x" + $HashChars[2 * $i] + $HashChars[2 * $i + 1] + ", "
|
||||
}
|
||||
Write-Output $Line
|
||||
}
|
||||
}
|
||||
|
||||
} catch {
|
||||
$BinaryReader.Close()
|
||||
$MemoryStream.Close()
|
||||
|
||||
throw $_
|
||||
return
|
||||
}
|
28
src/hash.c
28
src/hash.c
|
@ -1645,6 +1645,7 @@ BOOL efi_image_parse(uint8_t* efi, size_t len, struct efi_image_regions** regp)
|
|||
|
||||
dos = (void*)efi;
|
||||
nt = (void*)(efi + dos->e_lfanew);
|
||||
authsz = 0;
|
||||
|
||||
/*
|
||||
* Count maximum number of regions to be digested.
|
||||
|
@ -2093,11 +2094,11 @@ out:
|
|||
BOOL IsBufferInDB(const unsigned char* buf, const size_t len)
|
||||
{
|
||||
int i;
|
||||
uint8_t hash[32];
|
||||
uint8_t hash[SHA256_HASHSIZE];
|
||||
if (!HashBuffer(HASH_SHA256, buf, len, hash))
|
||||
return FALSE;
|
||||
for (i = 0; i < ARRAYSIZE(sha256db); i += 32)
|
||||
if (memcmp(hash, &sha256db[i], 32) == 0)
|
||||
for (i = 0; i < ARRAYSIZE(sha256db); i += SHA256_HASHSIZE)
|
||||
if (memcmp(hash, &sha256db[i], SHA256_HASHSIZE) == 0)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -2105,15 +2106,30 @@ BOOL IsBufferInDB(const unsigned char* buf, const size_t len)
|
|||
BOOL IsFileInDB(const char* path)
|
||||
{
|
||||
int i;
|
||||
uint8_t hash[32];
|
||||
uint8_t hash[SHA256_HASHSIZE];
|
||||
if (!HashFile(HASH_SHA256, path, hash))
|
||||
return FALSE;
|
||||
for (i = 0; i < ARRAYSIZE(sha256db); i += 32)
|
||||
if (memcmp(hash, &sha256db[i], 32) == 0)
|
||||
for (i = 0; i < ARRAYSIZE(sha256db); i += SHA256_HASHSIZE)
|
||||
if (memcmp(hash, &sha256db[i], SHA256_HASHSIZE) == 0)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int IsUefiBootloaderRevoked(const char* path)
|
||||
{
|
||||
int i;
|
||||
uint8_t hash[SHA256_HASHSIZE];
|
||||
if (!PE256File(path, hash))
|
||||
return -1;
|
||||
for (i = 0; i < ARRAYSIZE(pe256dbx); i += SHA256_HASHSIZE)
|
||||
if (memcmp(hash, &pe256dbx[i], SHA256_HASHSIZE) == 0)
|
||||
return 1;
|
||||
for (i = 0; i < ARRAYSIZE(pe256ssp); i += SHA256_HASHSIZE)
|
||||
if (memcmp(hash, &pe256ssp[i], SHA256_HASHSIZE) == 0)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(TEST) || defined(ALPHA)
|
||||
/* Convert a lowercase hex string to binary. Returned value must be freed */
|
||||
uint8_t* to_bin(const char* str)
|
||||
|
|
|
@ -86,15 +86,15 @@ BOOL enable_iso = TRUE, enable_joliet = TRUE, enable_rockridge = TRUE, has_ldlin
|
|||
#define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0)
|
||||
static const char* psz_extract_dir;
|
||||
static const char* bootmgr_name = "bootmgr";
|
||||
static const char* bootmgr_efi_name = "bootmgr.efi";
|
||||
const char* bootmgr_efi_name = "bootmgr.efi";
|
||||
static const char* grldr_name = "grldr";
|
||||
static const char* ldlinux_name = "ldlinux.sys";
|
||||
static const char* ldlinux_c32 = "ldlinux.c32";
|
||||
static const char* md5sum_name[] = { "MD5SUMS", "md5sum.txt" };
|
||||
static const char* casper_dirname = "/casper";
|
||||
static const char* proxmox_dirname = "/proxmox";
|
||||
static const char* efi_dirname = "/efi/boot";
|
||||
static const char* efi_bootname[ARCH_MAX] = {
|
||||
const char* efi_dirname = "/efi/boot";
|
||||
const char* efi_bootname[ARCH_MAX] = {
|
||||
"boot.efi", "bootia32.efi", "bootx64.efi", "bootarm.efi", "bootaa64.efi", "bootia64.efi",
|
||||
"bootriscv32.efi", "bootriscv64.efi", "bootriscv128.efi", "bootebc.efi" };
|
||||
static const char* sources_str = "/sources";
|
||||
|
|
35
src/rufus.c
35
src/rufus.c
|
@ -103,6 +103,7 @@ extern char* szStatusMessage;
|
|||
extern const char* old_c32_name[NB_OLD_C32];
|
||||
extern const char* cert_name[3];
|
||||
extern const char* FileSystemLabel[FS_MAX];
|
||||
extern const char *bootmgr_efi_name, *efi_dirname, *efi_bootname[ARCH_MAX];
|
||||
|
||||
/*
|
||||
* Globals
|
||||
|
@ -1543,11 +1544,36 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
|
|||
WriteSetting32(SETTING_WUE_OPTIONS, (UNATTEND_DEFAULT_MASK << 16) | unattend_xml_mask);
|
||||
}
|
||||
} else if (target_type == TT_UEFI) {
|
||||
char efi_path[MAX_PATH], tmp_path[MAX_PATH];
|
||||
if (!IS_EFI_BOOTABLE(img_report)) {
|
||||
// Unsupported ISO
|
||||
MessageBoxExU(hMainDialog, lmprintf(MSG_091), lmprintf(MSG_090), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid);
|
||||
goto out;
|
||||
}
|
||||
// coverity[swapped_arguments]
|
||||
if (GetTempFileNameU(temp_dir, APPLICATION_NAME, 0, tmp_path) != 0) {
|
||||
int i, j;
|
||||
for (i = 0; i < ARRAYSIZE(efi_bootname) + 1; i++) {
|
||||
if ((img_report.has_efi & (1 << i)) == 0)
|
||||
continue;
|
||||
if (i == 0)
|
||||
static_strcpy(efi_path, bootmgr_efi_name);
|
||||
else
|
||||
static_sprintf(efi_path, "%s/%s", efi_dirname, efi_bootname[i - 1]);
|
||||
if (ExtractISOFile(image_path, efi_path, tmp_path, FILE_ATTRIBUTE_NORMAL) == 0) {
|
||||
uprintf("Warning: Failed to extract '%s' to check for UEFI revocation", efi_path);
|
||||
continue;
|
||||
}
|
||||
j = IsUefiBootloaderRevoked(tmp_path);
|
||||
if (j > 0) {
|
||||
MessageBoxExU(hMainDialog, lmprintf(MSG_339,
|
||||
(j == 1) ? lmprintf(MSG_340) : lmprintf(MSG_341, "Error code: 0xc0000428")),
|
||||
lmprintf(MSG_338), MB_ICONWARNING | MB_IS_RTL, selected_langid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
DeleteFileU(tmp_path);
|
||||
}
|
||||
if (HAS_WIN7_EFI(img_report) && (!WimExtractCheck(FALSE))) {
|
||||
// Your platform cannot extract files from WIM archives => download 7-zip?
|
||||
if (MessageBoxExU(hMainDialog, lmprintf(MSG_102), lmprintf(MSG_101), MB_YESNO | MB_ICONERROR | MB_IS_RTL, selected_langid) == IDYES)
|
||||
|
@ -3860,8 +3886,15 @@ extern int TestHashes(void);
|
|||
if ((ctrl_without_focus || ((GetKeyState(VK_CONTROL) & 0x8000) && (msg.message == WM_KEYDOWN)))
|
||||
&& (msg.wParam == 'T')) {
|
||||
uint8_t sum[32] = { 0 };
|
||||
PE256File("C:\\Projects\\rufus\\bootx64.efi", sum);
|
||||
PE256File("C:\\Projects\\rufus\\winload_win10_1511.exe", sum);
|
||||
DumpBufferHex(sum, 32);
|
||||
|
||||
int aya = IsUefiBootloaderRevoked("C:\\Projects\\WDACTools\\en_windows_10_multiple_editions_version_1607_updated_jan_2017_x64_dvd_9714399.iso\\efi\\boot\\bootx64.efi");
|
||||
if (aya > 0) {
|
||||
MessageBoxExU(hMainDialog, lmprintf(MSG_339,
|
||||
(aya == 1) ? lmprintf(MSG_340) : lmprintf(MSG_341, "Error code: 0xc0000428")),
|
||||
lmprintf(MSG_338), MB_ICONWARNING | MB_IS_RTL, selected_langid);
|
||||
}
|
||||
// TestHashes();
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -701,6 +701,7 @@ extern BOOL HashFile(const unsigned type, const char* path, uint8_t* sum);
|
|||
extern BOOL PE256File(const char* path, uint8_t* hash);
|
||||
extern BOOL HashBuffer(const unsigned type, const uint8_t* buf, const size_t len, uint8_t* sum);
|
||||
extern BOOL IsFileInDB(const char* path);
|
||||
extern int IsUefiBootloaderRevoked(const char* path);
|
||||
extern BOOL IsBufferInDB(const unsigned char* buf, const size_t len);
|
||||
#define printbits(x) _printbits(sizeof(x), &x, 0)
|
||||
#define printbitslz(x) _printbits(sizeof(x), &x, 1)
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 4.2.2049"
|
||||
CAPTION "Rufus 4.2.2050"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -392,8 +392,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,2,2049,0
|
||||
PRODUCTVERSION 4,2,2049,0
|
||||
FILEVERSION 4,2,2050,0
|
||||
PRODUCTVERSION 4,2,2050,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -411,13 +411,13 @@ BEGIN
|
|||
VALUE "Comments", "https://rufus.ie"
|
||||
VALUE "CompanyName", "Akeo Consulting"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "4.2.2049"
|
||||
VALUE "FileVersion", "4.2.2050"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
VALUE "OriginalFilename", "rufus-4.2.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "4.2.2049"
|
||||
VALUE "ProductVersion", "4.2.2050"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
Loading…
Reference in a new issue