diff --git a/tsk/img/raw.c b/tsk/img/raw.c index b4864e4f361f6bc190d7e23ca7d62d37955fcd8a..861e1ff8db7334336c306e60e40aab344fb1b2d0 100755 --- a/tsk/img/raw.c +++ b/tsk/img/raw.c @@ -124,41 +124,71 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf, #ifdef TSK_WIN32 { + // Default to the values that were passed in + TSK_OFF_T offset_to_read = rel_offset; + size_t len_to_read = len; + char ** buf_pointer = &buf; + char * sector_aligned_buf = NULL; + + // 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. + if ((offset_to_read % raw_info->img_info.sector_size != 0) + && (TSTRNCMP(raw_info->img_info.images[idx], _TSK_T("\\\\.\\"), 4) == 0)) { + 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 + sector_aligned_buf = (char *)tsk_malloc(len_to_read); + if (sector_aligned_buf == NULL) { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_IMG_READ); + tsk_error_set_errstr("raw_read: error allocating memory to read file \"%" PRIttocTSK + "\" offset: %" PRIdOFF " read len: %" PRIuSIZE, + raw_info->img_info.images[idx], offset_to_read, len_to_read); + return -1; + } + buf_pointer = §or_aligned_buf; + } + DWORD nread; - if (cimg->seek_pos != rel_offset) { + if (cimg->seek_pos != offset_to_read) { LARGE_INTEGER li; - li.QuadPart = rel_offset; + li.QuadPart = offset_to_read; li.LowPart = SetFilePointer(cimg->fd, li.LowPart, &li.HighPart, FILE_BEGIN); if ((li.LowPart == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR)) { + if (sector_aligned_buf != NULL) { + free(sector_aligned_buf); + } int lastError = (int)GetLastError(); tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_SEEK); tsk_error_set_errstr("raw_read: file \"%" PRIttocTSK "\" offset %" PRIdOFF " seek - %d", - raw_info->img_info.images[idx], rel_offset, + raw_info->img_info.images[idx], offset_to_read, lastError); return -1; } - cimg->seek_pos = rel_offset; + cimg->seek_pos = offset_to_read; } //For physical drive when the buffer is larger than remaining data, // WinAPI ReadFile call returns -1 //in this case buffer of exact length must be passed to ReadFile - if ((raw_info->is_winobj) && (rel_offset + (TSK_OFF_T)len > raw_info->img_info.size )) - len = (size_t)(raw_info->img_info.size - rel_offset); + if ((raw_info->is_winobj) && (offset_to_read + (TSK_OFF_T)len_to_read > raw_info->img_info.size )) + len_to_read = (size_t)(raw_info->img_info.size - offset_to_read); - if (FALSE == ReadFile(cimg->fd, buf, (DWORD) len, &nread, NULL)) { + if (FALSE == ReadFile(cimg->fd, *buf_pointer, (DWORD)len_to_read, &nread, NULL)) { + if (sector_aligned_buf != NULL) { + free(sector_aligned_buf); + } int lastError = GetLastError(); tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_READ); tsk_error_set_errstr("raw_read: file \"%" PRIttocTSK "\" offset: %" PRIdOFF " read len: %" PRIuSIZE " - %d", - raw_info->img_info.images[idx], rel_offset, len, + raw_info->img_info.images[idx], offset_to_read, len_to_read, lastError); return -1; } @@ -166,25 +196,42 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf, // ReadFile returns TRUE and sets nread to zero. // We need to check if we've reached the end of a file and set nread to // the number of bytes read. - if ((raw_info->is_winobj) && (nread == 0) && (rel_offset + len == raw_info->img_info.size)) { - nread = (DWORD)len; + if ((raw_info->is_winobj) && (nread == 0) && (offset_to_read + len_to_read == raw_info->img_info.size)) { + nread = (DWORD)len_to_read; } cnt = (ssize_t) nread; if (raw_info->img_writer != NULL) { /* img_writer is not used with split images, so rel_offset is just the normal offset*/ - TSK_RETVAL_ENUM result = raw_info->img_writer->add(raw_info->img_writer, rel_offset, buf, cnt); + TSK_RETVAL_ENUM result = raw_info->img_writer->add(raw_info->img_writer, offset_to_read, *buf_pointer, cnt); // If WriteFile returns error in the addNewBlock, hadErrorExtending is 1 if (raw_info->img_writer->inFinalizeImageWriter && raw_info->img_writer->hadErrorExtending) { + if (sector_aligned_buf != NULL) { + free(sector_aligned_buf); + } tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_WRITE); tsk_error_set_errstr("raw_read: file \"%" PRIttocTSK "\" offset: %" PRIdOFF " tsk_img_writer_add cnt: %" PRIuSIZE " - %d", - raw_info->img_info.images[idx], rel_offset, cnt + raw_info->img_info.images[idx], offset_to_read, cnt ); return -1; } } + + // Update this with the actual bytes read + cimg->seek_pos += cnt; + + // If we had to do the sector alignment, copy the result into the original buffer and fix + // the number of bytes read + if (sector_aligned_buf != NULL) { + memcpy(buf, sector_aligned_buf + rel_offset % raw_info->img_info.sector_size, len); + cnt = cnt - offset_to_read % raw_info->img_info.sector_size; + if (cnt < 0) { + cnt = -1; + } + free(sector_aligned_buf); + } } #else if (cimg->seek_pos != rel_offset) { @@ -208,8 +255,8 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf, rel_offset, len, strerror(errno)); return -1; } -#endif cimg->seek_pos += cnt; +#endif return cnt; }