Skip to content
Snippets Groups Projects
Unverified Commit 41b388ee authored by Richard Cordovano's avatar Richard Cordovano Committed by GitHub
Browse files

Merge pull request #1854 from APriestman/6130_findSectorSize

6130 Calculate sector size for raw images
parents adccf957 ccda715e
No related branches found
No related tags found
No related merge requests found
...@@ -39,6 +39,17 @@ ...@@ -39,6 +39,17 @@
#define S_IFDIR __S_IFDIR #define S_IFDIR __S_IFDIR
#endif #endif
/**
* \internal
* Test if the image is a Windows device
* @param The path to test
*
* Return 1 if the path represents a Windows device, 0 otherwise
*/
static int
is_windows_device_path(const TSK_TCHAR * image_name) {
return (TSTRNCMP(image_name, _TSK_T("\\\\.\\"), 4) == 0);
}
/** /**
* \internal * \internal
...@@ -133,7 +144,7 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf, ...@@ -133,7 +144,7 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf,
// If the offset to seek to isn't sector-aligned and this is a device, we need to start at the previous sector boundary and // If the offset to seek to isn't sector-aligned and this is a device, we need to start at the previous sector boundary and
// read some extra data. // read some extra data.
if ((offset_to_read % raw_info->img_info.sector_size != 0) if ((offset_to_read % raw_info->img_info.sector_size != 0)
&& (TSTRNCMP(raw_info->img_info.images[idx], _TSK_T("\\\\.\\"), 4) == 0)) { && is_windows_device_path(raw_info->img_info.images[idx])) {
offset_to_read = (offset_to_read / raw_info->img_info.sector_size) * raw_info->img_info.sector_size; offset_to_read = (offset_to_read / raw_info->img_info.sector_size) * raw_info->img_info.sector_size;
len_to_read += raw_info->img_info.sector_size; // this length will already be a multiple of sector size len_to_read += raw_info->img_info.sector_size; // this length will already be a multiple of sector size
sector_aligned_buf = (char *)tsk_malloc(len_to_read); sector_aligned_buf = (char *)tsk_malloc(len_to_read);
...@@ -630,6 +641,119 @@ get_size(const TSK_TCHAR * a_file, uint8_t a_is_winobj) ...@@ -630,6 +641,119 @@ get_size(const TSK_TCHAR * a_file, uint8_t a_is_winobj)
return size; return size;
} }
#ifdef TSK_WIN32
/**
* \internal
* Test seeking to the given offset and then reading a sector.
* @param file_handle The open file handle to the image
* @param offset The offset to seek to (in bytes)
* @param len The length to read (in bytes). Should be a multiple of the sector size.
* @param buf An allocated buffer large enough to hold len bytes
*
* @return 1 if the seek/read is successful, 0 if not
*/
static int
test_sector_read(HANDLE file_handle, TSK_OFF_T offset, DWORD len, char * buf) {
LARGE_INTEGER li;
li.QuadPart = offset;
// Seek to the given offset
li.LowPart = SetFilePointer(file_handle, li.LowPart,
&li.HighPart, FILE_BEGIN);
if ((li.LowPart == INVALID_SET_FILE_POINTER) &&
(GetLastError() != NO_ERROR)) {
return 0;
}
// Read a byte at the given offset
DWORD nread;
if (FALSE == ReadFile(file_handle, buf, len, &nread, NULL)) {
return 0;
}
if (nread != len) {
return 0;
}
// Success
return 1;
}
/**
* Attempts to calculate the actual sector size needed for reading the image.
* If successful, the calculated sector size will be stored in raw_info. If it
* fails the sector_size field will not be updated.
* @param raw_info The incomplete IMG_RAW_INFO object. The sector_size field may be updated by this method.
* @param image_name Image file name
* @param image_size Image size
*/
static void
set_device_sector_size(IMG_RAW_INFO * raw_info, const TSK_TCHAR * image_name, TSK_OFF_T image_size) {
unsigned int min_sector_size = 512;
unsigned int max_sector_size = 4096;
HANDLE file_handle = CreateFile(image_name, FILE_READ_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0,
NULL);
if (file_handle == INVALID_HANDLE_VALUE) {
if (tsk_verbose) {
tsk_fprintf(stderr,
"find_sector_size: failed to open image \"%" PRIttocTSK "\"\n", image_name);
}
return;
}
// First test whether we need to align on sector boundaries
char* buf = malloc(max_sector_size);
int needs_sector_alignment = 0;
if (image_size > raw_info->img_info.sector_size) {
if (test_sector_read(file_handle, 1, raw_info->img_info.sector_size, buf)) {
needs_sector_alignment = 0;
}
else {
needs_sector_alignment = 1;
}
}
// If reading a sector starting at offset 1 failed, the assumption is that we have a device
// that requires reads to be sector-aligned.
if (needs_sector_alignment) {
// Start at the minimum (512) and double up to max_sector_size (4096)
unsigned int sector_size = min_sector_size;
while (sector_size <= max_sector_size) {
// If we don't have enough data to do the test just stop
if (image_size < sector_size * 2) {
break;
}
if (test_sector_read(file_handle, sector_size, sector_size, buf)) {
// Found a valid sector size
if (tsk_verbose) {
tsk_fprintf(stderr,
"find_sector_size: using sector size %d\n", sector_size);
}
raw_info->img_info.sector_size = sector_size;
if (file_handle != 0) {
CloseHandle(file_handle);
}
free(buf);
return;
}
sector_size *= 2;
}
if (tsk_verbose) {
tsk_fprintf(stderr,
"find_sector_size: failed to determine correct sector size. Reverting to default %d\n", raw_info->img_info.sector_size);
}
free(buf);
}
if (file_handle != 0) {
CloseHandle(file_handle);
}
}
#endif
/** /**
* \internal * \internal
...@@ -661,9 +785,6 @@ raw_open(int a_num_img, const TSK_TCHAR * const a_images[], ...@@ -661,9 +785,6 @@ raw_open(int a_num_img, const TSK_TCHAR * const a_images[],
img_info->close = raw_close; img_info->close = raw_close;
img_info->imgstat = raw_imgstat; img_info->imgstat = raw_imgstat;
img_info->sector_size = 512;
if (a_ssize)
img_info->sector_size = a_ssize;
raw_info->is_winobj = 0; raw_info->is_winobj = 0;
#if defined(TSK_WIN32) || defined(__CYGWIN__) #if defined(TSK_WIN32) || defined(__CYGWIN__)
...@@ -683,6 +804,20 @@ raw_open(int a_num_img, const TSK_TCHAR * const a_images[], ...@@ -683,6 +804,20 @@ raw_open(int a_num_img, const TSK_TCHAR * const a_images[],
return NULL; return NULL;
} }
/* Set the sector size */
img_info->sector_size = 512;
if (a_ssize) {
img_info->sector_size = a_ssize;
}
#ifdef TSK_WIN32
else if (is_windows_device_path(a_images[0])) {
/* On Windows, figure out the actual sector size if one was not given and this is a device.
* This is to prevent problems reading later. */
set_device_sector_size(raw_info, a_images[0], first_seg_size);
}
#endif
/* see if there are more of them... */ /* see if there are more of them... */
if ((a_num_img == 1) && (raw_info->is_winobj == 0)) { if ((a_num_img == 1) && (raw_info->is_winobj == 0)) {
if ((raw_info->img_info.images = if ((raw_info->img_info.images =
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment