예제 #1
0
// read utf32 and return unvalidated utf8
string get_possible_utf32(const sbuf_t &sbuf, size_t count, sbuf_t::byte_order_t byte_order) {

    // check for sequence
    if (chars_match(sbuf, count) || char_pairs_match(sbuf, count)) {
        // this is an uninteresting sequence, so return ""
        return "";
    }
    std::string utf8_string;
    std::back_insert_iterator<std::basic_string<char> > result = back_inserter(utf8_string);

    for (uint32_t i=0; i<count; i++) {
        try {
            uint32_t code_point;
            code_point = sbuf.get32u(i * 4, byte_order);
            try {
                result = utf8::append(code_point, result);
            } catch (utf8::invalid_code_point) {

                // invalid code point so put in the byte values directly,
                // disregarding endian convention
                utf8_string += (uint8_t)code_point;
                utf8_string += (uint8_t)code_point/0x100;
                utf8_string += (uint8_t)code_point/0x10000;
                utf8_string += (uint8_t)code_point/0x1000000;
            }
        } catch (sbuf_t::range_exception_t &e) {
            // at end of buffer
            break;
        }
    }
    return utf8_string;
}
    prefetch_record_t(const sbuf_t &sbuf):prefetch_version(), header_size(0), execution_filename(),
        execution_counter(0), execution_time(0), volume_path_name(),
        volume_serial_number(0), volume_creation_time(0),
        files(), directories() {

        // read fields in order until done or range exception
        try {

            // get prefetch version identifier
            uint8_t prefetch_version_byte = sbuf.get8u(0);

            // set values based on prefetch version
            size_t execution_time_offset=0;
            size_t execution_counter_offset=0;
            if (prefetch_version_byte == 0x11) {
                prefetch_version = "Windows XP";
                execution_time_offset = 0x78;
                execution_counter_offset = 0x90;
            } else if (prefetch_version_byte == 0x17) {
                prefetch_version = "Windows Vista or Windows 7";
                execution_time_offset = 0x80;
                execution_counter_offset = 0x98;
            } else {
                // program error: don't create prefetch_record if this byte is invalid.
                // This was an assert(0), but let's just return
                return ;
            }

            // size in bytes of the whole prefetch file
            uint32_t prefetch_file_length = sbuf.get32u(0x0c);

            // get execution file filename
            wstring utf16_execution_filename;
            sbuf.getUTF16(0x10, utf16_execution_filename);
            execution_filename = safe_utf16to8(utf16_execution_filename);

            // get the offset to Section A
            uint32_t section_a_offset = sbuf.get32u(0x54);
            header_size = section_a_offset; // header is everything before section A

            // validate the offset since we know what it should be
            if ((prefetch_version_byte == 0x11 && header_size != 0x98)		// XP and 2003
                    || (prefetch_version_byte == 0x17 && header_size != 0xf0)) {	// Vista and 7
                // invalid so quit trying
                return;
            }

            execution_time = sbuf.get64u(execution_time_offset);
            execution_counter = sbuf.get32u(execution_counter_offset);

            // get the list of files from Section C
            uint32_t section_c_offset = sbuf.get32u(0x64);
            uint32_t section_c_length = sbuf.get32u(0x68);
            sbuf_stream filename_stream(sbuf + section_c_offset);
            while (filename_stream.tell() < section_c_length) {
                wstring utf16_filename;
                filename_stream.getUTF16(utf16_filename);
                string filename = safe_utf16to8(utf16_filename);
                if (!valid_full_path_name(filename)) return;
                files.push_back(filename);
            }

            // Process Section D
            uint32_t section_d_offset = sbuf.get32u(0x6c);

            uint32_t volume_name_offset = sbuf.get32u(section_d_offset + 0x00);
            wstring utf16_volume_name;
            sbuf.getUTF16(section_d_offset+volume_name_offset, utf16_volume_name);
            volume_path_name = safe_utf16to8(utf16_volume_name);

            volume_creation_time = sbuf.get64i(section_d_offset+0x08);
            volume_serial_number = sbuf.get32u(section_d_offset+0x10);

            uint32_t section_d_2_offset = sbuf.get32u(section_d_offset + 0x1c);
            size_t   directory_offset = section_d_offset + section_d_2_offset;
            uint32_t num_directory_entries = sbuf.get32u(section_d_offset + 0x20);

            // get each of the directory entries from Section D subsection 2
            if (directory_offset > prefetch_file_length) {
                // the offset is out of range so don't get the list of directories
            } else {
                // calculate a rough maximum number of bytes for directory entries
                size_t upper_max = prefetch_file_length - directory_offset;

                sbuf_stream directory_stream = sbuf_stream(sbuf + directory_offset);

                for (uint32_t i=0; i<num_directory_entries; i++) {
                    // break if obviously out of range
                    if (directory_stream.tell() > upper_max) {
                        return;		// rest of data not good
                    }

                    // for directories, the first int16 is the directory name length.
                    // We read to \U0000 instead so we throw away the directory name length.
                    directory_stream.get16u();

                    // read the directory name
                    wstring utf16_directory_name;
                    directory_stream.getUTF16(utf16_directory_name);
                    string directory_name = safe_utf16to8(utf16_directory_name);
                    if (!valid_full_path_name(directory_name)) return;
                    directories.push_back(directory_name);
                }
            }
        } catch (sbuf_t::range_exception_t &e) {
            // no action, just return what was gleaned before range exception
        }
    }