mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[core] add file System detection from superblock
* Also prevent GitHub Actions from failing on VirusTotal upload
This commit is contained in:
		
							parent
							
								
									036f6260c5
								
							
						
					
					
						commit
						ebaa7d561a
					
				
					 6 changed files with 140 additions and 7 deletions
				
			
		
							
								
								
									
										1
									
								
								.github/workflows/codeql.nope
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/codeql.nope
									
										
									
									
										vendored
									
									
								
							|  | @ -1,3 +1,4 @@ | |||
| # Disabled on account of https://github.com/github/codeql-action/issues/850 | ||||
| name: "CodeQL" | ||||
| 
 | ||||
| on: | ||||
|  |  | |||
							
								
								
									
										1
									
								
								.github/workflows/mingw.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/mingw.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -80,6 +80,7 @@ jobs: | |||
|       run: sha256sum ./rufus.exe | ||||
| 
 | ||||
|     - name: Upload to VirusTotal | ||||
|       continue-on-error: true | ||||
|       if: ${{ matrix.env == 'i686' && github.event_name == 'push' }} | ||||
|       run: | | ||||
|         curl --request POST --url https://www.virustotal.com/vtapi/v2/file/scan --form apikey=${{ secrets.VIRUSTOTAL_API_KEY }} --form file=@./rufus.exe | ||||
|  |  | |||
							
								
								
									
										1
									
								
								.github/workflows/vs2022.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/vs2022.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -70,6 +70,7 @@ jobs: | |||
|       run: sha256sum ./rufus_${{ matrix.TARGET_PLATFORM }}.exe | ||||
| 
 | ||||
|     - name: Upload to VirusTotal | ||||
|       continue-on-error: true | ||||
|       if: ${{ github.event_name == 'push' }} | ||||
|       run: | | ||||
|         curl --request POST --url https://www.virustotal.com/vtapi/v2/file/scan --form apikey=${{ secrets.VIRUSTOTAL_API_KEY }} --form file=@./rufus_${{ matrix.TARGET_PLATFORM }}.exe | ||||
|  |  | |||
							
								
								
									
										131
									
								
								src/drive.c
									
										
									
									
									
								
							
							
						
						
									
										131
									
								
								src/drive.c
									
										
									
									
									
								
							|  | @ -1638,6 +1638,132 @@ out: | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| // This is a crude attempt at detecting file systems through their superblock magic.
 | ||||
| // Note that we only attempt to detect the file systems that Rufus can actually format.
 | ||||
| const char* GetFsName(HANDLE hPhysical, LARGE_INTEGER StartingOffset) | ||||
| { | ||||
| 	typedef struct { | ||||
| 		const char* name; | ||||
| 		const uint8_t magic[8]; | ||||
| 	} win_fs_type; | ||||
| 	const win_fs_type win_fs_types[] = { | ||||
| 		{ "exFAT", { 'E', 'X', 'F', 'A', 'T', ' ', ' ', ' ' } }, | ||||
| 		{ "NTFS", { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ' } }, | ||||
| 		{ "ReFS", { 'R', 'e', 'F', 'S', 0, 0, 0, 0 } } | ||||
| 	}; | ||||
| 	const  win_fs_type fat_fs_types[] = { | ||||
| 		{ "FAT", {  'F', 'A', 'T', ' ', ' ', ' ', ' ', ' ' } }, | ||||
| 		{ "FAT12", {  'F', 'A', 'T', '1', '2', ' ', ' ', ' ' } }, | ||||
| 		{ "FAT16", {  'F', 'A', 'T', '1', '6', ' ', ' ', ' ' } }, | ||||
| 		{ "FAT32", {  'F', 'A', 'T', '3', '2', ' ', ' ', ' ' } }, | ||||
| 	}; | ||||
| 	const uint32_t ext_feature[3][3] = { | ||||
| 		// feature_compat
 | ||||
| 		{ 0x0000017B, 0x00000004, 0x00000E00 }, | ||||
| 		// feature_ro_compat
 | ||||
| 		{ 0x00000003, 0x00000000, 0x00008FF8 }, | ||||
| 		// feature_incompat
 | ||||
| 		{ 0x00000013, 0x0000004C, 0x0003F780 } | ||||
| 	}; | ||||
| 	const char* ext_names[] = { "ext", "ext2", "ext3", "ext4" }; | ||||
| 	const char* ret = "(Unrecognized)"; | ||||
| 	DWORD i, j, offset, size, sector_size = 512; | ||||
| 	uint8_t* buf = calloc(sector_size, 1); | ||||
| 	if (buf == NULL) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	// 1. Try to detect FAT/exFAT/NTFS/ReFS through the 512 bytes superblock at offset 0
 | ||||
| 	if (!SetFilePointerEx(hPhysical, StartingOffset, NULL, FILE_BEGIN)) | ||||
| 		goto out; | ||||
| 	if (!ReadFile(hPhysical, buf, sector_size, &size, NULL) || size != sector_size) | ||||
| 		goto out; | ||||
| 
 | ||||
| 
 | ||||
| 	// The beginning of a superblock for FAT/exFAT/NTFS/ReFS is pretty much always the same:
 | ||||
| 	// There are 3 bytes potentially used for a jump instruction, and then are 8 bytes of
 | ||||
| 	// OEM Name which, even if *not* technically correct, we are going to assume hold an
 | ||||
| 	// immutable file system magic for exFAT/NTFS/ReFS (but not for FAT, see below).
 | ||||
| 	for (i = 0; i < ARRAYSIZE(win_fs_types); i++) | ||||
| 		if (memcmp(&buf[0x03], win_fs_types[i].magic, 8) == 0) | ||||
| 			break; | ||||
| 	if (i < ARRAYSIZE(win_fs_types)) { | ||||
| 		ret = win_fs_types[i].name; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	// For FAT, because the OEM Name may actually be set to something else than what we
 | ||||
| 	// expect, we poke the FAT12/16 Extended BIOS Parameter Block:
 | ||||
| 	// https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#Extended_BIOS_Parameter_Block
 | ||||
| 	// or FAT32 Extended BIOS Parameter Block:
 | ||||
| 	// https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#FAT32_Extended_BIOS_Parameter_Block
 | ||||
| 	for (offset = 0x36; offset <= 0x52; offset += 0x1C) { | ||||
| 		for (i = 0; i < ARRAYSIZE(fat_fs_types); i++) | ||||
| 			if (memcmp(&buf[offset], fat_fs_types[i].magic, 8) == 0) | ||||
| 				break; | ||||
| 		if (i < ARRAYSIZE(fat_fs_types)) { | ||||
| 			ret = fat_fs_types[i].name; | ||||
| 			goto out; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// 2. Try to detect Apple AFS/HFS/HFS+ through the 512 bytes superblock at either offset 0 or 1024
 | ||||
| 	// "NXSB" at offset 0x20 => APFS
 | ||||
| 	if (strncmp("NXSB", &buf[0x20], 4) == 0) { | ||||
| 		ret = "APFS"; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	// Switch to offset 1024
 | ||||
| 	memset(buf, sector_size, 0); | ||||
| 	StartingOffset.QuadPart += 0x0400ULL; | ||||
| 	if (!SetFilePointerEx(hPhysical, StartingOffset, NULL, FILE_BEGIN)) | ||||
| 		goto out; | ||||
| 	if (!ReadFile(hPhysical, buf, sector_size, &size, NULL) || size != sector_size) | ||||
| 		goto out; | ||||
| 	// "HX" or "H+" at offset 0x00 => HFS/HFS+
 | ||||
| 	if (buf[0] == 'H' && (buf[1] == 'X' || buf[1] == '+')) { | ||||
| 		ret = "HFS/HFS+"; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	// 3. Try to detect ext2/ext3/ext4 through the 512 bytes superblock at offset 1024
 | ||||
| 	// We're already at the right offset
 | ||||
| 	if (!SetFilePointerEx(hPhysical, StartingOffset, NULL, FILE_BEGIN)) | ||||
| 		goto out; | ||||
| 	if (!ReadFile(hPhysical, buf, sector_size, &size, NULL) || size != sector_size) | ||||
| 		goto out; | ||||
| 	if (buf[0x38] == 0x53 && buf[0x39] == 0xEF) { | ||||
| 		uint32_t rev = 0; | ||||
| 		for (i = 0; i < 3; i++) { | ||||
| 			uint32_t feature = *((uint32_t*)&buf[0x5C + 4 * i]); | ||||
| 			for (j = 0; j < 3; j++) { | ||||
| 				if (feature & ext_feature[i][j] && rev <= j) | ||||
| 					rev = j + 1; | ||||
| 			} | ||||
| 		} | ||||
| 		assert(rev < ARRAYSIZE(ext_names)); | ||||
| 		ret = ext_names[rev]; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	// 4. Try to detect UDF through by looking for a "BEA01\0" string at offset 0xC001
 | ||||
| 	// NB: This is not thorough UDF detection but good enough for our purpose.
 | ||||
| 	// For the full specs see: http://www.osta.org/specs/pdf/udf260.pdf
 | ||||
| 	memset(buf, sector_size, 0); | ||||
| 	StartingOffset.QuadPart += 0x8000ULL - 0x0400ULL; | ||||
| 	if (!SetFilePointerEx(hPhysical, StartingOffset, NULL, FILE_BEGIN)) | ||||
| 		goto out; | ||||
| 	if (!ReadFile(hPhysical, buf, sector_size, &size, NULL) || size != sector_size) | ||||
| 		goto out; | ||||
| 	if (strncmp("BEA01", &buf[1], 5) == 0) { | ||||
| 		ret = "UDF"; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	free(buf); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Fill the drive properties (size, FS, etc) | ||||
|  * Returns TRUE if the drive has a partition that can be mounted in Windows, FALSE otherwise | ||||
|  | @ -1754,9 +1880,11 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys | |||
| 					SelectedDrive.PartitionOffset[i] = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart; | ||||
| 					SelectedDrive.PartitionSize[i] = DriveLayout->PartitionEntry[i].PartitionLength.QuadPart; | ||||
| 				} | ||||
| 				suprintf("  Type: %s (0x%02x)\r\n  Size: %s (%lld bytes)\r\n  Start Sector: %lld, Boot: %s", | ||||
| 				suprintf("  Type: %s (0x%02x)\r\n  Detected File System: %s\r\n" | ||||
| 					"  Size: %s (%lld bytes)\r\n  Start Sector: %lld, Boot: %s", | ||||
| 					((part_type == 0x07 || super_floppy_disk) && (FileSystemName[0] != 0)) ? | ||||
| 					FileSystemName : GetMBRPartitionType(part_type), super_floppy_disk ? 0: part_type, | ||||
| 					GetFsName(hPhysical, DriveLayout->PartitionEntry[i].StartingOffset), | ||||
| 					SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE), | ||||
| 					DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, | ||||
| 					DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / SelectedDrive.SectorSize, | ||||
|  | @ -1789,6 +1917,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys | |||
| 				GetGPTPartitionType(&DriveLayout->PartitionEntry[i].Gpt.PartitionType)); | ||||
| 			if (DriveLayout->PartitionEntry[i].Gpt.Name[0] != 0) | ||||
| 				suprintf("  Name: '%S'", DriveLayout->PartitionEntry[i].Gpt.Name); | ||||
| 			suprintf("  Detected File System: %s", GetFsName(hPhysical, DriveLayout->PartitionEntry[i].StartingOffset)); | ||||
| 			suprintf("  ID: %s\r\n  Size: %s (%" PRIi64 " bytes)\r\n  Start Sector: %" PRIi64 ", Attributes: 0x%016" PRIX64, | ||||
| 				GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), | ||||
| 				SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE), | ||||
|  |  | |||
|  | @ -406,7 +406,8 @@ static BOOL IsRefsAvailable(MEDIA_TYPE MediaType) | |||
| 		return FALSE; | ||||
| 	if (nWindowsVersion < WINDOWS_8_1 || nWindowsBuildNumber <= 0) | ||||
| 		return FALSE; | ||||
| 	if (nWindowsBuildNumber < 16000) | ||||
| 	// Per https://gist.github.com/0xbadfca11/da0598e47dd643d933dc
 | ||||
| 	if (nWindowsBuildNumber < 16226) | ||||
| 		return TRUE; | ||||
| 	switch (nWindowsEdition) { | ||||
| 	case 0x0000000A: // Enterprise Server
 | ||||
|  |  | |||
							
								
								
									
										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 3.18.1866" | ||||
| CAPTION "Rufus 3.18.1867" | ||||
| FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | ||||
| BEGIN | ||||
|     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP | ||||
|  | @ -395,8 +395,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 3,18,1866,0 | ||||
|  PRODUCTVERSION 3,18,1866,0 | ||||
|  FILEVERSION 3,18,1867,0 | ||||
|  PRODUCTVERSION 3,18,1867,0 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -414,13 +414,13 @@ BEGIN | |||
|             VALUE "Comments", "https://rufus.ie" | ||||
|             VALUE "CompanyName", "Akeo Consulting" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "3.18.1866" | ||||
|             VALUE "FileVersion", "3.18.1867" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011-2022 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" | ||||
|             VALUE "OriginalFilename", "rufus-3.18.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "3.18.1866" | ||||
|             VALUE "ProductVersion", "3.18.1867" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue