Last active
April 28, 2023 14:39
-
-
Save glem0/8ba1ee9b96767fed74db24defabc1d7e to your computer and use it in GitHub Desktop.
A little program to analyse the mbr of any drive on your system, and provide information about the partitions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* analyse_mbr.c by glem */ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#define MBR_SIZE 512 | |
#define NUM_PARTITIONS 4 | |
/* offsets within the MBR */ | |
#define SEC_PARTITION_START 0x1BE | |
#define SEC_MAGICBYTES_START 0x1FE | |
/* offsets within a partition record */ | |
#define OFF_START_CHS 0x1 | |
#define OFF_PART_DESC 0x4 | |
#define OFF_END_CHS 0x5 | |
#define OFF_START_SEC 0x8 | |
#define OFF_PART_SZ 0xC | |
/* global mbr buffer */ | |
static uint8_t mbr[512]; | |
static void check_boot_indicator(uint32_t); | |
static void check_chs_values(char *, uint32_t); | |
static uint32_t check_partition_size(uint32_t); | |
static void check_starting_sector(uint32_t); | |
static void check_partition_fs(uint32_t); | |
static char * sector_to_size_str(uint32_t); | |
int | |
main(int argc, char **argv){ | |
/* sanity checking, need to provide drive name */ | |
if (argc < 2) { | |
printf("usage: %s /dev/<drive>\n", argv[0]); | |
exit(EXIT_FAILURE); | |
} | |
/* open drive and read first sector into mbr */ | |
printf("** Opening drive %s..\n", argv[1]); | |
FILE *root_drive = fopen(argv[1], "r"); | |
if (!root_drive) { | |
printf("Could not open %s, try running as root?\n", argv[1]); | |
exit(EXIT_FAILURE); | |
} | |
fread(&mbr, MBR_SIZE, 1, root_drive); | |
/* ensure magic bytes are in the sector read in */ | |
if (mbr[SEC_MAGICBYTES_START+1]==0xaa && mbr[SEC_MAGICBYTES_START]==0x55) | |
puts("** MBR magic bytes in place!"); | |
else { | |
puts("** Error - could not read magic bytes"); | |
exit(EXIT_FAILURE); | |
} | |
/* loop through the partitions and print information */ | |
for (uint8_t i = 0; i < NUM_PARTITIONS; i++) { | |
uint32_t start = SEC_PARTITION_START + i*0x10; | |
printf("** Analyzing Partition %u\n", i); | |
check_boot_indicator(start); | |
if(!check_partition_size(start+OFF_PART_SZ)) | |
continue; | |
check_chs_values("Starting", start+OFF_START_CHS); | |
check_chs_values("Ending ", start+OFF_END_CHS); | |
check_starting_sector(start+OFF_START_SEC); | |
check_partition_fs(start+OFF_PART_DESC); | |
} | |
} | |
/* | |
* prints the boot flag, indicating if this partition is bootable or not | |
*/ | |
static void | |
check_boot_indicator(uint32_t start) { | |
if (mbr[start]==0x00) | |
puts("\tThis is not bootable"); | |
else if(mbr[start]==0x80) | |
puts("\tThis is bootable"); | |
else | |
puts("\tError reading bootable flag"); | |
} | |
/* | |
* retrieve the CHS value of the start/end of the partition for the drive | |
*/ | |
static void | |
check_chs_values(char *str, uint32_t start) { | |
uint8_t c,h,s; | |
c = mbr[start]; | |
h = mbr[start+0x1]; | |
s = mbr[start+0x2]; | |
printf("\t%s CHS values C=%u, H=%u, S=%u\n", str, c, h, s); | |
} | |
/* | |
* retrieve the number of sectors into the disk drive the partition exists | |
*/ | |
static void | |
check_starting_sector(uint32_t start) { | |
uint8_t *start_loc = &mbr[start]; | |
uint32_t start_sec = *(uint32_t *)start_loc; | |
char *sz_str = sector_to_size_str(start_sec); | |
printf("\tPartition starts at sector number %u (%s in)\n", start_sec, sz_str); | |
} | |
/* | |
* retrieve the number of sectors the partition occupies | |
*/ | |
static uint32_t | |
check_partition_size(uint32_t start) { | |
uint8_t *size_loc = &mbr[start]; | |
uint32_t size = *(uint32_t *)size_loc; | |
char *sz_str = sector_to_size_str(size); | |
if (size) { | |
sz_str = sector_to_size_str(size); | |
printf("\tPartition is %u sectors (%s)\n", size, sz_str); | |
} else | |
puts("\tIs an empty partition"); | |
return size; | |
} | |
/* | |
* retrieve the ID indicating the type of filesystem the drive uses | |
*/ | |
static void | |
check_partition_fs(uint32_t start) { | |
uint8_t fs_id = mbr[start]; | |
printf("\tPartition filesystem id is %u\n", fs_id); | |
} | |
/* | |
* static function to convert a number of sectors into a useable size | |
*/ | |
static char * | |
sector_to_size_str(uint32_t size) { | |
double sz_kb, sz_mb, sz_gb; | |
char *sz_str = malloc(10); | |
sz_kb = size / 2; | |
sz_mb = sz_kb / 1024; | |
sz_gb = sz_mb / 1024; | |
if (sz_gb>=1) | |
sprintf(sz_str, "%.2fGB", sz_gb); | |
else if (sz_mb>=1) | |
sprintf(sz_str, "%.2fMB", sz_mb); | |
else | |
sprintf(sz_str, "%.2fKB", sz_kb); | |
return sz_str; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
** Opening drive /dev/sdb.. | |
** MBR magic bytes in place! | |
** Analyzing Partition 0 | |
This is not bootable | |
Partition is 1953521664 sectors (931.51GB) | |
Starting CHS values C=32, H=33, S=0 | |
Ending CHS values C=254, H=255, S=255 | |
Partition starts at sector number 2048 (1.00MB in) | |
Partition filesystem id is 7 | |
** Analyzing Partition 1 | |
This is not bootable | |
Is an empty partition | |
** Analyzing Partition 2 | |
This is not bootable | |
Is an empty partition | |
** Analyzing Partition 3 | |
This is not bootable | |
Is an empty partition |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment