I am currently working on a school project to read FAT32 formatted drive. I understand that the starting cluster of Rdet, number of bytes per sector, number of sectors per cluster are all located in boot sector and have successfully extracted said info. However, when i try to read the first Sector of RDET it just resulted in all zeroes.
Here's the code:
#include <iostream>
#include <windows.h>
#include <iomanip>
#include <vector>
#include <sstream>
#include <string>
using namespace std;
string convertToUpperCase(string input)
{
for (int i = 0; i < input.size(); i++)
if (input[i] >= 'a' && input[i] <= 'z')
input[i] = input[i] - 'a' + 'A';
return input;
}
string getHexRepresentation(const char* data, size_t size)
{
stringstream hexString;
for (size_t i = 0; i < size; ++i)
hexString << hex << setw(2) << setfill('0') << static_cast<int>(static_cast<unsigned char>(data[i])) << " ";
return convertToUpperCase(hexString.str());
}
void getArrayFromHex(const string& hexString, vector<string>& storedValues)
{
stringstream hexStream(hexString);
string temp;
while (getline(hexStream, temp, ' '))
storedValues.push_back(temp);
}
bool checkEmpty(vector<string> storedValues)
{
for (int i = 0; i < storedValues.size(); i++)
if (storedValues[i] != "00")
return false;
return true;
}
int convertHexToDec(const string& hexString)
{
int num;
stringstream(hexString) >> hex >> num;
return num;
}
string convertHexToAscii(string temp)
{
string result;
for (int i = 0; i < temp.length(); i += 2)
{
string byteString = temp.substr(i, 2);
char byte = static_cast<char>(convertHexToDec(byteString));
result += byte;
}
return result;
}
string convertStringToLittleEdian(string input)
{
string result = "";
string copy = input;
vector<string> temp;
while (copy != "")
{
temp.push_back(copy.substr(0, 2));
copy.erase(0, 2);
}
for (int i = temp.size() - 1; i >= 0; i--)
result += temp[i];
return result;
}
string getStringFromVector(vector<string> storedValues, int start, int length)
{
string result;
for (int i = start; i < start + length; i++)
result += storedValues[i];
return result;
}
int main()
{
const char* diskPath = "\\\\.\\E:";
string hexRepresentation;
HANDLE hDevice = CreateFileA(diskPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to open disk. Error code: " << GetLastError() << endl;
return 1;
}
const DWORD sectorSize = 512;
char sectorData[sectorSize];
vector<string> storedValues;
DWORD bytesRead;
SetFilePointer(hDevice, 0, NULL, FILE_BEGIN);
if (ReadFile(hDevice, sectorData, sectorSize, &bytesRead, NULL))
hexRepresentation = getHexRepresentation(sectorData, bytesRead);
else
cerr << "Failed to read sector. Error code: " << GetLastError() << endl;
CloseHandle(hDevice);
getArrayFromHex(hexRepresentation, storedValues);
//print boot sector
for (int i = 0; i < storedValues.size(); i++)
{
if (i % 16 == 0)
cout << endl;
cout << storedValues[i] << " ";
}
CloseHandle(hDevice);
cout << "\n";
DWORD bytePerSector = convertHexToDec(convertStringToLittleEdian(getStringFromVector(storedValues, 0xB, 2)));
cout << "Number of bytes per Sector = " << bytePerSector << "\n";
DWORD Sc = convertHexToDec(convertStringToLittleEdian(getStringFromVector(storedValues, 0xD, 1)));
cout << "Sc = " << Sc << "\n";
DWORD Sb = convertHexToDec(convertStringToLittleEdian(getStringFromVector(storedValues, 0xE, 2)));
cout << "Sb = " << Sb << "\n";
DWORD Nf = convertHexToDec(convertStringToLittleEdian(getStringFromVector(storedValues, 0x10, 1)));
cout << "Nf = " << Nf << "\n";
DWORD Sv = convertHexToDec(convertStringToLittleEdian(getStringFromVector(storedValues, 0x20, 4)));
cout << "Sv = " << Sv << "\n";
DWORD Sf = convertHexToDec(convertStringToLittleEdian(getStringFromVector(storedValues, 0x24, 4)));
cout << "Sf = " << Sf << "\n";
DWORD startClusterOfRdet = convertHexToDec(convertStringToLittleEdian(getStringFromVector(storedValues, 0x2C, 4)));
cout << "Starting cluster of RDET = " << startClusterOfRdet << "\n";
string FATtype = convertHexToAscii(getStringFromVector(storedValues, 0x52, 8));
cout << "FAT type: " << FATtype << "\n";
DWORD startSectorOfRDET = startClusterOfRdet * Sc;
DWORD startByteOfRDET = startSectorOfRDET * bytePerSector;
hDevice = CreateFileA(diskPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
SetFilePointer(hDevice, startByteOfRDET, NULL, FILE_BEGIN);
if (ReadFile(hDevice, sectorData, sectorSize, &bytesRead, NULL))
hexRepresentation = getHexRepresentation(sectorData, bytesRead);
CloseHandle(hDevice);
storedValues.clear();
getArrayFromHex(hexRepresentation, storedValues);
//print first sector of RDET
for (int i = 0; i < storedValues.size(); i++)
{
if (i % 16 == 0)
cout << endl;
cout << storedValues[i] << " ";
}
return 0;
}
This is just me trying to recreate the problem at a smaller scale without a bunch of classes, and irrelevant functions to the problem at hand. I'm desperate so any idea would be appreciated.
PS: Sorry for the awful code!
I've just figured it out on my own, so i just want to post an update of the answer on here in case anyone falls into the same situation. Even though the start cluster of RDET is stored inside of FAT32, i found a better way to access the first sector of RDET by using the following formula:
startSectorOfRdet = Sb + Sf * Nf;
I assume this is because in FAT32, RDET is also placed inside the data area, so when trying to access the first sector of said area, it also meant that I was able to find the RDET's first sector.
PS: Still don't know why the previous method didn't work.